Previous 15994 Revisions Next

r11532 Thursday 12th May, 2011 at 22:56:22 UTC by Angelo Salese
More shuffling around, nw
[src/mame/drivers]a3000.c a310.c a7000.c ami1200.c amiga.c atari400.c n64.c nes.c ng_aes.c pce.c snes.c
[src/mame/includes]nes.h pce.h
[src/mame/machine]aescart.c aescart.h amigacd.c amigacd.h amigacrt.c amigacrt.h amigafdc.c amigafdc.h amigakbd.c amigakbd.h ataricrt.c ataridev.h atarifdc.c nes.c nes_ines.c nes_mmc.c nes_mmc.h nes_pcb.c nes_unif.c pce.c snescart.c snescart.h
[src/mame/video]nes.c
[src/mess]mess.mak
[src/mess/devices]aescart.c* aescart.h*
[src/mess/drivers]a3000.c* a310.c* a7000.c* ami1200.c* amiga.c* atari400.c* n64.c* nes.c* ng_aes.c* pce.c* snes.c*
[src/mess/includes]nes.h* pce.h*
[src/mess/machine]amigacd.c* amigacd.h* amigacrt.c* amigacrt.h* amigafdc.c* amigafdc.h* amigakbd.c* amigakbd.h* ataricrt.c* ataridev.h* atarifdc.c* nes.c* nes_ines.c* nes_mmc.c* nes_mmc.h* nes_pcb.c* nes_unif.c* pce.c* snescart.c* snescart.h*
[src/mess/video]nes.c*

src/mame/machine/ataricrt.c
r11531r11532
1/***************************************************************************
2
3    MESS specific Atari init and Cartridge code for Atari 8 bit systems
4
5***************************************************************************/
6
7#include "emu.h"
8#include "emuopts.h"
9#include "includes/atari.h"
10#include "ataridev.h"
11#include "machine/ram.h"
12#include "hashfile.h"
13
14#define LEFT_CARTSLOT_MOUNTED  1
15#define RIGHT_CARTSLOT_MOUNTED 2
16
17/* PCB */
18enum
19{
20    A800_UNKNOWN = 0,
21   A800_4K, A800_8K, A800_12K, A800_16K,
22   A800_RIGHT_4K, A800_RIGHT_8K,
23   OSS_034M, OSS_M091, PHOENIX_8K, XEGS_32K,
24   BBSB, DIAMOND_64K, WILLIAMS_64K, EXPRESS_64,
25   SPARTADOS_X
26};
27
28static int a800_cart_loaded = 0;
29static int atari = 0;
30static int a800_cart_type = A800_UNKNOWN;
31
32/*************************************
33 *
34 *  Generic code
35 *
36 *************************************/
37
38
39// Currently, the drivers have fixed 40k RAM, however the function here is ready for different sizes too
40static void a800_setbank(running_machine &machine, int cart_mounted)
41{
42   offs_t ram_top;
43
44   // take care of 0x0000-0x7fff: RAM or NOP
45   ram_top = MIN(ram_get_size(machine.device(RAM_TAG)), 0x8000) - 1;
46   machine.device("maincpu")->memory().space(AS_PROGRAM)->install_readwrite_bank(0x0000, ram_top, "0000");
47   memory_set_bankptr(machine, "0000", ram_get_ptr(machine.device(RAM_TAG)));
48
49   // take care of 0x8000-0x9fff: A800 -> either right slot or RAM or NOP, others -> RAM or NOP
50   // is there anything in the right slot?
51   if (cart_mounted & RIGHT_CARTSLOT_MOUNTED)
52   {
53      machine.device("maincpu")->memory().space(AS_PROGRAM)->install_read_bank(0x8000, 0x9fff, "8000");
54      memory_set_bankptr(machine, "8000", machine.region("rslot")->base());
55      machine.device("maincpu")->memory().space(AS_PROGRAM)->unmap_write(0x8000, 0x9fff);
56   }
57   else if (a800_cart_type != BBSB)
58   {
59      ram_top = MIN(ram_get_size(machine.device(RAM_TAG)), 0xa000) - 1;
60      if (ram_top > 0x8000)
61      {
62         machine.device("maincpu")->memory().space(AS_PROGRAM)->install_readwrite_bank(0x8000, ram_top, "8000");
63         memory_set_bankptr(machine, "8000", ram_get_ptr(machine.device(RAM_TAG)) + 0x8000);
64      }
65   }
66
67   // take care of 0xa000-0xbfff: is there anything in the left slot?
68   if (cart_mounted & LEFT_CARTSLOT_MOUNTED)
69   {
70      // FIXME: this is an hack to keep XL working until we clean up its memory map as well!
71      if (atari == ATARI_800XL)
72      {
73         if (a800_cart_type == A800_16K)
74         {
75            machine.device("maincpu")->memory().space(AS_PROGRAM)->install_read_bank(0x8000, 0x9fff, "8000");
76            memory_set_bankptr(machine, "8000", machine.region("lslot")->base());
77            machine.device("maincpu")->memory().space(AS_PROGRAM)->unmap_write(0x8000, 0x9fff);
78
79            memcpy(machine.region("maincpu")->base() + 0x10000, machine.region("lslot")->base() + 0x2000, 0x2000);
80         }
81         else if (a800_cart_type == A800_8K)
82            memcpy(machine.region("maincpu")->base() + 0x10000, machine.region("lslot")->base(), 0x2000);
83         else
84            fatalerror("This type of cart is not supported yet in this driver. Please use a400 or a800.\n");
85      }
86      else if (a800_cart_type == A800_16K)
87      {
88         memory_set_bankptr(machine, "8000", machine.region("lslot")->base());
89         memory_set_bankptr(machine, "a000", machine.region("lslot")->base() + 0x2000);
90         machine.device("maincpu")->memory().space(AS_PROGRAM)->unmap_write(0x8000, 0xbfff);
91      }
92      else if (a800_cart_type == BBSB)
93      {
94         // this requires separate banking in 0x8000 & 0x9000!
95         machine.device("maincpu")->memory().space(AS_PROGRAM)->install_read_bank(0x8000, 0x8fff, "8000");
96         machine.device("maincpu")->memory().space(AS_PROGRAM)->install_read_bank(0x9000, 0x9fff, "9000");
97         memory_set_bankptr(machine, "8000", machine.region("lslot")->base() + 0x0000);
98         memory_set_bankptr(machine, "9000", machine.region("lslot")->base() + 0x4000);
99         memory_set_bankptr(machine, "a000", machine.region("lslot")->base() + 0x8000);
100         machine.device("maincpu")->memory().space(AS_PROGRAM)->unmap_write(0xa000, 0xbfff);
101      }
102      else if (a800_cart_type == OSS_034M)
103      {
104         // this requires separate banking in 0xa000 & 0xb000!
105         machine.device("maincpu")->memory().space(AS_PROGRAM)->install_read_bank(0xa000, 0xafff, "a000");
106         machine.device("maincpu")->memory().space(AS_PROGRAM)->install_read_bank(0xb000, 0xbfff, "b000");
107         memory_set_bankptr(machine, "b000", machine.region("lslot")->base() + 0x3000);
108         machine.device("maincpu")->memory().space(AS_PROGRAM)->unmap_write(0xa000, 0xbfff);
109      }
110      else if (a800_cart_type == OSS_M091)
111      {
112         // this requires separate banking in 0xa000 & 0xb000!
113         machine.device("maincpu")->memory().space(AS_PROGRAM)->install_read_bank(0xa000, 0xafff, "a000");
114         machine.device("maincpu")->memory().space(AS_PROGRAM)->install_read_bank(0xb000, 0xbfff, "b000");
115         memory_set_bankptr(machine, "b000", machine.region("lslot")->base());
116         machine.device("maincpu")->memory().space(AS_PROGRAM)->unmap_write(0xa000, 0xbfff);
117      }
118      else if (a800_cart_type == XEGS_32K)
119      {
120         memory_set_bankptr(machine, "8000", machine.region("lslot")->base());
121         memory_set_bankptr(machine, "a000", machine.region("lslot")->base() + 0x6000);
122         machine.device("maincpu")->memory().space(AS_PROGRAM)->unmap_write(0x8000, 0xbfff);
123      }
124      else
125      {
126         memory_set_bankptr(machine, "a000", machine.region("lslot")->base());
127         machine.device("maincpu")->memory().space(AS_PROGRAM)->unmap_write(0xa000, 0xbfff);
128      }
129   }
130}
131
132/* MESS specific parts that have to be started */
133static void ms_atari_machine_start(running_machine &machine, int type, int has_cart)
134{
135   /* set atari type (temporarily not used) */
136   atari = type;
137   a800_setbank(machine, a800_cart_loaded);
138}
139
140static void ms_atari800xl_machine_start(running_machine &machine, int type, int has_cart)
141{
142   /* set atari type (temporarily not used) */
143   atari = type;
144   a800_setbank(machine, a800_cart_loaded);
145}
146
147/*************************************
148 *
149 *  Atari 400
150 *
151 *************************************/
152
153MACHINE_START( a400 )
154{
155   atari_machine_start(machine);
156   ms_atari_machine_start(machine, ATARI_400, TRUE);
157}
158
159
160/*************************************
161 *
162 *  Atari 800
163 *
164 *************************************/
165
166MACHINE_START( a800 )
167{
168   atari_machine_start(machine);
169   ms_atari_machine_start(machine, ATARI_800, TRUE);
170}
171
172static WRITE8_HANDLER( x32_bank_w )
173{
174   //  printf("written %x\n", data);
175   int bank = data & 0x03;
176   memory_set_bankptr(space->machine(), "8000", space->machine().region("lslot")->base() + bank * 0x2000);
177}
178
179static WRITE8_HANDLER( w64_bank_w )
180{
181//  printf("write to %x\n", offset);
182
183   if (offset < 8)
184      memory_set_bankptr(space->machine(), "a000", space->machine().region("lslot")->base() + offset * 0x2000);
185   else
186      memory_set_bankptr(space->machine(), "a000", space->machine().region("maincpu")->base());
187   // FIXME: writes to 0x8-0xf should disable the cart
188}
189
190// this covers Express 64, Diamond 64 and SpartaDOS (same bankswitch, but at different addresses)
191static WRITE8_HANDLER( ex64_bank_w )
192{
193//  printf("write to %x\n", offset);
194
195   if (offset < 8)
196      memory_set_bankptr(space->machine(), "a000", space->machine().region("lslot")->base() + (7 - offset) * 0x2000);
197   else
198      memory_set_bankptr(space->machine(), "a000", space->machine().region("maincpu")->base());
199   // FIXME: writes to 0x8-0xf should disable the cart
200}
201
202static WRITE8_HANDLER( bbsb_bankl_w )
203{
204//  printf("write to %x\n", 0x8000 + offset);
205   if (offset >= 0xff6 && offset <= 0xff9)
206      memory_set_bankptr(space->machine(), "8000", space->machine().region("lslot")->base() + 0x0000 + (offset - 0xff6) * 0x1000);
207}
208
209static WRITE8_HANDLER( bbsb_bankh_w )
210{
211//  printf("write to %x\n", 0x9000 + offset);
212   if (offset >= 0xff6 && offset <= 0xff9)
213      memory_set_bankptr(space->machine(), "9000", space->machine().region("lslot")->base() + 0x4000 + (offset - 0xff6) * 0x1000);
214}
215
216static WRITE8_HANDLER( oss_034m_w )
217{
218   switch (offset & 0x0f)
219   {
220      case 0:
221      case 1:
222         memory_set_bankptr(space->machine(), "a000", space->machine().region("lslot")->base());
223         memory_set_bankptr(space->machine(), "b000", space->machine().region("lslot")->base() + 0x3000);
224         break;
225      case 2:
226      case 6:
227         // docs says this should put 0xff in the 0xa000 bank -> let's point to the end of the cart
228         memory_set_bankptr(space->machine(), "a000", space->machine().region("lslot")->base() + 0x4000);
229         memory_set_bankptr(space->machine(), "b000", space->machine().region("lslot")->base() + 0x3000);
230         break;
231      case 3:
232      case 7:
233         memory_set_bankptr(space->machine(), "a000", space->machine().region("lslot")->base() + 0x1000);
234         memory_set_bankptr(space->machine(), "b000", space->machine().region("lslot")->base() + 0x3000);
235         break;
236      case 4:
237      case 5:
238         memory_set_bankptr(space->machine(), "a000", space->machine().region("lslot")->base() + 0x2000);
239         memory_set_bankptr(space->machine(), "b000", space->machine().region("lslot")->base() + 0x3000);
240         break;
241      default:
242         memory_set_bankptr(space->machine(), "a000", space->machine().region("maincpu")->base() + 0xa000);
243         memory_set_bankptr(space->machine(), "b000", space->machine().region("maincpu")->base() + 0xb000);
244         break;
245   }
246}
247
248static WRITE8_HANDLER( oss_m091_w )
249{
250   switch (offset & 0x09)
251   {
252      case 0:
253         memory_set_bankptr(space->machine(), "a000", space->machine().region("lslot")->base() + 0x1000);
254         memory_set_bankptr(space->machine(), "b000", space->machine().region("lslot")->base());
255         break;
256      case 1:
257         memory_set_bankptr(space->machine(), "a000", space->machine().region("lslot")->base() + 0x3000);
258         memory_set_bankptr(space->machine(), "b000", space->machine().region("lslot")->base());
259         break;
260      case 8:
261         memory_set_bankptr(space->machine(), "a000", space->machine().region("maincpu")->base() + 0xa000);
262         memory_set_bankptr(space->machine(), "b000", space->machine().region("maincpu")->base() + 0xb000);
263         break;
264      case 9:
265         memory_set_bankptr(space->machine(), "a000", space->machine().region("lslot")->base() + 0x2000);
266         memory_set_bankptr(space->machine(), "b000", space->machine().region("lslot")->base());
267         break;
268   }
269}
270
271#if 0
272static int bbsb_bankl = 0;
273static int bbsb_bankh = 0;
274
275static WRITE8_HANDLER( bbsb_bankl_w )
276{
277   bbsb_bankl = offset; // 0,1,2,3
278}
279
280static WRITE8_HANDLER( bbsb_bankh_w )
281{
282   bbsb_bankh = offset; // 4,5,6,7
283}
284
285static READ8_HANDLER( bbsb_bankl_r )
286{
287   // return data from the selected bank (0,1,2,3)
288   UINT8 *mem = space->machine().region("lslot")->base();
289   return &mem[0x0000 + bbsb_bankl * 0x1000];
290}
291
292static READ8_HANDLER( bbsb_bankh_r )
293{
294   // return data from the selected bank (4,5,6,7)
295   UINT8 *mem = space->machine().region("lslot")->base();
296   return &mem[0x4000 + bbsb_bankh * 0x1000];
297}
298#endif
299
300typedef struct _a800_pcb  a800_pcb;
301struct _a800_pcb
302{
303   const char              *pcb_name;
304   int                     pcb_id;
305};
306
307// Here, we take the feature attribute from .xml (i.e. the PCB name) and we assign a unique ID to it
308// WARNING: most of these are still unsupported by the driver
309static const a800_pcb pcb_list[] =
310{
311   {"standard 4k", A800_8K},
312   {"standard 8k", A800_8K},
313   {"standard 12k", A800_16K},
314   {"standard 16k", A800_16K},
315   {"right slot 4k", A800_RIGHT_4K},
316   {"right slot 8k", A800_RIGHT_8K},
317
318   {"oss 034m", OSS_034M},
319   {"oss m091", OSS_M091},
320   {"phoenix 8k", PHOENIX_8K},
321   {"xegs 32k", XEGS_32K},
322   {"bbsb", BBSB},
323   {"diamond 64k", DIAMOND_64K},
324   {"williams 64k", WILLIAMS_64K},
325   {"express 64", EXPRESS_64},
326   {"spartados x", SPARTADOS_X},
327   {"N/A", A800_UNKNOWN}
328};
329
330static int a800_get_pcb_id(const char *pcb)
331{
332   int   i;
333
334   for (i = 0; i < ARRAY_LENGTH(pcb_list); i++)
335   {
336      if (!mame_stricmp(pcb_list[i].pcb_name, pcb))
337         return pcb_list[i].pcb_id;
338   }
339
340   return A800_UNKNOWN;
341}
342
343// currently this does nothing, but it will eventually install the memory handlers required by the mappers
344static void a800_setup_mappers(running_machine &machine, int type)
345{
346   switch (type)
347   {
348      case A800_4K:
349      case A800_RIGHT_4K:
350      case A800_12K:
351      case A800_8K:
352      case A800_16K:
353      case A800_RIGHT_8K:
354      case PHOENIX_8K:   // as normal 8k cart, but it can be disabled by writing to 0xd500-0xdfff
355         break;
356      case XEGS_32K:
357         machine.device("maincpu")->memory().space(AS_PROGRAM)->install_legacy_write_handler(0xd500, 0xd5ff, FUNC(x32_bank_w));
358         break;
359      case OSS_034M:
360         machine.device("maincpu")->memory().space(AS_PROGRAM)->install_legacy_write_handler(0xd500, 0xd5ff, FUNC(oss_034m_w));
361         break;
362      case OSS_M091:
363         machine.device("maincpu")->memory().space(AS_PROGRAM)->install_legacy_write_handler(0xd500, 0xd5ff, FUNC(oss_m091_w));
364         break;
365      case BBSB:
366         machine.device("maincpu")->memory().space(AS_PROGRAM)->install_legacy_write_handler(0x8000, 0x8fff, FUNC(bbsb_bankl_w));
367         machine.device("maincpu")->memory().space(AS_PROGRAM)->install_legacy_write_handler(0x9000, 0x9fff, FUNC(bbsb_bankh_w));
368         break;
369      case WILLIAMS_64K:
370         machine.device("maincpu")->memory().space(AS_PROGRAM)->install_legacy_write_handler(0xd500, 0xd50f, FUNC(w64_bank_w));
371         break;
372      case DIAMOND_64K:
373         machine.device("maincpu")->memory().space(AS_PROGRAM)->install_legacy_write_handler(0xd5d0, 0xd5df, FUNC(ex64_bank_w));
374         break;
375      case EXPRESS_64:
376         machine.device("maincpu")->memory().space(AS_PROGRAM)->install_legacy_write_handler(0xd570, 0xd57f, FUNC(ex64_bank_w));
377         break;
378      case SPARTADOS_X:
379         machine.device("maincpu")->memory().space(AS_PROGRAM)->install_legacy_write_handler(0xd5e0, 0xd5ef, FUNC(ex64_bank_w));
380         break;
381      default:
382         break;
383   }
384}
385
386static int a800_get_type(device_image_interface &image)
387{
388   UINT8 header[16];
389   image.fread(header, 0x10);
390   int hdr_type, cart_type = A800_UNKNOWN;
391
392   // add check of CART format
393   if (strncmp((const char *)header, "CART", 4))
394      fatalerror("Invalid header detected!\n");
395
396   hdr_type = (header[4] << 24) + (header[5] << 16) +  (header[6] << 8) + (header[7] << 0);
397   switch (hdr_type)
398   {
399      case 1:
400         cart_type = A800_8K;
401         break;
402      case 2:
403         cart_type = A800_16K;
404         break;
405      case 3:
406         cart_type = OSS_034M;
407         break;
408      case 8:
409         cart_type = WILLIAMS_64K;
410         break;
411      case 9:
412         cart_type = DIAMOND_64K;
413         break;
414      case 10:
415         cart_type = EXPRESS_64;
416         break;
417      case 11:
418         cart_type = SPARTADOS_X;
419         break;
420      case 12:
421         cart_type = XEGS_32K;
422         break;
423      case 15:
424         cart_type = OSS_M091;
425         break;
426      case 18:
427         cart_type = BBSB;
428         break;
429      case 21:
430         cart_type = A800_RIGHT_8K;
431         break;
432      case 39:
433         cart_type = PHOENIX_8K;
434         break;
435      case 4:
436      case 6:
437      case 7:
438      case 16:
439      case 19:
440      case 20:
441         fatalerror("Cart type \"%d\" means this is an Atari 5200 cart.\n", hdr_type);
442         break;
443      default:
444         mame_printf_info("Cart type \"%d\" is currently unsupported.\n", hdr_type);
445         break;
446   }
447   return cart_type;
448}
449
450static int a800_check_cart_type(device_image_interface &image)
451{
452   const char   *pcb_name;
453   int type = A800_UNKNOWN;
454
455   if (image.software_entry() == NULL)
456   {
457      UINT32 size = image.length();
458
459      // check if there is an header, if so extract cart_type from it, otherwise
460      // try to guess the cart_type from the file size (notice that after the
461      // a800_get_type call, we point at the start of the data)
462      if ((size % 0x1000) == 0x10)
463         type = a800_get_type(image);
464      else if (size == 0x4000)
465         type = A800_16K;
466      else if (size == 0x2000)
467      {
468         if (strcmp(image.device().tag(),"cart2") == 0)
469            type = A800_RIGHT_8K;
470         else
471            type = A800_8K;
472      }
473   }
474   else
475   {
476      if ((pcb_name = image.get_feature("cart_type")) != NULL)
477         type = a800_get_pcb_id(pcb_name);
478
479      switch (type)
480      {
481         case A800_UNKNOWN:
482         case A800_4K:
483         case A800_RIGHT_4K:
484         case A800_12K:
485         case A800_8K:
486         case A800_16K:
487         case A800_RIGHT_8K:
488            break;
489         default:
490            mame_printf_info("Cart type \"%s\" currently unsupported.\n", pcb_name);
491            break;
492      }
493   }
494
495   if ((strcmp(image.device().tag(),"cart2") == 0) && (type != A800_RIGHT_8K))
496      fatalerror("You cannot load this image '%s' in the right slot", image.filename());
497
498   return type;
499}
500
501DEVICE_IMAGE_LOAD( a800_cart )
502{
503   UINT32 size, start = 0;
504
505   a800_cart_loaded = a800_cart_loaded & ~LEFT_CARTSLOT_MOUNTED;
506   a800_cart_type = a800_check_cart_type(image);
507
508   a800_setup_mappers(image.device().machine(), a800_cart_type);
509
510   if (image.software_entry() == NULL)
511   {
512      size = image.length();
513      // if there is an header, skip it
514      if ((size % 0x1000) == 0x10)
515      {
516         size -= 0x10;
517         start = 0x10;
518      }
519      image.fread(image.device().machine().region("lslot")->base(), size - start);
520   }
521   else
522   {
523      size = image.get_software_region_length("rom");
524      memcpy(image.device().machine().region("lslot")->base(), image.get_software_region("rom"), size);
525   }
526
527   a800_cart_loaded |= (size > 0x0000) ? 1 : 0;
528
529   logerror("%s loaded left cartridge '%s' size %dK\n", image.device().machine().system().name, image.filename(), size/1024);
530   return IMAGE_INIT_PASS;
531}
532
533DEVICE_IMAGE_LOAD( a800_cart_right )
534{
535   UINT32 size, start = 0;
536
537   a800_cart_loaded = a800_cart_loaded & ~RIGHT_CARTSLOT_MOUNTED;
538   a800_cart_type = a800_check_cart_type(image);
539
540   a800_setup_mappers(image.device().machine(), a800_cart_type);
541
542   if (image.software_entry() == NULL)
543   {
544      size = image.length();
545      // if there is an header, skip it
546      if ((size % 0x1000) == 0x10)
547      {
548         size -= 0x10;
549         start = 0x10;
550      }
551      image.fread(image.device().machine().region("rslot")->base(), size - start);
552   }
553   else
554   {
555      size = image.get_software_region_length("rom");
556      memcpy(image.device().machine().region("rslot")->base(), image.get_software_region("rom"), size);
557   }
558
559   a800_cart_loaded |= (size > 0x0000) ? 2 : 0;
560
561   logerror("%s loaded right cartridge '%s' size 8K\n", image.device().machine().system().name, image.filename());
562   return IMAGE_INIT_PASS;
563}
564
565DEVICE_IMAGE_UNLOAD( a800_cart )
566{
567   a800_cart_loaded = a800_cart_loaded & ~LEFT_CARTSLOT_MOUNTED;
568   a800_cart_type = A800_UNKNOWN;
569   a800_setbank(image.device().machine(), a800_cart_loaded);
570}
571
572DEVICE_IMAGE_UNLOAD( a800_cart_right )
573{
574   a800_cart_loaded = a800_cart_loaded & ~RIGHT_CARTSLOT_MOUNTED;
575   a800_cart_type = A800_UNKNOWN;
576   a800_setbank(image.device().machine(), a800_cart_loaded);
577}
578
579
580/*************************************
581 *
582 *  Atari 800XL
583 *
584 *************************************/
585
586MACHINE_START( a800xl )
587{
588   atari_machine_start(machine);
589   ms_atari800xl_machine_start(machine, ATARI_800XL, TRUE);
590}
591
592/*************************************
593 *
594 *  Atari 5200 console
595 *
596 *************************************/
597
598MACHINE_START( a5200 )
599{
600   atari_machine_start(machine);
601   ms_atari_machine_start(machine, ATARI_800XL, TRUE);
602}
603
604
605DEVICE_IMAGE_LOAD( a5200_cart )
606{
607   UINT8 *mem = image.device().machine().region("maincpu")->base();
608   UINT32 size;
609
610   if (image.software_entry() == NULL)
611   {
612      /* load an optional (dual) cartidge */
613      size = image.fread(&mem[0x4000], 0x8000);
614   }
615   else
616   {
617      size = image.get_software_region_length("rom");
618      memcpy(mem + 0x4000, image.get_software_region("rom"), size);
619   }
620
621   if (size<0x8000) memmove(mem+0x4000+0x8000-size, mem+0x4000, size);
622   // mirroring of smaller cartridges
623   if (size <= 0x1000) memcpy(mem+0xa000, mem+0xb000, 0x1000);
624   if (size <= 0x2000) memcpy(mem+0x8000, mem+0xa000, 0x2000);
625   if (size <= 0x4000)
626   {
627      const char *info = hashfile_extrainfo(image);
628      memcpy(&mem[0x4000], &mem[0x8000], 0x4000);
629      if (info && !strcmp(info, "A13MIRRORING"))
630      {
631         memcpy(&mem[0x8000], &mem[0xa000], 0x2000);
632         memcpy(&mem[0x6000], &mem[0x4000], 0x2000);
633      }
634   }
635   logerror("A5200 loaded cartridge '%s' size %dK\n", image.filename() , size/1024);
636   return IMAGE_INIT_PASS;
637}
638
639DEVICE_IMAGE_UNLOAD( a5200_cart )
640{
641   UINT8 *mem = image.device().machine().region("maincpu")->base();
642   /* zap the cartridge memory (again) */
643   memset(&mem[0x4000], 0x00, 0x8000);
644}
645
646/*************************************
647 *
648 *  Atari XEGS
649 *
650 *************************************/
651
652static UINT8 xegs_banks = 0;
653static UINT8 xegs_cart = 0;
654
655static WRITE8_HANDLER( xegs_bankswitch )
656{
657   UINT8 *cart = space->machine().region("user1")->base();
658   data &= xegs_banks - 1;
659   memory_set_bankptr(space->machine(), "bank0", cart + data * 0x2000);
660}
661
662MACHINE_START( xegs )
663{
664   address_space *space = machine.device("maincpu")->memory().space(AS_PROGRAM);
665   UINT8 *cart = space->machine().region("user1")->base();
666   UINT8 *cpu  = space->machine().region("maincpu")->base();
667
668   atari_machine_start(machine);
669   space->install_legacy_write_handler(0xd500, 0xd5ff, FUNC(xegs_bankswitch));
670
671   if (xegs_cart)
672   {
673      memory_set_bankptr(machine, "bank0", cart);
674      memory_set_bankptr(machine, "bank1", cart + (xegs_banks - 1) * 0x2000);
675   }
676   else
677   {
678      // point to built-in Missile Command (this does not work well, though... FIXME!!)
679      memory_set_bankptr(machine, "bank0", cpu + 0x10000);
680      memory_set_bankptr(machine, "bank1", cpu + 0x10000);
681   }
682}
683
684DEVICE_IMAGE_LOAD( xegs_cart )
685{
686   UINT32 size;
687   UINT8 *ptr = image.device().machine().region("user1")->base();
688
689   if (image.software_entry() == NULL)
690   {
691      // skip the header
692      image.fseek(0x10, SEEK_SET);
693      size = image.length() - 0x10;
694      if (image.fread(ptr, size) != size)
695         return IMAGE_INIT_FAIL;
696   }
697   else
698   {
699      size = image.get_software_region_length("rom");
700      memcpy(ptr, image.get_software_region("rom"), size);
701   }
702
703   xegs_banks = size / 0x2000;
704   xegs_cart = 1;
705
706   return IMAGE_INIT_PASS;
707}
708
709DEVICE_IMAGE_UNLOAD( xegs_cart )
710{
711   xegs_cart = 0;
712   xegs_banks = 0;
713}
src/mame/machine/ataridev.h
r11531r11532
1/*
2    ataridev.h
3
4*/
5
6#ifndef _ATARIDEV_H
7#define _ATARIDEV_H
8
9#define ATARI_5200   0
10#define ATARI_400   1
11#define ATARI_800   2
12#define ATARI_600XL 3
13#define ATARI_800XL 4
14
15/*----------- defined in machine/ataricrt.c -----------*/
16
17MACHINE_START( a400 );
18MACHINE_START( a800 );
19MACHINE_START( a800xl );
20MACHINE_START( a5200 );
21MACHINE_START( xegs );
22
23DEVICE_IMAGE_LOAD( a800_cart );
24DEVICE_IMAGE_UNLOAD( a800_cart );
25
26DEVICE_IMAGE_LOAD( a800_cart_right );
27DEVICE_IMAGE_UNLOAD( a800_cart_right );
28
29DEVICE_IMAGE_LOAD( a5200_cart );
30DEVICE_IMAGE_UNLOAD( a5200_cart );
31
32DEVICE_IMAGE_LOAD( xegs_cart );
33DEVICE_IMAGE_UNLOAD( xegs_cart );
34
35
36/*----------- defined in machine/atarifdc.c -----------*/
37/***************************************************************************
38    MACROS
39***************************************************************************/
40
41DECLARE_LEGACY_DEVICE(ATARI_FDC, atari_fdc);
42
43#define MCFG_ATARI_FDC_ADD(_tag)   \
44   MCFG_DEVICE_ADD((_tag),  ATARI_FDC, 0)
45
46
47/***************************************************************************
48    FUNCTION PROTOTYPES
49***************************************************************************/
50READ8_DEVICE_HANDLER( atari_serin_r );
51WRITE8_DEVICE_HANDLER( atari_serout_w );
52WRITE_LINE_DEVICE_HANDLER( atarifdc_pia_cb2_w );
53
54#endif /* _ATARIDEV_H */
55
src/mame/machine/amigafdc.c
r11531r11532
1/****************************************************f***********************
2
3    Amiga floppy disk controller emulation
4
5    - The drive spins at 300 RPM = 1 Rev every 200ms
6    - At 2usec per bit, that's 12500 bytes per track, or 6250 words per track
7    - At 4usec per bit, that's 6250 bytes per track, or 3125 words per track
8    - Each standard amiga sector has 544 words per sector, and 11 sectors per track = 11968 bytes
9    - ( 12500(max) - 11968(actual) ) = 532 per track gap bytes
10
11***************************************************************************/
12
13
14#include "emu.h"
15#include "includes/amiga.h"
16#include "imagedev/flopdrv.h"
17#include "formats/ami_dsk.h"
18#include "amigafdc.h"
19#include "machine/6526cia.h"
20
21
22#define MAX_TRACK_BYTES         12500
23#define ACTUAL_TRACK_BYTES      11968
24#define GAP_TRACK_BYTES         ( MAX_TRACK_BYTES - ACTUAL_TRACK_BYTES )
25#define ONE_SECTOR_BYTES      (544*2)
26#define ONE_REV_TIME         200 /* ms */
27#define MAX_WORDS_PER_DMA_CYCLE   32 /* 64 bytes per dma cycle */
28#define DISK_DETECT_DELAY      1
29#define MAX_TRACKS            160
30#define MAX_MFM_TRACK_LEN      16384
31
32#define NUM_DRIVES 2
33
34/* required prototype */
35static void setup_fdc_buffer( device_t *device,int drive );
36
37/***************************************************************************
38    TYPE DEFINITIONS
39***************************************************************************/
40typedef struct {
41   int motor_on;
42   int side;
43   int dir;
44   int wprot;
45   int disk_changed;
46   device_image_interface *f;
47   UINT32 extinfo[MAX_TRACKS];
48   UINT32 extoffs[MAX_TRACKS];
49   int is_ext_image;
50   int cyl;
51   int tracklen;
52   UINT8 mfm[MAX_MFM_TRACK_LEN];
53   int   cached;
54   emu_timer *rev_timer;
55   emu_timer *sync_timer;
56   emu_timer *dma_timer;
57   int rev_timer_started;
58   int pos;
59   int len;
60   offs_t ptr;
61} fdc_def;
62
63typedef struct _amiga_fdc_t amiga_fdc_t;
64struct _amiga_fdc_t
65{
66   fdc_def fdc_status[NUM_DRIVES];
67
68   /* signals */
69   int fdc_sel;
70   int fdc_dir;
71   int fdc_side;
72   int fdc_step;
73   int fdc_rdy;
74};
75
76/*****************************************************************************
77    INLINE FUNCTIONS
78*****************************************************************************/
79INLINE amiga_fdc_t *get_safe_token(device_t *device)
80{
81   assert(device != NULL);
82   assert(device->type() == AMIGA_FDC);
83
84   return (amiga_fdc_t *)downcast<legacy_device_base *>(device)->token();
85}
86
87static TIMER_CALLBACK(fdc_rev_proc);
88static TIMER_CALLBACK(fdc_dma_proc);
89static TIMER_CALLBACK(fdc_sync_proc);
90static void check_extended_image( device_t *device, int id );
91
92static void amiga_load_proc(device_image_interface &image)
93{
94   amiga_fdc_t *fdc = get_safe_token(image.device().owner());
95   int id = floppy_get_drive(&image.device());
96   fdc->fdc_status[id].disk_changed = DISK_DETECT_DELAY;
97   fdc->fdc_status[id].f = &image;
98   fdc->fdc_status[id].cached = -1;
99   fdc->fdc_status[id].motor_on = 0;
100   fdc->fdc_status[id].rev_timer_started = 0;
101   fdc->fdc_status[id].rev_timer->reset(  );
102   fdc->fdc_status[id].sync_timer->reset(  );
103   fdc->fdc_status[id].dma_timer->reset(  );
104   fdc->fdc_rdy = 0;
105
106   check_extended_image( image.device().owner(), id );
107}
108
109static void amiga_unload_proc(device_image_interface &image)
110{
111   amiga_fdc_t *fdc = get_safe_token(image.device().owner());
112   int id = floppy_get_drive(&image.device());
113   fdc->fdc_status[id].disk_changed = DISK_DETECT_DELAY;
114   fdc->fdc_status[id].f = NULL;
115   fdc->fdc_status[id].cached = -1;
116   fdc->fdc_status[id].motor_on = 0;
117   fdc->fdc_status[id].rev_timer_started = 0;
118   fdc->fdc_status[id].rev_timer->reset(  );
119   fdc->fdc_status[id].sync_timer->reset(  );
120   fdc->fdc_status[id].dma_timer->reset(  );
121   fdc->fdc_rdy = 0;
122}
123
124/*-------------------------------------------------
125    DEVICE_START(amiga_fdc)
126-------------------------------------------------*/
127device_t *amiga_floppy_get_device_child(device_t *device,int drive)
128{
129   switch(drive) {
130      case 0 : return device->subdevice(FLOPPY_0);
131      case 1 : return device->subdevice(FLOPPY_1);
132   }
133   return NULL;
134}
135
136static DEVICE_START(amiga_fdc)
137{
138   amiga_fdc_t *fdc = get_safe_token(device);
139   int id;
140   for(id=0;id<2;id++)
141   {
142      fdc->fdc_status[id].rev_timer = device->machine().scheduler().timer_alloc(FUNC(fdc_rev_proc), (void*)device);
143      fdc->fdc_status[id].dma_timer = device->machine().scheduler().timer_alloc(FUNC(fdc_dma_proc), (void*)device);
144      fdc->fdc_status[id].sync_timer = device->machine().scheduler().timer_alloc(FUNC(fdc_sync_proc), (void*)device);
145      floppy_install_load_proc(amiga_floppy_get_device_child(device, id), amiga_load_proc);
146      floppy_install_unload_proc(amiga_floppy_get_device_child(device, id), amiga_unload_proc);
147      fdc->fdc_status[id].motor_on = 0;
148      fdc->fdc_status[id].side = 0;
149      fdc->fdc_status[id].dir = 0;
150      fdc->fdc_status[id].wprot = 1;
151      fdc->fdc_status[id].cyl = 0;
152      fdc->fdc_status[id].rev_timer_started = 0;
153      fdc->fdc_status[id].cached = -1;
154      fdc->fdc_status[id].pos = 0;
155      fdc->fdc_status[id].len = 0;
156      fdc->fdc_status[id].ptr = 0;
157      fdc->fdc_status[id].f = NULL;
158      fdc->fdc_status[id].is_ext_image = 0;
159      fdc->fdc_status[id].tracklen = MAX_TRACK_BYTES;
160      fdc->fdc_status[id].disk_changed = DISK_DETECT_DELAY;
161      fdc->fdc_status[id].rev_timer->reset(  );
162      fdc->fdc_status[id].sync_timer->reset(  );
163      fdc->fdc_status[id].dma_timer->reset(  );
164      memset( fdc->fdc_status[id].mfm, 0xaa, MAX_MFM_TRACK_LEN );
165   }
166   fdc->fdc_sel = 0x0f;
167   fdc->fdc_dir = 0;
168   fdc->fdc_side = 1;
169   fdc->fdc_step = 1;
170   fdc->fdc_rdy = 0;
171
172}
173
174
175/*-------------------------------------------------
176    DEVICE_RESET(amiga_fdc)
177-------------------------------------------------*/
178
179static DEVICE_RESET(amiga_fdc)
180{
181}
182
183static void check_extended_image( device_t *device, int id )
184{
185   UINT8   header[8], data[4];
186   amiga_fdc_t *fdc = get_safe_token(device);
187
188   fdc->fdc_status[id].is_ext_image = 0;
189
190   if ( fdc->fdc_status[id].f->fseek( 0, SEEK_SET ) )
191   {
192      logerror("FDC: image_fseek failed!\n" );
193      return;
194   }
195
196   fdc->fdc_status[id].f->fread( &header, sizeof( header ) );
197
198   if ( memcmp( header, "UAE--ADF", sizeof( header ) ) == 0 )
199   {
200      int      i;
201
202      for( i = 0; i < MAX_TRACKS; i++ )
203      {
204         fdc->fdc_status[id].f->fread( &data, sizeof( data ) );
205
206         /* data[0,1] = SYNC - data[2,3] = LEN */
207
208         fdc->fdc_status[id].extinfo[i] = data[0];
209         fdc->fdc_status[id].extinfo[i] <<= 8;
210         fdc->fdc_status[id].extinfo[i] |= data[1];
211         fdc->fdc_status[id].extinfo[i] <<= 8;
212         fdc->fdc_status[id].extinfo[i] |= data[2];
213         fdc->fdc_status[id].extinfo[i] <<= 8;
214         fdc->fdc_status[id].extinfo[i] |= data[3];
215
216         if ( i == 0 )
217            fdc->fdc_status[id].extoffs[i] = sizeof( header ) + ( MAX_TRACKS * sizeof( data ) );
218         else
219            fdc->fdc_status[id].extoffs[i] = fdc->fdc_status[id].extoffs[i-1] + ( fdc->fdc_status[id].extinfo[i-1] & 0xffff );
220      }
221
222      fdc->fdc_status[id].is_ext_image = 1;
223   }
224}
225
226static int fdc_get_curpos( device_t *device, int drive )
227{
228   amiga_state *state = device->machine().driver_data<amiga_state>();
229   double elapsed;
230   int speed;
231   int   bytes;
232   int pos;
233   amiga_fdc_t *fdc = get_safe_token(device);
234
235   if ( fdc->fdc_status[drive].rev_timer_started == 0 ) {
236      logerror("Rev timer not started on drive %d, cant get position!\n", drive );
237      return 0;
238   }
239
240   elapsed = fdc->fdc_status[drive].rev_timer ->elapsed( ).as_double();
241   speed = ( CUSTOM_REG(REG_ADKCON) & 0x100 ) ? 2 : 4;
242
243   bytes = elapsed /  attotime::from_usec( speed * 8 ).as_double();
244   pos = bytes % ( fdc->fdc_status[drive].tracklen );
245
246   return pos;
247}
248
249UINT16 amiga_fdc_get_byte (device_t *device)
250{
251   amiga_state *state = device->machine().driver_data<amiga_state>();
252   int pos;
253   int i, drive = -1;
254   UINT16 ret;
255   amiga_fdc_t *fdc = get_safe_token(device);
256
257   ret = ( ( CUSTOM_REG(REG_DSKLEN) >> 1 ) & 0x4000 ) & ( ( CUSTOM_REG(REG_DMACON) << 10 ) & 0x4000 );
258   ret |= ( CUSTOM_REG(REG_DSKLEN) >> 1 ) & 0x2000;
259
260   for ( i = 0; i < NUM_DRIVES; i++ ) {
261      if ( !( fdc->fdc_sel & ( 1 << i ) ) )
262         drive = i;
263   }
264
265   if ( drive == -1 )
266      return ret;
267
268   if ( fdc->fdc_status[drive].disk_changed )
269      return ret;
270
271   setup_fdc_buffer( device,drive );
272
273   pos = fdc_get_curpos( device, drive );
274
275   if ( fdc->fdc_status[drive].mfm[pos] == ( CUSTOM_REG(REG_DSRSYNC) >> 8 ) &&
276       fdc->fdc_status[drive].mfm[pos+1] == ( CUSTOM_REG(REG_DSRSYNC) & 0xff ) )
277         ret |= 0x1000;
278
279   if ( pos != fdc->fdc_status[drive].pos ) {
280      ret |= 0x8000;
281      fdc->fdc_status[drive].pos = pos;
282   }
283
284   ret |= fdc->fdc_status[drive].mfm[pos];
285
286   return ret;
287}
288
289static TIMER_CALLBACK(fdc_sync_proc)
290{
291   amiga_state *state = machine.driver_data<amiga_state>();
292   int drive = param;
293   UINT16         sync = CUSTOM_REG(REG_DSRSYNC);
294   int            cur_pos;
295   int            sector;
296   int            time;
297   amiga_fdc_t *fdc = get_safe_token((device_t*)ptr);
298
299   /* if floppy got ejected, stop */
300   if ( fdc->fdc_status[drive].disk_changed )
301      goto bail;
302
303   if ( fdc->fdc_status[drive].motor_on == 0 )
304      goto bail;
305
306   cur_pos = fdc_get_curpos( (device_t*)ptr, drive );
307
308   if ( cur_pos <= ( GAP_TRACK_BYTES + 6 ) )
309   {
310      sector = 0;
311   }
312   else
313   {
314      sector = ( cur_pos - ( GAP_TRACK_BYTES + 6 ) ) / ONE_SECTOR_BYTES;
315   }
316
317   setup_fdc_buffer( (device_t*)ptr, drive );
318
319   if ( cur_pos < 2 )
320      cur_pos = 2;
321
322   if ( fdc->fdc_status[drive].mfm[cur_pos-2] == ( ( sync >> 8 ) & 0xff ) &&
323       fdc->fdc_status[drive].mfm[cur_pos-1] == ( sync & 0xff ) )
324   {
325      address_space *space = machine.device("maincpu")->memory().space(AS_PROGRAM);
326
327      amiga_custom_w(space, REG_INTREQ, 0x8000 | INTENA_DSKSYN, 0xffff);
328   }
329
330   if ( sector < 10 )
331   {
332      /* start the sync timer */
333      time = ONE_SECTOR_BYTES;
334      time *= ( CUSTOM_REG(REG_ADKCON) & 0x0100 ) ? 2 : 4;
335      time *= 8;
336      fdc->fdc_status[drive].sync_timer->adjust(attotime::from_usec( time ), drive);
337      return;
338   }
339
340bail:
341   fdc->fdc_status[drive].sync_timer->reset(  );
342}
343
344static TIMER_CALLBACK(fdc_dma_proc)
345{
346   amiga_state *state = machine.driver_data<amiga_state>();
347   int drive = param;
348   amiga_fdc_t *fdc = get_safe_token((device_t*)ptr);
349
350   /* if DMA got disabled by the time we got here, stop operations */
351   if ( ( CUSTOM_REG(REG_DSKLEN) & 0x8000 ) == 0 )
352      goto bail;
353
354   if ( ( CUSTOM_REG(REG_DMACON) & 0x0210 ) == 0 )
355      goto bail;
356
357   /* if floppy got ejected, also stop */
358   if ( fdc->fdc_status[drive].disk_changed )
359      goto bail;
360
361   if ( fdc->fdc_status[drive].motor_on == 0 )
362      goto bail;
363
364   setup_fdc_buffer( (device_t*)ptr, drive );
365
366   if ( CUSTOM_REG(REG_DSKLEN) & 0x4000 ) /* disk write case, unsupported yet */
367   {
368      if ( fdc->fdc_status[drive].len > 0 )
369      {
370         address_space *space = machine.device("maincpu")->memory().space(AS_PROGRAM);
371
372         logerror("Write to disk unsupported yet\n" );
373
374         amiga_custom_w(space, REG_INTREQ, 0x8000 | INTENA_DSKBLK, 0xffff);
375      }
376   }
377   else
378   {
379      offs_t offset = fdc->fdc_status[drive].ptr;
380      int cur_pos = fdc->fdc_status[drive].pos;
381      int len = fdc->fdc_status[drive].len;
382
383      if ( len > MAX_WORDS_PER_DMA_CYCLE ) len = MAX_WORDS_PER_DMA_CYCLE;
384
385      fdc->fdc_status[drive].len -= len;
386
387      while ( len-- )
388      {
389         int dat = ( fdc->fdc_status[drive].mfm[cur_pos++] ) << 8;
390
391         cur_pos %= ( fdc->fdc_status[drive].tracklen );
392
393         dat |= fdc->fdc_status[drive].mfm[cur_pos++];
394
395         cur_pos %= ( fdc->fdc_status[drive].tracklen );
396
397         (*state->m_chip_ram_w)(state, offset, dat);
398
399         offset += 2;
400      }
401
402      fdc->fdc_status[drive].ptr = offset;
403      fdc->fdc_status[drive].pos = cur_pos;
404
405      if ( fdc->fdc_status[drive].len <= 0 )
406      {
407         address_space *space = machine.device("maincpu")->memory().space(AS_PROGRAM);
408
409         amiga_custom_w(space, REG_INTREQ, 0x8000 | INTENA_DSKBLK, 0xffff);
410      }
411      else
412      {
413         int time;
414         double   len_words = fdc->fdc_status[drive].len;
415         if ( len_words > MAX_WORDS_PER_DMA_CYCLE ) len_words = MAX_WORDS_PER_DMA_CYCLE;
416
417         time = len_words * 2;
418         time *= ( CUSTOM_REG(REG_ADKCON) & 0x0100 ) ? 2 : 4;
419         time *= 8;
420         fdc->fdc_status[drive].dma_timer->adjust(attotime::from_usec( time ), drive);
421         return;
422      }
423   }
424
425bail:
426   fdc->fdc_status[drive].dma_timer->reset(  );
427}
428
429void amiga_fdc_setup_dma( device_t *device ) {
430   amiga_state *state = device->machine().driver_data<amiga_state>();
431   int i, cur_pos, drive = -1, len_words = 0;
432   int time = 0;
433   amiga_fdc_t *fdc = get_safe_token(device);
434
435   for ( i = 0; i < NUM_DRIVES; i++ ) {
436      if ( !( fdc->fdc_sel & ( 1 << i ) ) )
437         drive = i;
438   }
439
440   if ( drive == -1 ) {
441      address_space *space = device->machine().device("maincpu")->memory().space(AS_PROGRAM);
442
443      logerror("Disk DMA started with no drive selected!\n" );
444      amiga_custom_w(space, REG_INTREQ, 0x8000 | INTENA_DSKBLK, 0xffff);
445      return;
446   }
447
448   if ( ( CUSTOM_REG(REG_DSKLEN) & 0x8000 ) == 0 )
449      goto bail;
450
451   if ( ( CUSTOM_REG(REG_DMACON) & 0x0210 ) == 0 )
452      goto bail;
453
454   if ( fdc->fdc_status[drive].disk_changed )
455      goto bail;
456
457   setup_fdc_buffer( device,drive );
458
459   fdc->fdc_status[drive].len = CUSTOM_REG(REG_DSKLEN) & 0x3fff;
460   fdc->fdc_status[drive].ptr = CUSTOM_REG_LONG(REG_DSKPTH);
461   fdc->fdc_status[drive].pos = cur_pos = fdc_get_curpos( device, drive );
462
463   /* we'll do a set amount at a time */
464   len_words = fdc->fdc_status[drive].len;
465   if ( len_words > MAX_WORDS_PER_DMA_CYCLE ) len_words = MAX_WORDS_PER_DMA_CYCLE;
466
467   if ( CUSTOM_REG(REG_ADKCON) & 0x0400 ) { /* Wait for sync */
468      if ( CUSTOM_REG(REG_DSRSYNC) != 0x4489 ) {
469         logerror("Attempting to read a non-standard SYNC\n" );
470      }
471
472      i = cur_pos;
473      do {
474         if ( fdc->fdc_status[drive].mfm[i] == ( CUSTOM_REG(REG_DSRSYNC) >> 8 ) &&
475             fdc->fdc_status[drive].mfm[i+1] == ( CUSTOM_REG(REG_DSRSYNC) & 0xff ) )
476               break;
477
478         i++;
479         i %= ( fdc->fdc_status[drive].tracklen );
480         time++;
481      } while( i != cur_pos );
482
483      if ( i == cur_pos && time != 0 ) {
484         logerror("SYNC not found on track!\n" );
485         return;
486      } else {
487         fdc->fdc_status[drive].pos = i + 2;
488         time += 2;
489      }
490   }
491
492   time += len_words * 2;
493   time *= ( CUSTOM_REG(REG_ADKCON) & 0x0100 ) ? 2 : 4;
494   time *= 8;
495   fdc->fdc_status[drive].dma_timer->adjust(attotime::from_usec( time ), drive);
496
497   return;
498
499bail:
500   fdc->fdc_status[drive].dma_timer->reset(  );
501}
502
503static void setup_fdc_buffer( device_t *device,int drive )
504{
505   int      sector, offset, len;
506   UINT8   temp_cyl[512*11];
507   amiga_fdc_t *fdc = get_safe_token(device);
508
509   /* no disk in drive */
510   if ( fdc->fdc_status[drive].f == NULL ) {
511      memset( &fdc->fdc_status[drive].mfm[0], 0xaa, 32 );
512      fdc->fdc_status[drive].disk_changed = DISK_DETECT_DELAY;
513      return;
514   }
515
516   len = 512*11;
517
518   offset = ( fdc->fdc_status[drive].cyl << 1 ) | fdc->fdc_side;
519
520   if ( fdc->fdc_status[drive].cached == offset )
521      return;
522
523#if 0
524   popmessage("T:%d S:%d", fdc->fdc_status[drive].cyl, fdc_side );
525#endif
526
527   if ( fdc->fdc_status[drive].is_ext_image )
528   {
529      len = fdc->fdc_status[drive].extinfo[offset] & 0xffff;
530
531      if ( len > ( MAX_MFM_TRACK_LEN - 2 ) )
532         len = MAX_MFM_TRACK_LEN - 2;
533
534      if ( fdc->fdc_status[drive].f->fseek( fdc->fdc_status[drive].extoffs[offset], SEEK_SET ) )
535      {
536         logerror("FDC: image_fseek failed!\n" );
537         fdc->fdc_status[drive].f = NULL;
538         fdc->fdc_status[drive].disk_changed = DISK_DETECT_DELAY;
539         return;
540      }
541
542      /* if SYNC is 0000, then its a regular amiga dos track image */
543      if ( ( fdc->fdc_status[drive].extinfo[offset] >> 16 ) == 0x0000 )
544      {
545         fdc->fdc_status[drive].f->fread( temp_cyl, len );
546         /* fall through to regular load */
547      }
548      else /* otherwise, it's a raw track */
549      {
550         fdc->fdc_status[drive].mfm[0] = ( fdc->fdc_status[drive].extinfo[offset] >> 24 ) & 0xff;
551         fdc->fdc_status[drive].mfm[1] = ( fdc->fdc_status[drive].extinfo[offset] >> 16 ) & 0xff;
552         fdc->fdc_status[drive].f->fread( &fdc->fdc_status[drive].mfm[2], len );
553         fdc->fdc_status[drive].tracklen = len + 2;
554         fdc->fdc_status[drive].cached = offset;
555         return;
556      }
557   }
558   else
559   {
560      if ( fdc->fdc_status[drive].f->fseek( offset * len, SEEK_SET ) )
561      {
562         logerror("FDC: image_fseek failed!\n" );
563         fdc->fdc_status[drive].f = NULL;
564         fdc->fdc_status[drive].disk_changed = DISK_DETECT_DELAY;
565         return;
566      }
567
568      fdc->fdc_status[drive].f->fread( temp_cyl, len );
569   }
570
571   fdc->fdc_status[drive].tracklen = MAX_TRACK_BYTES;
572
573   memset( &fdc->fdc_status[drive].mfm[ONE_SECTOR_BYTES*11], 0xaa, GAP_TRACK_BYTES );
574
575   for ( sector = 0; sector < 11; sector++ ) {
576      int x;
577       UINT8 *dest = ( &fdc->fdc_status[drive].mfm[(ONE_SECTOR_BYTES*sector)] );
578       UINT8 *src = &temp_cyl[sector*512];
579      UINT32 tmp;
580      UINT32 even, odd;
581      UINT32 hck = 0, dck = 0;
582
583      /* Preamble and sync */
584      *(dest + 0) = 0xaa;
585      *(dest + 1) = 0xaa;
586      *(dest + 2) = 0xaa;
587      *(dest + 3) = 0xaa;
588      *(dest + 4) = 0x44;
589      *(dest + 5) = 0x89;
590      *(dest + 6) = 0x44;
591      *(dest + 7) = 0x89;
592
593      /* Track and sector info */
594
595      tmp = 0xff000000 | (offset<<16) | (sector<<8) | (11 - sector);
596      odd = (tmp & 0x55555555) | 0xaaaaaaaa;
597      even = ( ( tmp >> 1 ) & 0x55555555 ) | 0xaaaaaaaa;
598      *(dest +  8) = (UINT8) ((even & 0xff000000)>>24);
599      *(dest +  9) = (UINT8) ((even & 0xff0000)>>16);
600      *(dest + 10) = (UINT8) ((even & 0xff00)>>8);
601      *(dest + 11) = (UINT8) ((even & 0xff));
602      *(dest + 12) = (UINT8) ((odd & 0xff000000)>>24);
603      *(dest + 13) = (UINT8) ((odd & 0xff0000)>>16);
604      *(dest + 14) = (UINT8) ((odd & 0xff00)>>8);
605      *(dest + 15) = (UINT8) ((odd & 0xff));
606
607      /* Fill unused space */
608
609      for (x = 16 ; x < 48; x++)
610         *(dest + x) = 0xaa;
611
612      /* Encode data section of sector */
613
614      for (x = 64 ; x < 576; x++)
615      {
616         tmp = *(src + x - 64);
617         odd = (tmp & 0x55);
618         even = (tmp>>1) & 0x55;
619         *(dest + x) = (UINT8) (even | 0xaa);
620         *(dest + x + 512) = (UINT8) (odd | 0xaa);
621      }
622
623      /* Calculate checksum for unused space */
624
625      for(x = 8; x < 48; x += 4)
626          hck ^= (((UINT32) *(dest + x))<<24) | (((UINT32) *(dest + x + 1))<<16) |
627                (((UINT32) *(dest + x + 2))<<8) | ((UINT32) *(dest + x + 3));
628
629      even = odd = hck;
630      odd >>= 1;
631      even |= 0xaaaaaaaa;
632      odd |= 0xaaaaaaaa;
633
634      *(dest + 48) = (UINT8) ((odd & 0xff000000)>>24);
635      *(dest + 49) = (UINT8) ((odd & 0xff0000)>>16);
636      *(dest + 50) = (UINT8) ((odd & 0xff00)>>8);
637      *(dest + 51) = (UINT8) (odd & 0xff);
638      *(dest + 52) = (UINT8) ((even & 0xff000000)>>24);
639      *(dest + 53) = (UINT8) ((even & 0xff0000)>>16);
640      *(dest + 54) = (UINT8) ((even & 0xff00)>>8);
641      *(dest + 55) = (UINT8) (even & 0xff);
642
643      /* Calculate checksum for data section */
644
645      for(x = 64; x < 1088; x += 4)
646         dck ^= (((UINT32) *(dest + x))<<24) | (((UINT32) *(dest + x + 1))<<16) |
647               (((UINT32) *(dest + x + 2))<< 8) |  ((UINT32) *(dest + x + 3));
648      even = odd = dck;
649      odd >>= 1;
650      even |= 0xaaaaaaaa;
651      odd |= 0xaaaaaaaa;
652      *(dest + 56) = (UINT8) ((odd & 0xff000000)>>24);
653      *(dest + 57) = (UINT8) ((odd & 0xff0000)>>16);
654      *(dest + 58) = (UINT8) ((odd & 0xff00)>>8);
655      *(dest + 59) = (UINT8) (odd & 0xff);
656      *(dest + 60) = (UINT8) ((even & 0xff000000)>>24);
657      *(dest + 61) = (UINT8) ((even & 0xff0000)>>16);
658      *(dest + 62) = (UINT8) ((even & 0xff00)>>8);
659      *(dest + 63) = (UINT8) (even & 0xff);
660   }
661
662   // update MFM data with proper CLK signal
663   int lastbit= 0;
664   for(int i=0;i<MAX_TRACK_BYTES ;i++)
665   {
666      UINT8 c=fdc->fdc_status[drive].mfm[i];
667      UINT8 dat = 0;
668      for(int j=0;j<8;j=j+2)
669      {
670         UINT8 c1=(c>>(6-j))&0x3;
671         if(c1&0x1)
672         {
673            dat |= (0x01<<(6-j));
674            lastbit=1;
675         }
676         else
677         {
678            if(lastbit==0 && (c1&0x2))
679            {
680               dat |= (0x02<<(6-j));
681            }
682            else
683            {
684               dat |= (0x00<<(6-j));
685            }
686            lastbit=0;
687         }
688      }
689      fdc->fdc_status[drive].mfm[i] = dat;
690   }
691   fdc->fdc_status[drive].cached = offset;
692}
693
694static TIMER_CALLBACK(fdc_rev_proc)
695{
696   amiga_state *state = machine.driver_data<amiga_state>();
697   int drive = param;
698   int time;
699   device_t *cia;
700   amiga_fdc_t *fdc = get_safe_token((device_t*)ptr);
701
702   /* Issue a index pulse when a disk revolution completes */
703   cia = machine.device("cia_1");
704   mos6526_flag_w(cia, 0);
705   mos6526_flag_w(cia, 1);
706
707   fdc->fdc_status[drive].rev_timer->adjust(attotime::from_msec( ONE_REV_TIME ), drive);
708   fdc->fdc_status[drive].rev_timer_started = 1;
709
710   if ( fdc->fdc_status[drive].is_ext_image == 0 )
711   {
712      /* also start the sync timer */
713      time = GAP_TRACK_BYTES + 6;
714      time *= ( CUSTOM_REG(REG_ADKCON) & 0x0100 ) ? 2 : 4;
715      time *= 8;
716      fdc->fdc_status[drive].sync_timer->adjust(attotime::from_usec( time ), drive);
717   }
718}
719
720static void start_rev_timer( device_t *device,int drive ) {
721//  double time;
722   amiga_fdc_t *fdc = get_safe_token(device);
723
724   if ( fdc->fdc_status[drive].rev_timer_started ) {
725      logerror("Revolution timer started twice?!\n" );
726      return;
727   }
728
729   fdc->fdc_status[drive].rev_timer->adjust(attotime::from_msec( ONE_REV_TIME ), drive);
730   fdc->fdc_status[drive].rev_timer_started = 1;
731}
732
733static void stop_rev_timer( device_t *device,int drive ) {
734   amiga_fdc_t *fdc = get_safe_token(device);
735
736   if ( fdc->fdc_status[drive].rev_timer_started == 0 ) {
737      logerror("Revolution timer never started?!\n" );
738      return;
739   }
740
741   fdc->fdc_status[drive].rev_timer->reset(  );
742   fdc->fdc_status[drive].rev_timer_started = 0;
743   fdc->fdc_status[drive].dma_timer->reset(  );
744   fdc->fdc_status[drive].sync_timer->reset(  );
745}
746
747static void fdc_setup_leds(device_t *device, int drive ) {
748
749   char portname[12];
750   amiga_fdc_t *fdc = get_safe_token(device);
751   sprintf(portname, "drive_%d_led", drive);
752   output_set_value(portname, fdc->fdc_status[drive].motor_on == 0 ? 0 : 1);
753
754   if ( drive == 0 )
755      set_led_status(device->machine(), 1, fdc->fdc_status[drive].motor_on ); /* update internal drive led */
756
757   if ( drive == 1 )
758      set_led_status(device->machine(), 2, fdc->fdc_status[drive].motor_on ); /* update external drive led */
759}
760
761static void fdc_stepdrive( device_t *device,int drive ) {
762   amiga_fdc_t *fdc = get_safe_token(device);
763
764   if ( fdc->fdc_dir ) {
765      if ( fdc->fdc_status[drive].cyl )
766         fdc->fdc_status[drive].cyl--;
767   } else {
768      if ( fdc->fdc_status[drive].cyl < 79 )
769         fdc->fdc_status[drive].cyl++;
770   }
771
772   /* Update disk detection if applicable */
773   if ( fdc->fdc_status[drive].f != NULL )
774   {
775      if ( fdc->fdc_status[drive].disk_changed > 0 )
776         fdc->fdc_status[drive].disk_changed--;
777   }
778}
779
780static void fdc_motor( device_t *device,int drive, int off ) {
781   amiga_fdc_t *fdc = get_safe_token(device);
782   int on = !off;
783
784   if ( ( fdc->fdc_status[drive].motor_on == 0 ) && on ) {
785      fdc->fdc_status[drive].pos = 0;
786
787      start_rev_timer( device,drive );
788
789   } else {
790      if ( fdc->fdc_status[drive].motor_on && off )
791         stop_rev_timer(device, drive );
792   }
793
794   fdc->fdc_status[drive].motor_on = on;
795}
796
797WRITE8_DEVICE_HANDLER( amiga_fdc_control_w )
798{
799   int step_pulse;
800   int drive;
801
802   amiga_fdc_t *fdc = get_safe_token(device);
803
804   if ( fdc->fdc_sel != ( ( data >> 3 ) & 15 ) )
805      fdc->fdc_rdy = 0;
806
807   fdc->fdc_sel = ( data >> 3 ) & 15;
808    fdc->fdc_side = 1 - ( ( data >> 2 ) & 1 );
809   fdc->fdc_dir = ( data >> 1 ) & 1;
810
811   step_pulse = data & 1;
812
813    if ( fdc->fdc_step != step_pulse ) {
814      fdc->fdc_step = step_pulse;
815
816       if ( fdc->fdc_step == 0 ) {
817          for ( drive = 0; drive < NUM_DRIVES; drive++ ) {
818            if ( !( fdc->fdc_sel & ( 1 << drive ) ) )
819                fdc_stepdrive( device, drive );
820         }
821      }
822   }
823
824   for ( drive = 0; drive < NUM_DRIVES; drive++ ) {
825      if ( !( fdc->fdc_sel & ( 1 << drive ) ) ) {
826         fdc_motor( device, drive, ( data >> 7 ) & 1 );
827         fdc_setup_leds( device,drive );
828      }
829    }
830}
831
832UINT8  amiga_fdc_status_r (device_t *device)
833{
834   int drive = -1, ret = 0x3c;
835   amiga_fdc_t *fdc = get_safe_token(device);
836   for ( drive = 0; drive < NUM_DRIVES; drive++ ) {
837      if ( !( fdc->fdc_sel & ( 1 << drive ) ) ) {
838
839         if ( fdc->fdc_status[drive].motor_on ) {
840            if ( fdc->fdc_rdy ) ret &= ~0x20;
841            fdc->fdc_rdy = 1;
842         } else {
843            /* return drive id */
844            ret &= ~0x20;
845         }
846
847         if ( fdc->fdc_status[drive].cyl == 0 )
848            ret &= ~0x10;
849
850         if ( fdc->fdc_status[drive].wprot )
851            ret &= ~0x08;
852
853         if ( fdc->fdc_status[drive].disk_changed )
854            ret &= ~0x04;
855
856         return ret;
857      }
858   }
859
860   return ret;
861}
862
863static const floppy_config amiga_floppy_config =
864{
865   DEVCB_NULL,
866   DEVCB_NULL,
867   DEVCB_NULL,
868   DEVCB_NULL,
869   DEVCB_NULL,
870   FLOPPY_STANDARD_3_5_DSHD,
871   FLOPPY_OPTIONS_NAME(amiga_only),
872   NULL
873};
874
875static MACHINE_CONFIG_FRAGMENT( amiga_fdc )
876   MCFG_FLOPPY_2_DRIVES_ADD(amiga_floppy_config)
877MACHINE_CONFIG_END
878
879
880DEVICE_GET_INFO( amiga_fdc )
881{
882   switch (state)
883   {
884      /* --- the following bits of info are returned as 64-bit signed integers --- */
885      case DEVINFO_INT_INLINE_CONFIG_BYTES:         info->i = 0;                                    break;
886      case DEVINFO_INT_TOKEN_BYTES:               info->i = sizeof(amiga_fdc_t);                        break;
887
888      /* --- the following bits of info are returned as pointers --- */
889      case DEVINFO_PTR_MACHINE_CONFIG:            info->machine_config = MACHINE_CONFIG_NAME(amiga_fdc);      break;
890
891      /* --- the following bits of info are returned as pointers to data or functions --- */
892      case DEVINFO_FCT_START:                     info->start = DEVICE_START_NAME(amiga_fdc);               break;
893      case DEVINFO_FCT_STOP:                     /* Nothing */                                    break;
894      case DEVINFO_FCT_RESET:                     info->reset = DEVICE_RESET_NAME(amiga_fdc);               break;
895
896      /* --- the following bits of info are returned as NULL-terminated strings --- */
897      case DEVINFO_STR_NAME:                     strcpy(info->s, "Amiga FDC");                        break;
898      case DEVINFO_STR_FAMILY:                  strcpy(info->s, "Amiga FDC");                        break;
899      case DEVINFO_STR_VERSION:                  strcpy(info->s, "1.0");                              break;
900      case DEVINFO_STR_SOURCE_FILE:               strcpy(info->s, __FILE__);                           break;
901      case DEVINFO_STR_CREDITS:                  strcpy(info->s, "Copyright the MESS Team");             break;
902   }
903}
904
905DEFINE_LEGACY_DEVICE(AMIGA_FDC, amiga_fdc);
src/mame/machine/amigakbd.c
r11531r11532
1/***************************************************************************
2
3    Amiga keyboard controller emulation
4
5***************************************************************************/
6
7
8#include "emu.h"
9#include "includes/amiga.h"
10#include "amigakbd.h"
11#include "machine/6526cia.h"
12
13
14#define KEYBOARD_BUFFER_SIZE   256
15
16typedef struct
17{
18   UINT8 *buf;
19   int buf_pos;
20   int cur_pos;
21   emu_timer *timer;
22} amigakbd_t;
23static amigakbd_t kbd;
24
25static void kbd_sendscancode( running_machine &machine, UINT8 scancode )
26{
27   int j;
28   device_t *cia = machine.device("cia_0");
29
30   /* send over to the cia A */
31   for( j = 0; j < 8; j++ )
32   {
33      mos6526_cnt_w( cia, 0 );   /* lower cnt */
34      mos6526_sp_w( cia, BIT(scancode << j, 7) ); /* set the serial data */
35      mos6526_cnt_w( cia, 1 );   /* raise cnt */
36   }
37}
38
39static TIMER_CALLBACK( kbd_update_callback )
40{
41   UINT8   scancode;
42
43   (void)param;
44
45   /* if we don't have pending data, bail */
46
47   if ( kbd.buf_pos == kbd.cur_pos )
48      return;
49
50   /* fetch the next scan code and send it to the Amiga */
51   scancode = kbd.buf[kbd.cur_pos++];
52   kbd.cur_pos %= KEYBOARD_BUFFER_SIZE;
53   kbd_sendscancode( machine, scancode );
54
55   /* if we still have more data, schedule another update */
56   if ( kbd.buf_pos != kbd.cur_pos )
57   {
58      kbd.timer->adjust(machine.primary_screen->frame_period() / 4);
59   }
60}
61
62static INPUT_CHANGED( kbd_update )
63{
64   int   index = (int)(FPTR)param, i;
65   UINT32   oldvalue = oldval * field.mask, newvalue = newval * field.mask;
66   UINT32   delta = oldvalue ^ newvalue;
67
68   /* Special case Page UP, which we will use as Action Replay button */
69   if ( (index == 3) && ( delta & 0x80000000 ) && ( newvalue & 0x80000000 ) )
70   {
71      const amiga_machine_interface *amiga_intf = amiga_get_interface(field.machine());
72
73      if ( amiga_intf != NULL && amiga_intf->nmi_callback )
74      {
75         (*amiga_intf->nmi_callback)(field.machine());
76      }
77   }
78   else
79   {
80      int key_buf_was_empty = ( kbd.buf_pos == kbd.cur_pos ) ? 1 : 0;
81
82      for( i = 0; i < 32; i++ )
83      {
84         if ( delta & ( 1 << i ) )
85         {
86            int down = ( newvalue & ( 1 << i ) ) ? 0 : 1;
87            int scancode = ( ( (index*32)+i ) << 1 ) | down;
88            int amigacode = ~scancode;
89
90            /* add the keycode to the buffer */
91            kbd.buf[kbd.buf_pos++] = amigacode & 0xff;
92            kbd.buf_pos %= KEYBOARD_BUFFER_SIZE;
93         }
94      }
95
96      /* if the buffer was empty and we have new data, start a timer to send the keystrokes */
97      if ( key_buf_was_empty && ( kbd.buf_pos != kbd.cur_pos ) )
98      {
99         kbd.timer->adjust(field.machine().primary_screen->frame_period() / 4);
100      }
101   }
102}
103
104void amigakbd_init( running_machine &machine )
105{
106   /* allocate a keyboard buffer */
107   kbd.buf = auto_alloc_array(machine, UINT8, KEYBOARD_BUFFER_SIZE);
108   kbd.buf_pos = 0;
109   kbd.cur_pos = 0;
110   kbd.timer = machine.scheduler().timer_alloc(FUNC(kbd_update_callback));
111   kbd.timer->reset();
112}
113
114/*********************************************************************************************/
115
116/* Layout is for the US A500 keyboard */
117
118INPUT_PORTS_START( amiga_us_keyboard )
119   PORT_START("amiga_keyboard_0")
120   PORT_BIT( 0x00000001, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CHANGED(kbd_update, 0) PORT_CODE(KEYCODE_TILDE) PORT_CHAR('`') PORT_CHAR('~')      // 00
121   PORT_BIT( 0x00000002, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CHANGED(kbd_update, 0) PORT_CODE(KEYCODE_1) PORT_CHAR('1') PORT_CHAR('!')         // 01
122   PORT_BIT( 0x00000004, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CHANGED(kbd_update, 0) PORT_CODE(KEYCODE_2) PORT_CHAR('2') PORT_CHAR('@')         // 02
123   PORT_BIT( 0x00000008, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CHANGED(kbd_update, 0) PORT_CODE(KEYCODE_3) PORT_CHAR('3') PORT_CHAR('#')         // 03
124   PORT_BIT( 0x00000010, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CHANGED(kbd_update, 0) PORT_CODE(KEYCODE_4) PORT_CHAR('4') PORT_CHAR('$')         // 04
125   PORT_BIT( 0x00000020, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CHANGED(kbd_update, 0) PORT_CODE(KEYCODE_5) PORT_CHAR('5') PORT_CHAR('%')         // 05
126   PORT_BIT( 0x00000040, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CHANGED(kbd_update, 0) PORT_CODE(KEYCODE_6) PORT_CHAR('6') PORT_CHAR('^')         // 06
127   PORT_BIT( 0x00000080, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CHANGED(kbd_update, 0) PORT_CODE(KEYCODE_7) PORT_CHAR('7') PORT_CHAR('&')         // 07
128   PORT_BIT( 0x00000100, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CHANGED(kbd_update, 0) PORT_CODE(KEYCODE_8) PORT_CHAR('8') PORT_CHAR('*')         // 08
129   PORT_BIT( 0x00000200, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CHANGED(kbd_update, 0) PORT_CODE(KEYCODE_9) PORT_CHAR('9') PORT_CHAR('(')         // 09
130   PORT_BIT( 0x00000400, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CHANGED(kbd_update, 0) PORT_CODE(KEYCODE_0) PORT_CHAR('0') PORT_CHAR(')')         // 0A
131   PORT_BIT( 0x00000800, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CHANGED(kbd_update, 0) PORT_CODE(KEYCODE_MINUS) PORT_CHAR('-') PORT_CHAR('_')      // 0B
132   PORT_BIT( 0x00001000, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CHANGED(kbd_update, 0) PORT_CODE(KEYCODE_EQUALS) PORT_CHAR('=') PORT_CHAR('+')      // 0C
133   PORT_BIT( 0x00002000, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CHANGED(kbd_update, 0) PORT_CODE(KEYCODE_BACKSLASH2) PORT_CHAR('\\') PORT_CHAR('\xA6')   // 0D
134   PORT_BIT( 0x00004000, IP_ACTIVE_HIGH, IPT_UNUSED) PORT_CHANGED(kbd_update, 0)                           // 0E
135   PORT_BIT( 0x00008000, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CHANGED(kbd_update, 0) PORT_CODE(KEYCODE_0_PAD) PORT_CHAR(UCHAR_MAMEKEY(0_PAD))   // 0F
136   PORT_BIT( 0x00010000, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CHANGED(kbd_update, 0) PORT_CODE(KEYCODE_Q) PORT_CHAR('q') PORT_CHAR('Q')         // 10
137   PORT_BIT( 0x00020000, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CHANGED(kbd_update, 0) PORT_CODE(KEYCODE_W) PORT_CHAR('w') PORT_CHAR('W')         // 11
138   PORT_BIT( 0x00040000, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CHANGED(kbd_update, 0) PORT_CODE(KEYCODE_E) PORT_CHAR('e') PORT_CHAR('E')         // 12
139   PORT_BIT( 0x00080000, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CHANGED(kbd_update, 0) PORT_CODE(KEYCODE_R) PORT_CHAR('r') PORT_CHAR('R')         // 13
140   PORT_BIT( 0x00100000, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CHANGED(kbd_update, 0) PORT_CODE(KEYCODE_T) PORT_CHAR('t') PORT_CHAR('T')         // 14
141   PORT_BIT( 0x00200000, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CHANGED(kbd_update, 0) PORT_CODE(KEYCODE_Y) PORT_CHAR('y') PORT_CHAR('Y')         // 15
142   PORT_BIT( 0x00400000, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CHANGED(kbd_update, 0) PORT_CODE(KEYCODE_U) PORT_CHAR('u') PORT_CHAR('U')         // 16
143   PORT_BIT( 0x00800000, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CHANGED(kbd_update, 0) PORT_CODE(KEYCODE_I) PORT_CHAR('i') PORT_CHAR('I')         // 17
144   PORT_BIT( 0x01000000, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CHANGED(kbd_update, 0) PORT_CODE(KEYCODE_O) PORT_CHAR('o') PORT_CHAR('O')         // 18
145   PORT_BIT( 0x02000000, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CHANGED(kbd_update, 0) PORT_CODE(KEYCODE_P) PORT_CHAR('p') PORT_CHAR('P')         // 19
146   PORT_BIT( 0x04000000, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CHANGED(kbd_update, 0) PORT_CODE(KEYCODE_OPENBRACE) PORT_CHAR('[') PORT_CHAR('{')   // 1A
147   PORT_BIT( 0x08000000, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CHANGED(kbd_update, 0) PORT_CODE(KEYCODE_CLOSEBRACE) PORT_CHAR(']') PORT_CHAR('}')   // 1B
148   PORT_BIT( 0x10000000, IP_ACTIVE_HIGH, IPT_UNUSED) PORT_CHANGED(kbd_update, 0)                           // 1C
149   PORT_BIT( 0x20000000, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CHANGED(kbd_update, 0) PORT_CODE(KEYCODE_1_PAD) PORT_CHAR(UCHAR_MAMEKEY(1_PAD))   // 1D
150   PORT_BIT( 0x40000000, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CHANGED(kbd_update, 0) PORT_CODE(KEYCODE_2_PAD) PORT_CHAR(UCHAR_MAMEKEY(2_PAD))   // 1E
151   PORT_BIT( 0x80000000, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CHANGED(kbd_update, 0) PORT_CODE(KEYCODE_3_PAD) PORT_CHAR(UCHAR_MAMEKEY(3_PAD))   // 1F
152
153   PORT_START("amiga_keyboard_1")
154   PORT_BIT( 0x00000001, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CHANGED(kbd_update, 1) PORT_CODE(KEYCODE_A) PORT_CHAR('a') PORT_CHAR('A')         // 20
155   PORT_BIT( 0x00000002, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CHANGED(kbd_update, 1) PORT_CODE(KEYCODE_S) PORT_CHAR('s') PORT_CHAR('S')         // 21
156   PORT_BIT( 0x00000004, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CHANGED(kbd_update, 1) PORT_CODE(KEYCODE_D) PORT_CHAR('d') PORT_CHAR('D')         // 22
157   PORT_BIT( 0x00000008, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CHANGED(kbd_update, 1) PORT_CODE(KEYCODE_F) PORT_CHAR('f') PORT_CHAR('F')         // 23
158   PORT_BIT( 0x00000010, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CHANGED(kbd_update, 1) PORT_CODE(KEYCODE_G) PORT_CHAR('g') PORT_CHAR('G')         // 24
159   PORT_BIT( 0x00000020, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CHANGED(kbd_update, 1) PORT_CODE(KEYCODE_H) PORT_CHAR('h') PORT_CHAR('H')         // 25
160   PORT_BIT( 0x00000040, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CHANGED(kbd_update, 1) PORT_CODE(KEYCODE_J) PORT_CHAR('j') PORT_CHAR('J')         // 26
161   PORT_BIT( 0x00000080, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CHANGED(kbd_update, 1) PORT_CODE(KEYCODE_K) PORT_CHAR('k') PORT_CHAR('K')         // 27
162   PORT_BIT( 0x00000100, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CHANGED(kbd_update, 1) PORT_CODE(KEYCODE_L) PORT_CHAR('l') PORT_CHAR('L')         // 28
163   PORT_BIT( 0x00000200, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CHANGED(kbd_update, 1) PORT_CODE(KEYCODE_COLON) PORT_CHAR(';') PORT_CHAR(':')      // 29
164   PORT_BIT( 0x00000400, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CHANGED(kbd_update, 1) PORT_CODE(KEYCODE_QUOTE) PORT_CHAR('\'') PORT_CHAR('"')      // 2A
165   PORT_BIT( 0x00000800, IP_ACTIVE_HIGH, IPT_UNUSED) PORT_CHANGED(kbd_update, 1)                           // 2B
166   PORT_BIT( 0x00001000, IP_ACTIVE_HIGH, IPT_UNUSED) PORT_CHANGED(kbd_update, 1)                           // 2C
167   PORT_BIT( 0x00002000, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CHANGED(kbd_update, 1) PORT_CODE(KEYCODE_4_PAD) PORT_CHAR(UCHAR_MAMEKEY(4_PAD))   // 2D
168   PORT_BIT( 0x00004000, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CHANGED(kbd_update, 1) PORT_CODE(KEYCODE_5_PAD) PORT_CHAR(UCHAR_MAMEKEY(5_PAD))   // 2E
169   PORT_BIT( 0x00008000, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CHANGED(kbd_update, 1) PORT_CODE(KEYCODE_6_PAD) PORT_CHAR(UCHAR_MAMEKEY(6_PAD))   // 2F
170   PORT_BIT( 0x00010000, IP_ACTIVE_HIGH, IPT_UNUSED) PORT_CHANGED(kbd_update, 1)                           // 30
171   PORT_BIT( 0x00020000, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CHANGED(kbd_update, 1) PORT_CODE(KEYCODE_Z) PORT_CHAR('z') PORT_CHAR('Z')         // 31
172   PORT_BIT( 0x00040000, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CHANGED(kbd_update, 1) PORT_CODE(KEYCODE_X) PORT_CHAR('x') PORT_CHAR('X')         // 32
173   PORT_BIT( 0x00080000, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CHANGED(kbd_update, 1) PORT_CODE(KEYCODE_C) PORT_CHAR('c') PORT_CHAR('C')         // 33
174   PORT_BIT( 0x00100000, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CHANGED(kbd_update, 1) PORT_CODE(KEYCODE_V) PORT_CHAR('v') PORT_CHAR('V')         // 34
175   PORT_BIT( 0x00200000, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CHANGED(kbd_update, 1) PORT_CODE(KEYCODE_B) PORT_CHAR('b') PORT_CHAR('B')         // 35
176   PORT_BIT( 0x00400000, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CHANGED(kbd_update, 1) PORT_CODE(KEYCODE_N) PORT_CHAR('n') PORT_CHAR('N')         // 36
177   PORT_BIT( 0x00800000, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CHANGED(kbd_update, 1) PORT_CODE(KEYCODE_M) PORT_CHAR('m') PORT_CHAR('M')         // 37
178   PORT_BIT( 0x01000000, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CHANGED(kbd_update, 1) PORT_CODE(KEYCODE_COMMA) PORT_CHAR(',') PORT_CHAR('<')      // 38
179   PORT_BIT( 0x02000000, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CHANGED(kbd_update, 1) PORT_CODE(KEYCODE_STOP)    PORT_CHAR('.') PORT_CHAR('>')      // 39
180   PORT_BIT( 0x04000000, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CHANGED(kbd_update, 1) PORT_CODE(KEYCODE_SLASH) PORT_CHAR('/') PORT_CHAR('?')      // 3A
181   PORT_BIT( 0x08000000, IP_ACTIVE_HIGH, IPT_UNUSED) PORT_CHANGED(kbd_update, 1)                           // 3B
182   PORT_BIT( 0x10000000, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CHANGED(kbd_update, 1) PORT_CODE(KEYCODE_DEL_PAD) PORT_CHAR(UCHAR_MAMEKEY(DEL_PAD))// 3C
183   PORT_BIT( 0x20000000, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CHANGED(kbd_update, 1) PORT_CODE(KEYCODE_7_PAD) PORT_CHAR(UCHAR_MAMEKEY(7_PAD))   // 3D
184   PORT_BIT( 0x40000000, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CHANGED(kbd_update, 1) PORT_CODE(KEYCODE_8_PAD) PORT_CHAR(UCHAR_MAMEKEY(8_PAD))   // 3E
185   PORT_BIT( 0x80000000, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CHANGED(kbd_update, 1) PORT_CODE(KEYCODE_9_PAD) PORT_CHAR(UCHAR_MAMEKEY(9_PAD))   // 3F
186
187   PORT_START("amiga_keyboard_2")
188   PORT_BIT( 0x00000001, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CHANGED(kbd_update, 2) PORT_CODE(KEYCODE_SPACE) PORT_CHAR(' ')                  // 40
189   PORT_BIT( 0x00000002, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CHANGED(kbd_update, 2) PORT_CODE(KEYCODE_BACKSPACE) PORT_CHAR(8)               // 41
190   PORT_BIT( 0x00000004, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CHANGED(kbd_update, 2) PORT_CODE(KEYCODE_TAB) PORT_CHAR('\t')                  // 42
191   PORT_BIT( 0x00000008, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CHANGED(kbd_update, 2) PORT_CODE(KEYCODE_ENTER_PAD) PORT_CHAR(UCHAR_MAMEKEY(ENTER_PAD))   // 43
192   PORT_BIT( 0x00000010, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CHANGED(kbd_update, 2) PORT_CODE(KEYCODE_ENTER) PORT_CHAR(13)                  // 44
193   PORT_BIT( 0x00000020, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CHANGED(kbd_update, 2) PORT_CODE(KEYCODE_ESC) PORT_CHAR(UCHAR_MAMEKEY(ESC))      // 45
194   PORT_BIT( 0x00000040, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CHANGED(kbd_update, 2) PORT_CODE(KEYCODE_DEL) PORT_CHAR(UCHAR_MAMEKEY(DEL))      // 46
195   PORT_BIT( 0x00000080, IP_ACTIVE_HIGH, IPT_UNUSED) PORT_CHANGED(kbd_update, 2)                           // 47
196   PORT_BIT( 0x00000100, IP_ACTIVE_HIGH, IPT_UNUSED) PORT_CHANGED(kbd_update, 2)                           // 48
197   PORT_BIT( 0x00000200, IP_ACTIVE_HIGH, IPT_UNUSED) PORT_CHANGED(kbd_update, 2)                           // 49
198   PORT_BIT( 0x00000400, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CHANGED(kbd_update, 2) PORT_CODE(KEYCODE_MINUS_PAD) PORT_CHAR(UCHAR_MAMEKEY(MINUS_PAD))   // 4A
199   PORT_BIT( 0x00000800, IP_ACTIVE_HIGH, IPT_UNUSED) PORT_CHANGED(kbd_update, 2)                           // 4B
200   PORT_BIT( 0x00001000, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CHANGED(kbd_update, 2) PORT_CODE(KEYCODE_UP) PORT_CHAR(UCHAR_MAMEKEY(UP))         // 4C
201   PORT_BIT( 0x00002000, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CHANGED(kbd_update, 2) PORT_CODE(KEYCODE_DOWN) PORT_CHAR(UCHAR_MAMEKEY(DOWN))      // 4D
202   PORT_BIT( 0x00004000, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CHANGED(kbd_update, 2) PORT_CODE(KEYCODE_RIGHT) PORT_CHAR(UCHAR_MAMEKEY(RIGHT))   // 4E
203   PORT_BIT( 0x00008000, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CHANGED(kbd_update, 2) PORT_CODE(KEYCODE_LEFT) PORT_CHAR(UCHAR_MAMEKEY(LEFT))      // 4F
204   PORT_BIT( 0x00010000, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CHANGED(kbd_update, 2) PORT_CODE(KEYCODE_F1) PORT_CHAR(UCHAR_MAMEKEY(F1))         // 50
205   PORT_BIT( 0x00020000, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CHANGED(kbd_update, 2) PORT_CODE(KEYCODE_F2) PORT_CHAR(UCHAR_MAMEKEY(F2))         // 51
206   PORT_BIT( 0x00040000, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CHANGED(kbd_update, 2) PORT_CODE(KEYCODE_F3) PORT_CHAR(UCHAR_MAMEKEY(F3))         // 52
207   PORT_BIT( 0x00080000, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CHANGED(kbd_update, 2) PORT_CODE(KEYCODE_F4) PORT_CHAR(UCHAR_MAMEKEY(F4))         // 53
208   PORT_BIT( 0x00100000, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CHANGED(kbd_update, 2) PORT_CODE(KEYCODE_F5) PORT_CHAR(UCHAR_MAMEKEY(F5))         // 54
209   PORT_BIT( 0x00200000, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CHANGED(kbd_update, 2) PORT_CODE(KEYCODE_F6) PORT_CHAR(UCHAR_MAMEKEY(F6))         // 55
210   PORT_BIT( 0x00400000, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CHANGED(kbd_update, 2) PORT_CODE(KEYCODE_F7) PORT_CHAR(UCHAR_MAMEKEY(F7))         // 56
211   PORT_BIT( 0x00800000, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CHANGED(kbd_update, 2) PORT_CODE(KEYCODE_F8) PORT_CHAR(UCHAR_MAMEKEY(F8))         // 57
212   PORT_BIT( 0x01000000, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CHANGED(kbd_update, 2) PORT_CODE(KEYCODE_F9) PORT_CHAR(UCHAR_MAMEKEY(F9))         // 58
213   PORT_BIT( 0x02000000, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CHANGED(kbd_update, 2) PORT_CODE(KEYCODE_F10) PORT_CHAR(UCHAR_MAMEKEY(F10))      // 59
214   PORT_BIT( 0x04000000, IP_ACTIVE_HIGH, IPT_UNUSED) PORT_CHANGED(kbd_update, 2)                           // 5A
215   PORT_BIT( 0x08000000, IP_ACTIVE_HIGH, IPT_UNUSED) PORT_CHANGED(kbd_update, 2)                           // 5B
216   PORT_BIT( 0x10000000, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CHANGED(kbd_update, 2) PORT_CODE(KEYCODE_SLASH_PAD) PORT_CHAR(UCHAR_MAMEKEY(SLASH_PAD))   // 5C
217   PORT_BIT( 0x20000000, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CHANGED(kbd_update, 2) PORT_CODE(KEYCODE_ASTERISK) PORT_CHAR(UCHAR_MAMEKEY(ASTERISK))   // 5D
218   PORT_BIT( 0x40000000, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CHANGED(kbd_update, 2) PORT_CODE(KEYCODE_PLUS_PAD) PORT_CHAR(UCHAR_MAMEKEY(PLUS_PAD))   // 5E
219   PORT_BIT( 0x80000000, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CHANGED(kbd_update, 2) PORT_CODE(KEYCODE_INSERT) PORT_CHAR(UCHAR_MAMEKEY(INSERT))   // 5F
220
221   PORT_START("amiga_keyboard_3")
222   PORT_BIT( 0x00000001, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CHANGED(kbd_update, 3) PORT_NAME("Shift (Left)") PORT_CODE(KEYCODE_LSHIFT) PORT_CHAR(UCHAR_SHIFT_1)   // 60
223   PORT_BIT( 0x00000002, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CHANGED(kbd_update, 3) PORT_NAME("Shift (Right)") PORT_CODE(KEYCODE_RSHIFT) PORT_CHAR(UCHAR_SHIFT_1)   // 61
224   PORT_BIT( 0x00000004, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CHANGED(kbd_update, 3) PORT_NAME("Caps Lock") PORT_CODE(KEYCODE_CAPSLOCK)         // 62
225   PORT_BIT( 0x00000008, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CHANGED(kbd_update, 3) PORT_NAME("Ctrl") PORT_CODE(KEYCODE_LCONTROL) PORT_CHAR(UCHAR_MAMEKEY(LCONTROL))// 63
226   PORT_BIT( 0x00000010, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CHANGED(kbd_update, 3) PORT_NAME("Alt (Left)") PORT_CODE(KEYCODE_LALT) PORT_CHAR(UCHAR_MAMEKEY(LALT))   // 64
227   PORT_BIT( 0x00000020, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CHANGED(kbd_update, 3) PORT_NAME("Alt (Right)") PORT_CODE(KEYCODE_RALT) PORT_CHAR(UCHAR_MAMEKEY(RALT))   // 65
228   PORT_BIT( 0x00000040, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CHANGED(kbd_update, 3) PORT_NAME("Amiga A (Left)") PORT_CODE(KEYCODE_LWIN)            // 66
229   PORT_BIT( 0x00000080, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CHANGED(kbd_update, 3) PORT_NAME("Amiga A (Right)")  PORT_CODE(KEYCODE_RWIN)         // 67
230   PORT_BIT( 0x00000100, IP_ACTIVE_HIGH, IPT_UNUSED) PORT_CHANGED(kbd_update, 3)                           // 68
231   PORT_BIT( 0x00000200, IP_ACTIVE_HIGH, IPT_UNUSED) PORT_CHANGED(kbd_update, 3)                           // 69
232   PORT_BIT( 0x00000400, IP_ACTIVE_HIGH, IPT_UNUSED) PORT_CHANGED(kbd_update, 3)                           // 6A
233   PORT_BIT( 0x00000800, IP_ACTIVE_HIGH, IPT_UNUSED) PORT_CHANGED(kbd_update, 3)                           // 6B
234   PORT_BIT( 0x00001000, IP_ACTIVE_HIGH, IPT_UNUSED) PORT_CHANGED(kbd_update, 3)                           // 6C
235   PORT_BIT( 0x00002000, IP_ACTIVE_HIGH, IPT_UNUSED) PORT_CHANGED(kbd_update, 3)                           // 6D
236   PORT_BIT( 0x00004000, IP_ACTIVE_HIGH, IPT_UNUSED) PORT_CHANGED(kbd_update, 3)                           // 6E
237   PORT_BIT( 0x00008000, IP_ACTIVE_HIGH, IPT_UNUSED) PORT_CHANGED(kbd_update, 3)                           // 6F
238   PORT_BIT( 0x00010000, IP_ACTIVE_HIGH, IPT_UNUSED) PORT_CHANGED(kbd_update, 3)                           // 70
239   PORT_BIT( 0x00020000, IP_ACTIVE_HIGH, IPT_UNUSED) PORT_CHANGED(kbd_update, 3)                           // 71
240   PORT_BIT( 0x00040000, IP_ACTIVE_HIGH, IPT_UNUSED) PORT_CHANGED(kbd_update, 3)                           // 72
241   PORT_BIT( 0x00080000, IP_ACTIVE_HIGH, IPT_UNUSED) PORT_CHANGED(kbd_update, 3)                           // 73
242   PORT_BIT( 0x00100000, IP_ACTIVE_HIGH, IPT_UNUSED) PORT_CHANGED(kbd_update, 3)                           // 74
243   PORT_BIT( 0x00200000, IP_ACTIVE_HIGH, IPT_UNUSED) PORT_CHANGED(kbd_update, 3)                           // 75
244   PORT_BIT( 0x00400000, IP_ACTIVE_HIGH, IPT_UNUSED) PORT_CHANGED(kbd_update, 3)                           // 76
245   PORT_BIT( 0x00800000, IP_ACTIVE_HIGH, IPT_UNUSED) PORT_CHANGED(kbd_update, 3)                           // 77
246   PORT_BIT( 0x01000000, IP_ACTIVE_HIGH, IPT_UNUSED) PORT_CHANGED(kbd_update, 3)                           // 78
247   PORT_BIT( 0x02000000, IP_ACTIVE_HIGH, IPT_UNUSED) PORT_CHANGED(kbd_update, 3)                           // 79
248   PORT_BIT( 0x04000000, IP_ACTIVE_HIGH, IPT_UNUSED) PORT_CHANGED(kbd_update, 3)                           // 7A
249   PORT_BIT( 0x08000000, IP_ACTIVE_HIGH, IPT_UNUSED) PORT_CHANGED(kbd_update, 3)                           // 7B
250   PORT_BIT( 0x10000000, IP_ACTIVE_HIGH, IPT_UNUSED) PORT_CHANGED(kbd_update, 3)                           // 7C
251   PORT_BIT( 0x20000000, IP_ACTIVE_HIGH, IPT_UNUSED) PORT_CHANGED(kbd_update, 3)                           // 7D
252   PORT_BIT( 0x40000000, IP_ACTIVE_HIGH, IPT_UNUSED) PORT_CHANGED(kbd_update, 3)                           // 7E
253   PORT_BIT( 0x80000000, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CHANGED(kbd_update, 3)   PORT_CODE(KEYCODE_PGUP)         // 7F NMI button
254INPUT_PORTS_END
src/mame/machine/amigafdc.h
r11531r11532
1#ifndef AMIGAFDC_H
2#define AMIGAFDC_H
3
4WRITE8_DEVICE_HANDLER( amiga_fdc_control_w );
5UINT8  amiga_fdc_status_r (device_t *device);
6UINT16 amiga_fdc_get_byte (device_t *device);
7void amiga_fdc_setup_dma( device_t *device );
8
9/***************************************************************************
10    MACROS
11***************************************************************************/
12
13DECLARE_LEGACY_DEVICE(AMIGA_FDC, amiga_fdc);
14
15#define MCFG_AMIGA_FDC_ADD(_tag)   \
16   MCFG_DEVICE_ADD((_tag),  AMIGA_FDC, 0)
17
18#endif /* AMIGAFDC_H */
src/mame/machine/amigakbd.h
r11531r11532
1#ifndef AMIGAKBD_H
2#define AMIGAKBD_H
3
4void amigakbd_init( running_machine &machine );
5
6INPUT_PORTS_EXTERN( amiga_us_keyboard );
7
8#endif /* AMIGAKBD_H */
src/mame/machine/amigacrt.c
r11531r11532
1/***************************************************************************
2
3    Amiga cartridge emulation
4
5TODO:
6- Investigate why the AR2/3 sometimes garble the video on exit from the cart
7- Add Nordic Power and similar carts
8- Add HRTMon A1200 cart
9
10***************************************************************************/
11
12
13#include "emu.h"
14#include "includes/amiga.h"
15#include "cpu/m68000/m68000.h"
16#include "machine/6526cia.h"
17#include "machine/amigacrt.h"
18
19enum
20{
21   /* supported cartridges */
22   ACTION_REPLAY            =   0,
23   ACTION_REPLAY_MKII,
24   ACTION_REPLAY_MKIII
25};
26
27typedef struct
28{
29   int cart_type;
30   int ar1_spurious;
31   UINT16 ar23_mode;
32} amigacrt_t;
33static amigacrt_t amigacrt;
34
35/***************************************************************************
36
37  Utilities
38
39***************************************************************************/
40
41static int check_kickstart_12_13( running_machine &machine, const char *cart_name )
42{
43   UINT16 * ksmem = (UINT16 *)machine.region( "user1" )->base();
44
45   if ( ksmem[2] == 0x00FC )
46      return 1;
47
48   logerror( "%s requires Kickstart version 1.2 or 1.3 - Cart not installed\n", cart_name );
49
50   return 0;
51}
52
53/***************************************************************************
54
55  Amiga Action Replay 1
56
57  Whenever you push the button, an NMI interrupt is generated.
58
59  The cartridge protects itself from being removed from memory by
60  generating an interrupt whenever either the spurious interrupt
61  vector is written at $60, or the nmi interrupt vector is written at
62  $7c. If the spurious interrupt vector at $60 is written, then
63  a NMI is generated, and the spurious irq vector is restored. If the
64  NMI vector at $7c is written, then a spurious interrupt is generated,
65  and the NMI vector is restored.
66
67  When breakpoints are set, the target address is replaced by a trap
68  instruction, and the original contents of the address are kept in
69  the cartridge's RAM. A trap handler is installed pointing to $40
70  in RAM, where code that clears memory address $60 followed by two
71  nops are written. There seems to be a small delay between the write
72  to $60 and until the actual NMI is generated, since the cart expects
73  the PC to be at $46 (at the second nop).
74
75***************************************************************************/
76
77static IRQ_CALLBACK(amiga_ar1_irqack)
78{
79   if ( irqline == 7 && amigacrt.ar1_spurious )
80   {
81      return M68K_INT_ACK_SPURIOUS;
82   }
83
84   return (24+irqline);
85}
86
87static TIMER_CALLBACK( amiga_ar1_delayed_nmi )
88{
89   (void)param;
90   cputag_set_input_line(machine, "maincpu", 7, PULSE_LINE);
91}
92
93static void amiga_ar1_nmi( running_machine &machine )
94{
95   amiga_state *state = machine.driver_data<amiga_state>();
96   /* get the cart's built-in ram */
97   UINT16 *ar_ram = (UINT16 *)machine.device("maincpu")->memory().space(AS_PROGRAM)->get_write_ptr(0x9fc000);
98
99   if ( ar_ram != NULL )
100   {
101      int i;
102
103      /* copy custom register values */
104      for( i = 0; i < 256; i++ )
105         ar_ram[0x1800+i] = CUSTOM_REG(i);
106
107      /* trigger NMI irq */
108      amigacrt.ar1_spurious = 0;
109      machine.scheduler().timer_set(machine.device<cpu_device>("maincpu")->cycles_to_attotime(28), FUNC(amiga_ar1_delayed_nmi));
110   }
111}
112
113static WRITE16_HANDLER( amiga_ar1_chipmem_w )
114{
115   amiga_state *state = space->machine().driver_data<amiga_state>();
116   int pc = cpu_get_pc(&space->device());
117
118   /* see if we're inside the AR1 rom */
119   if ( ((pc >> 16) & 0xff ) != 0xf0 )
120   {
121      /* if we're not, see if either the Spurious IRQ vector
122           or the NMI vector are being overwritten */
123      if ( offset == (0x60/2) || offset == (0x7c/2) )
124      {
125         /* trigger an NMI or spurious irq */
126         amigacrt.ar1_spurious = (offset == 0x60/2) ? 0 : 1;
127         space->machine().scheduler().timer_set(space->machine().device<cpu_device>("maincpu")->cycles_to_attotime(28), FUNC(amiga_ar1_delayed_nmi));
128      }
129   }
130
131   (*state->m_chip_ram_w)(state,  offset * 2, data );
132}
133
134static void amiga_ar1_check_overlay( running_machine &machine )
135{
136   machine.device("maincpu")->memory().space(AS_PROGRAM)->install_legacy_write_handler(0x000000, 0x00007f, FUNC(amiga_ar1_chipmem_w));
137}
138
139static void amiga_ar1_init( running_machine &machine )
140{
141   void *ar_ram;
142
143   /* check kickstart version */
144   if ( !check_kickstart_12_13( machine, "Amiga Action Replay" ) )
145   {
146      amigacrt.cart_type = -1;
147      return;
148   }
149
150   /* setup the cart ram */
151   ar_ram = auto_alloc_array(machine, UINT8, 0x4000);
152   memset(ar_ram, 0, 0x4000);
153
154   /* Install ROM */
155   machine.device("maincpu")->memory().space(AS_PROGRAM)->install_read_bank(0xf00000, 0xf7ffff, "bank2");
156   machine.device("maincpu")->memory().space(AS_PROGRAM)->unmap_write(0xf00000, 0xf7ffff);
157
158   /* Install RAM */
159   machine.device("maincpu")->memory().space(AS_PROGRAM)->install_readwrite_bank(0x9fc000, 0x9fffff, "bank3");
160
161   /* Configure Banks */
162   memory_set_bankptr(machine, "bank2", machine.region("user2")->base());
163   memory_set_bankptr(machine, "bank3", ar_ram);
164
165   amigacrt.ar1_spurious = 0;
166
167   /* Install IRQ ACK callback */
168   device_set_irq_callback(machine.device("maincpu"), amiga_ar1_irqack);
169}
170
171/***************************************************************************
172
173  Amiga Action Replay MKII/MKIII
174
175  Whenever you push the button, an overlay of the cartridge appears
176  in RAM and an NMI interrupt is generated. Only reads are overlayed.
177  Writes go directly to chipmem (so that the CPU can write the stack
178  information for the NMI). Once the interrupt is taken, the cart
179  disables the ROM overlay and checks it's internal mode register
180  to see why it was invoked.
181
182  When a breakpoint is set the cart replaces the target instruction
183  with a trap, and adds a trap handler that it locates in the $100-$120
184  area. The handler simply has one instruction: TST.B $BFE001. This cia
185  access is monitored, and the conditions match (PC < 120 and a previous
186  command requested the monitoring of the cia) then the cart is invoked.
187
188***************************************************************************/
189
190static void amiga_ar23_freeze( running_machine &machine );
191
192static READ16_HANDLER( amiga_ar23_cia_r )
193{
194   int pc = cpu_get_pc(&space->device());
195
196   if ( ACCESSING_BITS_0_7 && offset == 2048 && pc >= 0x40 && pc < 0x120 )
197   {
198      amiga_ar23_freeze(space->machine());
199   }
200
201   return amiga_cia_r( space, offset, mem_mask );
202}
203
204static WRITE16_HANDLER( amiga_ar23_mode_w )
205{
206   if ( data & 2 )
207   {
208      space->install_legacy_read_handler(0xbfd000, 0xbfefff, FUNC(amiga_ar23_cia_r));
209   }
210   else
211   {
212      space->install_legacy_read_handler(0xbfd000, 0xbfefff, FUNC(amiga_cia_r));
213   }
214
215   amigacrt.ar23_mode = (data&0x3);
216   if ( amigacrt.ar23_mode == 0 )
217      amigacrt.ar23_mode = 1;
218
219}
220
221static READ16_HANDLER( amiga_ar23_mode_r )
222{
223   amiga_state *state = space->machine().driver_data<amiga_state>();
224   UINT16 *mem = (UINT16 *)space->machine().region( "user2" )->base();
225
226   if ( ACCESSING_BITS_0_7 )
227   {
228      if ( offset < 2 )
229         return (mem[offset] | (amigacrt.ar23_mode&3));
230
231      if ( offset == 0x03 ) /* disable cart oberlay on chip mem */
232      {
233         UINT32 mirror_mask = state->m_chip_ram_size;
234
235         memory_set_bank(space->machine(), "bank1", 0);
236
237         while( (mirror_mask<<1) < 0x100000 )
238         {
239            mirror_mask |= ( mirror_mask << 1 );
240         }
241
242         /* overlay disabled, map RAM on 0x000000 */
243         space->install_write_bank(0x000000, state->m_chip_ram_size - 1, 0, mirror_mask, "bank1");
244      }
245   }
246
247   return mem[offset];
248}
249
250static WRITE16_HANDLER( amiga_ar23_chipmem_w )
251{
252   amiga_state *state = space->machine().driver_data<amiga_state>();
253   if ( offset == (0x08/2) )
254   {
255      if ( amigacrt.ar23_mode & 1 )
256         amiga_ar23_freeze(space->machine());
257   }
258
259   (*state->m_chip_ram_w)(state,  offset * 2, data );
260}
261
262static void amiga_ar23_freeze( running_machine &machine )
263{
264   amiga_state *state = machine.driver_data<amiga_state>();
265   int pc = cpu_get_pc(machine.device("maincpu"));
266
267   /* only freeze if we're not inside the cart's ROM */
268   if ( ((pc >> 16) & 0xfe ) != 0x40 )
269   {
270      /* get the cart's built-in ram */
271      UINT16 *ar_ram = (UINT16 *)machine.device("maincpu")->memory().space(AS_PROGRAM)->get_write_ptr(0x440000);
272
273      if ( ar_ram != NULL )
274      {
275         int      i;
276
277         for( i = 0; i < 0x100; i++ )
278            ar_ram[0x7800+i] = CUSTOM_REG(i);
279      }
280
281      /* overlay the cart rom's in chipram */
282      memory_set_bank(machine, "bank1", 2);
283
284      /* writes go to chipram */
285      machine.device("maincpu")->memory().space(AS_PROGRAM)->install_legacy_write_handler(0x000000, state->m_chip_ram_size - 1, FUNC(amiga_ar23_chipmem_w));
286
287      /* trigger NMI irq */
288      cputag_set_input_line(machine, "maincpu", 7, PULSE_LINE);
289   }
290}
291
292static void amiga_ar23_nmi( running_machine &machine )
293{
294   amigacrt.ar23_mode = 0;
295   amiga_ar23_freeze(machine);
296}
297
298#if 0
299static WRITE16_HANDLER( amiga_ar23_custom_w )
300{
301   int pc = cpu_get_pc(&space->device());
302
303   /* see if we're inside the AR2 rom */
304   if ( ((pc >> 16) & 0xfe ) != 0x40 )
305   {
306      /* get the cart's built-in ram */
307      UINT16 *ar_ram = (UINT16 *)memory_get_write_ptr(0, AS_PROGRAM, 0x440000);
308
309      if ( ar_ram != NULL )
310      {
311         ar_ram[0x7800+offset] = data;
312      }
313   }
314
315   amiga_custom_w( offset, data, mem_mask );
316}
317
318static READ16_HANDLER( amiga_ar23_custom_r )
319{
320   UINT16 data = amiga_custom_r( offset, mem_mask );
321
322   int pc = cpu_get_pc(&space->device());
323
324   /* see if we're inside the AR2 rom */
325   if ( ((pc >> 16) & 0xfe ) != 0x40 )
326   {
327      /* get the cart's built-in ram */
328      UINT16 *ar_ram = (UINT16 *)memory_get_write_ptr(0, AS_PROGRAM, 0x440000);
329
330      if ( ar_ram != NULL )
331      {
332         ar_ram[0x7800+offset] = data;
333      }
334   }
335
336   return data;
337}
338#endif
339
340static void amiga_ar23_check_overlay( running_machine &machine )
341{
342   amigacrt.ar23_mode = 3;
343   machine.device("maincpu")->memory().space(AS_PROGRAM)->install_legacy_write_handler(0x000000, 0x00000f, FUNC(amiga_ar23_chipmem_w));
344}
345
346static void amiga_ar23_init( running_machine &machine, int ar3 )
347{
348   amiga_state *state = machine.driver_data<amiga_state>();
349   UINT32 mirror = 0x20000, size = 0x1ffff;
350   void *ar_ram;
351
352   /* check kickstart version */
353   if ( !check_kickstart_12_13( machine, "Action Replay MKII or MKIII" ) )
354   {
355      amigacrt.cart_type = -1;
356      return;
357   }
358
359   /* setup the cart ram */
360   ar_ram = auto_alloc_array_clear(machine, UINT8,0x10000);
361
362   if ( ar3 )
363   {
364      mirror = 0;
365      size = 0x3ffff;
366   }
367
368   /* Install ROM */
369   machine.device("maincpu")->memory().space(AS_PROGRAM)->install_read_bank(0x400000, 0x400000+size, 0, mirror, "bank2");
370   machine.device("maincpu")->memory().space(AS_PROGRAM)->unmap_write(0x400000, 0x400000+size, 0, mirror);
371
372   /* Install RAM */
373   machine.device("maincpu")->memory().space(AS_PROGRAM)->install_read_bank(0x440000, 0x44ffff, "bank3");
374   machine.device("maincpu")->memory().space(AS_PROGRAM)->install_write_bank(0x440000, 0x44ffff, "bank3");
375
376   /* Install Custom chip monitor */
377//  machine.device("maincpu")->memory().space(AS_PROGRAM)->install_legacy_read_handler(0xdff000, 0xdff1ff, FUNC(amiga_ar23_custom_r));
378//  machine.device("maincpu")->memory().space(AS_PROGRAM)->install_legacy_write_handler(0xdff000, 0xdff1ff, FUNC(amiga_ar23_custom_w));
379
380   /* Install status/mode handlers */
381   machine.device("maincpu")->memory().space(AS_PROGRAM)->install_legacy_read_handler(0x400000, 0x400007, 0, mirror, FUNC(amiga_ar23_mode_r));
382   machine.device("maincpu")->memory().space(AS_PROGRAM)->install_legacy_write_handler(0x400000, 0x400003, 0, mirror, FUNC(amiga_ar23_mode_w));
383
384   /* Configure Banks */
385   memory_set_bankptr(machine, "bank2", machine.region("user2")->base());
386   memory_set_bankptr(machine, "bank3", ar_ram);
387
388   memory_configure_bank(machine, "bank1", 0, 2, state->m_chip_ram, 0);
389   memory_configure_bank(machine, "bank1", 1, 2, machine.region("user1")->base(), 0);
390   memory_configure_bank(machine, "bank1", 2, 2, machine.region("user2")->base(), 0);
391
392   amigacrt.ar23_mode = 3;
393}
394
395/***************************************************************************
396
397    MAME/MESS hooks
398
399***************************************************************************/
400
401void amiga_cart_init( running_machine &machine )
402{
403   /* see what is there */
404   UINT16 *mem = (UINT16 *)machine.region( "user2" )->base();
405
406   amigacrt.cart_type = -1;
407
408   if ( mem != NULL )
409   {
410      if ( mem[0x00] == 0x1111 )
411      {
412         amigacrt.cart_type = ACTION_REPLAY;
413         amiga_ar1_init(machine);
414      }
415      else if ( mem[0x0C] == 0x4D6B )
416      {
417         amigacrt.cart_type = ACTION_REPLAY_MKII;
418         amiga_ar23_init(machine, 0);
419      }
420      else if ( mem[0x0C] == 0x4D4B )
421      {
422         amigacrt.cart_type = ACTION_REPLAY_MKIII;
423         amiga_ar23_init(machine, 1);
424      }
425   }
426}
427
428void amiga_cart_check_overlay( running_machine &machine )
429{
430   if ( amigacrt.cart_type < 0 )
431      return;
432
433   switch( amigacrt.cart_type )
434   {
435      case ACTION_REPLAY:
436         amiga_ar1_check_overlay(machine);
437      break;
438
439      case ACTION_REPLAY_MKII:
440      case ACTION_REPLAY_MKIII:
441         amiga_ar23_check_overlay(machine);
442      break;
443   }
444}
445
446void amiga_cart_nmi( running_machine &machine )
447{
448   if ( amigacrt.cart_type < 0 )
449      return;
450
451   switch( amigacrt.cart_type )
452   {
453      case ACTION_REPLAY:
454         amiga_ar1_nmi(machine);
455      break;
456
457      case ACTION_REPLAY_MKII:
458      case ACTION_REPLAY_MKIII:
459         amiga_ar23_nmi(machine);
460      break;
461   }
462}
src/mame/machine/amigacrt.h
r11531r11532
1#ifndef AMIGACRT_H
2#define AMIGACRT_H
3
4void amiga_cart_init( running_machine &machine );
5void amiga_cart_check_overlay( running_machine &machine );
6void amiga_cart_nmi( running_machine &machine );
7
8#endif /* AMIGACRT_H */
src/mame/machine/nes_pcb.c
r11531r11532
1/*****************************************************************************************
2
3    NES Cart PCBs Emulation
4
5****************************************************************************************/
6
7typedef struct _nes_pcb  nes_pcb;
8struct _nes_pcb
9{
10   const char              *pcb_name;
11   int                     pcb_id;
12};
13
14// Here, we take the feature attribute from .xml (i.e. the PCB name) and we assign a unique ID to it
15static const nes_pcb pcb_list[] =
16{
17   /* Nintendo HROM, NROM, RROM, SROM & STROM */
18   { "HVC-HROM",         STD_NROM },
19   { "HVC-NROM",         STD_NROM },
20   { "HVC-NROM-128",     STD_NROM },
21   { "HVC-NROM-256",     STD_NROM },
22   { "HVC-RROM",         STD_NROM },
23   { "HVC-RROM-128",     STD_NROM },
24   { "HVC-RTROM",        STD_NROM },
25   { "HVC-SROM",         STD_NROM },
26   { "HVC-STROM",        STD_NROM },
27   { "NES-HROM",         STD_NROM },
28   { "NES-NROM",         STD_NROM },
29   { "NES-NROM-128",     STD_NROM },
30   { "NES-NROM-256",     STD_NROM },
31   { "NES-RROM",         STD_NROM },
32   { "NES-RROM-128",     STD_NROM },
33   { "NES-SROM",         STD_NROM },
34   { "NES-STROM",        STD_NROM },
35   /* "No mapper" boards by other manufacturer */
36   { "IREM-NROM-128",    STD_NROM },
37   { "IREM-NROM-256",    STD_NROM },
38   { "BANDAI-NROM-128",  STD_NROM },
39   { "BANDAI-NROM-256",  STD_NROM },
40   { "KONAMI-NROM-128",  STD_NROM },
41   { "SETA-NROM-128",    STD_NROM },
42   { "SUNSOFT-NROM-128", STD_NROM },
43   { "SUNSOFT-NROM-256", STD_NROM },
44   { "TAITO-NROM-128",   STD_NROM },
45   { "TAITO-NROM-256",   STD_NROM },
46   { "NAMCOT-3301",      STD_NROM },
47   { "NAMCOT-3302",      STD_NROM },
48   { "NAMCOT-3303",      STD_NROM },
49   { "NAMCOT-3304",      STD_NROM },
50   { "NAMCOT-3305",      STD_NROM },
51   { "NAMCOT-3311",      STD_NROM },
52   { "NAMCOT-3312",      STD_NROM },
53   { "NAMCOT-3411",      STD_NROM },
54   { "JALECO-JF-01",     STD_NROM },
55   { "JALECO-JF-02",     STD_NROM },
56   { "JALECO-JF-03",     STD_NROM },
57   { "JALECO-JF-04",     STD_NROM },
58   { "TENGEN-800003",    STD_NROM },
59   { "SACHEN-NROM",      STD_NROM },
60   /* Nintendo Family BASIC pcb (NROM + 2K or 4K WRAM) */
61   { "HVC-FAMILYBASIC",  HVC_FAMBASIC },
62   /* Game Genie */
63   { "CAMERICA-GAMEGENIE", GG_NROM },
64//
65   /* Nintendo UNROM/UOROM */
66   { "HVC-UNROM",        STD_UXROM },
67   { "HVC-UNEPROM",      STD_UXROM },
68   { "HVC-UOROM",        STD_UXROM },
69   { "NES-UNROM",        STD_UXROM },
70   { "NES-UNEPROM",      STD_UXROM },
71   { "NES-UOROM",        STD_UXROM },
72   { "HVC-UNROM+74HC08", UXROM_CC },
73   /* UxROM boards by other manufacturer */
74   { "IREM-UNROM",       STD_UXROM },
75   { "KONAMI-UNROM",     STD_UXROM },
76   { "TAITO-UNROM",      STD_UXROM },
77   { "JALECO-JF-15",     STD_UXROM },
78   { "JALECO-JF-18",     STD_UXROM },
79   { "JALECO-JF-39",     STD_UXROM },
80//
81   /* Nintendo CNROM */
82   { "HVC-CNROM",        STD_CNROM },
83   { "NES-CNROM",        STD_CNROM },
84   /* CxROM boards by other manufacturer */
85   { "BANDAI-CNROM",     STD_CNROM },
86   { "BANDAI-74*161/32", STD_CNROM },
87   { "KONAMI-CNROM",     STD_CNROM },
88   { "NAMCOT-CNROM+WRAM", STD_CNROM },
89   { "TAITO-CNROM",      STD_CNROM },
90   { "AVE-74*161",       STD_CNROM },
91   { "NTDEC-N715061",    STD_CNROM },
92   { "NTDEC-N715062",    STD_CNROM },
93   { "SACHEN-CNROM",     STD_CNROM },
94   /* Bandai Aerobics Studio (CNROM boards + special audio chip) */
95   { "BANDAI-PT-554",    BANDAI_PT554 },
96   /* FIXME: Is this the same as mapper 3? */
97   { "TENGEN-800008",    TENGEN_800008 },
98//
99   /* Nintendo AxROM */
100   { "HVC-AMROM",        STD_AXROM },
101   { "HVC-AN1ROM",       STD_AXROM },
102   { "HVC-ANROM",        STD_AXROM },
103   { "HVC-AOROM",        STD_AXROM },
104   { "NES-AMROM",        STD_AXROM },
105   { "NES-AN1ROM",       STD_AXROM },
106   { "NES-ANROM",        STD_AXROM },
107   { "NES-AOROM",        STD_AXROM },
108   /* AxROM boards by other manufacturer */
109   { "ACCLAIM-AOROM",    STD_AXROM },
110//
111   /* Nintendo PxROM */
112   { "HVC-PEEOROM",      STD_PXROM },
113   { "HVC-PNROM",        STD_PXROM },
114   { "NES-PEEOROM",      STD_PXROM },
115   { "NES-PNROM",        STD_PXROM },
116//
117   /* Nintendo FxROM */
118   { "HVC-FJROM",        STD_FXROM },
119   { "HVC-FKROM",        STD_FXROM },
120   { "NES-FJROM",        STD_FXROM },
121   { "NES-FKROM",        STD_FXROM },
122//
123   /* Nintendo BXROM */
124   { "HVC-BNROM",        STD_BXROM },
125   { "NES-BNROM",        STD_BXROM },
126   /* BxROM boards by other manufacturer */
127   { "IREM-BNROM",       STD_BXROM },
128//
129   /* Nintendo CPROM */
130   { "HVC-CPROM",        STD_CPROM },
131   { "NES-CPROM",        STD_CPROM },
132//
133   /* Nintendo GNROM & MHROM */
134   { "HVC-GNROM",        STD_GXROM },
135   { "NES-GNROM",        STD_GXROM },
136   { "HVC-MHROM",        STD_MXROM },
137   { "NES-MHROM",        STD_MXROM },
138   { "PAL-MH",           STD_MXROM },
139   /* GxROM boards by other manufacturer */
140   { "BANDAI-GNROM",     STD_GXROM },
141//
142   /* Nintendo NxROM */
143   { "HVC-NTBROM",       STD_NXROM },
144   { "NES-NTBROM",       STD_NXROM },
145   /* NxROM boards by other manufacturer (this board was mainly used by Sunsoft?) */
146   { "SUNSOFT-4",        STD_NXROM },
147   { "SUNSOFT-DCS",      SUNSOFT_DCS },
148   { "TENGEN-800042",    STD_NXROM },
149//
150   /* Nintendo JxROM */
151   { "HVC-JLROM",        STD_JXROM },
152   { "HVC-JSROM",        STD_JXROM },
153   { "NES-JLROM",        STD_JXROM },
154   { "NES-JSROM",        STD_JXROM },
155   { "NES-BTR",          STD_JXROM },
156   /* JxROM boards by other manufacturer (this board was mainly used by Sunsoft?) */
157   { "SUNSOFT-5A",       STD_JXROM },
158   { "SUNSOFT-5B",       STD_JXROM },
159   { "SUNSOFT-FME-7",    STD_JXROM },
160//
161   /* Nintendo UN1ROM */
162   { "HVC-UN1ROM",       STD_UN1ROM },
163   { "NES-UN1ROM",       STD_UN1ROM },
164//
165   /* Nintendo SxROM */
166   { "HVC-SAROM",        STD_SXROM },
167   { "HVC-SBROM",        STD_SXROM },
168   { "HVC-SC1ROM",       STD_SXROM },
169   { "HVC-SCROM",        STD_SXROM },
170   { "HVC-SEROM",        STD_SXROM },
171   { "HVC-SF1ROM",       STD_SXROM },
172   { "HVC-SFROM",        STD_SXROM },
173   { "HVC-SGROM",        STD_SXROM },
174   { "HVC-SH1ROM",       STD_SXROM },
175   { "HVC-SHROM",        STD_SXROM },
176   { "HVC-SIROM",        STD_SXROM },
177   { "HVC-SJROM",        STD_SXROM },
178   { "HVC-SKROM",        STD_SXROM },
179   { "HVC-SKEPROM",      STD_SXROM },
180   { "HVC-SL1ROM",       STD_SXROM },
181   { "HVC-SL2ROM",       STD_SXROM },
182   { "HVC-SL3ROM",       STD_SXROM },
183   { "HVC-SLROM",        STD_SXROM },
184   { "HVC-SLRROM",       STD_SXROM },
185   { "HVC-SMROM",        STD_SXROM },
186   { "HVC-SNROM",        STD_SXROM },
187   { "HVC-SUROM",        STD_SXROM },
188   { "HVC-SXROM",        STD_SXROM },
189   { "NES-SAROM",        STD_SXROM },
190   { "NES-SBROM",        STD_SXROM },
191   { "NES-SC1ROM",       STD_SXROM },
192   { "NES-SCROM",        STD_SXROM },
193   { "NES-SEROM",        STD_SXROM },
194   { "NES-SF1ROM",       STD_SXROM },
195   { "NES-SFROM",        STD_SXROM },
196   { "NES-SGROM",        STD_SXROM },
197   { "NES-SH1ROM",       STD_SXROM },
198   { "NES-SHROM",        STD_SXROM },
199   { "NES-SIROM",        STD_SXROM },
200   { "NES-SJROM",        STD_SXROM },
201   { "NES-SKROM",        STD_SXROM },
202   { "NES-SKEPROM",      STD_SXROM },
203   { "NES-SL1ROM",       STD_SXROM },
204   { "NES-SL2ROM",       STD_SXROM },
205   { "NES-SL3ROM",       STD_SXROM },
206   { "NES-SLROM",        STD_SXROM },
207   { "NES-SLRROM",       STD_SXROM },
208   { "NES-SMROM",        STD_SXROM },
209   { "NES-SNROM",        STD_SXROM },
210   { "NES-SUROM",        STD_SXROM },
211   { "NES-SXROM",        STD_SXROM },
212   { "NES-WH",           STD_SXROM },
213   { "NES-SOROM",        STD_SOROM },
214   { "HVC-SOROM",        STD_SOROM },
215   /* SxROM boards by other manufacturer */
216   { "KONAMI-SLROM",     STD_SXROM },
217   { "VIRGIN-SNROM",     STD_SXROM },
218//
219   /* Nintendo TxROM */
220   { "HVC-TBROM",        STD_TXROM },
221   { "HVC-TEROM",        STD_TXROM },
222   { "HVC-TFROM",        STD_TXROM },
223   { "HVC-TGROM",        STD_TXROM },
224   { "HVC-TKROM",        STD_TXROM },
225   { "HVC-TL1ROM",       STD_TXROM },
226   { "HVC-TL2ROM",       STD_TXROM },
227   { "HVC-TLROM",        STD_TXROM },
228   { "HVC-TNROM",        STD_TXROM },
229   { "HVC-TR1ROM",       STD_TVROM },
230   { "HVC-TSROM",        STD_TXROM },
231   { "HVC-TVROM",        STD_TVROM },
232   { "NES-B4",           STD_TXROM },
233   { "NES-TBROM",        STD_TXROM },
234   { "NES-TEROM",        STD_TXROM },
235   { "NES-TFROM",        STD_TXROM },
236   { "NES-TGROM",        STD_TXROM },
237   { "NES-TKROM",        STD_TXROM },
238   { "NES-TL1ROM",       STD_TXROM },
239   { "NES-TL2ROM",       STD_TXROM },
240   { "NES-TLROM",        STD_TXROM },
241   { "NES-TNROM",        STD_TXROM },
242   { "NES-TR1ROM",       STD_TVROM },
243   { "NES-TSROM",        STD_TXROM },
244   { "NES-TVROM",        STD_TVROM },
245   /* TxROM boards by other manufacturer */
246   { "ACCLAIM-MC-ACC",   STD_TXROM },
247   { "ACCLAIM-TLROM",    STD_TXROM },
248   { "KONAMI-TLROM",     STD_TXROM },
249//
250   /* Nintendo DxROM */
251   { "HVC-DE1ROM",       STD_DXROM },
252   { "HVC-DEROM",        STD_DXROM },
253   { "HVC-DRROM",        STD_DRROM },
254   { "NES-DE1ROM",       STD_DXROM },
255   { "NES-DEROM",        STD_DXROM },
256   { "NES-DRROM",        STD_DRROM },
257   /* DxROM boards by other manufacturer */
258   { "NAMCOT-3401",      STD_DXROM },
259   { "NAMCOT-3405",      STD_DXROM },
260   { "NAMCOT-3406",      STD_DXROM },
261   { "NAMCOT-3407",      STD_DXROM },
262   { "NAMCOT-3413",      STD_DXROM },
263   { "NAMCOT-3414",      STD_DXROM },
264   { "NAMCOT-3415",      STD_DXROM },
265   { "NAMCOT-3416",      STD_DXROM },
266   { "NAMCOT-3417",      STD_DXROM },
267   { "NAMCOT-3451",      STD_DXROM },
268   { "TENGEN-800002",    STD_DXROM },
269   { "TENGEN-800004",    STD_DRROM },
270   { "TENGEN-800030",    STD_DXROM },
271//
272   /* Nintendo HKROM */
273   { "HVC-HKROM",        STD_HKROM },
274   { "NES-HKROM",        STD_HKROM },
275//
276   /* Nintendo BNROM */
277   { "HVC-TQROM",        STD_TQROM },
278   { "NES-TQROM",        STD_TQROM },
279//
280   /* Nintendo TxSROM */
281   { "HVC-TKSROM",       STD_TXSROM },
282   { "HVC-TLSROM",       STD_TXSROM },
283   { "NES-TKSROM",       STD_TXSROM },
284   { "NES-TLSROM",       STD_TXSROM },
285//
286   /* Nintendo ExROM */
287   { "HVC-EKROM",        STD_EXROM },
288   { "HVC-ELROM",        STD_EXROM },
289   { "HVC-ETROM",        STD_EXROM },
290   { "HVC-EWROM",        STD_EXROM },
291   { "NES-EKROM",        STD_EXROM },
292   { "NES-ELROM",        STD_EXROM },
293   { "NES-ETROM",        STD_EXROM },
294   { "NES-EWROM",        STD_EXROM },
295//
296   /* Nintendo Custom boards */
297   { "PAL-ZZ",           PAL_ZZ },
298   { "NES-QJ",           NES_QJ },
299   { "NES-EVENT",        UNSUPPORTED_BOARD },
300//
301   /* Discrete board IC_74x139x74 */
302   { "JALECO-JF-05",     DIS_74X139X74 },
303   { "JALECO-JF-06",     DIS_74X139X74 },
304   { "JALECO-JF-07",     DIS_74X139X74 },
305   { "JALECO-JF-08",     DIS_74X139X74 },
306   { "JALECO-JF-09",     DIS_74X139X74 },
307   { "JALECO-JF-10",     DIS_74X139X74 },
308   { "KONAMI-74*139/74", DIS_74X139X74 },
309   { "TAITO-74*139/74",  DIS_74X139X74 },
310   /* Discrete board IC_74x377 */
311   { "AGCI-47516",       DIS_74X377 },
312   { "AVE-NINA-07",      DIS_74X377 },
313   { "COLORDREAMS-74*377", DIS_74X377 },
314   /* Discrete board IC_74x161x161x32 */
315   { "BANDAI-74*161/161/32", DIS_74X161X161X32 },
316   { "TAITO-74*161/161/32", DIS_74X161X161X32 },
317   /* Discrete board IC_74x161x138 */
318   { "BIT-CORP-74*161/138", DIS_74X161X138 },
319//
320   { "BANDAI-LZ93D50",   BANDAI_LZ93 },
321   { "BANDAI-LZ93D50+24C01", BANDAI_LZ93EX },
322   { "BANDAI-LZ93D50+24C02", BANDAI_LZ93EX },
323   { "BANDAI-FCG-1",     BANDAI_FCG },
324   { "BANDAI-FCG-2",     BANDAI_FCG },
325   { "BANDAI-JUMP2",     BANDAI_JUMP2 },
326   { "BANDAI-DATACH",    BANDAI_DATACH },
327   { "BANDAI-KARAOKE",   BANDAI_KARAOKE },
328   { "BANDAI-OEKAKIDS",  BANDAI_OEKAKIDS },
329   { "IREM-FCG-1",       BANDAI_FCG },
330//
331   { "IREM-G101",        IREM_G101 },
332   { "IREM-74*161/161/21/138", IREM_LROG017 },
333   { "IREM-H-3001",      IREM_H3001 },
334   { "IREM-H3001",       IREM_H3001 },
335   { "IREM-HOLYDIVER",   IREM_HOLYDIV },
336   { "IREM-TAM-S1",      IREM_TAM_S1 },
337//
338   { "JALECO-JF-23",     JALECO_SS88006 },
339   { "JALECO-JF-24",     JALECO_SS88006 },
340   { "JALECO-JF-25",     JALECO_SS88006 },
341   { "JALECO-JF-27",     JALECO_SS88006 },
342   { "JALECO-JF-29",     JALECO_SS88006 },
343   { "JALECO-JF-30",     JALECO_SS88006 },
344   { "JALECO-JF-31",     JALECO_SS88006 },
345   { "JALECO-JF-32",     JALECO_SS88006 },
346   { "JALECO-JF-33",     JALECO_SS88006 },
347   { "JALECO-JF-34",     JALECO_SS88006 },
348   { "JALECO-JF-35",     JALECO_SS88006 },
349   { "JALECO-JF-36",     JALECO_SS88006 },
350   { "JALECO-JF-37",     JALECO_SS88006 },
351   { "JALECO-JF-38",     JALECO_SS88006 },
352   { "JALECO-JF-40",     JALECO_SS88006 },
353   { "JALECO-JF-41",     JALECO_SS88006 },
354   { "JALECO-JF-11",     JALECO_JF11 },
355   { "JALECO-JF-12",     JALECO_JF11 },
356   { "JALECO-JF-14",     JALECO_JF11 },
357   { "JALECO-JF-13",     JALECO_JF13 },
358   { "JALECO-JF-16",     JALECO_JF16 },
359   { "JALECO-JF-17",     JALECO_JF17 },
360   { "JALECO-JF-26",     JALECO_JF17 },
361   { "JALECO-JF-28",     JALECO_JF17 },
362   { "JALECO-JF-19",     JALECO_JF19 },
363   { "JALECO-JF-21",     JALECO_JF19 },
364//
365   { "KONAMI-VRC-1",     KONAMI_VRC1 },
366   { "JALECO-JF-20",     KONAMI_VRC1 },
367   { "JALECO-JF-22",     KONAMI_VRC1 },
368   { "KONAMI-VRC-2",     KONAMI_VRC2 },
369   { "KONAMI-VRC-3",     KONAMI_VRC3 },
370   { "KONAMI-VRC-4",     KONAMI_VRC4 },
371   { "KONAMI-VRC-6",     KONAMI_VRC6 },
372   { "KONAMI-VRC-7",     KONAMI_VRC7 },
373   { "UNL-VRC7",         KONAMI_VRC7 },
374//
375   { "NAMCOT-163",       NAMCOT_163 },
376   { "NAMCOT-175",       NAMCOT_163 },
377   { "NAMCOT-340",       NAMCOT_163 },
378   { "NAMCOT-3425",      NAMCOT_3425 },
379   { "NAMCOT-3433",      NAMCOT_34X3 },
380   { "NAMCOT-3443",      NAMCOT_34X3 },
381   { "NAMCOT-3446",      NAMCOT_3446 },
382   { "NAMCOT-3453",      NAMCOT_3453 },
383//
384   { "SUNSOFT-1",        SUNSOFT_1 },
385   { "SUNSOFT-2",        SUNSOFT_2 },
386   { "SUNSOFT-3",        SUNSOFT_3 },
387   //
388   { "TAITO-TC0190FMC",  TAITO_TC0190FMC },
389   { "TAITO-TC0190FMC+PAL16R4", TAITO_TC0190FMCP },
390   { "TAITO-TC0350FMR",  TAITO_TC0190FMC },
391   { "TAITO-X1-005",     TAITO_X1_005 },   // two variants exist, depending on pin17 & pin31 connections
392   { "TAITO-X1-017",     TAITO_X1_017 },
393//
394   { "AGCI-50282",       AGCI_50282 },
395   { "AVE-NINA-01",      AVE_NINA01 },
396   { "AVE-NINA-02",      AVE_NINA01 },
397   { "AVE-NINA-03",      AVE_NINA06 },
398   { "AVE-NINA-06",      AVE_NINA06 },
399   { "AVE-MB-91",        AVE_NINA06 },
400   { "TXC-74*138/175",   AVE_NINA06 },
401   { "UNL-SA-016-1M",    AVE_NINA06 },
402   { "CAMERICA-ALGN",    CAMERICA_BF9093 },
403   { "CAMERICA-BF9093",  CAMERICA_BF9093 },
404   { "CAMERICA-BF9097",  CAMERICA_BF9097 },
405   { "CAMERICA-ALGQ",    CAMERICA_BF9096 },
406   { "CAMERICA-BF9096",  CAMERICA_BF9096 },
407   { "CAMERICA-GOLDENFIVE", CAMERICA_GOLDENFIVE },
408   { "CNE-DECATHLON",    CNE_DECATHLON },
409   { "CNE-PSB",          CNE_FSB },
410   { "CNE-SHLZ",         CNE_SHLZ },
411   { "JYCOMPANY-A",      UNSUPPORTED_BOARD },   // mapper 90
412   { "JYCOMPANY-B",      UNSUPPORTED_BOARD },   // mapper 209
413   { "JYCOMPANY-C",      UNSUPPORTED_BOARD },   // mapper 211
414   { "NTDEC-112",        NTDEC_ASDER },   // mapper 112 (better rename this board tag, to avoid confusion with TC-112!!
415   { "NTDEC-TC-112",     NTDEC_FIGHTINGHERO },
416   { "NTDEC-193",        NTDEC_FIGHTINGHERO },   // mapper 193
417   { "UNL-TEK90",        UNSUPPORTED_BOARD },   // related to JY Company? (i.e. mappers 90, 209, 211?)
418   { "UNL-SA-002",       SACHEN_TCU02 },
419   { "UNL-SA-009",       SACHEN_SA009 },
420   { "UNL-SA-0036",      SACHEN_SA0036 },
421   { "UNL-SA-0037",      SACHEN_SA0037 },
422   { "UNL-SA-72007",     SACHEN_SA72007 },
423   { "UNL-SA-72008",     SACHEN_SA72008 },
424   { "UNL-SA-NROM",      SACHEN_TCA01 },
425   { "UNL-SACHEN-TCA01", SACHEN_TCA01 },
426   { "SACHEN-8259A",     SACHEN_8259A },
427   { "UNL-SACHEN-8259A", SACHEN_8259A },
428   { "SACHEN-8259B",     SACHEN_8259B },
429   { "UNL-SACHEN-8259B", SACHEN_8259B },
430   { "SACHEN-8259C",     SACHEN_8259C },
431   { "UNL-SACHEN-8259C", SACHEN_8259C },
432   { "SACHEN-8259D",     SACHEN_8259D },
433   { "UNL-SACHEN-8259D", SACHEN_8259D },
434   { "UNL-SACHEN-74LS374N", SACHEN_74LS374 },
435   { "UNL-SACHEN-74LS374N-A", SACHEN_74LS374_A },   /* FIXME: Made up boards the different mirroring handling */
436   { "UNL-TC-U01-1.5M",  SACHEN_TCU01 },
437   { "TENGEN-800032",    TENGEN_800032 },
438   { "TENGEN-800037",    TENGEN_800037 },
439   { "WAIXING-A",        WAIXING_TYPE_A },
440   { "WAIXING-A-1",      WAIXING_TYPE_A_1 },   /* FIXME: Made up boards the different CHRRAM banks (see Ji Jia Zhan Shi) */
441   { "WAIXING-B",        WAIXING_TYPE_B },
442   { "WAIXING-C",        WAIXING_TYPE_C },
443   { "WAIXING-D",        WAIXING_TYPE_D },
444   { "WAIXING-E",        WAIXING_TYPE_E },
445   { "WAIXING-F",        WAIXING_TYPE_F },
446   { "WAIXING-G",        WAIXING_TYPE_G },
447   { "WAIXING-H",        WAIXING_TYPE_H },
448   { "WAIXING-I",        WAIXING_TYPE_I },
449   { "WAIXING-J",        WAIXING_TYPE_J },
450   { "WAIXING-SGZLZ",    WAIXING_SGZLZ },
451   { "WAIXING-SEC",      WAIXING_SECURITY },
452   { "WAIXING-SGZ",      WAIXING_SGZ },
453   { "WAIXING-PS2",      WAIXING_PS2 },
454   { "WAIXING-FFV",      WAIXING_FFV },
455   { "WAIXING-ZS",       WAIXING_ZS },
456   { "WAIXING-DQ8",      WAIXING_DQ8 },
457   { "WAIXING-SH2",      WAIXING_SH2 },
458//
459   { "TXC-TW",           TXC_TW },
460   { "TXC-STRIKEWOLF",   TXC_STRIKEWOLF },
461   { "TXC-MXMDHTWO",     TXC_MXMDHTWO },
462   { "UNL-22211",        TXC_22211A },
463   /* FIXME: Made up boards the different mirroring handling */
464   { "UNL-22211-A",      TXC_22211A },
465   { "UNL-22211-B",      TXC_22211B },
466   { "UNL-22211-C",      TXC_22211C },
467   { "UNL-REXSOFT-DBZ5", REXSOFT_DBZ5 },
468   { "UNL-SL1632",       REXSOFT_SL1632 },
469   { "SUBOR-BOARD-0",    SUBOR_TYPE0 },
470   { "SUBOR-BOARD-1",    SUBOR_TYPE1 },
471   { "SOMERITEAM-SL-12", SOMERI_SL12 }, // mapper 116
472   { "UNL-CONY",         CONY_BOARD },
473   { "UNL-GOUDER",       GOUDER_37017 },
474   { "UNL-NITRA",        NITRA_TDA },
475   { "UNL-HOSENKAN",     HOSENKAN_BOARD },
476   { "UNL-SUPERGAME",    SUPERGAME_LIONKING },
477   { "UNL-PANDAPRINCE",  KAY_PANDAPRINCE },
478   { "DREAMTECH01",      DREAMTECH_BOARD },
479   { "DAOU-306",         OPENCORP_DAOU306 },
480   { "HES",              HES_BOARD },
481   /* FIXME: Made up boards the different mirroring handling? */
482   { "HES-6IN1",         HES6IN1_BOARD },
483   { "SUPERGAME-BOOGERMAN", SUPERGAME_BOOGERMAN },
484   { "FUTUREMEDIA",      FUTUREMEDIA_BOARD },
485   { "FUKUTAKE",         FUKUTAKE_BOARD },
486   { "MAGICSERIES",      MAGICSERIES_MD },
487   { "KASING",           KASING_BOARD },
488   { "HENGGEDIANZI",     HENGEDIANZI_BOARD },
489   { "HENGGEDIANZI-XJZB", HENGEDIANZI_XJZB },
490   { "KAISER-KS7058",    KAISER_KS7058 },
491   { "KAISER-KS202",     KAISER_KS202 },// mapper 56
492   { "KAISER-KS7022",    KAISER_KS7022 },// mapper 175
493   { "UNL-KS7017",       KAISER_KS7017 },
494   { "UNL-KS7032",       KAISER_KS7032 }, //  mapper 142
495   { "RCM-GS2015",       RCM_GS2015 },
496   { "RCM-TETRISFAMILY", RCM_TETRISFAMILY },
497   { "UNL-NINJARYU",     UNSUPPORTED_BOARD },// mapper 111
498   { "UNL-NANJING",      NANJING_BOARD },// mapper 163
499   { "WHIRLWIND-2706",   WHIRLWIND_2706 },
500   { "UNL-H2288",        UNL_H2288 },
501   { "UNL-DANCE",        UNSUPPORTED_BOARD },
502   { "UNL-EDU2000",      UNL_EDU2K },
503   { "UNL-SHERO",        UNSUPPORTED_BOARD /*SACHEN_SHERO*/ },
504   { "UNL-TF1201",       UNSUPPORTED_BOARD /*UNL_TF1201*/ },
505   { "RUMBLESTATION",    RUMBLESTATION_BOARD },   // mapper 46
506   { "UNL-WORLDHERO",    UNSUPPORTED_BOARD },// mapper 27
507   { "UNL-A9746",        UNSUPPORTED_BOARD },// mapper 219
508   { "UNL-603-5052",     UNL_603_5052 },// mapper 238?
509   { "UNL-SHJY3",        UNL_SHJY3 },// mapper 253
510   { "UNL-RACERMATE",    UNL_RACERMATE },// mapper 168
511   { "UNL-N625092",      UNL_N625092 },
512   { "BMC-N625092",      UNL_N625092 },
513   { "UNL-SC-127",       UNL_SC127 },
514   { "UNL-SMB2J",        UNL_SMB2J },
515   { "BTL-SMB2C",        UNL_SMB2J },
516   { "UNL-MK2",          UNL_MK2 },
517   { "UNL-XZY",          UNL_XZY },
518   { "UNL-KOF96",        UNL_KOF96 },
519   { "UNL-SUPERFIGHTER3", UNL_SUPERFIGHTER3 },
520   { "UNL-8237",         UNL_8237 },
521   { "UNL-AX5705",       UNL_AX5705 },
522   { "UNL-CC-21",        UNL_CC21 },
523   { "UNL-KOF97",        UNL_KOF97 },
524   { "UNL-T-230",        UNL_T230 },
525   { "UNL-STUDYNGAME",   UNL_STUDYNGAME },   // mapper 39
526   { "UNL-OneBus",       UNSUPPORTED_BOARD },
527//
528   { "BTL-SMB2A",         BTL_SMB2A },
529   { "BTL-MARIOBABY",     BTL_MARIOBABY },
530   { "BTL-AISENSHINICOL", BTL_AISENSHINICOL },
531   { "BTL-SMB2B",         BTL_SMB2B },
532   { "BTL-SMB3",          BTL_SMB3 },
533   { "BTL-SUPERBROS11",   BTL_SUPERBROS11 },
534   { "BTL-DRAGONNINJA",   BTL_DRAGONNINJA },
535   { "BTL-MARIO1-MALEE2", UNSUPPORTED_BOARD },   // mapper 55?
536   { "BTL-2708",          UNSUPPORTED_BOARD },// mapper 103
537   { "BTL-TOBIDASEDAISAKUSEN", BTL_TOBIDASE },// mapper 120
538   { "BTL-SHUIGUANPIPE",  UNSUPPORTED_BOARD },// mapper 183
539   { "BTL-PIKACHUY2K",    BTL_PIKACHUY2K },// mapper 254
540//
541   { "BMC-190IN1",          BMC_190IN1 },
542   { "BMC-64IN1NOREPEAT",   BMC_64IN1NR },
543   { "BMC-A65AS",           BMC_A65AS },
544   { "BMC-GS-2004",         BMC_GS2004 },
545   { "BMC-GS-2013",         BMC_GS2013 },
546   { "BMC-NOVELDIAMOND9999999IN1", BMC_NOVELDIAMOND },
547   { "BMC-9999999IN1",      BMC_9999999IN1 }, // mapper 213... same as BMC-NOVELDIAMOND9999999IN1 ??
548   { "BMC-SUPER24IN1SC03",  BMC_S24IN1SC03 },
549   { "BMC-SUPERHIK8IN1",    BMC_HIK8IN1 },
550   { "BMC-T-262",           BMC_T262 },
551   { "BMC-WS",              BMC_WS },
552   { "MLT-ACTION52",        ACTENT_ACT52 },
553   { "MLT-CALTRON6IN1",     CALTRON_6IN1 },
554   { "MLT-MAXI15",          UNSUPPORTED_BOARD}, //  mapper 234
555   { "BMC-SUPERBIG-7IN1",   BMC_SUPERBIG_7IN1 },
556   { "BMC-SUPERHIK-4IN1",   BMC_SUPERHIK_4IN1 },
557   { "BMC-BALLGAMES-11IN1", BMC_BALLGAMES_11IN1 },
558   { "BMC-MARIOPARTY-7IN1", BMC_MARIOPARTY_7IN1 },
559   { "BMC-GKA",             BMC_GKA },
560   { "BMC-GKB",             BMC_GKB },
561   { "BMC-SUPER700IN1",     BMC_SUPER_700IN1 },
562   { "BMC-FAMILY-4646B",    BMC_FAMILY_4646B },
563   { "BMC-36IN1",           BMC_36IN1 },
564   { "BMC-21IN1",           BMC_21IN1 },
565   { "BMC-150IN1",          BMC_150IN1 },
566   { "BMC-35IN1",           BMC_35IN1 },
567   { "BMC-64IN1",           BMC_64IN1 },
568   { "BMC-15IN1",           BMC_15IN1 },
569   { "BMC-SUPERHIK-300IN1", BMC_SUPERHIK_300IN1 },
570   { "BMC-SUPERGUN-20IN1",  BMC_SUPERGUN_20IN1 },
571   { "BMC-GOLDENCARD-6IN1", BMC_GOLDENCARD_6IN1 },
572   { "BMC-72IN1",           BMC_72IN1 },
573   { "BMC-76IN1",           BMC_76IN1 },
574   { "BMC-SUPER42IN1",      BMC_SUPER_42IN1 },
575   { "BMC-1200IN1",         BMC_1200IN1 },
576   { "BMC-31IN1",           BMC_31IN1 },
577   { "BMC-22GAMES",         BMC_22GAMES },
578   { "BMC-20IN1",           BMC_20IN1 },
579   { "BMC-110IN1",          BMC_110IN1 },
580   { "BMC-810544-C-A1",     BMC_810544 },
581   { "BMC-411120-C",        UNSUPPORTED_BOARD },
582   { "BMC-830118C",         UNSUPPORTED_BOARD },
583   { "BMC-12-IN-1",         UNSUPPORTED_BOARD },
584   { "BMC-NTD-03",          BMC_NTD_03 },
585   { "BMC-8157",            UNSUPPORTED_BOARD /*BMC_8157*/ },
586   { "BMC-BS-5",            BMC_BENSHENG_BS5 },
587   { "BMC-FK23C",           BMC_FK23C },
588   { "BMC-FK23CA",          BMC_FK23CA },
589   { "BMC-GHOSTBUSTERS63IN1", BMC_G63IN1 },
590   { "BMC-SUPERVISION16IN1", UNSUPPORTED_BOARD },   // mapper 53
591   { "BMC-RESETBASED-4IN1", UNSUPPORTED_BOARD },// mapper 60 with 64k prg and 32k chr
592   { "BMC-VT5201",          BMC_VT5201 },// mapper 60 otherwise
593   { "BMC-D1038",           BMC_VT5201 }, // mapper 60?
594   { "BMC-42IN1RESETSWITCH", UNSUPPORTED_BOARD },   // mapper 60?
595   { "BMC-SUPER22GAMES",    UNSUPPORTED_BOARD },// mapper 233
596   { "BMC-GOLDENGAME-150IN1", UNSUPPORTED_BOARD },// mapper 235 with 2M PRG
597   { "BMC-GOLDENGAME-260IN1", UNSUPPORTED_BOARD },// mapper 235 with 4M PRG
598   { "BMC-70IN1",           UNSUPPORTED_BOARD },   // mapper 236?
599   { "BMC-70IN1B",          UNSUPPORTED_BOARD },   // mapper 236?
600   { "BMC-SUPERHIK-KOF",    UNSUPPORTED_BOARD },// mapper 251
601   { "BMC-POWERJOY",        BMC_PJOY84 },
602// are there dumps of games with these boards?
603   { "BMC-13IN1JY110",   UNSUPPORTED_BOARD }, //  [mentioned in FCEUMM source - we need more info]
604   { "BMC-GK-192",       UNSUPPORTED_BOARD }, //  [mentioned in FCEUMM source - we need more info]
605   { "KONAMI-QTAI",      UNSUPPORTED_BOARD }, //  [mentioned in FCEUMM source - we need more info]
606   { "UNL-3D-BLOCK",     UNSUPPORTED_BOARD }, //  [mentioned in FCEUMM source - we need more info]
607   { "UNL-C-N22M",       UNSUPPORTED_BOARD }, //  [mentioned in FCEUMM source - we need more info]
608   { "UNL-PEC-586",      UNSUPPORTED_BOARD }, //  [mentioned in FCEUMM source - we need more info]
609//
610   { "UNKNOWN",          UNKNOWN_BOARD }  //  a few pirate dumps uses the wrong mapper...
611};
612
613const nes_pcb *nes_pcb_lookup( const char *board )
614{
615   int i;
616   for (i = 0; i < ARRAY_LENGTH(pcb_list); i++)
617   {
618      if (!mame_stricmp(pcb_list[i].pcb_name, board))
619         return &pcb_list[i];
620   }
621   return NULL;
622}
623
624int nes_get_pcb_id( running_machine &machine, const char *feature )
625{
626   const nes_pcb *pcb = nes_pcb_lookup(feature);
627
628   if (pcb == NULL)
629      fatalerror("Unimplemented PCB type %s\n", feature);
630
631   return pcb->pcb_id;
632}
633
634/************************************************
635
636   PCB Emulation (to be moved to MAME later)
637
638   In the end, iNES, UNIF and xml should be
639   simply handled through a look-up table
640   which associates the mapper/board/feature
641   to the correct pcb_id and then the core
642   function pcb_handlers_setup should be called
643   to set-up the expected handlers and callbacks
644
645   Similarly, PC-10, VSNES and NES-based
646   multigame boards, should simply call
647   pcb_handlers_setup with the proper pcb_id
648   at the beginning, rather than use ad hoc
649   implementations.
650
651************************************************/
652
653// helper function for the few mappers reading from 0x8000-0xffff for protection
654INLINE UINT8 mmc_hi_access_rom( running_machine &machine, UINT32 offset )
655{
656   nes_state *state = machine.driver_data<nes_state>();
657
658   // usual ROM access
659   switch (offset & 0x6000)
660   {
661      case 0x0000:
662         return state->m_rom[0x10000 + state->m_prg_bank[0] * 0x2000 + (offset & 0x1fff)];
663      case 0x2000:
664         return state->m_rom[0x10000 + state->m_prg_bank[1] * 0x2000 + (offset & 0x1fff)];
665      case 0x4000:
666         return state->m_rom[0x10000 + state->m_prg_bank[2] * 0x2000 + (offset & 0x1fff)];
667      case 0x6000:
668         return state->m_rom[0x10000 + state->m_prg_bank[3] * 0x2000 + (offset & 0x1fff)];
669   }
670   return 0;
671}
672
673/*************************************************************
674
675 NROM board emulation
676
677 Games: Mario Bros., Super Mario Bros., Tennis and most of
678 the first generation games
679
680 iNES: mapper 0
681
682 In MESS: Supported, no need of specific handlers or IRQ
683
684 *************************************************************/
685
686/*************************************************************
687
688 UxROM board emulation
689
690 Games: Castlevania, Dragon Quest II, Duck Tales, MegaMan,
691 Metal Gear
692
693 writes to 0x8000-0xffff change PRG 16K lower banks
694
695 missing BC?
696
697 iNES: mapper 2
698
699 In MESS: Supported.
700
701 *************************************************************/
702
703static WRITE8_HANDLER( uxrom_w )
704{
705   LOG_MMC(("uxrom_w, offset: %04x, data: %02x\n", offset, data));
706
707   prg16_89ab(space->machine(), data);
708}
709
710/*************************************************************
711
712 Nihon Bussan UNROM M5
713
714 Games: Crazy Climber Jpn
715
716 Very simple mapper: prg16_89ab is always set to bank 0,
717 while prg16_cdef is set by writes to 0x8000-0xffff. The game
718 uses a custom controller.
719
720 iNES: mapper 180
721
722 In MESS: Supported.
723
724 *************************************************************/
725
726static WRITE8_HANDLER( uxrom_cc_w )
727{
728   LOG_MMC(("uxrom_cc_w, offset: %04x, data: %02x\n", offset, data));
729
730   prg16_cdef(space->machine(), data);
731}
732
733/*************************************************************
734
735 UN1ROM board emulation
736
737 Games: Senjou no Okami
738
739 writes to 0x8000-0xffff change PRG 16K lower banks
740
741 missing BC?
742
743 iNES: mapper 94
744
745 In MESS: Supported.
746
747 *************************************************************/
748
749static WRITE8_HANDLER( un1rom_w )
750{
751   LOG_MMC(("un1rom_w, offset: %04x, data: %02x\n", offset, data));
752
753   prg16_89ab(space->machine(), data >> 2);
754}
755
756/*************************************************************
757
758 CNROM board emulation
759
760 Games: B-Wings, Mighty Bomb Jack, Seicross, Spy vs. Spy,
761 Adventure Island, Flipull, Friday 13th, GeGeGe no
762 Kitarou, Ghostbusters, Gradius, Hokuto no Ken, Milon's
763 Secret Castle
764
765 writes to 0x8000-0xffff change CHR 8K banks
766
767 missing BC?
768
769 iNES: mappers 3 & 185 (the latter for games using Pins as
770 protection)
771
772 Notice that BANDAI_PT554 board (Aerobics Studio) uses very
773 similar hardware but with an additional sound chip which
774 gets writes to 0x6000 (currently unemulated in MESS)
775
776 In MESS: Supported
777
778 *************************************************************/
779
780static WRITE8_HANDLER( cnrom_w )
781{
782   nes_state *state = space->machine().driver_data<nes_state>();
783   LOG_MMC(("cnrom_w, offset: %04x, data: %02x\n", offset, data));
784
785   if (state->m_ce_mask)
786   {
787      chr8(space->machine(), data & ~state->m_ce_mask, CHRROM);
788
789      if ((data & state->m_ce_mask) == state->m_ce_state)
790         state->m_chr_open_bus = 0;
791      else
792         state->m_chr_open_bus = 1;
793   }
794   else
795      chr8(space->machine(), data, CHRROM);
796}
797
798/*************************************************************
799
800 Bandai PT-554 board emulation
801
802 This is used by Aerobics Studio. It is basically a CNROM board
803 with an additional sound chip which is not currently emulated by
804 MESS
805
806 iNES: mapper 3?
807
808 *************************************************************/
809
810static WRITE8_HANDLER( bandai_pt554_m_w )
811{
812   LOG_MMC(("Bandai PT-554 Sound write, data: %02x\n", data));
813
814   // according to NEStopia, this is the effect
815   if (!BIT(data, 6))
816   {
817      // send command (data & 0x07) to sound chip
818   }
819}
820
821/*************************************************************
822
823 CPROM board emulation
824
825 Games: Videomation
826
827 writes to 0x8000-0xffff change CHR 4K lower banks
828
829 iNES: mapper 13
830
831 In MESS: Supported
832
833 *************************************************************/
834
835static WRITE8_HANDLER( cprom_w )
836{
837   LOG_MMC(("cprom_w, offset: %04x, data: %02x\n", offset, data));
838   chr4_4(space->machine(), data, CHRRAM);
839}
840
841/*************************************************************
842
843 AxROM board emulation
844
845 Games: Arch Rivals, Battletoads, Cabal, Commando, Solstice
846
847 writes to 0x8000-0xffff change PRG banks + sets mirroring
848
849 missing BC for AMROM?
850
851 iNES: mapper 7
852
853 In MESS: Supported
854
855 *************************************************************/
856
857static WRITE8_HANDLER( axrom_w )
858{
859   LOG_MMC(("axrom_w, offset: %04x, data: %02x\n", offset, data));
860
861   set_nt_mirroring(space->machine(), BIT(data, 4) ? PPU_MIRROR_HIGH : PPU_MIRROR_LOW);
862   prg32(space->machine(), data);
863}
864
865/*************************************************************
866
867 BxROM board emulation
868
869 writes to 0x8000-0xffff change PRG banks
870
871 missing BC?
872
873 iNES: mapper 34
874
875 *************************************************************/
876
877static WRITE8_HANDLER( bxrom_w )
878{
879   /* This portion of the mapper is nearly identical to Mapper 7, except no one-screen mirroring */
880   /* Deadly Towers is really a BxROM game - the demo screens look wrong using mapper 7. */
881   LOG_MMC(("bxrom_w, offset: %04x, data: %02x\n", offset, data));
882
883   prg32(space->machine(), data);
884}
885
886/*************************************************************
887
888 GxROM/MxROM board emulation
889
890 writes to 0x8000-0xffff change PRG and CHR banks
891
892 missing BC?
893
894 iNES: mapper 66
895
896 *************************************************************/
897
898static WRITE8_HANDLER( gxrom_w )
899{
900   LOG_MMC(("gxrom_w, offset %04x, data: %02x\n", offset, data));
901
902   prg32(space->machine(), (data & 0xf0) >> 4);
903   chr8(space->machine(), data & 0x0f, CHRROM);
904}
905
906/*************************************************************
907
908 SxROM (MMC1 based) board emulation
909
910 iNES: mapper 1 (and 155 for the MMC1A variant which does not
911 have WRAM disable bit)
912
913 *************************************************************/
914
915static TIMER_CALLBACK( mmc1_resync_callback )
916{
917   nes_state *state = machine.driver_data<nes_state>();
918   state->m_mmc1_reg_write_enable = 1;
919}
920
921
922static void mmc1_set_wram( address_space *space, int board )
923{
924   running_machine &machine = space->machine();
925   nes_state *state = machine.driver_data<nes_state>();
926   UINT8 bank = BIT(state->m_mmc_reg[0], 4) ? BIT(state->m_mmc_reg[1], 4) : BIT(state->m_mmc_reg[1], 3);
927
928   switch (board)
929   {
930      case STD_SXROM:      // here also reads are disabled!
931         if (!BIT(state->m_mmc_reg[3], 4))
932            space->install_readwrite_bank(0x6000, 0x7fff, "bank5");
933         else
934         {
935            space->unmap_readwrite(0x6000, 0x7fff);
936            break;
937         }
938      case STD_SXROM_A:   // ignore WRAM enable bit
939         if (state->m_battery_size > 0x2000)
940            wram_bank(machine, ((state->m_mmc_reg[1] & 3) >> 2), NES_BATTERY);
941         else if (state->m_battery_size)
942            wram_bank(machine, 0, NES_BATTERY);
943         break;
944      case STD_SOROM:      // there are 2 WRAM banks only and battery is bank 2 for the cart (hence, we invert bank, because we have battery first)
945         if (!BIT(state->m_mmc_reg[3], 4))
946            space->install_readwrite_bank(0x6000, 0x7fff, "bank5");
947         else
948         {
949            space->unmap_readwrite(0x6000, 0x7fff);
950            break;
951         }
952      case STD_SOROM_A:   // ignore WRAM enable bit
953         wram_bank(machine, 0, bank ? NES_BATTERY : NES_WRAM);
954         break;
955   }
956}
957
958static void mmc1_set_prg( running_machine &machine )
959{
960   nes_state *state = machine.driver_data<nes_state>();
961   UINT8 prg_mode, prg_offset;
962
963   prg_mode = state->m_mmc_reg[0] & 0x0c;
964   /* prg_mode&0x8 determines bank size: 32k (if 0) or 16k (if 1)? when in 16k mode,
965     prg_mode&0x4 determines which half of the PRG space we can swap: if it is 4,
966     mmc_reg[3] sets banks at 0x8000; if it is 0, mmc_reg[3] sets banks at 0xc000. */
967
968   prg_offset = state->m_mmc_reg[1] & 0x10;
969   /* In principle, mmc_reg[2]&0x10 might affect "extended" banks as well, when chr_mode=1.
970     However, quoting Disch's docs: When in 4k CHR mode, 0x10 in both $A000 and $C000 *must* be
971     set to the same value, or else pages will constantly be swapped as graphics render!
972     Hence, we use only mmc_reg[1]&0x10 for prg_offset */
973
974   switch (prg_mode)
975   {
976      case 0x00:
977      case 0x04:
978//          printf("PRG 32 bank %d \n", (prg_offset + state->m_mmc_reg[3]) >> 1);
979         prg32(machine, (prg_offset + state->m_mmc_reg[3]) >> 1);
980         break;
981      case 0x08:
982//          printf("PRG 16 bank %d (high) \n", prg_offset + state->m_mmc_reg[3]);
983         prg16_89ab(machine, prg_offset + 0);
984         prg16_cdef(machine, prg_offset + state->m_mmc_reg[3]);
985         break;
986      case 0x0c:
987//          printf("PRG 16 bank %d (low) \n", prg_offset + state->m_mmc_reg[3]);
988         prg16_89ab(machine, prg_offset + state->m_mmc_reg[3]);
989         prg16_cdef(machine, prg_offset + 0x0f);
990         break;
991   }
992}
993
994static void mmc1_set_prg_wram( address_space *space, int board )
995{
996   mmc1_set_prg(space->machine());
997   mmc1_set_wram(space, board);
998}
999
1000static void mmc1_set_chr( running_machine &machine )
1001{
1002   nes_state *state = machine.driver_data<nes_state>();
1003   UINT8 chr_mode = BIT(state->m_mmc_reg[0], 4);
1004
1005   if (chr_mode)
1006   {
1007      chr4_0(machine, state->m_mmc_reg[1] & 0x1f, state->m_mmc_chr_source);
1008      chr4_4(machine, state->m_mmc_reg[2] & 0x1f, state->m_mmc_chr_source);
1009   }
1010   else
1011      chr8(machine, (state->m_mmc_reg[1] & 0x1f) >> 1, state->m_mmc_chr_source);
1012}
1013
1014static void common_sxrom_write_handler( address_space *space, offs_t offset, UINT8 data, int board )
1015{
1016   running_machine &machine = space->machine();
1017   nes_state *state = machine.driver_data<nes_state>();
1018   /* Note that there is only one latch and shift counter, shared amongst the 4 regs */
1019   /* Space Shuttle will not work if they have independent variables. */
1020
1021   /* here we would need to add an if(cpu_cycles_passed>1) test, and
1022     if requirement is not met simply return without writing anything.
1023     Some games (AD&D Hillsfar, Bill & Ted Excellent Adventure, Cosmic
1024     Wars, Rocket Ranger, Sesame Street 123 and Snow Brothers) rely on
1025     this behavior!! */
1026   if (state->m_mmc1_reg_write_enable == 0)
1027   {
1028      return;
1029   }
1030   else
1031   {
1032      state->m_mmc1_reg_write_enable = 0;
1033      space->machine().scheduler().synchronize(FUNC(mmc1_resync_callback));
1034   }
1035
1036   if (data & 0x80)
1037   {
1038      state->m_mmc1_count = 0;
1039      state->m_mmc1_latch = 0;
1040
1041      /* Set reg at 0x8000 to size 16k and lower half swap - needed for Robocop 3, Dynowars */
1042      state->m_mmc_reg[0] |= 0x0c;
1043      mmc1_set_prg_wram(space, board);
1044      return;
1045   }
1046
1047   if (state->m_mmc1_count < 5)
1048   {
1049      if (state->m_mmc1_count == 0) state->m_mmc1_latch = 0;
1050      state->m_mmc1_latch >>= 1;
1051      state->m_mmc1_latch |= (data & 0x01) ? 0x10 : 0x00;
1052      state->m_mmc1_count++;
1053   }
1054
1055   if (state->m_mmc1_count == 5)
1056   {
1057      switch (offset & 0x6000)   /* Which reg shall we write to? */
1058      {
1059         case 0x0000:
1060            state->m_mmc_reg[0] = state->m_mmc1_latch;
1061
1062            switch (state->m_mmc_reg[0] & 0x03)
1063            {
1064            case 0: set_nt_mirroring(machine, PPU_MIRROR_LOW); break;
1065            case 1: set_nt_mirroring(machine, PPU_MIRROR_HIGH); break;
1066            case 2: set_nt_mirroring(machine, PPU_MIRROR_VERT); break;
1067            case 3: set_nt_mirroring(machine, PPU_MIRROR_HORZ); break;
1068            }
1069            mmc1_set_chr(machine);
1070            mmc1_set_prg_wram(space, board);
1071            break;
1072         case 0x2000:
1073            state->m_mmc_reg[1] = state->m_mmc1_latch;
1074            mmc1_set_chr(machine);
1075            mmc1_set_prg_wram(space, board);
1076            break;
1077         case 0x4000:
1078            state->m_mmc_reg[2] = state->m_mmc1_latch;
1079            mmc1_set_chr(machine);
1080            break;
1081         case 0x6000:
1082            state->m_mmc_reg[3] = state->m_mmc1_latch;
1083            mmc1_set_prg_wram(space, board);
1084            break;
1085      }
1086      state->m_mmc1_count = 0;
1087   }
1088}
1089
1090static WRITE8_HANDLER( sxrom_w )
1091{
1092   nes_state *state = space->machine().driver_data<nes_state>();
1093
1094   LOG_MMC(("sxrom_w, offset: %04x, data: %02x\n", offset, data));
1095   common_sxrom_write_handler(space, offset, data, state->m_pcb_id);
1096}
1097
1098/*************************************************************
1099
1100 PxROM (MMC2 based) board emulation
1101
1102 Games: Punch Out!!, Mike Tyson's Punch Out!!
1103
1104 iNES: mapper 9
1105
1106 In MESS: Supported
1107
1108 *************************************************************/
1109
1110static void mmc2_latch( device_t *device, offs_t offset )
1111{
1112   nes_state *state = device->machine().driver_data<nes_state>();
1113   if ((offset & 0x3ff0) == 0x0fd0)
1114   {
1115      LOG_MMC(("mmc2 vrom latch switch (bank 0 low): %02x\n", state->m_mmc_reg[0]));
1116      state->m_mmc_latch1 = 0xfd;
1117      chr4_0(device->machine(), state->m_mmc_reg[0], CHRROM);
1118   }
1119   else if ((offset & 0x3ff0) == 0x0fe0)
1120   {
1121      LOG_MMC(("mmc2 vrom latch switch (bank 0 high): %02x\n", state->m_mmc_reg[1]));
1122      state->m_mmc_latch1 = 0xfe;
1123      chr4_0(device->machine(), state->m_mmc_reg[1], CHRROM);
1124   }
1125   else if ((offset & 0x3ff0) == 0x1fd0)
1126   {
1127      LOG_MMC(("mmc2 vrom latch switch (bank 1 low): %02x\n", state->m_mmc_reg[2]));
1128      state->m_mmc_latch2 = 0xfd;
1129      chr4_4(device->machine(), state->m_mmc_reg[2], CHRROM);
1130   }
1131   else if ((offset & 0x3ff0) == 0x1fe0)
1132   {
1133      LOG_MMC(("mmc2 vrom latch switch (bank 0 high): %02x\n", state->m_mmc_reg[3]));
1134      state->m_mmc_latch2 = 0xfe;
1135      chr4_4(device->machine(), state->m_mmc_reg[3], CHRROM);
1136   }
1137}
1138
1139static WRITE8_HANDLER( pxrom_w )
1140{
1141   nes_state *state = space->machine().driver_data<nes_state>();
1142   LOG_MMC(("pxrom_w, offset: %04x, data: %02x\n", offset, data));
1143   switch (offset & 0x7000)
1144   {
1145      case 0x2000:
1146         prg8_89(space->machine(), data);
1147         break;
1148      case 0x3000:
1149         state->m_mmc_reg[0] = data;
1150         if (state->m_mmc_latch1 == 0xfd)
1151            chr4_0(space->machine(), state->m_mmc_reg[0], CHRROM);
1152         break;
1153      case 0x4000:
1154         state->m_mmc_reg[1] = data;
1155         if (state->m_mmc_latch1 == 0xfe)
1156            chr4_0(space->machine(), state->m_mmc_reg[1], CHRROM);
1157         break;
1158      case 0x5000:
1159         state->m_mmc_reg[2] = data;
1160         if (state->m_mmc_latch2 == 0xfd)
1161            chr4_4(space->machine(), state->m_mmc_reg[2], CHRROM);
1162         break;
1163      case 0x6000:
1164         state->m_mmc_reg[3] = data;
1165         if (state->m_mmc_latch2 == 0xfe)
1166            chr4_4(space->machine(), state->m_mmc_reg[3], CHRROM);
1167         break;
1168      case 0x7000:
1169         set_nt_mirroring(space->machine(), BIT(data, 0) ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT);
1170         break;
1171      default:
1172         LOG_MMC(("MMC2 uncaught w: %04x:%02x\n", offset, data));
1173         break;
1174   }
1175}
1176
1177/*************************************************************
1178
1179 FxROM (MMC4 based) board emulation
1180
1181 Games: Famicom Wars, Fire Emblem, Fire Emblem Gaiden
1182
1183 iNES: mapper 10
1184
1185 In MESS: Supported
1186
1187*************************************************************/
1188
1189static WRITE8_HANDLER( fxrom_w )
1190{
1191   LOG_MMC(("fxrom_w, offset: %04x, data: %02x\n", offset, data));
1192   switch (offset & 0x7000)
1193   {
1194      case 0x2000:
1195         prg16_89ab(space->machine(), data);
1196         break;
1197      default:
1198         pxrom_w(space, offset, data);
1199         break;
1200   }
1201}
1202
1203/*************************************************************
1204
1205 TxROM (MMC3 based) board emulation
1206
1207 iNES: mapper 4
1208
1209 *************************************************************/
1210
1211static void mmc3_set_wram( address_space *space )
1212{
1213   running_machine &machine = space->machine();
1214   nes_state *state = machine.driver_data<nes_state>();
1215
1216   // skip this function if we are emulating a MMC3 clone with mid writes
1217   if (state->m_mmc_write_mid != NULL)
1218      return;
1219
1220   if (BIT(state->m_mmc3_wram_protect, 7))
1221      space->install_readwrite_bank(0x6000, 0x7fff, "bank5");
1222   else
1223   {
1224      space->unmap_readwrite(0x6000, 0x7fff);
1225      return;
1226   }
1227
1228   if (!BIT(state->m_mmc3_wram_protect, 6))
1229      space->install_write_bank(0x6000, 0x7fff, "bank5");
1230   else
1231   {
1232      space->unmap_write(0x6000, 0x7fff);
1233      return;
1234   }
1235}
1236
1237static void mmc3_set_prg( running_machine &machine, int prg_base, int prg_mask )
1238{
1239   nes_state *state = machine.driver_data<nes_state>();
1240   UINT8 prg_flip = (state->m_mmc3_latch & 0x40) ? 2 : 0;
1241
1242   state->m_mmc3_prg_cb(machine, 0, prg_base | (state->m_mmc_prg_bank[0 ^ prg_flip] & prg_mask));
1243   state->m_mmc3_prg_cb(machine, 1, prg_base | (state->m_mmc_prg_bank[1] & prg_mask));
1244   state->m_mmc3_prg_cb(machine, 2, prg_base | (state->m_mmc_prg_bank[2 ^ prg_flip] & prg_mask));
1245   state->m_mmc3_prg_cb(machine, 3, prg_base | (state->m_mmc_prg_bank[3] & prg_mask));
1246}
1247
1248static void mmc3_set_chr( running_machine &machine, UINT8 chr, int chr_base, int chr_mask )
1249{
1250   nes_state *state = machine.driver_data<nes_state>();
1251   UINT8 chr_page = (state->m_mmc3_latch & 0x80) >> 5;
1252
1253   state->m_mmc3_chr_cb(machine, chr_page ^ 0, chr_base | ((state->m_mmc_vrom_bank[0] & ~0x01) & chr_mask), chr);
1254   state->m_mmc3_chr_cb(machine, chr_page ^ 1, chr_base | ((state->m_mmc_vrom_bank[0] |  0x01) & chr_mask), chr);
1255   state->m_mmc3_chr_cb(machine, chr_page ^ 2, chr_base | ((state->m_mmc_vrom_bank[1] & ~0x01) & chr_mask), chr);
1256   state->m_mmc3_chr_cb(machine, chr_page ^ 3, chr_base | ((state->m_mmc_vrom_bank[1] |  0x01) & chr_mask), chr);
1257   state->m_mmc3_chr_cb(machine, chr_page ^ 4, chr_base | (state->m_mmc_vrom_bank[2] & chr_mask), chr);
1258   state->m_mmc3_chr_cb(machine, chr_page ^ 5, chr_base | (state->m_mmc_vrom_bank[3] & chr_mask), chr);
1259   state->m_mmc3_chr_cb(machine, chr_page ^ 6, chr_base | (state->m_mmc_vrom_bank[4] & chr_mask), chr);
1260   state->m_mmc3_chr_cb(machine, chr_page ^ 7, chr_base | (state->m_mmc_vrom_bank[5] & chr_mask), chr);
1261}
1262
1263/* Here, IRQ counter decrements every scanline. */
1264static void mmc3_irq( device_t *device, int scanline, int vblank, int blanked )
1265{
1266   nes_state *state = device->machine().driver_data<nes_state>();
1267
1268   if (scanline < PPU_BOTTOM_VISIBLE_SCANLINE)
1269   {
1270      int priorCount = state->m_IRQ_count;
1271      if ((state->m_IRQ_count == 0) || state->m_IRQ_clear)
1272         state->m_IRQ_count = state->m_IRQ_count_latch;
1273      else
1274         state->m_IRQ_count--;
1275
1276      if (state->m_IRQ_enable && !blanked && (state->m_IRQ_count == 0) && (priorCount || state->m_IRQ_clear /*|| !state->m_mmc3_alt_irq*/)) // according to blargg the latter should be present as well, but it breaks Rampart and Joe & Mac US: they probably use the alt irq!
1277      {
1278         LOG_MMC(("irq fired, scanline: %d (MAME %d, beam pos: %d)\n", scanline,
1279                device->machine().primary_screen->vpos(), device->machine().primary_screen->hpos()));
1280         device_set_input_line(state->m_maincpu, M6502_IRQ_LINE, HOLD_LINE);
1281      }
1282   }
1283   state->m_IRQ_clear = 0;
1284}
1285
1286static WRITE8_HANDLER( txrom_w )
1287{
1288   nes_state *state = space->machine().driver_data<nes_state>();
1289   UINT8 mmc_helper, cmd;
1290
1291   LOG_MMC(("txrom_w, offset: %04x, data: %02x\n", offset, data));
1292
1293   switch (offset & 0x6001)
1294   {
1295      case 0x0000:
1296         mmc_helper = state->m_mmc3_latch ^ data;
1297         state->m_mmc3_latch = data;
1298
1299         /* Has PRG Mode changed? */
1300         if (mmc_helper & 0x40)
1301            mmc3_set_prg(space->machine(), state->m_mmc_prg_base, state->m_mmc_prg_mask);
1302
1303         /* Has CHR Mode changed? */
1304         if (mmc_helper & 0x80)
1305            mmc3_set_chr(space->machine(), state->m_mmc_chr_source, state->m_mmc_chr_base, state->m_mmc_chr_mask);
1306         break;
1307
1308      case 0x0001:
1309         cmd = state->m_mmc3_latch & 0x07;
1310         switch (cmd)
1311         {
1312         case 0: case 1:   // these do not need to be separated: we take care of them in set_chr!
1313         case 2: case 3: case 4: case 5:
1314            state->m_mmc_vrom_bank[cmd] = data;
1315            mmc3_set_chr(space->machine(), state->m_mmc_chr_source, state->m_mmc_chr_base, state->m_mmc_chr_mask);
1316            break;
1317         case 6:
1318         case 7:
1319            state->m_mmc_prg_bank[cmd - 6] = data;
1320            mmc3_set_prg(space->machine(), state->m_mmc_prg_base, state->m_mmc_prg_mask);
1321            break;
1322         }
1323         break;
1324
1325      case 0x2000:
1326         set_nt_mirroring(space->machine(), BIT(data, 0) ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT);
1327         break;
1328
1329      case 0x2001:
1330         state->m_mmc3_wram_protect = data;
1331         mmc3_set_wram(space);
1332         break;
1333
1334      case 0x4000:
1335         state->m_IRQ_count_latch = data;
1336         break;
1337
1338      case 0x4001:
1339         state->m_IRQ_count = 0;
1340         break;
1341
1342      case 0x6000:
1343         state->m_IRQ_enable = 0;
1344         break;
1345
1346      case 0x6001:
1347         state->m_IRQ_enable = 1;
1348         break;
1349
1350      default:
1351         logerror("txrom_w uncaught: %04x value: %02x\n", offset + 0x8000, data);
1352         break;
1353   }
1354}
1355
1356/*************************************************************
1357
1358 HKROM (MMC6 based) board emulation
1359
1360 iNES: mapper 4
1361
1362 *************************************************************/
1363
1364static WRITE8_HANDLER( hkrom_m_w )
1365{
1366   nes_state *state = space->machine().driver_data<nes_state>();
1367   UINT8 write_hi, write_lo;
1368   LOG_MMC(("hkrom_m_w, offset: %04x, data: %02x\n", offset, data));
1369
1370   if (offset < 0x1000)
1371      return;
1372
1373   // banks can be written only if both read & write is enabled!
1374   write_hi = ((state->m_mmc6_reg & 0xc0) == 0xc0);
1375   write_lo = ((state->m_mmc6_reg & 0x30) == 0x30);
1376
1377   if (BIT(offset, 9) && write_hi)   // access to upper 1k
1378      state->m_mapper_bram[offset & (state->m_mapper_bram_size - 1)] = data;
1379
1380   if (!BIT(offset, 9) && write_lo)   // access to lower 1k
1381      state->m_mapper_bram[offset & (state->m_mapper_bram_size - 1)] = data;
1382}
1383
1384static READ8_HANDLER( hkrom_m_r )
1385{
1386   nes_state *state = space->machine().driver_data<nes_state>();
1387   LOG_MMC(("hkrom_m_r, offset: %04x\n", offset));
1388
1389   if (offset < 0x1000)
1390      return 0xff;   // here it should be open bus
1391
1392   if (!(state->m_mmc6_reg & 0xa0))
1393      return 0xff;   // here it should be open bus
1394
1395   if (BIT(offset, 9) && BIT(state->m_mmc6_reg, 7))   // access to upper 1k when upper read is enabled
1396      return state->m_mapper_bram[offset & (state->m_mapper_bram_size - 1)];
1397
1398   if (!BIT(offset, 9) && BIT(state->m_mmc6_reg, 5))   // access to lower 1k when lower read is enabled
1399      return state->m_mapper_bram[offset & (state->m_mapper_bram_size - 1)];
1400
1401   // If only one bank is enabled for reading, the other reads back as zero
1402   return 0x00;
1403}
1404
1405static WRITE8_HANDLER( hkrom_w )
1406{
1407   nes_state *state = space->machine().driver_data<nes_state>();
1408   UINT8 mmc6_helper;
1409   LOG_MMC(("hkrom_w, offset: %04x, data: %02x\n", offset, data));
1410
1411   switch (offset & 0x6001)
1412   {
1413      case 0x0000:
1414         mmc6_helper = state->m_mmc3_latch ^ data;
1415         state->m_mmc3_latch = data;
1416
1417         if (!state->m_mmc_latch2 && BIT(data, 5))   // if WRAM is disabled and has to be enabled, write
1418            state->m_mmc_latch2 = BIT(data, 5);   // (once WRAM has been enabled, it cannot be disabled without resetting the game)
1419
1420         /* Has PRG Mode changed? */
1421         if (BIT(mmc6_helper, 6))
1422            mmc3_set_prg(space->machine(), state->m_mmc_prg_base, state->m_mmc_prg_mask);
1423
1424         /* Has CHR Mode changed? */
1425         if (BIT(mmc6_helper, 7))
1426            mmc3_set_chr(space->machine(), state->m_mmc_chr_source, state->m_mmc_chr_base, state->m_mmc_chr_mask);
1427         break;
1428
1429      case 0x2001:
1430         if (state->m_mmc_latch2)
1431            state->m_mmc6_reg = data;
1432         break;
1433
1434      case 0x4001:
1435         state->m_IRQ_count = 0;
1436         state->m_IRQ_clear = 1;
1437         break;
1438
1439      default:
1440         txrom_w(space, offset, data);
1441         break;
1442   }
1443}
1444
1445/*************************************************************
1446
1447 TxSROM (MMC3 based) board emulation
1448
1449 Games: Armadillo, Play Action Football, Pro Hockey, RPG
1450 Jinsei Game, Y's 3
1451
1452 iNES: mapper 118
1453
1454 In MESS: Supported. It also uses mmc3_irq.
1455
1456 *************************************************************/
1457
1458static void txsrom_set_mirror( running_machine &machine )
1459{
1460   nes_state *state = machine.driver_data<nes_state>();
1461   if (state->m_mmc3_latch & 0x80)
1462   {
1463      set_nt_page(machine, 0, CIRAM, (state->m_mmc_vrom_bank[2] & 0x80) >> 7, 1);
1464      set_nt_page(machine, 1, CIRAM, (state->m_mmc_vrom_bank[3] & 0x80) >> 7, 1);
1465      set_nt_page(machine, 2, CIRAM, (state->m_mmc_vrom_bank[4] & 0x80) >> 7, 1);
1466      set_nt_page(machine, 3, CIRAM, (state->m_mmc_vrom_bank[5] & 0x80) >> 7, 1);
1467   }
1468   else
1469   {
1470      set_nt_page(machine, 0, CIRAM, (state->m_mmc_vrom_bank[0] & 0x80) >> 7, 1);
1471      set_nt_page(machine, 1, CIRAM, (state->m_mmc_vrom_bank[0] & 0x80) >> 7, 1);
1472      set_nt_page(machine, 2, CIRAM, (state->m_mmc_vrom_bank[1] & 0x80) >> 7, 1);
1473      set_nt_page(machine, 3, CIRAM, (state->m_mmc_vrom_bank[1] & 0x80) >> 7, 1);
1474   }
1475}
1476
1477static void txsrom_chr_cb( running_machine &machine, int start, int bank, int source )
1478{
1479   txsrom_set_mirror(machine);   // we could probably update only for one (e.g. the first) call, to slightly optimize the code
1480   chr1_x(machine, start, bank, source);
1481}
1482
1483static WRITE8_HANDLER( txsrom_w )
1484{
1485   LOG_MMC(("txsrom_w, offset: %04x, data: %02x\n", offset, data));
1486
1487   switch (offset & 0x6001)
1488   {
1489      case 0x2000:
1490         break;
1491
1492      default:
1493         txrom_w(space, offset, data);
1494         break;
1495   }
1496}
1497
1498/*************************************************************
1499
1500 TQROM (MMC3 based) board emulation
1501
1502 Games: Pin Bot, High Speed
1503
1504 iNES: mapper 119
1505
1506 In MESS: Supported. It also uses mmc3_irq.
1507
1508 *************************************************************/
1509
1510static void tqrom_set_chr( running_machine &machine )
1511{
1512   nes_state *state = machine.driver_data<nes_state>();
1513   UINT8 chr_page = (state->m_mmc3_latch & 0x80) >> 5;
1514   UINT8 chr_src[6], chr_mask[6];
1515   int i;
1516
1517   for (i = 0; i < 6; i++)
1518   {
1519      chr_src[i] = (state->m_mmc_vrom_bank[i] & 0x40) ? CHRRAM : CHRROM;
1520      chr_mask[i] =  (state->m_mmc_vrom_bank[i] & 0x40) ? 0x07 : 0x3f;
1521   }
1522
1523   chr1_x(machine, chr_page ^ 0, ((state->m_mmc_vrom_bank[0] & ~0x01) & chr_mask[0]), chr_src[0]);
1524   chr1_x(machine, chr_page ^ 1, ((state->m_mmc_vrom_bank[0] |  0x01) & chr_mask[0]), chr_src[0]);
1525   chr1_x(machine, chr_page ^ 2, ((state->m_mmc_vrom_bank[1] & ~0x01) & chr_mask[1]), chr_src[1]);
1526   chr1_x(machine, chr_page ^ 3, ((state->m_mmc_vrom_bank[1] |  0x01) & chr_mask[1]), chr_src[1]);
1527   chr1_x(machine, chr_page ^ 4, (state->m_mmc_vrom_bank[2] & chr_mask[2]), chr_src[2]);
1528   chr1_x(machine, chr_page ^ 5, (state->m_mmc_vrom_bank[3] & chr_mask[3]), chr_src[3]);
1529   chr1_x(machine, chr_page ^ 6, (state->m_mmc_vrom_bank[4] & chr_mask[4]), chr_src[4]);
1530   chr1_x(machine, chr_page ^ 7, (state->m_mmc_vrom_bank[5] & chr_mask[5]), chr_src[5]);
1531}
1532
1533static WRITE8_HANDLER( tqrom_w )
1534{
1535   nes_state *state = space->machine().driver_data<nes_state>();
1536   UINT8 mmc_helper, cmd;
1537   LOG_MMC(("tqrom_w, offset: %04x, data: %02x\n", offset, data));
1538
1539   switch (offset & 0x6001)
1540   {
1541      case 0x0000:
1542         mmc_helper = state->m_mmc3_latch ^ data;
1543         state->m_mmc3_latch = data;
1544
1545         /* Has PRG Mode changed? */
1546         if (mmc_helper & 0x40)
1547            mmc3_set_prg(space->machine(), state->m_mmc_prg_base, state->m_mmc_prg_mask);
1548
1549         /* Has CHR Mode changed? */
1550         if (mmc_helper & 0x80)
1551            tqrom_set_chr(space->machine());
1552         break;
1553      case 0x0001: /* $8001 */
1554         cmd = state->m_mmc3_latch & 0x07;
1555         switch (cmd)
1556         {
1557         case 0: case 1:   // these do not need to be separated: we take care of them in set_chr!
1558         case 2: case 3: case 4: case 5:
1559            state->m_mmc_vrom_bank[cmd] = data;
1560            tqrom_set_chr(space->machine());
1561            break;
1562         case 6:
1563         case 7:
1564            state->m_mmc_prg_bank[cmd - 6] = data;
1565            mmc3_set_prg(space->machine(), state->m_mmc_prg_base, state->m_mmc_prg_mask);
1566            break;
1567         }
1568         break;
1569
1570      default:
1571         txrom_w(space, offset, data);
1572         break;
1573   }
1574}
1575
1576/*************************************************************
1577
1578 PAL-ZZ board (MMC3 variant for European 3-in-1 Nintendo cart
1579 Super Mario Bros. + Tetris + Nintendo World Cup)
1580
1581 iNES: mapper 37
1582
1583 *************************************************************/
1584
1585static WRITE8_HANDLER( zz_m_w )
1586{
1587   nes_state *state = space->machine().driver_data<nes_state>();
1588   UINT8 mmc_helper = data & 0x07;
1589   LOG_MMC(("zz_m_w, offset: %04x, data: %02x\n", offset, data));
1590
1591   state->m_mmc_prg_base = (BIT(mmc_helper, 2) << 4) | (((mmc_helper & 0x03) == 0x03) ? 0x08 : 0);
1592   state->m_mmc_prg_mask = (mmc_helper << 1) | 0x07;
1593   state->m_mmc_chr_base = BIT(mmc_helper, 2) << 7;
1594   state->m_mmc_chr_mask = 0x7f;
1595   mmc3_set_prg(space->machine(), state->m_mmc_prg_base, state->m_mmc_prg_mask);
1596   mmc3_set_chr(space->machine(), state->m_mmc_chr_source, state->m_mmc_chr_base, state->m_mmc_chr_mask);
1597}
1598
1599/*************************************************************
1600
1601 NES-QJ board (MMC3 variant for US 2-in-1 Nintendo cart
1602 Super Spike V'Ball + Nintendo World Cup)
1603
1604 iNES: mapper 47
1605
1606 *************************************************************/
1607
1608static WRITE8_HANDLER( qj_m_w )
1609{
1610   nes_state *state = space->machine().driver_data<nes_state>();
1611   LOG_MMC(("qj_m_w, offset: %04x, data: %02x\n", offset, data));
1612
1613   state->m_mmc_prg_base = BIT(data, 0) << 4;
1614   state->m_mmc_prg_mask = 0x0f;
1615   state->m_mmc_chr_base = BIT(data, 0) << 7;
1616   state->m_mmc_chr_mask = 0x7f;
1617   mmc3_set_prg(space->machine(), state->m_mmc_prg_base, state->m_mmc_prg_mask);
1618   mmc3_set_chr(space->machine(), state->m_mmc_chr_source, state->m_mmc_chr_base, state->m_mmc_chr_mask);
1619}
1620
1621/*************************************************************
1622
1623 ExROM (MMC5 based) board emulation
1624
1625 Games: Castlevania III, Just Breed, many Koei titles
1626
1627 iNES: mapper 5
1628
1629 MESS status: Mostly Unsupported
1630
1631 *************************************************************/
1632
1633#if 0
1634static void mmc5_update_chr_a( running_machine &machine )
1635{
1636   nes_state *state = machine.driver_data<nes_state>();
1637   switch (state->m_mmc5_chr_mode)
1638   {
1639      case 0:   // 8k banks
1640         chr8(machine, state->m_mmc5_vrom_regA[7] & 0xff, CHRROM);
1641         break;
1642
1643      case 1:   // 4k banks
1644         chr4_0(machine, state->m_mmc5_vrom_regA[3] & 0xff, CHRROM);
1645         chr4_4(machine, state->m_mmc5_vrom_regA[7] & 0xff, CHRROM);
1646         break;
1647
1648      case 2:   // 2k banks
1649         chr2_0(machine, state->m_mmc5_vrom_regA[1], CHRROM);
1650         chr2_2(machine, state->m_mmc5_vrom_regA[3], CHRROM);
1651         chr2_4(machine, state->m_mmc5_vrom_regA[5], CHRROM);
1652         chr2_6(machine, state->m_mmc5_vrom_regA[7], CHRROM);
1653         break;
1654
1655      case 3:   // 1k banks
1656         chr1_0(machine, state->m_mmc5_vrom_regA[0], CHRROM);
1657         chr1_1(machine, state->m_mmc5_vrom_regA[1], CHRROM);
1658         chr1_2(machine, state->m_mmc5_vrom_regA[2], CHRROM);
1659         chr1_3(machine, state->m_mmc5_vrom_regA[3], CHRROM);
1660         chr1_4(machine, state->m_mmc5_vrom_regA[4], CHRROM);
1661         chr1_5(machine, state->m_mmc5_vrom_regA[5], CHRROM);
1662         chr1_6(machine, state->m_mmc5_vrom_regA[6], CHRROM);
1663         chr1_7(machine, state->m_mmc5_vrom_regA[7], CHRROM);
1664         break;
1665   }
1666}
1667
1668static void mmc5_update_chr_b( running_machine &machine )
1669{
1670   nes_state *state = machine.driver_data<nes_state>();
1671   switch (state->m_mmc5_chr_mode)
1672   {
1673      case 0:   // 8k banks
1674         chr8(machine, state->m_mmc5_vrom_regB[3] & 0xff, CHRROM);
1675         break;
1676
1677      case 1:   // 4k banks
1678         chr4_0(machine, state->m_mmc5_vrom_regB[3] & 0xff, CHRROM);
1679         chr4_4(machine, state->m_mmc5_vrom_regB[3] & 0xff, CHRROM);
1680         break;
1681
1682      case 2:   // 2k banks
1683         chr2_0(machine, state->m_mmc5_vrom_regB[1], CHRROM);
1684         chr2_2(machine, state->m_mmc5_vrom_regB[3], CHRROM);
1685         chr2_4(machine, state->m_mmc5_vrom_regB[1], CHRROM);
1686         chr2_6(machine, state->m_mmc5_vrom_regB[3], CHRROM);
1687         break;
1688
1689      case 3:   // 1k banks
1690         chr1_0(machine, state->m_mmc5_vrom_regB[0], CHRROM);
1691         chr1_1(machine, state->m_mmc5_vrom_regB[1], CHRROM);
1692         chr1_2(machine, state->m_mmc5_vrom_regB[2], CHRROM);
1693         chr1_3(machine, state->m_mmc5_vrom_regB[3], CHRROM);
1694         chr1_4(machine, state->m_mmc5_vrom_regB[0], CHRROM);
1695         chr1_5(machine, state->m_mmc5_vrom_regB[1], CHRROM);
1696         chr1_6(machine, state->m_mmc5_vrom_regB[2], CHRROM);
1697         chr1_7(machine, state->m_mmc5_vrom_regB[3], CHRROM);
1698         break;
1699   }
1700}
1701#endif
1702
1703static void mmc5_update_prg( running_machine &machine )
1704{
1705   nes_state *state = machine.driver_data<nes_state>();
1706   int bank1, bank2, bank3;
1707
1708   switch (state->m_mmc5_prg_mode)
1709   {
1710      case 0:   // 32k banks
1711         prg32(machine, state->m_mmc5_prg_regs[3] >> 2);
1712         break;
1713
1714      case 1:   // 16k banks
1715         //          printf("problema 1: %x\n", state->m_mmc5_prg_regs[1]);
1716         bank1 = state->m_mmc5_prg_regs[1];
1717
1718         if (!BIT(bank1, 7))
1719         {
1720            state->m_prg_bank[0] = state->m_prg_chunks + (bank1 & 0x06);
1721            state->m_prg_bank[1] = state->m_prg_chunks + (bank1 & 0x06) + 1;
1722            memory_set_bank(machine, "bank1", state->m_prg_bank[0]);
1723            memory_set_bank(machine, "bank2", state->m_prg_bank[1]);
1724         }
1725         else
1726            prg16_89ab(machine, bank1 >> 1);
1727
1728         prg16_cdef(machine, state->m_mmc5_prg_regs[3] >> 1);
1729         break;
1730
1731      case 2:   // 16k-8k banks
1732         //          printf("problema 2: %x %x\n", state->m_mmc5_prg_regs[1], state->m_mmc5_prg_regs[2]);
1733         bank1 = state->m_mmc5_prg_regs[1];
1734         bank3 = state->m_mmc5_prg_regs[2];
1735
1736         if (!BIT(bank1, 7))
1737         {
1738            state->m_prg_bank[0] = state->m_prg_chunks + (bank1 & 0x06);
1739            state->m_prg_bank[1] = state->m_prg_chunks + (bank1 & 0x06) + 1;
1740            memory_set_bank(machine, "bank1", state->m_prg_bank[0]);
1741            memory_set_bank(machine, "bank2", state->m_prg_bank[1]);
1742         }
1743         else
1744            prg16_89ab(machine, (bank1 & 0x7f) >> 1);
1745
1746         if (!BIT(bank3, 7))
1747         {
1748            state->m_prg_bank[2] = state->m_prg_chunks + (bank3 & 0x07);
1749            memory_set_bank(machine, "bank3", state->m_prg_bank[2]);
1750         }
1751         else
1752            prg8_cd(machine, bank3 & 0x7f);
1753
1754         prg8_ef(machine, state->m_mmc5_prg_regs[3]);
1755         break;
1756
1757      case 3:   // 8k banks
1758         //          printf("problema 3: %x %x %x\n", state->m_mmc5_prg_regs[0], state->m_mmc5_prg_regs[1], state->m_mmc5_prg_regs[2]);
1759         bank1 = state->m_mmc5_prg_regs[0];
1760         bank2 = state->m_mmc5_prg_regs[1];
1761         bank3 = state->m_mmc5_prg_regs[2];
1762
1763         if (!BIT(bank1, 7))
1764         {
1765            state->m_prg_bank[0] = state->m_prg_chunks + (bank1 & 0x07);
1766            memory_set_bank(machine, "bank1", state->m_prg_bank[0]);
1767         }
1768         else
1769            prg8_89(machine, bank1 & 0x7f);
1770
1771         if (!BIT(bank2, 7))
1772         {
1773            state->m_prg_bank[1] = state->m_prg_chunks + (bank2 & 0x07);
1774            memory_set_bank(machine, "bank2", state->m_prg_bank[1]);
1775         }
1776         else
1777            prg8_ab(machine, bank2 & 0x7f);
1778
1779         if (!BIT(bank3, 7))
1780         {
1781            state->m_prg_bank[2] = state->m_prg_chunks + (bank3 & 0x07);
1782            memory_set_bank(machine, "bank3", state->m_prg_bank[2]);
1783         }
1784         else
1785            prg8_cd(machine, bank3 & 0x7f);
1786
1787         prg8_ef(machine, state->m_mmc5_prg_regs[3]);
1788         break;
1789   }
1790}
1791
1792static void mmc5_update_render_mode( running_machine &machine )
1793{
1794}
1795
1796static void mmc5_irq( device_t *device, int scanline, int vblank, int blanked )
1797{
1798   nes_state *state = device->machine().driver_data<nes_state>();
1799
1800#if 1
1801   if (scanline == 0)
1802      state->m_IRQ_status |= 0x40;
1803   else if (scanline > PPU_BOTTOM_VISIBLE_SCANLINE)
1804      state->m_IRQ_status &= ~0x40;
1805#endif
1806
1807   if (scanline == state->m_IRQ_count)
1808   {
1809      if (state->m_IRQ_enable)
1810         device_set_input_line(state->m_maincpu, M6502_IRQ_LINE, HOLD_LINE);
1811
1812      state->m_IRQ_status = 0xff;
1813   }
1814
1815   /* FIXME: this is ok, but then we would need to update them again when we have the BG Hblank
1816     I leave it commented out until the PPU is updated for this */
1817   //  if (ppu2c0x_is_sprite_8x16(state->m_ppu) || state->m_mmc5_last_chr_a)
1818   //      mmc5_update_chr_a(device->machine());
1819   //  else
1820   //      mmc5_update_chr_b(device->machine());
1821}
1822
1823static void mmc5_ppu_mirror( running_machine &machine, int page, int src )
1824{
1825   switch (src)
1826   {
1827      case 0:   /* CIRAM0 */
1828         set_nt_page(machine, page, CIRAM, 0, 1);
1829         break;
1830      case 1:   /* CIRAM1 */
1831         set_nt_page(machine, page, CIRAM, 1, 1);
1832         break;
1833      case 2:   /* ExRAM */
1834         set_nt_page(machine, page, EXRAM, 0, 1);   // actually only works during rendering.
1835         break;
1836      case 3: /* Fill Registers */
1837         set_nt_page(machine, page, MMC5FILL, 0, 0);
1838         break;
1839      default:
1840         fatalerror("This should never happen");
1841         break;
1842   }
1843}
1844
1845static READ8_HANDLER( exrom_l_r )
1846{
1847   nes_state *state = space->machine().driver_data<nes_state>();
1848   int retVal;
1849
1850   /* $5c00 - $5fff: extended videoram attributes */
1851   if ((offset >= 0x1b00) && (offset <= 0x1eff))
1852   {
1853      return state->m_mapper_ram[offset - 0x1b00];
1854   }
1855
1856   switch (offset)
1857   {
1858      case 0x1104: /* $5204 */
1859#if 0
1860         if (current_scanline == MMC5_scanline)
1861            return 0x80;
1862         else
1863            return 0x00;
1864#else
1865         retVal = state->m_IRQ_status;
1866         state->m_IRQ_status &= ~0x80;
1867         return retVal;
1868#endif
1869
1870      case 0x1105: /* $5205 */
1871         return (state->m_mult1 * state->m_mult2) & 0xff;
1872      case 0x1106: /* $5206 */
1873         return ((state->m_mult1 * state->m_mult2) & 0xff00) >> 8;
1874
1875      default:
1876         logerror("** MMC5 uncaught read, offset: %04x\n", offset + 0x4100);
1877         return 0x00;
1878   }
1879}
1880
1881
1882static WRITE8_HANDLER( exrom_l_w )
1883{
1884   nes_state *state = space->machine().driver_data<nes_state>();
1885
1886   //  LOG_MMC(("Mapper 5 write, offset: %04x, data: %02x\n", offset + 0x4100, data));
1887   /* Send $5000-$5015 to the sound chip */
1888   if ((offset >= 0xf00) && (offset <= 0xf15))
1889   {
1890      nes_psg_w(state->m_sound, offset & 0x1f, data);
1891      return;
1892   }
1893
1894   /* $5c00 - $5fff: extended videoram attributes */
1895   if ((offset >= 0x1b00) && (offset <= 0x1eff))
1896   {
1897      if (state->m_MMC5_vram_protect == 0x03)
1898         state->m_mapper_ram[offset - 0x1b00] = data;
1899      return;
1900   }
1901
1902   switch (offset)
1903   {
1904      case 0x1000: /* $5100 */
1905         state->m_mmc5_prg_mode = data & 0x03;
1906         //          mmc5_update_prg(space->machine());
1907         LOG_MMC(("MMC5 rom bank mode: %02x\n", data));
1908         break;
1909
1910      case 0x1001: /* $5101 */
1911         state->m_mmc5_chr_mode = data & 0x03;
1912         // update chr
1913         LOG_MMC(("MMC5 vrom bank mode: %02x\n", data));
1914         break;
1915
1916      case 0x1002: /* $5102 */
1917         if (data == 0x02)
1918            state->m_MMC5_vram_protect |= 1;
1919         else
1920            state->m_MMC5_vram_protect = 0;
1921         LOG_MMC(("MMC5 vram protect 1: %02x\n", data));
1922         break;
1923      case 0x1003: /* 5103 */
1924         if (data == 0x01)
1925            state->m_MMC5_vram_protect |= 2;
1926         else
1927            state->m_MMC5_vram_protect = 0;
1928         LOG_MMC(("MMC5 vram protect 2: %02x\n", data));
1929         break;
1930
1931      case 0x1004: /* $5104 - Extra VRAM (EXRAM) control */
1932         state->m_mmc5_vram_control = data & 0x03;
1933         // update render
1934         mmc5_update_render_mode(space->machine());
1935         LOG_MMC(("MMC5 exram control: %02x\n", data));
1936         break;
1937
1938      case 0x1005: /* $5105 */
1939         mmc5_ppu_mirror(space->machine(), 0, data & 0x03);
1940         mmc5_ppu_mirror(space->machine(), 1, (data & 0x0c) >> 2);
1941         mmc5_ppu_mirror(space->machine(), 2, (data & 0x30) >> 4);
1942         mmc5_ppu_mirror(space->machine(), 3, (data & 0xc0) >> 6);
1943         // update render
1944         mmc5_update_render_mode(space->machine());
1945         break;
1946
1947         /* tile data for MMC5 flood-fill NT mode */
1948      case 0x1006:
1949         state->m_MMC5_floodtile = data;
1950         break;
1951
1952         /* attr data for MMC5 flood-fill NT mode */
1953      case 0x1007:
1954         switch (data & 3)
1955      {
1956         default:
1957         case 0: state->m_MMC5_floodattr = 0x00; break;
1958         case 1: state->m_MMC5_floodattr = 0x55; break;
1959         case 2: state->m_MMC5_floodattr = 0xaa; break;
1960         case 3: state->m_MMC5_floodattr = 0xff; break;
1961      }
1962         break;
1963
1964      case 0x1013: /* $5113 */
1965         LOG_MMC(("MMC5 mid RAM bank select: %02x\n", data & 0x07));
1966         // FIXME: a few Koei games have both WRAM & BWRAM but here we don't support this (yet)
1967         if (state->m_battery)
1968            wram_bank(space->machine(), data, NES_BATTERY);
1969         else
1970            wram_bank(space->machine(), data, NES_WRAM);
1971         break;
1972
1973
1974      case 0x1014: /* $5114 */
1975      case 0x1015: /* $5115 */
1976      case 0x1016: /* $5116 */
1977      case 0x1017: /* $5117 */
1978         state->m_mmc5_prg_regs[offset & 3] = data;
1979         mmc5_update_prg(space->machine());
1980         break;
1981
1982#if 0
1983      // these do not work as expected... I guess we definitely need the bank update at proper times (with BG vs. sprite timing)
1984      case 0x1020: /* $5120 */
1985      case 0x1021: /* $5121 */
1986      case 0x1022: /* $5122 */
1987      case 0x1023: /* $5123 */
1988      case 0x1024: /* $5124 */
1989      case 0x1025: /* $5125 */
1990      case 0x1026: /* $5126 */
1991      case 0x1027: /* $5127 */
1992         data |= (state->m_mmc5_chr_high << 8);
1993         if (!state->m_mmc5_last_chr_a)
1994         {
1995            state->m_mmc5_vrom_regA[offset & 0x07] = data;
1996            state->m_mmc5_last_chr_a = 1;
1997            if (ppu2c0x_get_current_scanline(state->m_ppu) == 240 || !ppu2c0x_is_sprite_8x16(state->m_ppu))
1998               mmc5_update_chr_a(space->machine());
1999         }
2000         break;
2001
2002
2003      case 0x1028: /* $5128 */
2004      case 0x1029: /* $5129 */
2005      case 0x102a: /* $512a */
2006      case 0x102b: /* $512b */
2007         data |= (state->m_mmc5_chr_high << 8);
2008         state->m_mmc5_vrom_regB[offset & 0x03] = data;
2009         state->m_mmc5_last_chr_a = 0;
2010         if (ppu2c0x_get_current_scanline(state->m_ppu) == 240 || !ppu2c0x_is_sprite_8x16(state->m_ppu))
2011            mmc5_update_chr_b(space->machine());
2012         break;
2013
2014      case 0x1030: /* $5130 */
2015         state->m_mmc5_chr_high = data & 0x03;
2016         if (state->m_mmc5_vram_control == 1)
2017         {
2018            // in this case state->m_mmc5_chr_high selects which 256KB of CHR ROM
2019            // is to be used for all background tiles on the screen.
2020         }
2021         break;
2022
2023#endif
2024
2025      case 0x1020: /* $5120 */
2026         LOG_MMC(("MMC5 $5120 vrom select: %02x (mode: %d)\n", data, state->m_mmc5_chr_mode));
2027         switch (state->m_mmc5_chr_mode)
2028      {
2029         case 0x03:
2030            /* 1k switch */
2031            state->m_MMC5_vrom_bank[0] = data | (state->m_mmc5_high_chr << 8);
2032            //                  mapper5_sync_vrom(0);
2033            chr1_0(space->machine(), state->m_MMC5_vrom_bank[0], CHRROM);
2034            //                  state->m_nes_vram_sprite[0] = state->m_MMC5_vrom_bank[0] * 64;
2035            //                  vrom_next[0] = 4;
2036            //                  vrom_page_a = 1;
2037            //                  vrom_page_b = 0;
2038            break;
2039      }
2040         break;
2041      case 0x1021: /* $5121 */
2042         LOG_MMC(("MMC5 $5121 vrom select: %02x (mode: %d)\n", data, state->m_mmc5_chr_mode));
2043         switch (state->m_mmc5_chr_mode)
2044      {
2045         case 0x02:
2046            /* 2k switch */
2047            chr2_0(space->machine(), data | (state->m_mmc5_high_chr << 8), CHRROM);
2048            break;
2049         case 0x03:
2050            /* 1k switch */
2051            state->m_MMC5_vrom_bank[1] = data | (state->m_mmc5_high_chr << 8);
2052            //                  mapper5_sync_vrom(0);
2053            chr1_1(space->machine(), state->m_MMC5_vrom_bank[1], CHRROM);
2054            //                  state->m_nes_vram_sprite[1] = state->m_MMC5_vrom_bank[0] * 64;
2055            //                  vrom_next[1] = 5;
2056            //                  vrom_page_a = 1;
2057            //                  vrom_page_b = 0;
2058            break;
2059      }
2060         break;
2061      case 0x1022: /* $5122 */
2062         LOG_MMC(("MMC5 $5122 vrom select: %02x (mode: %d)\n", data, state->m_mmc5_chr_mode));
2063         switch (state->m_mmc5_chr_mode)
2064      {
2065         case 0x03:
2066            /* 1k switch */
2067            state->m_MMC5_vrom_bank[2] = data | (state->m_mmc5_high_chr << 8);
2068            //                  mapper5_sync_vrom(0);
2069            chr1_2(space->machine(), state->m_MMC5_vrom_bank[2], CHRROM);
2070            //                  state->m_nes_vram_sprite[2] = state->m_MMC5_vrom_bank[0] * 64;
2071            //                  vrom_next[2] = 6;
2072            //                  vrom_page_a = 1;
2073            //                  vrom_page_b = 0;
2074            break;
2075      }
2076         break;
2077      case 0x1023: /* $5123 */
2078         LOG_MMC(("MMC5 $5123 vrom select: %02x (mode: %d)\n", data, state->m_mmc5_chr_mode));
2079         switch (state->m_mmc5_chr_mode)
2080      {
2081         case 0x01:
2082            chr4_0(space->machine(), data, CHRROM);
2083            break;
2084         case 0x02:
2085            /* 2k switch */
2086            chr2_2(space->machine(), data | (state->m_mmc5_high_chr << 8), CHRROM);
2087            break;
2088         case 0x03:
2089            /* 1k switch */
2090            state->m_MMC5_vrom_bank[3] = data | (state->m_mmc5_high_chr << 8);
2091            //                  mapper5_sync_vrom(0);
2092            chr1_3(space->machine(), state->m_MMC5_vrom_bank[3], CHRROM);
2093            //                  state->m_nes_vram_sprite[3] = state->m_MMC5_vrom_bank[0] * 64;
2094            //                  vrom_next[3] = 7;
2095            //                  vrom_page_a = 1;
2096            //                  vrom_page_b = 0;
2097            break;
2098      }
2099         break;
2100      case 0x1024: /* $5124 */
2101         LOG_MMC(("MMC5 $5124 vrom select: %02x (mode: %d)\n", data, state->m_mmc5_chr_mode));
2102         switch (state->m_mmc5_chr_mode)
2103      {
2104         case 0x03:
2105            /* 1k switch */
2106            state->m_MMC5_vrom_bank[4] = data | (state->m_mmc5_high_chr << 8);
2107            //                  mapper5_sync_vrom(0);
2108            chr1_4(space->machine(), state->m_MMC5_vrom_bank[4], CHRROM);
2109            //                  state->m_nes_vram_sprite[4] = state->m_MMC5_vrom_bank[0] * 64;
2110            //                  vrom_next[0] = 0;
2111            //                  vrom_page_a = 0;
2112            //                  vrom_page_b = 0;
2113            break;
2114      }
2115         break;
2116      case 0x1025: /* $5125 */
2117         LOG_MMC(("MMC5 $5125 vrom select: %02x (mode: %d)\n", data, state->m_mmc5_chr_mode));
2118         switch (state->m_mmc5_chr_mode)
2119      {
2120         case 0x02:
2121            /* 2k switch */
2122            chr2_4(space->machine(), data | (state->m_mmc5_high_chr << 8), CHRROM);
2123            break;
2124         case 0x03:
2125            /* 1k switch */
2126            state->m_MMC5_vrom_bank[5] = data | (state->m_mmc5_high_chr << 8);
2127            //                  mapper5_sync_vrom(0);
2128            chr1_5(space->machine(), state->m_MMC5_vrom_bank[5], CHRROM);
2129            //                  state->m_nes_vram_sprite[5] = state->m_MMC5_vrom_bank[0] * 64;
2130            //                  vrom_next[1] = 1;
2131            //                  vrom_page_a = 0;
2132            //                  vrom_page_b = 0;
2133            break;
2134      }
2135         break;
2136      case 0x1026: /* $5126 */
2137         LOG_MMC(("MMC5 $5126 vrom select: %02x (mode: %d)\n", data, state->m_mmc5_chr_mode));
2138         switch (state->m_mmc5_chr_mode)
2139      {
2140         case 0x03:
2141            /* 1k switch */
2142            state->m_MMC5_vrom_bank[6] = data | (state->m_mmc5_high_chr << 8);
2143            //                  mapper5_sync_vrom(0);
2144            chr1_6(space->machine(), state->m_MMC5_vrom_bank[6], CHRROM);
2145            //                  state->m_nes_vram_sprite[6] = state->m_MMC5_vrom_bank[0] * 64;
2146            //                  vrom_next[2] = 2;
2147            //                  vrom_page_a = 0;
2148            //                  vrom_page_b = 0;
2149            break;
2150      }
2151         break;
2152      case 0x1027: /* $5127 */
2153         LOG_MMC(("MMC5 $5127 vrom select: %02x (mode: %d)\n", data, state->m_mmc5_chr_mode));
2154         switch (state->m_mmc5_chr_mode)
2155      {
2156         case 0x00:
2157            /* 8k switch */
2158            chr8(space->machine(), data, CHRROM);
2159            break;
2160         case 0x01:
2161            /* 4k switch */
2162            chr4_4(space->machine(), data, CHRROM);
2163            break;
2164         case 0x02:
2165            /* 2k switch */
2166            chr2_6(space->machine(), data | (state->m_mmc5_high_chr << 8), CHRROM);
2167            break;
2168         case 0x03:
2169            /* 1k switch */
2170            state->m_MMC5_vrom_bank[7] = data | (state->m_mmc5_high_chr << 8);
2171            //                  mapper5_sync_vrom(0);
2172            chr1_7(space->machine(), state->m_MMC5_vrom_bank[7], CHRROM);
2173            //                  state->m_nes_vram_sprite[7] = state->m_MMC5_vrom_bank[0] * 64;
2174            //                  vrom_next[3] = 3;
2175            //                  vrom_page_a = 0;
2176            //                  vrom_page_b = 0;
2177            break;
2178      }
2179         break;
2180      case 0x1028: /* $5128 */
2181         LOG_MMC(("MMC5 $5128 vrom select: %02x (mode: %d)\n", data, state->m_mmc5_chr_mode));
2182         switch (state->m_mmc5_chr_mode)
2183      {
2184         case 0x03:
2185            /* 1k switch */
2186            state->m_MMC5_vrom_bank[8] = data | (state->m_mmc5_high_chr << 8);
2187            //                  nes_vram[vrom_next[0]] = data * 64;
2188            //                  nes_vram[0 + (vrom_page_a*4)] = data * 64;
2189            //                  nes_vram[0] = data * 64;
2190            chr1_4(space->machine(), state->m_MMC5_vrom_bank[8], CHRROM);
2191            //                  mapper5_sync_vrom(1);
2192            if (!state->m_vrom_page_b)
2193            {
2194               state->m_vrom_page_a ^= 0x01;
2195               state->m_vrom_page_b = 1;
2196            }
2197            break;
2198      }
2199         break;
2200      case 0x1029: /* $5129 */
2201         LOG_MMC(("MMC5 $5129 vrom select: %02x (mode: %d)\n", data, state->m_mmc5_chr_mode));
2202         switch (state->m_mmc5_chr_mode)
2203      {
2204         case 0x02:
2205            /* 2k switch */
2206            chr2_0(space->machine(), data | (state->m_mmc5_high_chr << 8), CHRROM);
2207            chr2_4(space->machine(), data | (state->m_mmc5_high_chr << 8), CHRROM);
2208            break;
2209         case 0x03:
2210            /* 1k switch */
2211            state->m_MMC5_vrom_bank[9] = data | (state->m_mmc5_high_chr << 8);
2212            //                  nes_vram[vrom_next[1]] = data * 64;
2213            //                  nes_vram[1 + (vrom_page_a*4)] = data * 64;
2214            //                  nes_vram[1] = data * 64;
2215            chr1_5(space->machine(), state->m_MMC5_vrom_bank[9], CHRROM);
2216            //                  mapper5_sync_vrom(1);
2217            if (!state->m_vrom_page_b)
2218            {
2219               state->m_vrom_page_a ^= 0x01;
2220               state->m_vrom_page_b = 1;
2221            }
2222            break;
2223      }
2224         break;
2225      case 0x102a: /* $512a */
2226         LOG_MMC(("MMC5 $512a vrom select: %02x (mode: %d)\n", data, state->m_mmc5_chr_mode));
2227         switch (state->m_mmc5_chr_mode)
2228      {
2229         case 0x03:
2230            /* 1k switch */
2231            state->m_MMC5_vrom_bank[10] = data | (state->m_mmc5_high_chr << 8);
2232            //                  nes_vram[vrom_next[2]] = data * 64;
2233            //                  nes_vram[2 + (vrom_page_a*4)] = data * 64;
2234            //                  nes_vram[2] = data * 64;
2235            chr1_6(space->machine(), state->m_MMC5_vrom_bank[10], CHRROM);
2236            //                  mapper5_sync_vrom(1);
2237            if (!state->m_vrom_page_b)
2238            {
2239               state->m_vrom_page_a ^= 0x01;
2240               state->m_vrom_page_b = 1;
2241            }
2242            break;
2243      }
2244         break;
2245      case 0x102b: /* $512b */
2246         LOG_MMC(("MMC5 $512b vrom select: %02x (mode: %d)\n", data, state->m_mmc5_chr_mode));
2247         switch (state->m_mmc5_chr_mode)
2248      {
2249         case 0x00:
2250            /* 8k switch */
2251            /* switches in first half of an 8K bank!) */
2252            chr4_0(space->machine(), data << 1, CHRROM);
2253            chr4_4(space->machine(), data << 1, CHRROM);
2254            break;
2255         case 0x01:
2256            /* 4k switch */
2257            chr4_0(space->machine(), data, CHRROM);
2258            chr4_4(space->machine(), data, CHRROM);
2259            break;
2260         case 0x02:
2261            /* 2k switch */
2262            chr2_2(space->machine(), data | (state->m_mmc5_high_chr << 8), CHRROM);
2263            chr2_6(space->machine(), data | (state->m_mmc5_high_chr << 8), CHRROM);
2264            break;
2265         case 0x03:
2266            /* 1k switch */
2267            state->m_MMC5_vrom_bank[11] = data | (state->m_mmc5_high_chr << 8);
2268            //                  nes_vram[vrom_next[3]] = data * 64;
2269            //                  nes_vram[3 + (vrom_page_a*4)] = data * 64;
2270            //                  nes_vram[3] = data * 64;
2271            chr1_7(space->machine(), state->m_MMC5_vrom_bank[11], CHRROM);
2272            //                  mapper5_sync_vrom(1);
2273            if (!state->m_vrom_page_b)
2274            {
2275               state->m_vrom_page_a ^= 0x01;
2276               state->m_vrom_page_b = 1;
2277            }
2278            break;
2279      }
2280         break;
2281
2282      case 0x1030: /* $5130 */
2283         state->m_mmc5_high_chr = data & 0x03;
2284         if (state->m_mmc5_vram_control == 1)
2285         {
2286            // in this case state->m_mmc5_high_chr selects which 256KB of CHR ROM
2287            // is to be used for all background tiles on the screen.
2288         }
2289         break;
2290
2291
2292      case 0x1100: /* $5200 */
2293         state->m_mmc5_split_scr = data;
2294         // in EX2 and EX3 modes, no split screen
2295         if (state->m_mmc5_vram_control & 0x02)
2296            state->m_mmc5_split_scr &= 0x7f;
2297         state->m_mmc5_split_ctrl = data;
2298         break;
2299
2300      case 0x1101: /* $5201 */
2301         state->m_mmc5_split_yst = (data >= 240) ? data - 16 : data;
2302         break;
2303
2304      case 0x1102: /* $5202 */
2305         state->m_mmc5_split_bank = data;
2306         break;
2307
2308      case 0x1103: /* $5203 */
2309         state->m_IRQ_count = data;
2310         state->m_MMC5_scanline = data;
2311         LOG_MMC(("MMC5 irq scanline: %d\n", state->m_IRQ_count));
2312         break;
2313      case 0x1104: /* $5204 */
2314         state->m_IRQ_enable = data & 0x80;
2315         LOG_MMC(("MMC5 irq enable: %02x\n", data));
2316         break;
2317      case 0x1105: /* $5205 */
2318         state->m_mult1 = data;
2319         break;
2320      case 0x1106: /* $5206 */
2321         state->m_mult2 = data;
2322         break;
2323
2324      default:
2325         logerror("** MMC5 uncaught write, offset: %04x, data: %02x\n", offset + 0x4100, data);
2326         break;
2327   }
2328}
2329
2330/*************************************************************
2331
2332 NTBROM & Sunsoft-4 board emulation
2333
2334 Part of this can be used also for Sunsoft Double Cassette
2335 System... which games use it?
2336
2337 iNES: mapper 68
2338
2339 *************************************************************/
2340
2341static void ntbrom_mirror( running_machine &machine, int mirror, int mirr0, int mirr1 )
2342{
2343   switch (mirror)
2344   {
2345      case 0x00:
2346         set_nt_mirroring(machine, PPU_MIRROR_HORZ);
2347         break;
2348      case 0x01:
2349         set_nt_mirroring(machine, PPU_MIRROR_VERT);
2350         break;
2351      case 0x02:
2352         set_nt_mirroring(machine, PPU_MIRROR_LOW);
2353         break;
2354      case 0x03:
2355         set_nt_mirroring(machine, PPU_MIRROR_HIGH);
2356         break;
2357      case 0x10:
2358         set_nt_page(machine, 0, ROM, mirr0 | 0x80, 0);
2359         set_nt_page(machine, 1, ROM, mirr1 | 0x80, 0);
2360         set_nt_page(machine, 2, ROM, mirr0 | 0x80, 0);
2361         set_nt_page(machine, 3, ROM, mirr1 | 0x80, 0);
2362         break;
2363      case 0x11:
2364         set_nt_page(machine, 0, ROM, mirr0 | 0x80, 0);
2365         set_nt_page(machine, 1, ROM, mirr0 | 0x80, 0);
2366         set_nt_page(machine, 2, ROM, mirr1 | 0x80, 0);
2367         set_nt_page(machine, 3, ROM, mirr1 | 0x80, 0);
2368         break;
2369      case 0x12:
2370         set_nt_page(machine, 0, ROM, mirr0 | 0x80, 0);
2371         set_nt_page(machine, 1, ROM, mirr0 | 0x80, 0);
2372         set_nt_page(machine, 2, ROM, mirr0 | 0x80, 0);
2373         set_nt_page(machine, 3, ROM, mirr0 | 0x80, 0);
2374         break;
2375      case 0x13:
2376         set_nt_page(machine, 0, ROM, mirr1 | 0x80, 0);
2377         set_nt_page(machine, 1, ROM, mirr1 | 0x80, 0);
2378         set_nt_page(machine, 2, ROM, mirr1 | 0x80, 0);
2379         set_nt_page(machine, 3, ROM, mirr1 | 0x80, 0);
2380         break;
2381   }
2382}
2383
2384static WRITE8_HANDLER( ntbrom_w )
2385{
2386   nes_state *state = space->machine().driver_data<nes_state>();
2387
2388   LOG_MMC(("ntbrom_w, offset %04x, data: %02x\n", offset, data));
2389
2390   switch (offset & 0x7000)
2391   {
2392      case 0x0000:
2393         chr2_0(space->machine(), data, CHRROM);
2394         break;
2395      case 0x1000:
2396         chr2_2(space->machine(), data, CHRROM);
2397         break;
2398      case 0x2000:
2399         chr2_4(space->machine(), data, CHRROM);
2400         break;
2401      case 0x3000:
2402         chr2_6(space->machine(), data, CHRROM);
2403         break;
2404      case 0x4000:
2405         state->m_mmc_latch1 = data & 0x7f;
2406         ntbrom_mirror(space->machine(), state->m_mmc_reg[0], state->m_mmc_latch1, state->m_mmc_latch2);
2407         break;
2408      case 0x5000:
2409         state->m_mmc_latch2 = data & 0x7f;
2410         ntbrom_mirror(space->machine(), state->m_mmc_reg[0], state->m_mmc_latch1, state->m_mmc_latch2);
2411         break;
2412      case 0x6000:
2413         state->m_mmc_reg[0] = data & 0x13;
2414         ntbrom_mirror(space->machine(), state->m_mmc_reg[0], state->m_mmc_latch1, state->m_mmc_latch2);
2415         break;
2416      case 0x7000:
2417         prg16_89ab(space->machine(), data);
2418         break;
2419      default:
2420         LOG_MMC(("ntbrom_w uncaught write, offset: %04x, data: %02x\n", offset, data));
2421         break;
2422   }
2423}
2424
2425/*************************************************************
2426
2427 JxROM & Sunsoft 5A / 5B / FME7 board emulation
2428
2429 Notice that Sunsoft-5B = FME7 + sound chip (the latter being
2430 currently unemulated in MESS)
2431
2432 iNES: mapper 69
2433
2434 *************************************************************/
2435
2436/* Here, IRQ counter decrements every CPU cycle. Since we update it every scanline,
2437 we need to decrement it by 114 (Each scanline consists of 341 dots and, on NTSC,
2438 there are 3 dots to every 1 CPU cycle, hence 114 is the number of cycles per scanline ) */
2439static void jxrom_irq( device_t *device, int scanline, int vblank, int blanked )
2440{
2441   nes_state *state = device->machine().driver_data<nes_state>();
2442
2443   /* TODO: change to reflect the actual number of cycles spent */
2444   if ((state->m_IRQ_enable & 0x80) && (state->m_IRQ_enable & 0x01))
2445   {
2446      if (state->m_IRQ_count <= 114)
2447      {
2448         state->m_IRQ_count = 0xffff;
2449         device_set_input_line(state->m_maincpu, M6502_IRQ_LINE, HOLD_LINE);
2450      }
2451      else
2452         state->m_IRQ_count -= 114;
2453   }
2454   else if (state->m_IRQ_enable & 0x01)   // if enable bit 7 is not set, only decrement the counter!
2455   {
2456      if (state->m_IRQ_count <= 114)
2457         state->m_IRQ_count = 0xffff;
2458      else
2459         state->m_IRQ_count -= 114;
2460   }
2461}
2462
2463static WRITE8_HANDLER( jxrom_w )
2464{
2465   nes_state *state = space->machine().driver_data<nes_state>();
2466   LOG_MMC(("jxrom_w, offset %04x, data: %02x\n", offset, data));
2467
2468   switch (offset & 0x6000)
2469   {
2470      case 0x0000:
2471         state->m_mmc_latch1 = data & 0x0f;
2472         break;
2473
2474      case 0x2000:
2475         switch (state->m_mmc_latch1)
2476         {
2477         case 0: case 1: case 2: case 3: case 4: case 5: case 6: case 7:
2478            chr1_x(space->machine(), state->m_mmc_latch1, data, CHRROM);
2479            break;
2480
2481         case 8:
2482            if (!(data & 0x40))
2483            {
2484               // is PRG ROM
2485               space->unmap_write(0x6000, 0x7fff);
2486               prg8_67(space->machine(), data & 0x3f);
2487            }
2488            else if (data & 0x80)
2489            {
2490               // is PRG RAM
2491               space->install_write_bank(0x6000, 0x7fff, "bank5");
2492               state->m_prg_bank[4] = state->m_battery_bank5_start + (data & 0x3f);
2493               memory_set_bank(space->machine(), "bank5", state->m_prg_bank[4]);
2494            }
2495            break;
2496
2497         case 9:
2498            prg8_89(space->machine(), data);
2499            break;
2500         case 0x0a:
2501            prg8_ab(space->machine(), data);
2502            break;
2503         case 0x0b:
2504            prg8_cd(space->machine(), data);
2505            break;
2506         case 0x0c:
2507            switch (data & 0x03)
2508            {
2509            case 0x00: set_nt_mirroring(space->machine(), PPU_MIRROR_VERT); break;
2510            case 0x01: set_nt_mirroring(space->machine(), PPU_MIRROR_HORZ); break;
2511            case 0x02: set_nt_mirroring(space->machine(), PPU_MIRROR_LOW); break;
2512            case 0x03: set_nt_mirroring(space->machine(), PPU_MIRROR_HIGH); break;
2513            }
2514            break;
2515         case 0x0d:
2516            state->m_IRQ_enable = data;
2517            break;
2518         case 0x0e:
2519            state->m_IRQ_count = (state->m_IRQ_count & 0xff00) | data;
2520            break;
2521         case 0x0f:
2522            state->m_IRQ_count = (state->m_IRQ_count & 0x00ff) | (data << 8);
2523            break;
2524         }
2525         break;
2526
2527         /* Here we would have sound command for Sunsoft 5b variant */
2528         //      case 0x4000:
2529         //      case 0x6000:
2530
2531      case 0x4000:
2532         LOG_MMC(("Sunsoft-5B Sound: Register select write, data: %02x\n", data));
2533         break;
2534      case 0x6000:
2535         LOG_MMC(("Sunsoft-5B Sound: Register write, data: %02x\n", data));
2536         break;
2537      default:
2538         logerror("jxrom_w uncaught %04x value: %02x\n", offset + 0x8000, data);
2539         break;
2540   }
2541}
2542
2543/*************************************************************
2544
2545 DxROM & Namcot 3433 - 3443 board emulation
2546
2547 Games: Dragon Spirit - Aratanaru Densetsu, Namcot Mahjong, Quinty
2548
2549 These are the same board, but DRROM (and Tengen 800004) have
2550 4-screen mirroring
2551
2552 iNES: mappers 88, 206 (same as 88 but possibly 4-screen mirroring)
2553
2554 *************************************************************/
2555
2556static WRITE8_HANDLER( dxrom_w )
2557{
2558   nes_state *state = space->machine().driver_data<nes_state>();
2559   LOG_MMC(("dxrom_w, offset: %04x, data: %02x\n", offset, data));
2560
2561    if (offset >= 0x2000)
2562      return;
2563
2564   switch (offset & 1)
2565   {
2566      case 1:
2567         switch (state->m_mmc_latch1 & 0x07)
2568         {
2569         case 0: chr2_0(space->machine(), data >> 1, CHRROM); break;
2570         case 1: chr2_2(space->machine(), data >> 1, CHRROM); break;
2571         case 2: chr1_4(space->machine(), data | 0x40, CHRROM); break;
2572         case 3: chr1_5(space->machine(), data | 0x40, CHRROM); break;
2573         case 4: chr1_6(space->machine(), data | 0x40, CHRROM); break;
2574         case 5: chr1_7(space->machine(), data | 0x40, CHRROM); break;
2575         case 6: prg8_89(space->machine(), data); break;
2576         case 7: prg8_ab(space->machine(), data); break;
2577         }
2578         break;
2579      case 0:
2580         state->m_mmc_latch1 = data;
2581         break;
2582   }
2583}
2584
2585
2586/*************************************************************
2587
2588 Namcot 3453 board emulation
2589
2590 Games: Devil Man
2591
2592 These are the same as Namcot 34x3, but with additional mirroring
2593 control
2594
2595 iNES: mapper 154
2596
2597 *************************************************************/
2598
2599static WRITE8_HANDLER( namcot3453_w )
2600{
2601   LOG_MMC(("namcot3453_w, offset: %04x, data: %02x\n", offset, data));
2602
2603   // additional mirroring control when writing to even addresses
2604   if (!(offset & 1))
2605      set_nt_mirroring(space->machine(), BIT(data, 6) ? PPU_MIRROR_HIGH : PPU_MIRROR_LOW);
2606
2607   dxrom_w(space, offset, data);
2608}
2609
2610/*************************************************************
2611
2612 Namcot 3446 board emulation
2613
2614 Games: Digital Devil Monogatari - Megami Tensei
2615
2616 These are similar Namcot 34x3, but different bankswitch capabilities
2617
2618 iNES: mapper 76
2619
2620 *************************************************************/
2621
2622static WRITE8_HANDLER( namcot3446_w )
2623{
2624   nes_state *state = space->machine().driver_data<nes_state>();
2625   LOG_MMC(("namcot3446_w, offset: %04x, data: %02x\n", offset, data));
2626
2627   // NEStopia does not have this!
2628   if (offset >= 0x2000)
2629   {
2630      if (!(offset & 1))
2631         set_nt_mirroring(space->machine(), BIT(data, 0) ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT);
2632      return;
2633   }
2634
2635   switch (offset & 1)
2636   {
2637      case 1:
2638         switch (state->m_mmc_latch1 & 0x07)
2639         {
2640         case 2: chr2_0(space->machine(), data, CHRROM); break;
2641         case 3: chr2_2(space->machine(), data, CHRROM); break;
2642         case 4: chr2_4(space->machine(), data, CHRROM); break;
2643         case 5: chr2_6(space->machine(), data, CHRROM); break;
2644         case 6: BIT(state->m_mmc_latch1, 6) ? prg8_cd(space->machine(), data) : prg8_89(space->machine(), data); break;
2645         case 7: prg8_ab(space->machine(), data); break;
2646         }
2647         break;
2648      case 0:
2649         state->m_mmc_latch1 = data;
2650         break;
2651   }
2652}
2653
2654/*************************************************************
2655
2656 Namcot 3425 board emulation
2657
2658 Games: Dragon Buster
2659
2660 These are similar Namcot 34x3, but with NT mirroring (two
2661 different modes)
2662
2663 iNES: mapper 95
2664
2665 *************************************************************/
2666
2667static WRITE8_HANDLER( namcot3425_w )
2668{
2669   nes_state *state = space->machine().driver_data<nes_state>();
2670   UINT8 mode;
2671   LOG_MMC(("namcot3425_w, offset: %04x, data: %02x\n", offset, data));
2672   if (offset >= 0x2000)
2673      return;
2674
2675   switch (offset & 1)
2676   {
2677      case 1:
2678         mode = state->m_mmc_latch1 & 0x07;
2679         switch (mode)
2680         {
2681         case 0: chr2_0(space->machine(), data >> 1, CHRROM); break;
2682         case 1: chr2_2(space->machine(), data >> 1, CHRROM); break;
2683         case 2:
2684         case 3:
2685         case 4:
2686         case 5:
2687            chr1_x(space->machine(), 2 + mode, data, CHRROM);
2688            state->m_mmc_reg[mode - 2] = BIT(data, 5);
2689            if (!BIT(state->m_mmc_latch1, 7))
2690            {
2691                  set_nt_page(space->machine(), 0, CIRAM, state->m_mmc_reg[0], 1);
2692                  set_nt_page(space->machine(), 1, CIRAM, state->m_mmc_reg[1], 1);
2693                  set_nt_page(space->machine(), 2, CIRAM, state->m_mmc_reg[2], 1);
2694                  set_nt_page(space->machine(), 3, CIRAM, state->m_mmc_reg[3], 1);
2695            }
2696            else
2697               set_nt_mirroring(space->machine(), PPU_MIRROR_HORZ);
2698            break;
2699         case 6: prg8_89(space->machine(), data); break;
2700         case 7: prg8_ab(space->machine(), data); break;
2701         }
2702         break;
2703      case 0:
2704         state->m_mmc_latch1 = data;
2705         break;
2706   }
2707}
2708
2709/*************************************************************
2710
2711 Discrete Logic board IC 74x377 by Color Dreams / Nina-007 emulation
2712
2713 Games: many Color Dreams and Wisdom Tree titles
2714
2715 iNES: mapper 11
2716
2717 In MESS: Supported
2718
2719 *************************************************************/
2720
2721static WRITE8_HANDLER( dis_74x377_w )
2722{
2723   nes_state *state = space->machine().driver_data<nes_state>();
2724   LOG_MMC(("dis_74x377_w, offset: %04x, data: %02x\n", offset, data));
2725
2726   chr8(space->machine(), data >> 4, state->m_mmc_chr_source);
2727   prg32(space->machine(), data & 0x0f);
2728}
2729
2730/*************************************************************
2731
2732 Discrete Logic board IC 74x139x74 by Konami & Jaleco
2733
2734 iNES: mapper 87
2735
2736 *************************************************************/
2737
2738static WRITE8_HANDLER( dis_74x139x74_m_w )
2739{
2740   LOG_MMC(("dis_74x139x74_m_w, offset: %04x, data: %02x\n", offset, data));
2741
2742   chr8(space->machine(), ((data & 0x02) >> 1) | ((data & 0x01) << 1), CHRROM);
2743}
2744
2745/*************************************************************
2746
2747 Discrete Logic board IC 74x161x138
2748
2749 Games: Crime Busters
2750
2751 iNES: mapper 38
2752
2753 *************************************************************/
2754
2755static WRITE8_HANDLER( dis_74x161x138_m_w )
2756{
2757   LOG_MMC(("dis_74x161x138_m_w, offset: %04x, data: %02x\n", offset, data));
2758
2759   chr8(space->machine(), data >> 2, CHRROM);
2760   prg32(space->machine(), data);
2761}
2762
2763/*************************************************************
2764
2765 Discrete Logic board IC 74x161x161x32
2766
2767 There are two variants (one with hardwired mirroring, the
2768 other with a mirroring control), making necessary two distinct
2769 mappers & pcb_id
2770
2771 iNES: mappers 70 & 152
2772
2773 *************************************************************/
2774
2775static WRITE8_HANDLER( dis_74x161x161x32_w )
2776{
2777   nes_state *state = space->machine().driver_data<nes_state>();
2778   LOG_MMC(("dis_74x161x161x32_w, offset: %04x, data: %02x\n", offset, data));
2779
2780   if (!state->m_hard_mirroring)   // there are two 'variants' depending on hardwired or mapper ctrl mirroring
2781      set_nt_mirroring(space->machine(), BIT(data, 7) ? PPU_MIRROR_HIGH : PPU_MIRROR_LOW);
2782   chr8(space->machine(), data, CHRROM);
2783   prg16_89ab(space->machine(), data >> 4);
2784}
2785
2786/*************************************************************
2787
2788 Bandai LZ93D50 boards emulation
2789
2790 There are several variants: plain board with or without SRAM,
2791 board + 24C01 EEPROM, board + 24C02 EEPROM, board + Barcode
2792 Reader (DATACH).
2793 We currently only emulate the base hardware.
2794
2795 Games: Crayon Shin-Chan - Ora to Poi Poi, Dragon Ball Z Gaiden,
2796 Dragon Ball Z II & III, Rokudenashi Blues, SD Gundam
2797 Gaiden - KGM2, Dragon Ball Z, Magical Taruruuto-kun, SD Gundam
2798 Gaiden [with EEPROM], Dragon Ball, Dragon Ball 3, Famicom Jump,
2799 Famicom Jump II [no EEPROM], Datach Games
2800
2801 At the moment, we don't support EEPROM I/O
2802
2803 iNES: mappers 16, 153, 157 & 159
2804
2805 In MESS: Supported
2806
2807 *************************************************************/
2808
2809/* Here, IRQ counter decrements every CPU cycle. Since we update it every scanline,
2810 we need to decrement it by 114 (Each scanline consists of 341 dots and, on NTSC,
2811 there are 3 dots to every 1 CPU cycle, hence 114 is the number of cycles per scanline ) */
2812static void bandai_lz_irq( device_t *device, int scanline, int vblank, int blanked )
2813{
2814   nes_state *state = device->machine().driver_data<nes_state>();
2815
2816   /* 114 is the number of cycles per scanline */
2817   /* TODO: change to reflect the actual number of cycles spent */
2818   if (state->m_IRQ_enable)
2819   {
2820      if (state->m_IRQ_count <= 114)
2821      {
2822         device_set_input_line(state->m_maincpu, M6502_IRQ_LINE, HOLD_LINE);
2823         state->m_IRQ_count = (0xffff - 114 + state->m_IRQ_count);   // wrap around the 16 bits counter
2824      }
2825      state->m_IRQ_count -= 114;
2826   }
2827}
2828
2829static WRITE8_HANDLER( lz93d50_w )
2830{
2831   nes_state *state = space->machine().driver_data<nes_state>();
2832   LOG_MMC(("lz93d50_w, offset: %04x, data: %02x\n", offset, data));
2833
2834   switch (offset & 0x000f)
2835   {
2836      case 0: case 1: case 2: case 3:
2837      case 4: case 5: case 6: case 7:
2838         chr1_x(space->machine(), offset & 0x07, data, state->m_mmc_chr_source);
2839         break;
2840      case 8:
2841         prg16_89ab(space->machine(), data);
2842         break;
2843      case 9:
2844         switch (data & 0x03)
2845         {
2846         case 0: set_nt_mirroring(space->machine(), PPU_MIRROR_VERT); break;
2847         case 1: set_nt_mirroring(space->machine(), PPU_MIRROR_HORZ); break;
2848         case 2: set_nt_mirroring(space->machine(), PPU_MIRROR_LOW); break;
2849         case 3: set_nt_mirroring(space->machine(), PPU_MIRROR_HIGH); break;
2850         }
2851         break;
2852      case 0x0a:
2853         state->m_IRQ_enable = data & 0x01;
2854         break;
2855      case 0x0b:
2856         state->m_IRQ_count = (state->m_IRQ_count & 0xff00) | data;
2857         break;
2858      case 0x0c:
2859         state->m_IRQ_count = (state->m_IRQ_count & 0x00ff) | (data << 8);
2860         break;
2861      default:
2862         logerror("lz93d50_w uncaught write, offset: %04x, data: %02x\n", offset, data);
2863         break;
2864   }
2865}
2866
2867static WRITE8_HANDLER( lz93d50_m_w )
2868{
2869   nes_state *state = space->machine().driver_data<nes_state>();
2870   LOG_MMC(("lz93d50_m_w, offset: %04x, data: %02x\n", offset, data));
2871
2872   if (!state->m_battery && !state->m_wram)
2873      lz93d50_w(space, offset & 0x0f, data);
2874   else if (state->m_battery)
2875      state->m_battery_ram[offset] = data;
2876   else
2877      state->m_wram[offset] = data;
2878}
2879
2880static void fjump2_set_prg( running_machine &machine )
2881{
2882   nes_state *state = machine.driver_data<nes_state>();
2883   UINT8 mmc_helper = 0;
2884   int i;
2885
2886   for (i = 0; i < 8; i++)
2887      mmc_helper |= ((state->m_mmc_reg[i] & 0x01) << 4);
2888
2889   prg16_89ab(machine, mmc_helper | state->m_mmc_latch1);
2890   prg16_cdef(machine, mmc_helper | 0x0f);
2891}
2892
2893static WRITE8_HANDLER( fjump2_w )
2894{
2895   nes_state *state = space->machine().driver_data<nes_state>();
2896   LOG_MMC(("fjump2_w, offset: %04x, data: %02x\n", offset, data));
2897
2898   switch (offset & 0x000f)
2899   {
2900      case 0: case 1: case 2: case 3:
2901      case 4: case 5: case 6: case 7:
2902         state->m_mmc_reg[offset & 0x000f] = data;
2903         fjump2_set_prg(space->machine());
2904         break;
2905      case 8:
2906         state->m_mmc_latch1 = (data & 0x0f);
2907         fjump2_set_prg(space->machine());
2908         break;
2909      default:
2910         lz93d50_m_w(space, offset & 0x0f, data);
2911         break;
2912   }
2913}
2914
2915/*************************************************************
2916
2917 Bandai Karaoke Studio board emulation
2918
2919 Games: Karaoke Studio
2920
2921 Note: we currently do not emulate the mic
2922
2923 iNES: mapper 188
2924
2925 *************************************************************/
2926
2927static WRITE8_HANDLER( bandai_ks_w )
2928{
2929   LOG_MMC(("bandai_ks_w, offset: %04x, data: %02x\n", offset, data));
2930
2931   prg16_89ab(space->machine(), data ^ 0x08);
2932}
2933
2934/*************************************************************
2935
2936 Bandai Oeka Kids board emulation
2937
2938 Games: Oeka Kids - Anpanman no Hiragana Daisuki, Oeka
2939 Kids - Anpanman to Oekaki Shiyou!!
2940
2941 iNES: mapper 96
2942
2943 In MESS: Preliminary Support.
2944
2945 *************************************************************/
2946
2947static WRITE8_HANDLER( bandai_ok_w )
2948{
2949   nes_state *state = space->machine().driver_data<nes_state>();
2950   UINT8 mmc_helper;
2951   LOG_MMC(("mapper96_w, offset: %04x, data: %02x\n", offset, data));
2952
2953   prg32(space->machine(), data);
2954
2955   state->m_mmc_latch1 = data;
2956   mmc_helper = (state->m_mmc_latch1 & 0x03) | (data & 0x04);
2957   chr4_0(space->machine(), mmc_helper, CHRRAM);
2958   chr4_4(space->machine(), 0x03 | (data & 0x04), CHRRAM);
2959}
2960
2961/*************************************************************
2962
2963 Irem LROG017 - Discrete board emulation (74*161/161/21/138)
2964
2965 Games: Napoleon Senki
2966
2967 iNES: mapper 77
2968
2969 *************************************************************/
2970
2971static WRITE8_HANDLER( lrog017_w )
2972{
2973   LOG_MMC(("lrog017_w, offset: %04x, data: %02x\n", offset, data));
2974
2975   prg32(space->machine(), data);
2976   chr2_0(space->machine(), (data >> 4), CHRROM);
2977}
2978
2979/*************************************************************
2980
2981 Irem Holy Diver board emulation
2982
2983 iNES: mapper 78 (shared with JF-16)
2984
2985 *************************************************************/
2986
2987static WRITE8_HANDLER( irem_hd_w )
2988{
2989   LOG_MMC(("irem_hd_w, offset: %04x, data: %02x\n", offset, data));
2990
2991   set_nt_mirroring(space->machine(), BIT(data, 3) ? PPU_MIRROR_VERT : PPU_MIRROR_HORZ);
2992   chr8(space->machine(), data >> 4, CHRROM);
2993   prg16_89ab(space->machine(), data);
2994}
2995
2996/*************************************************************
2997
2998 Irem TAM-S1 board emulation
2999
3000 Games: Kaiketsu Yanchamaru
3001
3002 iNES: mapper 97
3003
3004 In MESS: Supported.
3005
3006 *************************************************************/
3007
3008static WRITE8_HANDLER( tam_s1_w )
3009{
3010   LOG_MMC(("tam_s1_w, offset: %04x, data: %02x\n", offset, data));
3011
3012   if (offset < 0x4000)
3013   {
3014      set_nt_mirroring(space->machine(), BIT(data, 7) ? PPU_MIRROR_VERT : PPU_MIRROR_HORZ);
3015      prg16_cdef(space->machine(), data);
3016   }
3017}
3018
3019/*************************************************************
3020
3021 Irem G-101 board emulation
3022
3023 Major League uses hardwired mirroring
3024
3025 iNES: mapper 32
3026
3027 *************************************************************/
3028
3029static WRITE8_HANDLER( g101_w )
3030{
3031   nes_state *state = space->machine().driver_data<nes_state>();
3032   LOG_MMC(("g101_w, offset: %04x, data: %02x\n", offset, data));
3033
3034   switch (offset & 0x7000)
3035   {
3036      case 0x0000:
3037         // NEStopia here differs a little bit
3038         state->m_mmc_latch1 ? prg8_cd(space->machine(), data) : prg8_89(space->machine(), data);
3039         break;
3040      case 0x1000:
3041         state->m_mmc_latch1 = BIT(data, 1);
3042         if (!state->m_hard_mirroring)   // there are two 'variants' depending on hardwired or mapper ctrl mirroring
3043            set_nt_mirroring(space->machine(), BIT(data, 0) ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT);
3044         break;
3045      case 0x2000:
3046         prg8_ab(space->machine(), data);
3047         break;
3048      case 0x3000:
3049         chr1_x(space->machine(), offset & 0x07, data, CHRROM);
3050         break;
3051   }
3052}
3053
3054/*************************************************************
3055
3056 Irem H-3001 board emulation
3057
3058 Games: Daiku no Gen San 2 - Akage no Dan no Gyakushuu,
3059 Kaiketsu Yanchamaru 3, Spartan X 2
3060
3061 iNES: mapper 65
3062
3063 In MESS: Supported.
3064
3065 *************************************************************/
3066
3067/* Here, IRQ counter decrements every CPU cycle. Since we update it every scanline,
3068 we need to decrement it by 114 (Each scanline consists of 341 dots and, on NTSC,
3069 there are 3 dots to every 1 CPU cycle, hence 114 is the number of cycles per scanline ) */
3070static void h3001_irq( device_t *device, int scanline, int vblank, int blanked )
3071{
3072   nes_state *state = device->machine().driver_data<nes_state>();
3073   if (state->m_IRQ_enable)
3074   {
3075      state->m_IRQ_count -= 114;
3076
3077      if (state->m_IRQ_count <= 114)
3078      {
3079         state->m_IRQ_enable = 0;
3080         device_set_input_line(state->m_maincpu, M6502_IRQ_LINE, HOLD_LINE);
3081      }
3082   }
3083}
3084
3085static WRITE8_HANDLER( h3001_w )
3086{
3087   nes_state *state = space->machine().driver_data<nes_state>();
3088   LOG_MMC(("h3001_w, offset %04x, data: %02x\n", offset, data));
3089
3090   switch (offset & 0x7fff)
3091   {
3092      case 0x0000:
3093         prg8_89(space->machine(), data);
3094         break;
3095
3096      case 0x1001:
3097         set_nt_mirroring(space->machine(), BIT(data, 7) ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT);
3098         break;
3099
3100      case 0x1003:
3101         state->m_IRQ_enable = data & 0x80;
3102         break;
3103
3104      case 0x1004:
3105         state->m_IRQ_count = state->m_IRQ_count_latch;
3106         break;
3107
3108      case 0x1005:
3109         state->m_IRQ_count_latch = (state->m_IRQ_count_latch & 0x00ff) | (data << 8);
3110         break;
3111
3112      case 0x1006:
3113         state->m_IRQ_count_latch = (state->m_IRQ_count_latch & 0xff00) | data;
3114         break;
3115
3116      case 0x2000:
3117         prg8_ab(space->machine(), data);
3118         break;
3119
3120      case 0x3000: case 0x3001: case 0x3002: case 0x3003:
3121      case 0x3004: case 0x3005: case 0x3006: case 0x3007:
3122         chr1_x(space->machine(), offset & 0x07, data, CHRROM);
3123         break;
3124
3125      case 0x4000:
3126         prg8_cd(space->machine(), data);
3127         break;
3128
3129      default:
3130         break;
3131   }
3132}
3133
3134/*************************************************************
3135
3136 Jaleco SS88006 board emulation, aka JF-27, JF-29, JF-30, ...,
3137 JF-38, JF-40, JF-41
3138
3139 Games: Lord of King, Magic John, Moe Pro '90, Ninja Jajamaru,
3140 Pizza Pop, Plasma Ball
3141
3142 iNES: mapper 18
3143
3144 In MESS: Supported
3145
3146 *************************************************************/
3147
3148/* Here, IRQ counter decrements every CPU cycle. Since we update it every scanline,
3149 we need to decrement it by 114 (Each scanline consists of 341 dots and, on NTSC,
3150 there are 3 dots to every 1 CPU cycle, hence 114 is the number of cycles per scanline ) */
3151static void ss88006_irq( device_t *device, int scanline, int vblank, int blanked )
3152{
3153   nes_state *state = device->machine().driver_data<nes_state>();
3154
3155   /* Increment & check the IRQ scanline counter */
3156   if (state->m_IRQ_enable)
3157   {
3158      LOG_MMC(("scanline: %d, irq count: %04x\n", scanline, state->m_IRQ_count));
3159      if (state->m_IRQ_mode & 0x08)
3160      {
3161         if ((state->m_IRQ_count & 0x000f) < 114)   // always true, but we only update the IRQ once per scanlines so we cannot be more precise :(
3162         {
3163            device_set_input_line(state->m_maincpu, M6502_IRQ_LINE, HOLD_LINE);
3164            state->m_IRQ_count = (state->m_IRQ_count & ~0x000f) | (0x0f - (114 & 0x0f) + (state->m_IRQ_count & 0x000f)); // sort of wrap around the counter
3165         }
3166         // decrements should not affect upper bits, so we don't do anything here (114 > 0x0f)
3167      }
3168      else if (state->m_IRQ_mode & 0x04)
3169      {
3170         if ((state->m_IRQ_count & 0x00ff) < 114)
3171         {
3172            device_set_input_line(state->m_maincpu, M6502_IRQ_LINE, HOLD_LINE);
3173            state->m_IRQ_count = (state->m_IRQ_count & ~0x00ff) | (0xff - 114 + (state->m_IRQ_count & 0x00ff));   // wrap around the 8 bits counter
3174         }
3175         else
3176            state->m_IRQ_count -= 114;
3177      }
3178      else if (state->m_IRQ_mode & 0x02)
3179      {
3180         if ((state->m_IRQ_count & 0x0fff)  < 114)
3181         {
3182            device_set_input_line(state->m_maincpu, M6502_IRQ_LINE, HOLD_LINE);
3183            state->m_IRQ_count = (state->m_IRQ_count & ~0x0fff) | (0xfff - 114 + (state->m_IRQ_count & 0x0fff));   // wrap around the 12 bits counter
3184         }
3185         else
3186            state->m_IRQ_count -= 114;
3187      }
3188      else if (state->m_IRQ_count < 114)
3189      {
3190         device_set_input_line(state->m_maincpu, M6502_IRQ_LINE, HOLD_LINE);
3191         state->m_IRQ_count = (0xffff - 114 + state->m_IRQ_count);   // wrap around the 16 bits counter
3192      }
3193      else
3194         state->m_IRQ_count -= 114;
3195   }
3196}
3197
3198static WRITE8_HANDLER( ss88006_w )
3199{
3200   nes_state *state = space->machine().driver_data<nes_state>();
3201   UINT8 bank;
3202   LOG_MMC(("mapper18_w, offset: %04x, data: %02x\n", offset, data));
3203
3204   switch (offset & 0x7003)
3205   {
3206      case 0x0000:
3207         state->m_mmc_prg_bank[0] = (state->m_mmc_prg_bank[0] & 0xf0) | (data & 0x0f);
3208         prg8_89(space->machine(), state->m_mmc_prg_bank[0]);
3209         break;
3210      case 0x0001:
3211         state->m_mmc_prg_bank[0] = (state->m_mmc_prg_bank[0] & 0x0f) | (data << 4);
3212         prg8_89(space->machine(), state->m_mmc_prg_bank[0]);
3213         break;
3214      case 0x0002:
3215         state->m_mmc_prg_bank[1] = (state->m_mmc_prg_bank[1] & 0xf0) | (data & 0x0f);
3216         prg8_ab(space->machine(), state->m_mmc_prg_bank[1]);
3217         break;
3218      case 0x0003:
3219         state->m_mmc_prg_bank[1] = (state->m_mmc_prg_bank[1] & 0x0f) | (data << 4);
3220         prg8_ab(space->machine(), state->m_mmc_prg_bank[1]);
3221         break;
3222      case 0x1000:
3223         state->m_mmc_prg_bank[2] = (state->m_mmc_prg_bank[2] & 0xf0) | (data & 0x0f);
3224         prg8_cd(space->machine(), state->m_mmc_prg_bank[2]);
3225         break;
3226      case 0x1001:
3227         state->m_mmc_prg_bank[2] = (state->m_mmc_prg_bank[2] & 0x0f) | (data << 4);
3228         prg8_cd(space->machine(), state->m_mmc_prg_bank[2]);
3229         break;
3230
3231         /* $9002, 3 (1002, 3) uncaught = Jaleco Baseball writes 0 */
3232         /* believe it's related to battery-backed ram enable/disable */
3233
3234      case 0x2000: case 0x2001: case 0x2002: case 0x2003:
3235      case 0x3000: case 0x3001: case 0x3002: case 0x3003:
3236      case 0x4000: case 0x4001: case 0x4002: case 0x4003:
3237      case 0x5000: case 0x5001: case 0x5002: case 0x5003:
3238         bank = ((offset & 0x7000) - 0x2000) / 0x0800 + ((offset & 0x0002) >> 1);
3239         if (offset & 0x0001)
3240            state->m_mmc_vrom_bank[bank] = (state->m_mmc_vrom_bank[bank] & 0x0f) | ((data & 0x0f)<< 4);
3241         else
3242            state->m_mmc_vrom_bank[bank] = (state->m_mmc_vrom_bank[bank] & 0xf0) | (data & 0x0f);
3243
3244         chr1_x(space->machine(), bank, state->m_mmc_vrom_bank[bank], CHRROM);
3245         break;
3246
3247      case 0x6000:
3248         state->m_IRQ_count_latch = (state->m_IRQ_count_latch & 0xfff0) | (data & 0x0f);
3249         break;
3250      case 0x6001:
3251         state->m_IRQ_count_latch = (state->m_IRQ_count_latch & 0xff0f) | ((data & 0x0f) << 4);
3252         break;
3253      case 0x6002:
3254         state->m_IRQ_count_latch = (state->m_IRQ_count_latch & 0xf0ff) | ((data & 0x0f) << 8);
3255         break;
3256      case 0x6003:
3257         state->m_IRQ_count_latch = (state->m_IRQ_count_latch & 0x0fff) | ((data & 0x0f) << 12);
3258         break;
3259
3260      case 0x7000:
3261         state->m_IRQ_count = state->m_IRQ_count_latch;
3262         break;
3263      case 0x7001:
3264         state->m_IRQ_enable = data & 0x01;
3265         state->m_IRQ_mode = data & 0x0e;
3266         break;
3267
3268      case 0x7002:
3269         switch (data & 0x03)
3270         {
3271         case 0: set_nt_mirroring(space->machine(), PPU_MIRROR_HORZ); break;
3272         case 1: set_nt_mirroring(space->machine(), PPU_MIRROR_VERT); break;
3273         case 2: set_nt_mirroring(space->machine(), PPU_MIRROR_LOW); break;
3274         case 3: set_nt_mirroring(space->machine(), PPU_MIRROR_HIGH); break;
3275         }
3276         break;
3277
3278      default:
3279         logerror("Jaleco SS88006 uncaught write, addr: %04x, value: %02x\n", offset + 0x8000, data);
3280         break;
3281   }
3282}
3283
3284/*************************************************************
3285
3286 Jaleco JF-11, JF-12 & JF-14 boards emulation
3287
3288 Games: Bio Senshi Dan, Mississippi Satsujin Jiken
3289
3290 iNES: mapper 140
3291
3292 In MESS: Supported.
3293
3294 *************************************************************/
3295
3296static WRITE8_HANDLER( jf11_m_w )
3297{
3298   LOG_MMC(("jf11_m_w, offset: %04x, data: %02x\n", offset, data));
3299   chr8(space->machine(), data, CHRROM);
3300   prg32(space->machine(), data >> 4);
3301}
3302
3303/*************************************************************
3304
3305 Jaleco JF-13 board emulation
3306
3307 Games: Moero Pro Yakyuu
3308
3309 Note: we don't emulate the additional sound hardware.
3310
3311 iNES: mapper 86
3312
3313 In MESS: Supported.
3314
3315 *************************************************************/
3316
3317static WRITE8_HANDLER( jf13_m_w )
3318{
3319   LOG_MMC(("jf13_m_w, offset: %04x, data: %02x\n", offset, data));
3320
3321   if (offset == 0)
3322   {
3323      prg32(space->machine(), (data >> 4) & 0x03);
3324      chr8(space->machine(), ((data >> 4) & 0x04) | (data & 0x03), CHRROM);
3325   }
3326
3327   if (offset == 0x1000)
3328   {
3329      LOG_MMC(("Jaleco JF-13 sound write, data: %02x\n", data));
3330      // according to NEStopia, this is the effect
3331      if ((data & 0x30) == 0x20)
3332      {
3333         // send command (data & 0x1f) to sound chip
3334      }
3335   }
3336}
3337
3338/*************************************************************
3339
3340 Jaleco JF-16 board emulation
3341
3342 iNES: mapper 78 (shared with a diff Irem board)
3343
3344 *************************************************************/
3345
3346static WRITE8_HANDLER( jf16_w )
3347{
3348   LOG_MMC(("jf16_w, offset: %04x, data: %02x\n", offset, data));
3349
3350   set_nt_mirroring(space->machine(), BIT(data, 3) ? PPU_MIRROR_HIGH : PPU_MIRROR_LOW);
3351   chr8(space->machine(), data >> 4, CHRROM);
3352   prg16_89ab(space->machine(), data);
3353}
3354
3355/*************************************************************
3356
3357 Jaleco JF-17, JF-26 & JF-28 boards emulation
3358
3359 Note: we don't emulate the additional sound hardware.
3360
3361 Games: Moero!! Juudou Warriors, Moero!! Pro Tennis, Pinball
3362 Quest Jpn
3363
3364 iNES: mapper 72
3365
3366 In MESS: Supported.
3367
3368 *************************************************************/
3369
3370static WRITE8_HANDLER( jf17_w )
3371{
3372   LOG_MMC(("jf17_w, offset: %04x, data: %02x\n", offset, data));
3373
3374   if (BIT(data, 7))
3375      prg16_89ab(space->machine(), data & 0x0f);
3376   if (BIT(data, 6))
3377      chr8(space->machine(), data & 0x0f, CHRROM);
3378   if (BIT(data, 5) && !BIT(data,4))
3379      LOG_MMC(("Jaleco JF-17 sound write, data: %02x\n", data & 0x1f));
3380}
3381
3382/*************************************************************
3383
3384 Jaleco JF-19 & JF-21 boards emulation
3385
3386 Note: we don't emulate the additional sound hardware.
3387
3388 Games: Moero Pro Soccer, Moero Pro Yakyuu '88
3389
3390 iNES: mapper 92
3391
3392 In MESS: Supported (no samples).
3393
3394 *************************************************************/
3395
3396static WRITE8_HANDLER( jf19_w )
3397{
3398   LOG_MMC(("jf19_w, offset: %04x, data: %02x\n", offset, data));
3399
3400   if (BIT(data, 7))
3401      prg16_cdef(space->machine(), data & 0x0f);
3402   if (BIT(data, 6))
3403      chr8(space->machine(), data & 0x0f, CHRROM);
3404   if (BIT(data, 5) && !BIT(data,4))
3405      LOG_MMC(("Jaleco JF-19 sound write, data: %02x\n", data & 0x1f));
3406}
3407
3408/*************************************************************
3409
3410 Konami VRC1 and Jaleco JF20, JF22
3411
3412 Games: Exciting Boxing, Ganbare Goemon!, Tetsuwan Atom
3413
3414 iNES: mapper 75
3415
3416 In MESS: Supported.
3417
3418 *************************************************************/
3419
3420static WRITE8_HANDLER( konami_vrc1_w )
3421{
3422   nes_state *state = space->machine().driver_data<nes_state>();
3423   LOG_MMC(("konami_vrc1_w, offset: %04x, data: %02x\n", offset, data));
3424
3425   switch (offset & 0x7000)
3426   {
3427      case 0x0000:
3428         prg8_89(space->machine(), data);
3429         break;
3430      case 0x1000:
3431         set_nt_mirroring(space->machine(), (data & 0x01) ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT);
3432         state->m_mmc_vrom_bank[0] = (state->m_mmc_vrom_bank[0] & 0x0f) | ((data & 0x02) << 3);
3433         state->m_mmc_vrom_bank[1] = (state->m_mmc_vrom_bank[1] & 0x0f) | ((data & 0x04) << 2);
3434         chr4_0(space->machine(), state->m_mmc_vrom_bank[0], CHRROM);
3435         chr4_4(space->machine(), state->m_mmc_vrom_bank[1], CHRROM);
3436         break;
3437      case 0x2000:
3438         prg8_ab(space->machine(), data);
3439         break;
3440      case 0x4000:
3441         prg8_cd(space->machine(), data);
3442         break;
3443      case 0x6000:
3444         state->m_mmc_vrom_bank[0] = (state->m_mmc_vrom_bank[0] & 0x10) | (data & 0x0f);
3445         chr4_0(space->machine(), state->m_mmc_vrom_bank[0], CHRROM);
3446         break;
3447      case 0x7000:
3448         state->m_mmc_vrom_bank[1] = (state->m_mmc_vrom_bank[1] & 0x10) | (data & 0x0f);
3449         chr4_4(space->machine(), state->m_mmc_vrom_bank[1], CHRROM);
3450         break;
3451   }
3452}
3453
3454/*************************************************************
3455
3456 Konami VRC-2
3457
3458 In MESS: Supported.
3459
3460 *************************************************************/
3461
3462static WRITE8_HANDLER( konami_vrc2_w )
3463{
3464   nes_state *state = space->machine().driver_data<nes_state>();
3465   UINT8 bank, shift, mask;
3466   UINT32 shifted_offs = (offset & 0x7000)
3467                  | ((offset << (9 - state->m_vrc_ls_prg_a)) & 0x200)
3468                  | ((offset << (8 - state->m_vrc_ls_prg_b)) & 0x100);
3469   LOG_MMC(("konami_vrc2_w, offset: %04x, data: %02x\n", offset, data));
3470
3471   if (offset < 0x1000)
3472      prg8_89(space->machine(), data);
3473   else if (offset < 0x2000)
3474   {
3475      switch (data & 0x03)
3476      {
3477         case 0x00: set_nt_mirroring(space->machine(), PPU_MIRROR_VERT); break;
3478         case 0x01: set_nt_mirroring(space->machine(), PPU_MIRROR_HORZ); break;
3479         case 0x02: set_nt_mirroring(space->machine(), PPU_MIRROR_LOW); break;
3480         case 0x03: set_nt_mirroring(space->machine(), PPU_MIRROR_HIGH); break;
3481      }
3482   }
3483   else if (offset < 0x3000)
3484      prg8_ab(space->machine(), data);
3485   else if (offset < 0x7000)
3486   {
3487      bank = ((shifted_offs & 0x7000) - 0x3000) / 0x0800 + BIT(shifted_offs, 9);
3488      shift = BIT(shifted_offs, 8) * 4;
3489      mask = (0xf0 >> shift);
3490      state->m_mmc_vrom_bank[bank] = (state->m_mmc_vrom_bank[bank] & mask)
3491                           | (((data >> state->m_vrc_ls_chr) & 0x0f) << shift);
3492      chr1_x(space->machine(), bank, state->m_mmc_vrom_bank[bank], CHRROM);
3493   }
3494   else
3495      logerror("konami_vrc2_w uncaught write, addr: %04x value: %02x\n", offset + 0x8000, data);
3496}
3497
3498/*************************************************************
3499
3500 Konami VRC3
3501
3502 Games: Salamander
3503
3504 iNES: mapper 73
3505
3506 In MESS: Supported. It also uses konami_irq.
3507
3508 *************************************************************/
3509
3510static WRITE8_HANDLER( konami_vrc3_w )
3511{
3512   LOG_MMC(("konami_vrc3_w, offset: %04x, data: %02x\n", offset, data));
3513   nes_state *state = space->machine().driver_data<nes_state>();
3514
3515   switch (offset & 0x7000)
3516   {
3517      case 0x0000:
3518      case 0x1000:
3519         /* dunno which address controls these */
3520         state->m_IRQ_count_latch = data;
3521         state->m_IRQ_enable_latch = data;
3522         break;
3523      case 0x2000:
3524         state->m_IRQ_enable = data;
3525         break;
3526      case 0x3000:
3527         state->m_IRQ_count &= ~0x0f;
3528         state->m_IRQ_count |= data & 0x0f;
3529         break;
3530      case 0x4000:
3531         state->m_IRQ_count &= ~0xf0;
3532         state->m_IRQ_count |= (data & 0x0f) << 4;
3533         break;
3534      case 0x7000:
3535         prg16_89ab(space->machine(), data);
3536         break;
3537      default:
3538         logerror("konami_vrc3_w uncaught write, offset %04x, data: %02x\n", offset, data);
3539         break;
3540   }
3541}
3542
3543/*************************************************************
3544
3545 Konami VRC-4
3546
3547 In MESS: Supported
3548
3549 *************************************************************/
3550
3551static void vrc4_set_prg( running_machine &machine )
3552{
3553   nes_state *state = machine.driver_data<nes_state>();
3554   if (state->m_mmc_latch1 & 0x02)
3555   {
3556      prg8_89(machine, 0xfe);
3557      prg8_cd(machine, state->m_mmc_prg_bank[0]);
3558   }
3559   else
3560   {
3561      prg8_89(machine, state->m_mmc_prg_bank[0]);
3562      prg8_cd(machine, 0xfe);
3563   }
3564}
3565
3566static void konami_irq( device_t *device, int scanline, int vblank, int blanked )
3567{
3568   nes_state *state = device->machine().driver_data<nes_state>();
3569   /* Increment & check the IRQ scanline counter */
3570   if (state->m_IRQ_enable && (++state->m_IRQ_count == 0x100))
3571   {
3572      state->m_IRQ_count = state->m_IRQ_count_latch;
3573      state->m_IRQ_enable = state->m_IRQ_enable_latch;
3574      device_set_input_line(state->m_maincpu, M6502_IRQ_LINE, HOLD_LINE);
3575   }
3576}
3577
3578static WRITE8_HANDLER( konami_vrc4_w )
3579{
3580   nes_state *state = space->machine().driver_data<nes_state>();
3581   UINT8 bank, shift, mask;
3582   UINT32 shifted_offs = (offset & 0x7000)
3583                  | ((offset << (9 - state->m_vrc_ls_prg_a)) & 0x200)
3584                  | ((offset << (8 - state->m_vrc_ls_prg_b)) & 0x100);
3585   LOG_MMC(("konami_vrc4_w, offset: %04x, data: %02x\n", offset, data));
3586
3587   if (offset < 0x1000)
3588   {
3589      state->m_mmc_prg_bank[0] = data;
3590      vrc4_set_prg(space->machine());
3591   }
3592   else if (offset >= 0x2000 && offset < 0x3000)
3593      prg8_ab(space->machine(), data);
3594   else
3595   {
3596      switch (shifted_offs & 0x7300)
3597      {
3598         case 0x1000:
3599         case 0x1100:
3600            switch (data & 0x03)
3601            {
3602            case 0x00: set_nt_mirroring(space->machine(), PPU_MIRROR_VERT); break;
3603            case 0x01: set_nt_mirroring(space->machine(), PPU_MIRROR_HORZ); break;
3604            case 0x02: set_nt_mirroring(space->machine(), PPU_MIRROR_LOW); break;
3605            case 0x03: set_nt_mirroring(space->machine(), PPU_MIRROR_HIGH); break;
3606            }
3607            break;
3608         case 0x1200:
3609         case 0x1300:
3610            state->m_mmc_latch1 = data & 0x02;
3611            vrc4_set_prg(space->machine());
3612            break;
3613         case 0x3000:
3614         case 0x3100:
3615         case 0x3200:
3616         case 0x3300:
3617         case 0x4000:
3618         case 0x4100:
3619         case 0x4200:
3620         case 0x4300:
3621         case 0x5000:
3622         case 0x5100:
3623         case 0x5200:
3624         case 0x5300:
3625         case 0x6000:
3626         case 0x6100:
3627         case 0x6200:
3628         case 0x6300:
3629            bank = ((shifted_offs & 0x7000) - 0x3000) / 0x0800 + BIT(shifted_offs, 9);
3630            shift = BIT(shifted_offs, 8) * 4;
3631            mask = (0xf0 >> shift);
3632            state->m_mmc_vrom_bank[bank] = (state->m_mmc_vrom_bank[bank] & mask) | ((data & 0x0f) << shift);
3633            chr1_x(space->machine(), bank, state->m_mmc_vrom_bank[bank], CHRROM);
3634            break;
3635         case 0x7000:
3636            state->m_IRQ_count_latch = (state->m_IRQ_count_latch & 0xf0) | (data & 0x0f);
3637            break;
3638         case 0x7100:
3639            state->m_IRQ_count_latch = (state->m_IRQ_count_latch & 0x0f) | ((data & 0x0f) << 4);
3640            break;
3641         case 0x7200:
3642            state->m_IRQ_mode = data & 0x04;   // currently not implemented: 0 = prescaler mode / 1 = CPU mode
3643            state->m_IRQ_enable = data & 0x02;
3644            state->m_IRQ_enable_latch = data & 0x01;
3645            if (data & 0x02)
3646               state->m_IRQ_count = state->m_IRQ_count_latch;
3647            break;
3648         case 0x7300:
3649            state->m_IRQ_enable = state->m_IRQ_enable_latch;
3650            break;
3651         default:
3652            logerror("konami_vrc4_w uncaught write, addr: %04x value: %02x\n", shifted_offs + 0x8000, data);
3653            break;
3654      }
3655   }
3656}
3657
3658/*************************************************************
3659
3660 Konami VRC-6
3661
3662 In MESS: Supported. It also uses konami_irq (there are IRQ
3663 issues though: see Akumajou Densetsu intro).
3664
3665 *************************************************************/
3666
3667static WRITE8_HANDLER( konami_vrc6_w )
3668{
3669   nes_state *state = space->machine().driver_data<nes_state>();
3670   UINT8 bank;
3671   UINT32 shifted_offs = (offset & 0x7000)
3672                  | ((offset << (9 - state->m_vrc_ls_prg_a)) & 0x200)
3673                  | ((offset << (8 - state->m_vrc_ls_prg_b)) & 0x100);
3674   LOG_MMC(("konami_vrc6_w, offset: %04x, data: %02x\n", offset, data));
3675
3676   if (offset < 0x1000)
3677      prg16_89ab(space->machine(), data);
3678   else if (offset >= 0x4000 && offset < 0x5000)
3679      prg8_cd(space->machine(), data);
3680   else
3681   {
3682      switch (shifted_offs & 0x7300)
3683      {
3684         case 0x1000:
3685         case 0x1100:
3686         case 0x1200:
3687         case 0x2000:
3688         case 0x2100:
3689         case 0x2200:
3690         case 0x3000:
3691         case 0x3100:
3692         case 0x3200:
3693            LOG_MMC(("Konami VRC-6 Sound write, offset: %04x, data: %02x\n", shifted_offs & 0x7300, data));
3694            break;
3695         case 0x3300:
3696            switch (data & 0x0c)
3697            {
3698            case 0x00: set_nt_mirroring(space->machine(), PPU_MIRROR_VERT); break;
3699            case 0x04: set_nt_mirroring(space->machine(), PPU_MIRROR_HORZ); break;
3700            case 0x08: set_nt_mirroring(space->machine(), PPU_MIRROR_LOW); break;
3701            case 0x0c: set_nt_mirroring(space->machine(), PPU_MIRROR_HIGH); break;
3702            }
3703            break;
3704         case 0x5000:
3705         case 0x5100:
3706         case 0x5200:
3707         case 0x5300:
3708         case 0x6000:
3709         case 0x6100:
3710         case 0x6200:
3711         case 0x6300:
3712            bank = ((shifted_offs & 0x7000) - 0x5000) / 0x0400 + ((shifted_offs & 0x0300) >> 8);
3713            chr1_x(space->machine(), bank, data, CHRROM);
3714            break;
3715         case 0x7000:
3716            state->m_IRQ_count_latch = data;
3717            break;
3718         case 0x7100:
3719            state->m_IRQ_mode = data & 0x04;   // currently not implemented: 0 = prescaler mode / 1 = CPU mode
3720            state->m_IRQ_enable = data & 0x02;
3721            state->m_IRQ_enable_latch = data & 0x01;
3722            if (data & 0x02)
3723               state->m_IRQ_count = state->m_IRQ_count_latch;
3724            break;
3725         case 0x7200:
3726            state->m_IRQ_enable = state->m_IRQ_enable_latch;
3727            break;
3728         default:
3729            logerror("konami_vrc6_w uncaught write, addr: %04x value: %02x\n", shifted_offs + 0x8000, data);
3730            break;
3731      }
3732   }
3733}
3734
3735/*************************************************************
3736
3737 Konami VRC7
3738
3739 Games: Lagrange Point, Tiny Toon Adventures 2
3740
3741 iNES: mapper 85
3742
3743 In MESS: Supported. It also uses konami_irq.
3744
3745 *************************************************************/
3746
3747static WRITE8_HANDLER( konami_vrc7_w )
3748{
3749   nes_state *state = space->machine().driver_data<nes_state>();
3750   UINT8 bank;
3751   LOG_MMC(("konami_vrc7_w, offset: %04x, data: %02x\n", offset, data));
3752
3753   switch (offset & 0x7018)
3754   {
3755      case 0x0000:
3756         prg8_89(space->machine(), data);
3757         break;
3758      case 0x0008:
3759      case 0x0010:
3760      case 0x0018:
3761         prg8_ab(space->machine(), data);
3762         break;
3763
3764      case 0x1000:
3765         prg8_cd(space->machine(), data);
3766         break;
3767
3768         /* TODO: there are sound regs in here */
3769
3770      case 0x2000:
3771      case 0x2008:
3772      case 0x2010:
3773      case 0x2018:
3774      case 0x3000:
3775      case 0x3008:
3776      case 0x3010:
3777      case 0x3018:
3778      case 0x4000:
3779      case 0x4008:
3780      case 0x4010:
3781      case 0x4018:
3782      case 0x5000:
3783      case 0x5008:
3784      case 0x5010:
3785      case 0x5018:
3786         bank = ((offset & 0x7000) - 0x2000) / 0x0800 + ((offset & 0x0018) ? 1 : 0);
3787         chr1_x(space->machine(), bank, data, state->m_mmc_chr_source);
3788         break;
3789
3790      case 0x6000:
3791         switch (data & 0x03)
3792         {
3793         case 0x00: set_nt_mirroring(space->machine(), PPU_MIRROR_VERT); break;
3794         case 0x01: set_nt_mirroring(space->machine(), PPU_MIRROR_HORZ); break;
3795         case 0x02: set_nt_mirroring(space->machine(), PPU_MIRROR_LOW); break;
3796         case 0x03: set_nt_mirroring(space->machine(), PPU_MIRROR_HIGH); break;
3797         }
3798         break;
3799      case 0x6008: case 0x6010: case 0x6018:
3800         state->m_IRQ_count_latch = data;
3801         break;
3802      case 0x7000:
3803         state->m_IRQ_mode = data & 0x04;   // currently not implemented: 0 = prescaler mode / 1 = CPU mode
3804         state->m_IRQ_enable = data & 0x02;
3805         state->m_IRQ_enable_latch = data & 0x01;
3806         if (data & 0x02)
3807            state->m_IRQ_count = state->m_IRQ_count_latch;
3808         break;
3809      case 0x7008: case 0x7010: case 0x7018:
3810         state->m_IRQ_enable = state->m_IRQ_enable_latch;
3811         break;
3812
3813      default:
3814         logerror("konami_vrc7_w uncaught write, addr: %04x value: %02x\n", offset + 0x8000, data);
3815         break;
3816   }
3817}
3818
3819/*************************************************************
3820
3821 Namcot-163 board emulation
3822
3823 Games: Battle Fleet, Family Circuit '91, Famista '90, '91,
3824 '92 & '94, Megami Tensei II, Top Striker, Wagyan Land 2 & 3
3825
3826 iNES: mapper 19
3827
3828 In MESS: Supported
3829
3830 *************************************************************/
3831
3832/* Here, IRQ counter decrements every CPU cycle. Since we update it every scanline,
3833 we need to decrement it by 114 (Each scanline consists of 341 dots and, on NTSC,
3834 there are 3 dots to every 1 CPU cycle, hence 114 is the number of cycles per scanline ) */
3835static void namcot_irq( device_t *device, int scanline, int vblank, int blanked )
3836{
3837   nes_state *state = device->machine().driver_data<nes_state>();
3838
3839   if (state->m_IRQ_enable)
3840   {
3841      if (state->m_IRQ_count >= (0x7fff - 114))
3842      {
3843         device_set_input_line(state->m_maincpu, M6502_IRQ_LINE, HOLD_LINE);
3844         state->m_IRQ_count = 0;
3845      }
3846      else
3847         state->m_IRQ_count += 114;
3848   }
3849}
3850
3851static WRITE8_HANDLER( namcot163_l_w )
3852{
3853   nes_state *state = space->machine().driver_data<nes_state>();
3854   LOG_MMC(("namcot163_l_w, offset: %04x, data: %02x\n", offset, data));
3855   offset += 0x100;
3856
3857   switch (offset & 0x1800)
3858   {
3859      case 0x0800:
3860         LOG_MMC(("Namcot-163 sound reg write, data: %02x\n", data));
3861         break;
3862      case 0x1000: /* low byte of IRQ */
3863         state->m_IRQ_count = (state->m_IRQ_count & 0x7f00) | data;
3864         break;
3865      case 0x1800: /* high byte of IRQ, IRQ enable in high bit */
3866         state->m_IRQ_count = (state->m_IRQ_count & 0xff) | ((data & 0x7f) << 8);
3867         state->m_IRQ_enable = data & 0x80;
3868         break;
3869   }
3870}
3871
3872static READ8_HANDLER( namcot163_l_r )
3873{
3874   nes_state *state = space->machine().driver_data<nes_state>();
3875   LOG_MMC(("namcot163_l_r, offset: %04x\n", offset));
3876   offset += 0x100;
3877
3878   switch (offset & 0x1800)
3879   {
3880      case 0x1000:
3881         return state->m_IRQ_count & 0xff;
3882      case 0x1800:
3883         return (state->m_IRQ_count >> 8) & 0xff;
3884      case 0x0800:
3885         LOG_MMC(("Namcot-163 sound reg read\n"));
3886      default:
3887         return 0x00;
3888   }
3889}
3890
3891static void namcot163_set_mirror( running_machine &machine, UINT8 page, UINT8 data )
3892{
3893   if (!(data < 0xe0))
3894      set_nt_page(machine, page, CIRAM, data & 0x01, 1);
3895   else
3896      set_nt_page(machine, page, ROM, data, 0);
3897}
3898
3899static WRITE8_HANDLER( namcot163_w )
3900{
3901   nes_state *state = space->machine().driver_data<nes_state>();
3902   LOG_MMC(("namcot163_w, offset: %04x, data: %02x\n", offset, data));
3903   switch (offset & 0x7800)
3904   {
3905      case 0x0000: case 0x0800:
3906      case 0x1000: case 0x1800:
3907      case 0x2000: case 0x2800:
3908      case 0x3000: case 0x3800:
3909         chr1_x(space->machine(), offset / 0x800, data, CHRROM);
3910         break;
3911      case 0x4000:
3912         namcot163_set_mirror(space->machine(), 0, data);
3913         break;
3914      case 0x4800:
3915         namcot163_set_mirror(space->machine(), 1, data);
3916         break;
3917      case 0x5000:
3918         namcot163_set_mirror(space->machine(), 2, data);
3919         break;
3920      case 0x5800:
3921         namcot163_set_mirror(space->machine(), 3, data);
3922         break;
3923      case 0x6000:
3924         prg8_89(space->machine(), data & 0x3f);
3925         break;
3926      case 0x6800:
3927         state->m_mmc_latch1 = data & 0xc0;      // this should enable High CHRRAM, but we still have to properly implement it!
3928         prg8_ab(space->machine(), data & 0x3f);
3929         break;
3930      case 0x7000:
3931         prg8_cd(space->machine(), data & 0x3f);
3932         break;
3933      case 0x7800:
3934         LOG_MMC(("Namcot-163 sound address write, data: %02x\n", data));
3935         break;
3936   }
3937}
3938
3939/*************************************************************
3940
3941 Sunsoft-1 board emulation
3942
3943 Games: Atlantis no Nazo, Kanshakudama Nage Kantarou no
3944 Toukaidou Gojuusan Tsugi, Wing of Madoola, Fantasy Zone
3945
3946 iNES: mapper 184 (Fantasy Zone uses this board with no
3947 CHRROM, and the register switches PRG banks)
3948
3949 *************************************************************/
3950
3951static WRITE8_HANDLER( sunsoft1_m_w )
3952{
3953   nes_state *state = space->machine().driver_data<nes_state>();
3954   LOG_MMC(("sunsoft1_m_w, offset: %04x, data: %02x\n", offset, data));
3955
3956   if (state->m_chr_chunks)
3957   {
3958      chr4_0(space->machine(), data & 0x0f, CHRROM);
3959      chr4_4(space->machine(), data >> 4, CHRROM);
3960   }
3961   else
3962      prg16_89ab(space->machine(), data & 0x0f);
3963}
3964
3965/*************************************************************
3966
3967 Sunsoft-2 board emulation
3968
3969 The two games using this board have incompatible mirroring
3970 wiring, making necessary two distinct mappers & pcb_id
3971
3972 iNES: mapper 89 & 93
3973
3974 *************************************************************/
3975
3976static WRITE8_HANDLER( sunsoft2_w )
3977{
3978   nes_state *state = space->machine().driver_data<nes_state>();
3979   UINT8 sunsoft_helper = (data & 0x07) | ((data & 0x80) ? 0x08 : 0x00);
3980   LOG_MMC(("sunsoft2_w, offset: %04x, data: %02x\n", offset, data));
3981
3982   if (!state->m_hard_mirroring)   // there are two 'variants' depending on hardwired or mapper ctrl mirroring
3983      set_nt_mirroring(space->machine(), BIT(data, 3) ? PPU_MIRROR_HIGH : PPU_MIRROR_LOW);
3984   if (state->m_chr_chunks)
3985      chr8(space->machine(), sunsoft_helper, CHRROM);
3986
3987   prg16_89ab(space->machine(), data >> 4);
3988}
3989
3990/*************************************************************
3991
3992 Sunsoft-3 board emulation
3993
3994 The two games using this board have incompatible mirroring
3995 wiring, making necessary two distinct mappers & pcb_id
3996
3997 iNES: mapper 67
3998
3999 *************************************************************/
4000
4001/* Here, IRQ counter decrements every CPU cycle. Since we update it every scanline,
4002 we need to decrement it by 114 (Each scanline consists of 341 dots and, on NTSC,
4003 there are 3 dots to every 1 CPU cycle, hence 114 is the number of cycles per scanline ) */
4004static void sunsoft3_irq( device_t *device, int scanline, int vblank, int blanked )
4005{
4006   nes_state *state = device->machine().driver_data<nes_state>();
4007
4008   /* TODO: change to reflect the actual number of cycles spent: both using 114 or cycling 114,114,113
4009     produces a 1-line glitch in Fantasy Zone 2: it really requires the counter to be updated each CPU cycle! */
4010   if (state->m_IRQ_enable)
4011   {
4012      if (state->m_IRQ_count <= 114)
4013      {
4014         state->m_IRQ_enable = 0;
4015         state->m_IRQ_count = 0xffff;
4016         device_set_input_line(state->m_maincpu, M6502_IRQ_LINE, HOLD_LINE);
4017      }
4018      else
4019         state->m_IRQ_count -= 114;
4020   }
4021}
4022
4023static WRITE8_HANDLER( sunsoft3_w )
4024{
4025   nes_state *state = space->machine().driver_data<nes_state>();
4026   LOG_MMC(("sunsoft3_w, offset %04x, data: %02x\n", offset, data));
4027
4028   switch (offset & 0x7800)
4029   {
4030      case 0x0800:
4031         chr2_0(space->machine(), data, CHRROM);
4032         break;
4033      case 0x1800:
4034         chr2_2(space->machine(), data, CHRROM);
4035         break;
4036      case 0x2800:
4037         chr2_4(space->machine(), data, CHRROM);
4038         break;
4039      case 0x3800:
4040         chr2_6(space->machine(), data, CHRROM);
4041         break;
4042      case 0x4000:
4043      case 0x4800:
4044         state->m_IRQ_toggle ^= 1;
4045         if (state->m_IRQ_toggle)
4046            state->m_IRQ_count = (state->m_IRQ_count & 0x00ff) | (data << 8);
4047         else
4048            state->m_IRQ_count = (state->m_IRQ_count & 0xff00) | data;
4049         break;
4050      case 0x5800:
4051         state->m_IRQ_enable = BIT(data, 4);
4052         state->m_IRQ_toggle = 0;
4053         break;
4054      case 0x6800:
4055         switch (data & 3)
4056         {
4057         case 0x00: set_nt_mirroring(space->machine(), PPU_MIRROR_VERT); break;
4058         case 0x01: set_nt_mirroring(space->machine(), PPU_MIRROR_HORZ); break;
4059         case 0x02: set_nt_mirroring(space->machine(), PPU_MIRROR_LOW); break;
4060         case 0x03: set_nt_mirroring(space->machine(), PPU_MIRROR_HIGH); break;
4061         }
4062         break;
4063      case 0x7800:
4064         prg16_89ab(space->machine(), data);
4065         break;
4066      default:
4067         LOG_MMC(("sunsoft3_w uncaught write, offset: %04x, data: %02x\n", offset, data));
4068         break;
4069   }
4070}
4071
4072/*************************************************************
4073
4074 Taito TC0190FMC + board emulation
4075
4076 Games: Akira, Bakushou!! Jinsei Gekijou, Don Doko Don,
4077 Insector X, Operation Wolf, Power Blazer, Takeshi no
4078 Sengoku Fuuunji
4079
4080 iNES: mapper 33
4081
4082 In MESS: Supported.
4083
4084 *************************************************************/
4085
4086static WRITE8_HANDLER( tc0190fmc_w )
4087{
4088   LOG_MMC(("tc0190fmc_w, offset: %04x, data: %02x\n", offset, data));
4089
4090   switch (offset & 0x7003)
4091   {
4092      case 0x0000:
4093         set_nt_mirroring(space->machine(), BIT(data, 6) ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT);
4094         prg8_89(space->machine(), data);
4095         break;
4096      case 0x0001:
4097         prg8_ab(space->machine(), data);
4098         break;
4099      case 0x0002:
4100         chr2_0(space->machine(), data, CHRROM);
4101         break;
4102      case 0x0003:
4103         chr2_2(space->machine(), data, CHRROM);
4104         break;
4105      case 0x2000:
4106         chr1_4(space->machine(), data, CHRROM);
4107         break;
4108      case 0x2001:
4109         chr1_5(space->machine(), data, CHRROM);
4110         break;
4111      case 0x2002:
4112         chr1_6(space->machine(), data, CHRROM);
4113         break;
4114      case 0x2003:
4115         chr1_7(space->machine(), data, CHRROM);
4116         break;
4117   }
4118}
4119
4120/*************************************************************
4121
4122 Taito TC0190FMC + PAL16R4 board emulation
4123
4124 Games: Bakushou!! Jinsei Gekijou 3, Bubble Bobble 2,
4125 Captain Saver, Don Doko Don 2, Flintstones, Jetsons
4126
4127 This is basically Mapper 33 + IRQ. Notably, IRQ works the
4128 same as MMC3 irq, BUT latch values are "inverted" (XOR'ed
4129 with 0xff) and there is a little delay (not implemented yet)
4130 We simply use MMC3 IRQ and XOR the value written in the
4131 register 0xc000 below
4132
4133 iNES: mapper 48
4134
4135 In MESS: Supported.
4136
4137 *************************************************************/
4138
4139static WRITE8_HANDLER( tc0190fmc_p16_w )
4140{
4141   nes_state *state = space->machine().driver_data<nes_state>();
4142   LOG_MMC(("tc0190fmc_p16_w, offset: %04x, data: %02x\n", offset, data));
4143
4144   switch (offset & 0x7003)
4145   {
4146      case 0x0000:
4147         prg8_89(space->machine(), data);
4148         break;
4149      case 0x0001:
4150      case 0x0002:
4151      case 0x0003:
4152      case 0x2000:
4153      case 0x2001:
4154      case 0x2002:
4155      case 0x2003:
4156         tc0190fmc_w(space, offset, data);
4157         break;
4158      case 0x4000:
4159         state->m_IRQ_count_latch = (0x100 - data) & 0xff;
4160         break;
4161      case 0x4001:
4162         state->m_IRQ_count = state->m_IRQ_count_latch;
4163         break;
4164      case 0x4002:
4165         state->m_IRQ_enable = 1;
4166         break;
4167      case 0x4003:
4168         state->m_IRQ_enable = 0;
4169         break;
4170      case 0x6000:
4171         set_nt_mirroring(space->machine(), BIT(data, 6) ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT);
4172         break;
4173   }
4174}
4175
4176/*************************************************************
4177
4178 Taito X1-005 board emulation
4179
4180 Actually, Fudou Myouou Den uses a variant of the board with
4181 CIRAM, making necessary two distinct mappers & pcb_id.
4182
4183 Also, we miss to emulate the security check at 0x7ef8 / 0x7ef9
4184 and the 0x80 ram!
4185
4186 iNES: mappers 80 & 207
4187
4188 *************************************************************/
4189
4190static WRITE8_HANDLER( x1005_m_w )
4191{
4192   nes_state *state = space->machine().driver_data<nes_state>();
4193   LOG_MMC(("x1005_m_w, offset: %04x, data: %02x\n", offset, data));
4194
4195   switch (offset)
4196   {
4197      case 0x1ef0:
4198         chr2_0(space->machine(), (data & 0x7f) >> 1, CHRROM);
4199         break;
4200      case 0x1ef1:
4201         chr2_2(space->machine(), (data & 0x7f) >> 1, CHRROM);
4202         break;
4203      case 0x1ef2:
4204         chr1_4(space->machine(), data, CHRROM);
4205         break;
4206      case 0x1ef3:
4207         chr1_5(space->machine(), data, CHRROM);
4208         break;
4209      case 0x1ef4:
4210         chr1_6(space->machine(), data, CHRROM);
4211         break;
4212      case 0x1ef5:
4213         chr1_7(space->machine(), data, CHRROM);
4214         break;
4215      case 0x1ef6:
4216      case 0x1ef7:
4217         set_nt_mirroring(space->machine(), BIT(data, 0) ? PPU_MIRROR_VERT : PPU_MIRROR_HORZ);
4218         break;
4219      case 0x1ef8:
4220      case 0x1ef9:
4221         state->m_mmc_latch1 = data;
4222         break;
4223      case 0x1efa:
4224      case 0x1efb:
4225         prg8_89(space->machine(), data);
4226         break;
4227      case 0x1efc:
4228      case 0x1efd:
4229         prg8_ab(space->machine(), data);
4230         break;
4231      case 0x1efe:
4232      case 0x1eff:
4233         prg8_cd(space->machine(), data);
4234         break;
4235      default:
4236         logerror("mapper80_m_w uncaught addr: %04x, value: %02x\n", offset + 0x6000, data);
4237         break;
4238   }
4239
4240   if (offset >= 0x1f00 && state->m_mapper_ram != NULL && state->m_mmc_latch1 == 0xa3)
4241      state->m_mapper_ram[offset & (state->m_mapper_ram_size - 1)] = data;
4242   else if (offset >= 0x1f00 && state->m_mapper_bram != NULL && state->m_mmc_latch1 == 0xa3)
4243      state->m_mapper_bram[offset & (state->m_mapper_bram_size - 1)] = data;
4244}
4245
4246static READ8_HANDLER( x1005_m_r )
4247{
4248   nes_state *state = space->machine().driver_data<nes_state>();
4249   LOG_MMC(("x1005a_m_r, offset: %04x\n", offset));
4250
4251   if (offset >= 0x1f00 && state->m_mapper_ram != NULL && state->m_mmc_latch1 == 0xa3)
4252      return state->m_mapper_ram[offset & (state->m_mapper_ram_size - 1)];
4253   else if (offset >= 0x1f00 && state->m_mapper_bram != NULL && state->m_mmc_latch1 == 0xa3)
4254      return state->m_mapper_bram[offset & (state->m_mapper_bram_size - 1)];
4255
4256   return 0xff;
4257}
4258
4259static WRITE8_HANDLER( x1005a_m_w )
4260{
4261   LOG_MMC(("x1005a_m_w, offset: %04x, data: %02x\n", offset, data));
4262
4263   // similar to x1005_m_w but mirroring is handled differently
4264   if (offset == 0x1ef6 || offset == 0x1ef7)
4265      return;
4266
4267   switch (offset)
4268   {
4269      case 0x1ef0:
4270         set_nt_page(space->machine(), 0, CIRAM, (data & 0x80) ? 1 : 0, 1);
4271         set_nt_page(space->machine(), 1, CIRAM, (data & 0x80) ? 1 : 0, 1);
4272         break;
4273      case 0x1ef1:
4274         set_nt_page(space->machine(), 2, CIRAM, (data & 0x80) ? 1 : 0, 1);
4275         set_nt_page(space->machine(), 3, CIRAM, (data & 0x80) ? 1 : 0, 1);
4276         break;
4277   }
4278
4279   x1005_m_w(space, offset, data);
4280}
4281
4282/*************************************************************
4283
4284 Taito X1-017 board emulation
4285
4286 We miss to emulate the security check at 0x6000-0x73ff
4287 and the ram!
4288
4289 Games: Kyuukyoku Harikiri Koushien, Kyuukyoku Harikiri
4290 Stadium, SD Keiji - Blader
4291
4292 iNES: mapper 82
4293
4294 In MESS: Supported.
4295
4296 *************************************************************/
4297
4298static void x1017_set_chr( running_machine &machine )
4299{
4300   nes_state *state = machine.driver_data<nes_state>();
4301   if (state->m_mmc_latch1)
4302   {
4303      chr2_4(machine, state->m_mmc_vrom_bank[0] >> 1, CHRROM);
4304      chr2_6(machine, state->m_mmc_vrom_bank[1] >> 1, CHRROM);
4305   }
4306   else
4307   {
4308      chr2_0(machine, state->m_mmc_vrom_bank[0] >> 1, CHRROM);
4309      chr2_2(machine, state->m_mmc_vrom_bank[1] >> 1, CHRROM);
4310   }
4311   chr1_x(machine, 4 ^ state->m_mmc_latch1, state->m_mmc_vrom_bank[2], CHRROM);
4312   chr1_x(machine, 5 ^ state->m_mmc_latch1, state->m_mmc_vrom_bank[3], CHRROM);
4313   chr1_x(machine, 6 ^ state->m_mmc_latch1, state->m_mmc_vrom_bank[4], CHRROM);
4314   chr1_x(machine, 7 ^ state->m_mmc_latch1, state->m_mmc_vrom_bank[5], CHRROM);
4315}
4316
4317static WRITE8_HANDLER( x1017_m_w )
4318{
4319   nes_state *state = space->machine().driver_data<nes_state>();
4320   UINT8 reg = offset & 0x07;
4321   LOG_MMC(("x1017_m_w, offset: %04x, data: %02x\n", offset, data));
4322
4323   switch (offset)
4324   {
4325      case 0x1ef0:
4326      case 0x1ef1:
4327         if (state->m_mmc_vrom_bank[reg] != data)
4328         {
4329            state->m_mmc_vrom_bank[reg] = data;
4330            x1017_set_chr(space->machine());
4331         }
4332         break;
4333      case 0x1ef2:
4334      case 0x1ef3:
4335      case 0x1ef4:
4336      case 0x1ef5:
4337         if (state->m_mmc_vrom_bank[reg] != data)
4338         {
4339            state->m_mmc_vrom_bank[reg] = data;
4340            x1017_set_chr(space->machine());
4341         }
4342         break;
4343      case 0x1ef6:
4344         set_nt_mirroring(space->machine(), BIT(data, 0) ? PPU_MIRROR_VERT : PPU_MIRROR_HORZ);
4345         state->m_mmc_latch1 = ((data & 0x02) << 1);
4346         x1017_set_chr(space->machine());
4347         break;
4348      case 0x1ef7:
4349      case 0x1ef8:
4350      case 0x1ef9:
4351         state->m_mmc_reg[(offset & 0x0f) - 7] = data;
4352         break;
4353      case 0x1efa:
4354         prg8_89(space->machine(), data >> 2);
4355         break;
4356      case 0x1efb:
4357         prg8_ab(space->machine(), data >> 2);
4358         break;
4359      case 0x1efc:
4360         prg8_cd(space->machine(), data >> 2);
4361         break;
4362      default:
4363         logerror("x1017_m_w uncaught write, addr: %04x, value: %02x\n", offset + 0x6000, data);
4364         break;
4365   }
4366}
4367
4368static READ8_HANDLER( x1017_m_r )
4369{
4370   nes_state *state = space->machine().driver_data<nes_state>();
4371   LOG_MMC(("x1017_m_r, offset: %04x\n", offset));
4372
4373   // 2+2+1 KB of Internal RAM can be independently enabled/disabled!
4374   if (offset < 0x0800 && state->m_mapper_bram != NULL && state->m_mmc_reg[0] == 0xca)
4375      return state->m_mapper_bram[offset & (state->m_mapper_bram_size - 1)];
4376   if (offset < 0x1000 && state->m_mapper_bram != NULL && state->m_mmc_reg[1] == 0x69)
4377      return state->m_mapper_bram[offset & (state->m_mapper_bram_size - 1)];
4378   if (offset < 0x1800 && state->m_mapper_bram != NULL && state->m_mmc_reg[2] == 0x84)
4379      return state->m_mapper_bram[offset & (state->m_mapper_bram_size - 1)];
4380
4381   return 0xff;
4382}
4383
4384/*************************************************************
4385
4386      MISC UNLICENSED BOARDS
4387
4388 *************************************************************/
4389
4390/*************************************************************
4391
4392 AGCI 50282 bootleg board emulation
4393
4394 Games: Death Race
4395
4396 iNES: mapper 144
4397
4398 In MESS: Supported.
4399
4400 *************************************************************/
4401
4402static WRITE8_HANDLER( agci_50282_w )
4403{
4404   LOG_MMC(("agci_50282_w, offset: %04x, data: %02x\n", offset, data));
4405
4406   offset += 0x8000;
4407   data |= (space->read_byte(offset) & 1);
4408
4409   chr8(space->machine(), data >> 4, CHRROM);
4410   prg32(space->machine(), data);
4411}
4412
4413/*************************************************************
4414
4415 AVE NINA-001 board emulation
4416
4417 iNES: mapper 34
4418
4419 *************************************************************/
4420
4421static WRITE8_HANDLER( nina01_m_w )
4422{
4423   LOG_MMC(("nina01_m_w, offset: %04x, data: %02x\n", offset, data));
4424
4425   switch (offset)
4426   {
4427      case 0x1ffd:
4428         prg32(space->machine(), data);
4429         break;
4430      case 0x1ffe:
4431         chr4_0(space->machine(), data, CHRROM);
4432         break;
4433      case 0x1fff:
4434         chr4_4(space->machine(), data, CHRROM);
4435         break;
4436   }
4437}
4438
4439/*************************************************************
4440
4441 AVE NINA-003, NINA-006 and MB-91 boards emulation
4442
4443 Games: Krazy Kreatures, Poke Block, Puzzle, Pyramid,
4444 Solitaire, Ultimate League Soccer
4445
4446 iNES: mapper 79
4447
4448 In MESS: Supported.
4449
4450 *************************************************************/
4451
4452static WRITE8_HANDLER( nina06_l_w )
4453{
4454   LOG_MMC(("nina06_l_w, offset: %04x, data: %02x\n", offset, data));
4455
4456   if (!(offset & 0x0100))
4457   {
4458      prg32(space->machine(), data >> 3);
4459      chr8(space->machine(), data, CHRROM);
4460   }
4461}
4462
4463/*************************************************************
4464
4465 Active Entertainment Action 52 board emulation
4466
4467 iNES: mapper 228
4468
4469 *************************************************************/
4470
4471static WRITE8_HANDLER( ae_act52_w )
4472{
4473   int pbank, cbank;
4474   UINT8 pmode;
4475   LOG_MMC(("ae_act52_w, offset: %04x, data: %02x\n", offset, data));
4476
4477   set_nt_mirroring(space->machine(), BIT(offset, 13) ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT);
4478
4479   cbank = (data & 0x03) | ((offset & 0x0f) << 2);
4480   chr8(space->machine(), cbank, CHRROM);
4481
4482   pmode = offset & 0x20;
4483   pbank = (offset & 0x1fc0) >> 6;
4484   if (pmode)
4485   {
4486      prg16_89ab(space->machine(), pbank);
4487      prg16_cdef(space->machine(), pbank);
4488   }
4489   else
4490      prg32(space->machine(), pbank >> 1);
4491}
4492
4493
4494/*************************************************************
4495
4496 C & E Bootleg Board for Decathlon
4497
4498 Games: Decathlon
4499
4500 Pretty simple mapper: writes to 0x8065-0x80a4 set prg32 to
4501 data & 3; writes to 0x80a5-0x80e4 set chr8 to data & 7
4502
4503 iNES: mapper 244
4504
4505 In MESS: Supported.
4506
4507 *************************************************************/
4508
4509static WRITE8_HANDLER( cne_decathl_w )
4510{
4511   LOG_MMC(("cne_decathl_w, offset: %04x, data: %02x\n", offset, data));
4512
4513   if (offset < 0x0065)
4514      return;
4515   if (offset < 0x00a5)
4516   {
4517      prg32(space->machine(), (offset - 0x0065) & 0x03);
4518      return;
4519   }
4520   if (offset < 0x00e5)
4521   {
4522      chr8(space->machine(), (offset - 0x00a5) & 0x07, CHRROM);
4523   }
4524}
4525
4526/*************************************************************
4527
4528 C & E Bootleg Board for Fong Shen Bang
4529
4530 Games: Fong Shen Bang - Zhu Lu Zhi Zhan
4531
4532 Simple mapper: writes to 0x6000-0x67ff set PRG and CHR banks.
4533 Namely, 0x6000->0x6003 select resp. prg8_89, prg8_ab, prg8_cd
4534 and prg8_ef. 0x6004->0x6007 select resp. crh2_0, chr2_2,
4535 chr2_4 and chr2_6. In 0x6800-0x7fff lies WRAM.
4536
4537 iNES: mapper 246
4538
4539 In MESS: Supported.
4540
4541 *************************************************************/
4542
4543static WRITE8_HANDLER( cne_fsb_m_w )
4544{
4545   nes_state *state = space->machine().driver_data<nes_state>();
4546   LOG_MMC(("cne_fsb_m_w, offset: %04x, data: %02x\n", offset, data));
4547
4548   if (offset < 0x0800)
4549   {
4550      switch (offset & 0x0007)
4551      {
4552         case 0x0000:
4553            prg8_89(space->machine(), data);
4554            break;
4555         case 0x0001:
4556            prg8_ab(space->machine(), data);
4557            break;
4558         case 0x0002:
4559            prg8_cd(space->machine(), data);
4560            break;
4561         case 0x0003:
4562            prg8_ef(space->machine(), data);
4563            break;
4564         case 0x0004:
4565            chr2_0(space->machine(), data, CHRROM);
4566            break;
4567         case 0x0005:
4568            chr2_2(space->machine(), data, CHRROM);
4569            break;
4570         case 0x0006:
4571            chr2_4(space->machine(), data, CHRROM);
4572            break;
4573         case 0x0007:
4574            chr2_6(space->machine(), data, CHRROM);
4575            break;
4576      }
4577   }
4578   else
4579      state->m_battery_ram[offset] = data;
4580}
4581
4582/*************************************************************
4583
4584 C & E Bootleg Board for Sheng Huo Lie Zhuan
4585
4586 Games: Jing Ke Xin Zhuan, Sheng Huo Lie Zhuan
4587
4588 Simple Mapper: writes to 0x4020-0x5fff sets prg32 to
4589 data>>4 and chr8 to data&f. We currently do not map
4590 writes to 0x4020-0x40ff (to do: verify if this produces
4591 issues)
4592
4593 iNES: mapper 240
4594
4595 In MESS: Supported.
4596
4597 *************************************************************/
4598
4599static WRITE8_HANDLER( cne_shlz_l_w )
4600{
4601   LOG_MMC(("cne_shlz_l_w, offset: %04x, data: %02x\n", offset, data));
4602
4603   prg32(space->machine(), data >> 4);
4604   chr8(space->machine(), data & 0x0f, CHRROM);
4605}
4606
4607/*************************************************************
4608
4609 Caltron 6 in 1 Board
4610
4611 Games: 6 in 1 by Caltron
4612
4613 iNES: mapper 41
4614
4615 In MESS: Supported.
4616
4617 *************************************************************/
4618
4619static WRITE8_HANDLER( caltron6in1_m_w )
4620{
4621   nes_state *state = space->machine().driver_data<nes_state>();
4622   LOG_MMC(("caltron6in1_m_w, offset: %04x, data: %02x\n", offset, data));
4623
4624   state->m_mmc_latch1 = offset & 0xff;
4625   set_nt_mirroring(space->machine(), BIT(data, 5) ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT);
4626   prg32(space->machine(), offset & 0x07);
4627}
4628
4629static WRITE8_HANDLER( caltron6in1_w )
4630{
4631   nes_state *state = space->machine().driver_data<nes_state>();
4632   LOG_MMC(("caltron6in1_w, offset: %04x, data: %02x\n", offset, data));
4633
4634   if (state->m_mmc_latch1 & 0x04)
4635      chr8(space->machine(), ((state->m_mmc_latch1 & 0x18) >> 1) | (data & 0x03), CHRROM);
4636}
4637
4638/*************************************************************
4639
4640 Camerica Boards (BF9093, BF9097, BF909X, ALGNV11)
4641
4642 Games: Linus Spacehead's Cosmic Crusade, Micro Machines,
4643 Mig-29, Stunt Kids
4644
4645 To emulate NT mirroring for BF9097 board (missing in BF9093)
4646 we use crc_hack, however Fire Hawk is broken (but without
4647 mirroring there would be no helicopter graphics).
4648
4649 iNES: mapper 71
4650
4651 In MESS: Partially Supported.
4652
4653 *************************************************************/
4654
4655static WRITE8_HANDLER( bf9093_w )
4656{
4657   nes_state *state = space->machine().driver_data<nes_state>();
4658   LOG_MMC(("bf9093_w, offset: %04x, data: %02x\n", offset, data));
4659
4660   switch (offset & 0x7000)
4661   {
4662      case 0x0000:
4663      case 0x1000:
4664         if (!state->m_hard_mirroring)
4665            set_nt_mirroring(space->machine(), BIT(data, 4) ? PPU_MIRROR_HIGH : PPU_MIRROR_LOW);
4666         break;
4667      case 0x4000:
4668      case 0x5000:
4669      case 0x6000:
4670      case 0x7000:
4671         prg16_89ab(space->machine(), data);
4672         break;
4673   }
4674}
4675
4676/*************************************************************
4677
4678 Camerica BF9096 & ALGQV11 Boards
4679
4680 Games: Quattro Adventure, Quattro Arcade, Quattro Sports
4681
4682 Writes to 0x8000-0x9fff set prg block to (data&0x18)>>1,
4683 writes to 0xa000-0xbfff set prg page to data&3. selected
4684 prg are: prg16_89ab = block|page, prg_cdef = 3|page.
4685 For more info on the hardware to bypass the NES lockout, see
4686 Kevtris' Camerica Mappers documentation.
4687
4688 iNES: mapper 232
4689
4690 In MESS: Supported.
4691
4692 *************************************************************/
4693
4694static void bf9096_set_prg( running_machine &machine )
4695{
4696   nes_state *state = machine.driver_data<nes_state>();
4697   prg16_89ab(machine, (state->m_mmc_latch2 & 0x03) | ((state->m_mmc_latch1 & 0x18) >> 1));
4698   prg16_cdef(machine, 0x03 | ((state->m_mmc_latch1 & 0x18) >> 1));
4699}
4700
4701static WRITE8_HANDLER( bf9096_w )
4702{
4703   nes_state *state = space->machine().driver_data<nes_state>();
4704   LOG_MMC(("bf9096_w, offset: %04x, data: %02x\n", offset, data));
4705
4706   if (offset < 0x2000)
4707      state->m_mmc_latch1 = data;
4708   else
4709      state->m_mmc_latch2 = data;
4710
4711   bf9096_set_prg(space->machine());
4712}
4713
4714/*************************************************************
4715
4716 Camerica Golden Five board
4717
4718 Games: Pegasus 5 in 1
4719
4720 iNES: mapper 104
4721
4722 In MESS: Supported.
4723
4724 *************************************************************/
4725
4726static WRITE8_HANDLER( golden5_w )
4727{
4728   nes_state *state = space->machine().driver_data<nes_state>();
4729   LOG_MMC(("golden5_w, offset: %04x, data: %02x\n", offset, data));
4730
4731   if (offset < 0x4000)
4732   {
4733      if (data & 0x08)
4734      {
4735         state->m_mmc_prg_bank[0] = ((data & 0x07) << 4) | (state->m_mmc_prg_bank[0] & 0x0f);
4736         prg16_89ab(space->machine(), state->m_mmc_prg_bank[0]);
4737         prg16_cdef(space->machine(), ((data & 0x07) << 4) | 0x0f);
4738      }
4739
4740   }
4741   else
4742   {
4743      state->m_mmc_prg_bank[0] = (state->m_mmc_prg_bank[0] & 0x70) | (data & 0x0f);
4744      prg16_89ab(space->machine(), state->m_mmc_prg_bank[0]);
4745   }
4746}
4747
4748/*************************************************************
4749
4750 Cony Bootleg Board
4751
4752 Games: Dragon Ball Party, Fatal Fury 2, Street Blaster II
4753 Pro, World Heroes 2
4754
4755 iNES: mapper 83
4756
4757 In MESS: Supported.
4758
4759 *************************************************************/
4760
4761static WRITE8_HANDLER( cony_l_w )
4762{
4763   nes_state *state = space->machine().driver_data<nes_state>();
4764   LOG_MMC(("cony_l_w, offset: %04x, data: %02x\n", offset, data));
4765
4766   if (offset >= 0x1000 && offset < 0x1103) // from 0x5100-0x51ff
4767      state->m_mapper83_low_reg[offset & 0x03] = data;
4768}
4769
4770static READ8_HANDLER( cony_l_r )
4771{
4772   nes_state *state = space->machine().driver_data<nes_state>();
4773   LOG_MMC(("cony_l_r, offset: %04x\n", offset));
4774
4775   if (offset == 0x0f00)   // 0x5000
4776   {
4777      // read dipswitch bit! - currently unimplemented
4778   }
4779   if (offset >= 0x1000 && offset < 0x1103) // from 0x5100-0x51ff
4780      return state->m_mapper83_low_reg[offset & 0x03];
4781   else
4782      return 0x00;
4783}
4784
4785static void cony_set_prg( running_machine &machine )
4786{
4787   nes_state *state = machine.driver_data<nes_state>();
4788   prg16_89ab(machine, state->m_mapper83_reg[8] & 0x3f);
4789   prg16_cdef(machine, (state->m_mapper83_reg[8] & 0x30) | 0x0f);
4790}
4791
4792static void cony_set_chr( running_machine &machine )
4793{
4794   nes_state *state = machine.driver_data<nes_state>();
4795   // FIXME: here we emulate at least 3 different boards!!!
4796   // one board switches 1k VROM banks only
4797   // one writes to 0x8000 and then switches 2k VROM banks only
4798   // one writes to 0x831n (n=2,3,4,5) and then switches 2k VROM banks only
4799   // we should split them and possibly document the proper behavior of each variant
4800   if (state->m_mmc_latch1 && !state->m_mmc_latch2)
4801   {
4802      chr2_0(machine, state->m_mapper83_reg[0], CHRROM);
4803      chr2_2(machine, state->m_mapper83_reg[1], CHRROM);
4804      chr2_4(machine, state->m_mapper83_reg[6], CHRROM);
4805      chr2_6(machine, state->m_mapper83_reg[7], CHRROM);
4806   }
4807   else
4808   {
4809      chr1_0(machine, state->m_mapper83_reg[0] | ((state->m_mapper83_reg[8] & 0x30) << 4), CHRROM);
4810      chr1_1(machine, state->m_mapper83_reg[1] | ((state->m_mapper83_reg[8] & 0x30) << 4), CHRROM);
4811      chr1_2(machine, state->m_mapper83_reg[2] | ((state->m_mapper83_reg[8] & 0x30) << 4), CHRROM);
4812      chr1_3(machine, state->m_mapper83_reg[3] | ((state->m_mapper83_reg[8] & 0x30) << 4), CHRROM);
4813      chr1_4(machine, state->m_mapper83_reg[4] | ((state->m_mapper83_reg[8] & 0x30) << 4), CHRROM);
4814      chr1_5(machine, state->m_mapper83_reg[5] | ((state->m_mapper83_reg[8] & 0x30) << 4), CHRROM);
4815      chr1_6(machine, state->m_mapper83_reg[6] | ((state->m_mapper83_reg[8] & 0x30) << 4), CHRROM);
4816      chr1_7(machine, state->m_mapper83_reg[7] | ((state->m_mapper83_reg[8] & 0x30) << 4), CHRROM);
4817   }
4818}
4819
4820static WRITE8_HANDLER( cony_w )
4821{
4822   nes_state *state = space->machine().driver_data<nes_state>();
4823   LOG_MMC(("cony_w, offset: %04x, data: %02x\n", offset, data));
4824
4825   switch (offset)
4826   {
4827      case 0x0000:
4828         state->m_mmc_latch1 = 1;
4829      case 0x3000:
4830      case 0x30ff:
4831      case 0x31ff:
4832         state->m_mapper83_reg[8] = data;
4833         cony_set_prg(space->machine());
4834         cony_set_chr(space->machine());
4835         break;
4836      case 0x0100:
4837         state->m_mmc_reg[0] = data & 0x80;
4838         switch (data & 0x03)
4839         {
4840         case 0:
4841            set_nt_mirroring(space->machine(), PPU_MIRROR_VERT);
4842            break;
4843         case 1:
4844            set_nt_mirroring(space->machine(), PPU_MIRROR_HORZ);
4845            break;
4846         case 2:
4847            set_nt_mirroring(space->machine(), PPU_MIRROR_LOW);
4848            break;
4849         case 3:
4850            set_nt_mirroring(space->machine(), PPU_MIRROR_HIGH);
4851            break;
4852         }
4853         break;
4854      case 0x0200:
4855         state->m_IRQ_count = (state->m_IRQ_count & 0xff00) | data;
4856         break;
4857      case 0x0201:
4858         state->m_IRQ_enable = state->m_mmc_reg[0];
4859         state->m_IRQ_count = (data << 8) | (state->m_IRQ_count & 0xff);
4860         break;
4861      case 0x0300:
4862         prg8_89(space->machine(), data);
4863         break;
4864      case 0x0301:
4865         prg8_ab(space->machine(), data);
4866         break;
4867      case 0x0302:
4868         prg8_cd(space->machine(), data);
4869         break;
4870      case 0x0312:
4871      case 0x0313:
4872      case 0x0314:
4873      case 0x0315:
4874         state->m_mmc_latch2 = 1;
4875      case 0x0310:
4876      case 0x0311:
4877      case 0x0316:
4878      case 0x0317:
4879         state->m_mapper83_reg[offset - 0x0310] = data;
4880         cony_set_chr(space->machine());
4881         break;
4882      case 0x0318:
4883         state->m_mapper83_reg[9] = data;
4884         cony_set_prg(space->machine());
4885         break;
4886   }
4887}
4888
4889/*************************************************************
4890
4891 Board DREAMTECH01
4892
4893 Games: Korean Igo
4894
4895 In MESS: Supported
4896
4897 *************************************************************/
4898
4899static WRITE8_HANDLER( dreamtech_l_w )
4900{
4901   LOG_MMC(("dreamtech_l_w offset: %04x, data: %02x\n", offset, data));
4902   offset += 0x100;
4903
4904   if (offset == 0x1020)   /* 0x5020 */
4905      prg16_89ab(space->machine(), data);
4906}
4907
4908/*************************************************************
4909
4910 Bootleg Board by Fukutake
4911
4912 Games: Study Box
4913
4914 iNES: mapper 186
4915
4916 In MESS: Unsupported.
4917
4918
4919 *************************************************************/
4920
4921static WRITE8_HANDLER( fukutake_l_w )
4922{
4923   nes_state *state = space->machine().driver_data<nes_state>();
4924   LOG_MMC(("fukutake_l_w offset: %04x, data: %02x\n", offset, data));
4925   offset += 0x100;
4926
4927   if (offset >= 0x200 && offset < 0x400)
4928   {
4929      if (offset & 1)
4930         prg16_89ab(space->machine(), data);
4931      else
4932         wram_bank(space->machine(), data >> 6, NES_WRAM);
4933   }
4934   else if (offset >= 0x400 && offset < 0xf00)
4935      state->m_mapper_ram[offset - 0x400] = data;
4936}
4937
4938static READ8_HANDLER( fukutake_l_r )
4939{
4940   nes_state *state = space->machine().driver_data<nes_state>();
4941   LOG_MMC(("fukutake_l_r offset: %04x\n", offset));
4942   offset += 0x100;
4943
4944   if (offset >= 0x200 && offset < 0x400)
4945   {
4946      if (offset == 0x200 || offset == 0x201 || offset == 0x203)
4947         return 0x00;
4948      else if (offset == 0x202)
4949         return 0x40;
4950      else
4951         return 0xff;
4952   }
4953   else if (offset >= 0x400 && offset < 0xf00)
4954      return state->m_mapper_ram[offset - 0x400];
4955
4956   return 0;
4957}
4958
4959/*************************************************************
4960
4961 Bootleg Board by Future Media
4962
4963 Games: Crayon Shin-chan (C), San Guo Zhi 4 - Chi Bi Feng Yun
4964
4965 iNES: mapper 117
4966
4967 In MESS: Unsupported.
4968
4969 *************************************************************/
4970
4971static void futuremedia_irq( device_t *device, int scanline, int vblank, int blanked )
4972{
4973   nes_state *state = device->machine().driver_data<nes_state>();
4974   //  if (scanline < PPU_BOTTOM_VISIBLE_SCANLINE)
4975   {
4976      if (state->m_IRQ_enable && state->m_IRQ_count)
4977      {
4978         state->m_IRQ_count--;
4979         if (!state->m_IRQ_count)
4980            device_set_input_line(state->m_maincpu, M6502_IRQ_LINE, HOLD_LINE);
4981      }
4982   }
4983}
4984
4985static WRITE8_HANDLER( futuremedia_w )
4986{
4987   nes_state *state = space->machine().driver_data<nes_state>();
4988   LOG_MMC(("futuremedia_w, offset: %04x, data: %02x\n", offset, data));
4989
4990   switch (offset)
4991   {
4992      case 0x0000:
4993         prg8_89(space->machine(), data);
4994         break;
4995      case 0x0001:
4996         prg8_ab(space->machine(), data);
4997         break;
4998      case 0x0002:
4999         prg8_cd(space->machine(), data);
5000         break;
5001      case 0x0003:
5002         prg8_ef(space->machine(), data);
5003         break;
5004      case 0x2000:
5005      case 0x2001:
5006      case 0x2002:
5007      case 0x2003:
5008      case 0x2004:
5009      case 0x2005:
5010      case 0x2006:
5011      case 0x2007:
5012         chr1_x(space->machine(), offset & 0x07, data, CHRROM);
5013         break;
5014
5015      case 0x5000:
5016         set_nt_mirroring(space->machine(), BIT(data, 0) ?  PPU_MIRROR_HORZ : PPU_MIRROR_VERT);
5017         break;
5018
5019      case 0x4001:
5020         state->m_IRQ_count_latch = data;
5021         break;
5022      case 0x4002:
5023         // IRQ cleared
5024         break;
5025      case 0x4003:
5026         state->m_IRQ_count = state->m_IRQ_count_latch;
5027         break;
5028      case 0x6000:
5029         state->m_IRQ_enable = data & 0x01;
5030         break;
5031   }
5032}
5033
5034/*************************************************************
5035
5036 Bootleg Board 37017 (?) by Gouder
5037
5038 Games: Street Fighter IV
5039
5040 MMC3 clone. It also requires reads from 0x5000-0x7fff.
5041
5042 iNES: mapper 208
5043
5044 In MESS: Preliminary Support.
5045
5046 *************************************************************/
5047
5048static WRITE8_HANDLER( gouder_sf4_l_w )
5049{
5050   nes_state *state = space->machine().driver_data<nes_state>();
5051   static const UINT8 conv_table[256] =
5052   {
5053      0x59,0x59,0x59,0x59,0x59,0x59,0x59,0x59,0x59,0x49,0x19,0x09,0x59,0x49,0x19,0x09,
5054      0x59,0x59,0x59,0x59,0x59,0x59,0x59,0x59,0x51,0x41,0x11,0x01,0x51,0x41,0x11,0x01,
5055      0x59,0x59,0x59,0x59,0x59,0x59,0x59,0x59,0x59,0x49,0x19,0x09,0x59,0x49,0x19,0x09,
5056      0x59,0x59,0x59,0x59,0x59,0x59,0x59,0x59,0x51,0x41,0x11,0x01,0x51,0x41,0x11,0x01,
5057      0x00,0x10,0x40,0x50,0x00,0x10,0x40,0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
5058      0x08,0x18,0x48,0x58,0x08,0x18,0x48,0x58,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
5059      0x00,0x10,0x40,0x50,0x00,0x10,0x40,0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
5060      0x08,0x18,0x48,0x58,0x08,0x18,0x48,0x58,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
5061      0x59,0x59,0x59,0x59,0x59,0x59,0x59,0x59,0x58,0x48,0x18,0x08,0x58,0x48,0x18,0x08,
5062      0x59,0x59,0x59,0x59,0x59,0x59,0x59,0x59,0x50,0x40,0x10,0x00,0x50,0x40,0x10,0x00,
5063      0x59,0x59,0x59,0x59,0x59,0x59,0x59,0x59,0x58,0x48,0x18,0x08,0x58,0x48,0x18,0x08,
5064      0x59,0x59,0x59,0x59,0x59,0x59,0x59,0x59,0x50,0x40,0x10,0x00,0x50,0x40,0x10,0x00,
5065      0x01,0x11,0x41,0x51,0x01,0x11,0x41,0x51,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
5066      0x09,0x19,0x49,0x59,0x09,0x19,0x49,0x59,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
5067      0x01,0x11,0x41,0x51,0x01,0x11,0x41,0x51,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
5068      0x09,0x19,0x49,0x59,0x09,0x19,0x49,0x59,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
5069   };
5070
5071   LOG_MMC(("gouder_sf4_l_w, offset: %04x, data: %02x\n", offset, data));
5072
5073   if (!(offset < 0x1700))
5074      state->m_mmc_reg[offset & 0x03] = data ^ conv_table[state->m_mmc_reg[4]];
5075   else if (!(offset < 0xf00))
5076      state->m_mmc_reg[4] = data;
5077   else if (!(offset < 0x700))
5078      prg32(space->machine(), ((data >> 3) & 0x02) | (data & 0x01));
5079}
5080
5081static READ8_HANDLER( gouder_sf4_l_r )
5082{
5083   nes_state *state = space->machine().driver_data<nes_state>();
5084   LOG_MMC(("gouder_sf4_l_r, offset: %04x\n", offset));
5085
5086   if (!(offset < 0x1700))
5087      return state->m_mmc_reg[offset & 0x03];
5088
5089   return 0x00;
5090}
5091
5092/* writes to 0x8000-0xffff are like MMC3 but no PRG bankswitch (beacuse it is handled by low writes) */
5093static void gouder_sf4_prg_cb( running_machine &machine, int start, int bank )
5094{
5095   return;
5096}
5097
5098
5099/*************************************************************
5100
5101 Bootleg Board by Henggedianzi
5102
5103 Games: Mei Guo Fu Hao, Shang Gu Shen Jian , Wang Zi Fu
5104 Chou Ji
5105
5106 Writes to 0x8000-0xffff set prg32. Moreover, data&0x20 sets
5107 NT mirroring.
5108
5109 iNES: mapper 177
5110
5111 In MESS: Supported.
5112
5113 *************************************************************/
5114
5115static WRITE8_HANDLER( henggedianzi_w )
5116{
5117   LOG_MMC(("henggedianzi_w, offset: %04x, data: %02x\n", offset, data));
5118
5119   prg32(space->machine(), data);
5120   set_nt_mirroring(space->machine(), BIT(data, 5) ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT);
5121}
5122
5123/*************************************************************
5124
5125 Bootleg Board by Henggedianzi
5126
5127 Games: Xing He Zhan Shi
5128
5129 Writes to 0x5000-0x5fff set prg32 banks, writes to 0x8000-
5130 0xffff set NT mirroring
5131
5132 iNES: mapper 179
5133
5134 In MESS: Supported.
5135
5136 *************************************************************/
5137
5138static WRITE8_HANDLER( heng_xjzb_l_w )
5139{
5140   LOG_MMC(("heng_xjzb_l_w, offset: %04x, data: %02x\n", offset, data));
5141   offset += 0x4100;
5142
5143   if (offset & 0x5000)
5144      prg32(space->machine(), data >> 1);
5145}
5146
5147static WRITE8_HANDLER( heng_xjzb_w )
5148{
5149   LOG_MMC(("heng_xjzb_w, offset: %04x, data: %02x\n", offset, data));
5150
5151   set_nt_mirroring(space->machine(), BIT(data, 0) ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT);
5152}
5153
5154/*************************************************************
5155
5156 Bootleg Board by HES (also used by others)
5157
5158 Games: AV Hanafuda Club, AV Soccer, Papillon, Sidewinder,
5159 Total Funpack
5160
5161 Actually, two variant: one for HES 6-in-1 with mirroring control
5162 and one for AV Soccer and others with hardwired mirroring
5163
5164 iNES: mapper 113
5165
5166 In MESS: Supported.
5167
5168 *************************************************************/
5169
5170static WRITE8_HANDLER( hes6in1_l_w )
5171{
5172   LOG_MMC(("hes6in1_l_w, offset: %04x, data: %02x\n", offset, data));
5173
5174   if (!(offset & 0x100))
5175   {
5176      prg32(space->machine(), (data & 0x38) >> 3);
5177      chr8(space->machine(), (data & 0x07) | ((data & 0x40) >> 3), CHRROM);
5178      set_nt_mirroring(space->machine(), BIT(data, 7) ? PPU_MIRROR_VERT : PPU_MIRROR_HORZ);
5179   }
5180}
5181
5182static WRITE8_HANDLER( hes_l_w )
5183{
5184   LOG_MMC(("hes_l_w, offset: %04x, data: %02x\n", offset, data));
5185
5186   if (!(offset & 0x100))
5187   {
5188      prg32(space->machine(), (data & 0x38) >> 3);
5189      chr8(space->machine(), (data & 0x07) | ((data & 0x40) >> 3), CHRROM);
5190   }
5191}
5192
5193/*************************************************************
5194
5195 Bootleg Board by Hosenkan
5196
5197 Games: Pocahontas, Super Donkey Kong
5198
5199 iNES: mapper 182
5200
5201 In MESS: Supported.
5202
5203 *************************************************************/
5204
5205static WRITE8_HANDLER( hosenkan_w )
5206{
5207   nes_state *state = space->machine().driver_data<nes_state>();
5208   LOG_MMC(("hosenkan_w, offset: %04x, data: %02x\n", offset, data));
5209
5210   switch (offset & 0x7003)
5211   {
5212      case 0x0001:
5213         set_nt_mirroring(space->machine(), BIT(data, 0) ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT);
5214         break;
5215      case 0x2000:
5216         state->m_mmc_latch1 = data;
5217         break;
5218      case 0x4000:
5219         switch (state->m_mmc_latch1)
5220      {
5221         case 0:
5222            chr2_0(space->machine(), data >> 1, CHRROM);
5223            break;
5224         case 1:
5225            chr1_5(space->machine(), data, CHRROM);
5226            break;
5227         case 2:
5228            chr2_2(space->machine(), data >> 1, CHRROM);
5229            break;
5230         case 3:
5231            chr1_7(space->machine(), data, CHRROM);
5232            break;
5233         case 4:
5234            prg8_89(space->machine(), data);
5235            break;
5236         case 5:
5237            prg8_ab(space->machine(), data);
5238            break;
5239         case 6:
5240            chr1_4(space->machine(), data, CHRROM);
5241            break;
5242         case 7:
5243            chr1_6(space->machine(), data, CHRROM);
5244            break;
5245      }
5246         break;
5247      case 0x6003:
5248         if (data)
5249         {
5250            state->m_IRQ_count = data;
5251            state->m_IRQ_enable = 1;
5252         }
5253         else
5254            state->m_IRQ_enable = 0;
5255         break;
5256   }
5257}
5258
5259/*************************************************************
5260
5261 Kaiser Board KS7058
5262
5263 Games: Tui Do Woo Ma Jeung
5264
5265 Writes to 0xf000-0xffff set 4k chr banks. Namely, if
5266 offset&0x80 is 0 the lower 4k are set, if it is 1 the
5267 upper 4k are set.
5268
5269 iNES: mapper 171
5270
5271 In MESS: Supported.
5272
5273 *************************************************************/
5274
5275static WRITE8_HANDLER( ks7058_w )
5276{
5277   LOG_MMC(("ks7058_w, offset: %04x, data: %02x\n", offset, data));
5278
5279   switch (offset & 0x7080)
5280   {
5281      case 0x7000:
5282         chr4_0(space->machine(), data, CHRROM);
5283         break;
5284      case 0x7080:
5285         chr4_4(space->machine(), data, CHRROM);
5286         break;
5287   }
5288}
5289
5290/*************************************************************
5291
5292 Kaiser Board KS7022
5293
5294 Games: 15 in 1
5295
5296 iNES: mapper 175
5297
5298 In MESS: Supported?
5299
5300 *************************************************************/
5301
5302static WRITE8_HANDLER( ks7022_w )
5303{
5304   nes_state *state = space->machine().driver_data<nes_state>();
5305   LOG_MMC(("ks7022_w, offset: %04x, data: %02x\n", offset, data));
5306
5307   if (offset == 0)
5308      set_nt_mirroring(space->machine(), BIT(data, 2) ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT);
5309
5310   if (offset == 0x2000)
5311      state->m_mmc_latch1 = data & 0x0f;
5312}
5313
5314static READ8_HANDLER( ks7022_r )
5315{
5316   nes_state *state = space->machine().driver_data<nes_state>();
5317   LOG_MMC(("ks7022_r, offset: %04x\n", offset));
5318
5319   if (offset == 0x7ffc)
5320   {
5321      chr8(space->machine(), state->m_mmc_latch1, CHRROM);
5322      prg16_89ab(space->machine(), state->m_mmc_latch1);
5323      prg16_cdef(space->machine(), state->m_mmc_latch1);
5324   }
5325
5326   return mmc_hi_access_rom(space->machine(), offset);
5327}
5328
5329/*************************************************************
5330
5331 Kaiser Board KS7032
5332
5333 Games:
5334
5335 iNES:
5336
5337 In MESS:
5338
5339 *************************************************************/
5340
5341static void ks7032_prg_update( running_machine &machine )
5342{
5343   nes_state *state = machine.driver_data<nes_state>();
5344
5345   prg8_67(machine, state->m_mmc_reg[4]);
5346   prg8_89(machine, state->m_mmc_reg[1]);
5347   prg8_ab(machine, state->m_mmc_reg[2]);
5348   prg8_cd(machine, state->m_mmc_reg[3]);
5349}
5350
5351static void ks7032_irq( device_t *device, int scanline, int vblank, int blanked )
5352{
5353   nes_state *state = device->machine().driver_data<nes_state>();
5354
5355   if (state->m_IRQ_enable)
5356   {
5357      if (state->m_IRQ_count >= (0xffff - 114))
5358      {
5359         state->m_IRQ_enable = 0;
5360         state->m_IRQ_count = state->m_IRQ_count_latch;
5361         device_set_input_line(state->m_maincpu, M6502_IRQ_LINE, HOLD_LINE);
5362      }
5363      else
5364         state->m_IRQ_count += 114;
5365   }
5366}
5367
5368static WRITE8_HANDLER( ks7032_w )
5369{
5370   nes_state *state = space->machine().driver_data<nes_state>();
5371   LOG_MMC(("ks7032_w, offset: %04x, data: %02x\n", offset, data));
5372
5373   switch (offset & 0x7000)
5374   {
5375      case 0x0000:
5376         state->m_IRQ_count = (state->m_IRQ_count & 0xfff0) | (data & 0x0f);
5377         break;
5378      case 0x1000:
5379         state->m_IRQ_count = (state->m_IRQ_count & 0xff0f) | ((data & 0x0f) << 4);
5380         break;
5381      case 0x2000:
5382         state->m_IRQ_count = (state->m_IRQ_count & 0xf0ff) | ((data & 0x0f) << 8);
5383         break;
5384      case 0x3000:
5385         state->m_IRQ_count = (state->m_IRQ_count & 0x0fff) | ((data & 0x0f) << 12);
5386         break;
5387      case 0x4000:
5388         state->m_IRQ_enable = 1;
5389         break;
5390      case 0x6000:
5391         state->m_mmc_latch1 = data & 0x07;
5392         break;
5393      case 0x7000:
5394         state->m_mmc_reg[state->m_mmc_latch1] = data;
5395         ks7032_prg_update(space->machine());
5396         break;
5397   }
5398}
5399
5400/*************************************************************
5401
5402 Kaiser Board KS202
5403
5404 Games:
5405
5406 iNES:
5407
5408 In MESS: Supported?
5409
5410 *************************************************************/
5411
5412
5413static WRITE8_HANDLER( ks202_w )
5414{
5415   nes_state *state = space->machine().driver_data<nes_state>();
5416   LOG_MMC(("ks202_w, offset: %04x, data: %02x\n", offset, data));
5417
5418   switch (offset & 0x7000)
5419   {
5420      case 0x0000:
5421         state->m_IRQ_count = (state->m_IRQ_count & 0xfff0) | (data & 0x0f);
5422         break;
5423      case 0x1000:
5424         state->m_IRQ_count = (state->m_IRQ_count & 0xff0f) | ((data & 0x0f) << 4);
5425         break;
5426      case 0x2000:
5427         state->m_IRQ_count = (state->m_IRQ_count & 0xf0ff) | ((data & 0x0f) << 8);
5428         break;
5429      case 0x3000:
5430         state->m_IRQ_count = (state->m_IRQ_count & 0x0fff) | ((data & 0x0f) << 12);
5431         break;
5432      case 0x4000:
5433         state->m_IRQ_enable = 1;
5434         break;
5435      case 0x6000:
5436         state->m_mmc_latch1 = data & 0x07;
5437         break;
5438      case 0x7000:
5439         state->m_mmc_reg[state->m_mmc_latch1] = data;
5440         ks7032_prg_update(space->machine());
5441         switch (offset & 0xc00)
5442         {
5443         case 0x800:
5444            set_nt_mirroring(space->machine(), BIT(data, 0) ? PPU_MIRROR_VERT : PPU_MIRROR_HORZ);
5445            break;
5446         case 0xc00:
5447            chr1_x(space->machine(), offset & 0x07, data, CHRROM);
5448            break;
5449         }
5450         break;
5451   }
5452}
5453
5454/*************************************************************
5455
5456 Kaiser Board KS7017
5457
5458 Games:
5459
5460 iNES:
5461
5462 In MESS: Not working
5463
5464 *************************************************************/
5465
5466static void mmc_fds_irq( device_t *device, int scanline, int vblank, int blanked )
5467{
5468   nes_state *state = device->machine().driver_data<nes_state>();
5469
5470   if (state->m_IRQ_enable)
5471   {
5472      if (state->m_IRQ_count <= 114)
5473      {
5474         device_set_input_line(state->m_maincpu, M6502_IRQ_LINE, HOLD_LINE);
5475         state->m_IRQ_enable = 0;
5476         state->m_IRQ_status |= 0x01;
5477      }
5478      else
5479         state->m_IRQ_count -= 114;
5480   }
5481}
5482
5483static WRITE8_HANDLER( ks7017_l_w )
5484{
5485   nes_state *state = space->machine().driver_data<nes_state>();
5486   LOG_MMC(("ks7022_w, offset: %04x, data: %02x\n", offset, data));
5487
5488   offset += 0x100;
5489
5490   if (offset >= 0xa00 && offset < 0xb00)
5491      state->m_mmc_latch1 = ((offset >> 2) & 0x03) | ((offset >> 4) & 0x04);
5492
5493   if (offset >= 0x1000 && offset < 0x1100)
5494      prg16_89ab(space->machine(), state->m_mmc_latch1);
5495}
5496
5497WRITE8_HANDLER( ks7017_extra_w )
5498{
5499   nes_state *state = space->machine().driver_data<nes_state>();
5500   LOG_MMC(("ks7017_extra_w, offset: %04x, data: %02x\n", offset, data));
5501
5502   offset += 0x20;
5503
5504   if (offset == 0x0020) /* 0x4020 */
5505      state->m_IRQ_count = (state->m_IRQ_count & 0xff00) | data;
5506
5507   if (offset == 0x0021) /* 0x4021 */
5508      state->m_IRQ_count = (state->m_IRQ_count & 0x00ff) | (data << 8);
5509
5510   if (offset == 0x0025) /* 0x4025 */
5511      set_nt_mirroring(space->machine(), BIT(data, 3) ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT);
5512}
5513
5514READ8_HANDLER( ks7017_extra_r )
5515{
5516   nes_state *state = space->machine().driver_data<nes_state>();
5517   LOG_MMC(("ks7017_extra_r, offset: %04x\n", offset));
5518
5519   state->m_IRQ_status &= ~0x01;
5520   return state->m_IRQ_status;
5521}
5522
5523/*************************************************************
5524
5525 Bootleg Board by Kay (for Panda Prince)
5526
5527 Games: The Panda Prince, Sonic 3d Blast 6, SFZ2 '97, YuYu '97
5528 (and its title hack MK6), UMK3, Super Lion King 2
5529
5530 MMC3 clone. This is basically KOF96 board + protection
5531
5532 iNES: mapper 121
5533
5534 In MESS: Most game works, with some graphical issues.
5535
5536 *************************************************************/
5537
5538static WRITE8_HANDLER( kay_pp_l_w )
5539{
5540   nes_state *state = space->machine().driver_data<nes_state>();
5541   LOG_MMC(("kay_pp_l_w, offset: %04x, data: %02x\n", offset, data));
5542   offset += 0x100;
5543
5544   if (offset >= 0x1000)
5545   {
5546      switch (data & 0x03)
5547      {
5548         case 0x00:
5549         case 0x01:
5550            state->m_mmc_reg[0] = 0x83;
5551            break;
5552         case 0x02:
5553            state->m_mmc_reg[0] = 0x42;
5554            break;
5555         case 0x03:
5556            state->m_mmc_reg[0] = 0x00;
5557            break;
5558      }
5559   }
5560}
5561
5562static READ8_HANDLER( kay_pp_l_r )
5563{
5564   nes_state *state = space->machine().driver_data<nes_state>();
5565   LOG_MMC(("kay_pp_l_r, offset: %04x\n", offset));
5566   offset += 0x100;
5567
5568   if (offset >= 0x1000)
5569      return state->m_mmc_reg[0];
5570   else
5571      return 0xff;
5572}
5573
5574static void kay_pp_update_regs( running_machine &machine )
5575{
5576   nes_state *state = machine.driver_data<nes_state>();
5577
5578   switch (state->m_mmc_reg[5] & 0x3f)
5579   {
5580      case 0x20:
5581      case 0x29:
5582      case 0x2b:
5583      case 0x3f:
5584         state->m_mmc_reg[7] = 1;
5585         state->m_mmc_reg[1] = state->m_mmc_reg[6];
5586         break;
5587      case 0x26:
5588         state->m_mmc_reg[7] = 0;
5589         state->m_mmc_reg[1] = state->m_mmc_reg[6];
5590         break;
5591      case 0x2c:
5592         state->m_mmc_reg[7] = 1;
5593         if (state->m_mmc_reg[6])
5594            state->m_mmc_reg[1] = state->m_mmc_reg[6];
5595         break;
5596
5597      case 0x28:
5598         state->m_mmc_reg[7] = 0;
5599         state->m_mmc_reg[2] = state->m_mmc_reg[6];
5600         break;
5601
5602      case 0x2a:
5603         state->m_mmc_reg[7] = 0;
5604         state->m_mmc_reg[3] = state->m_mmc_reg[6];
5605         break;
5606
5607      case 0x2f:
5608         break;
5609
5610      default:
5611         state->m_mmc_reg[5] = 0;
5612         break;
5613   }
5614}
5615
5616static void kay_pp_prg_cb( running_machine &machine, int start, int bank )
5617{
5618   nes_state *state = machine.driver_data<nes_state>();
5619
5620   if (state->m_mmc_reg[5] & 0x3f)
5621   {
5622      prg8_x(machine, start, bank & 0x3f);
5623      prg8_ef(machine, state->m_mmc_reg[1]);
5624      prg8_cd(machine, state->m_mmc_reg[2]);
5625      prg8_ab(machine, state->m_mmc_reg[3]);
5626   }
5627   else
5628      prg8_x(machine, start, bank & 0x3f);
5629}
5630
5631static void kay_pp_chr_cb( running_machine &machine, int start, int bank, int source )
5632{
5633   nes_state *state = machine.driver_data<nes_state>();
5634   UINT8 chr_page = (state->m_mmc3_latch & 0x80) >> 5;
5635
5636   if ((start & 0x04) == chr_page)
5637      bank |= 0x100;
5638
5639   chr1_x(machine, start, bank, source);
5640}
5641
5642static WRITE8_HANDLER( kay_pp_w )
5643{
5644   nes_state *state = space->machine().driver_data<nes_state>();
5645   LOG_MMC(("kay_pp_w, offset: %04x, data: %02x\n", offset, data));
5646
5647   switch (offset & 0x6003)
5648   {
5649      case 0x0000:
5650         txrom_w(space, offset, data);
5651         mmc3_set_prg(space->machine(), state->m_mmc_prg_base, state->m_mmc_prg_mask);
5652         break;
5653
5654      case 0x0001:
5655         state->m_mmc_reg[6] = (BIT(data, 0) << 5) | (BIT(data, 1) << 4) | (BIT(data, 2) << 3)
5656                        | (BIT(data, 3) << 2) | (BIT(data, 4) << 1) | BIT(data, 5);
5657         if (!state->m_mmc_reg[7])
5658            kay_pp_update_regs(space->machine());
5659         txrom_w(space, offset, data);
5660         mmc3_set_prg(space->machine(), state->m_mmc_prg_base, state->m_mmc_prg_mask);
5661         break;
5662
5663      case 0x0003:
5664         state->m_mmc_reg[5] = data;
5665         kay_pp_update_regs(space->machine());
5666         txrom_w(space, 0x0000, data);
5667         mmc3_set_prg(space->machine(), state->m_mmc_prg_base, state->m_mmc_prg_mask);
5668         break;
5669
5670      default:
5671         txrom_w(space, offset, data);
5672         break;
5673   }
5674}
5675
5676/*************************************************************
5677
5678 Bootleg Board by Kasing
5679
5680 Games: AV Jiu Ji Mahjong, Bao Qing Tian, Thunderbolt 2,
5681 Shisen Mahjong 2
5682
5683 MMC3 clone
5684
5685 iNES: mapper 115
5686
5687 In MESS: Supported
5688
5689 *************************************************************/
5690
5691static void kasing_prg_cb( running_machine &machine, int start, int bank )
5692{
5693   nes_state *state = machine.driver_data<nes_state>();
5694   if (BIT(state->m_mmc_reg[0], 7))
5695      prg32(machine, state->m_mmc_reg[0] >> 1);
5696   else
5697      prg8_x(machine, start, bank);
5698}
5699
5700static WRITE8_HANDLER( kasing_m_w )
5701{
5702   nes_state *state = space->machine().driver_data<nes_state>();
5703   LOG_MMC(("kasing_m_w, offset: %04x, data: %02x\n", offset, data));
5704
5705   switch (offset & 0x01)
5706   {
5707      case 0x00:
5708         state->m_mmc_reg[0] = data;
5709         mmc3_set_prg(space->machine(), state->m_mmc_prg_base, state->m_mmc_prg_mask);
5710         break;
5711      case 0x01:
5712         state->m_mmc_chr_base = (data & 0x01) ? 0x100 : 0x000;
5713         mmc3_set_chr(space->machine(), state->m_mmc_chr_source, state->m_mmc_chr_base, state->m_mmc_chr_mask);
5714         break;
5715   }
5716}
5717
5718/*************************************************************
5719
5720 Bootleg Board by Magic Series
5721
5722 Games: Magic Dragon
5723
5724 Very simple mapper: writes to 0x8000-0xffff set prg32 and chr8
5725 banks
5726
5727 iNES: mapper 107
5728
5729 In MESS: Supported.
5730
5731 *************************************************************/
5732
5733static WRITE8_HANDLER( magics_md_w )
5734{
5735   LOG_MMC(("magics_md_w, offset: %04x, data: %02x\n", offset, data));
5736
5737   prg32(space->machine(), data >> 1);
5738   chr8(space->machine(), data, CHRROM);
5739}
5740
5741/*************************************************************
5742
5743 Bootleg Board by Nanjing
5744
5745 Games: A lot of pirate originals
5746
5747 iNES: mapper 163
5748
5749 In MESS: Unsupported.
5750
5751 *************************************************************/
5752
5753static void nanjing_irq( device_t *device, int scanline, int vblank, int blanked )
5754{
5755   nes_state *state = device->machine().driver_data<nes_state>();
5756
5757   if (BIT(state->m_mmc_reg[0], 7))
5758   {
5759      if (scanline == 127)
5760      {
5761         chr4_0(device->machine(), 1, CHRRAM);
5762         chr4_4(device->machine(), 1, CHRRAM);
5763      }
5764
5765      if (scanline == 239)
5766      {
5767         chr4_0(device->machine(), 0, CHRRAM);
5768         chr4_4(device->machine(), 0, CHRRAM);
5769      }
5770   }
5771
5772}
5773
5774static WRITE8_HANDLER( nanjing_l_w )
5775{
5776   nes_state *state = space->machine().driver_data<nes_state>();
5777   LOG_MMC(("nanjing_l_w, offset: %04x, data: %02x\n", offset, data));
5778
5779   offset += 0x100;
5780
5781   if (offset < 0x1000)
5782      return;
5783
5784   if (offset == 0x1100)   // 0x5100
5785   {
5786      if (data == 6)
5787         prg32(space->machine(), 3);
5788      return;
5789   }
5790
5791   if (offset == 0x1101)   // 0x5101
5792   {
5793      UINT8 temp = state->m_mmc_count;
5794      state->m_mmc_count = data;
5795
5796      if (temp & !data)
5797         state->m_mmc_latch2 ^= 0xff;
5798   }
5799
5800   switch (offset & 0x300)
5801   {
5802      case 0x000:
5803      case 0x200:
5804         state->m_mmc_reg[BIT(offset, 9)] = data;
5805         if (!BIT(state->m_mmc_reg[0], 7) && ppu2c0x_get_current_scanline(state->m_ppu) <= 127)
5806            chr8(space->machine(), 0, CHRRAM);
5807         break;
5808      case 0x300:
5809         state->m_mmc_latch1 = data;
5810         break;
5811   }
5812
5813   prg32(space->machine(), (state->m_mmc_reg[0] & 0x0f) | ((state->m_mmc_reg[1] & 0x0f) << 4));
5814}
5815
5816static READ8_HANDLER( nanjing_l_r )
5817{
5818   nes_state *state = space->machine().driver_data<nes_state>();
5819   UINT8 value = 0;
5820   LOG_MMC(("nanjing_l_r, offset: %04x\n", offset));
5821
5822   offset += 0x100;
5823
5824   if (offset < 0x1000)
5825      return 0;
5826
5827   switch (offset & 0x700)
5828   {
5829      case 0x100:
5830         value = state->m_mmc_latch1;
5831         break;
5832      case 0x500:
5833         value = state->m_mmc_latch2 & state->m_mmc_latch1;
5834         break;
5835      case 0x000:
5836      case 0x200:
5837      case 0x300:
5838      case 0x400:
5839      case 0x600:
5840      case 0x700:
5841         value = 4;
5842         break;
5843   }
5844   return value;
5845}
5846
5847/*************************************************************
5848
5849 Bootleg Board by Nitra
5850
5851 Games: Time Diver Avenger
5852
5853 This acts basically like a MMC3 with different use of write
5854 address.
5855
5856 iNES: mapper 250
5857
5858 In MESS: Supported.
5859
5860 *************************************************************/
5861
5862static WRITE8_HANDLER( nitra_w )
5863{
5864   LOG_MMC(("nitra_w, offset: %04x, data: %02x\n", offset, data));
5865
5866   txrom_w(space, (offset & 0x6000) | ((offset & 0x400) >> 10), offset & 0xff);
5867}
5868
5869/*************************************************************
5870
5871 NTDEC ASDER Bootleg Board
5872
5873 Games: Cobra Mission, Fighting Hero III, Huang Di, Master
5874 Shooter
5875
5876 iNES: mapper 112
5877
5878 In MESS: Supported.
5879
5880 *************************************************************/
5881
5882static WRITE8_HANDLER( ntdec_asder_w )
5883{
5884   nes_state *state = space->machine().driver_data<nes_state>();
5885   LOG_MMC(("ntdec_asder_w, offset: %04x, data: %02x\n", offset, data));
5886
5887   switch (offset)
5888   {
5889      case 0x0000:
5890         state->m_mmc_latch1 = data & 0x07;
5891         break;
5892      case 0x2000:
5893         switch (state->m_mmc_latch1)
5894      {
5895         case 0:
5896            prg8_89(space->machine(), data);
5897            break;
5898         case 1:
5899            prg8_ab(space->machine(), data);
5900            break;
5901         case 2:
5902            data &= 0xfe;
5903            chr1_0(space->machine(), data, CHRROM);
5904            chr1_1(space->machine(), data + 1, CHRROM);
5905            break;
5906         case 3:
5907            data &= 0xfe;
5908            chr1_2(space->machine(), data, CHRROM);
5909            chr1_3(space->machine(), data + 1, CHRROM);
5910            break;
5911         case 4:
5912            chr1_4(space->machine(), data, CHRROM);
5913            break;
5914         case 5:
5915            chr1_5(space->machine(), data, CHRROM);
5916            break;
5917         case 6:
5918            chr1_6(space->machine(), data, CHRROM);
5919            break;
5920         case 7:
5921            chr1_7(space->machine(), data, CHRROM);
5922            break;
5923      }
5924         break;
5925      case 0x6000:
5926         set_nt_mirroring(space->machine(), BIT(data, 0) ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT);
5927         break;
5928   }
5929}
5930
5931/*************************************************************
5932
5933 Bootleg Board by NTDEC for Fighting Hero
5934
5935 Games: Fighting Hero
5936
5937 Very simple mapper: writes to 0x6000-0x7fff swap PRG and
5938 CHR banks.
5939
5940 iNES: mapper 193
5941
5942 In MESS: Supported.
5943
5944 *************************************************************/
5945
5946static WRITE8_HANDLER( ntdec_fh_m_w )
5947{
5948   LOG_MMC(("ntdec_fh_m_w, offset: %04x, data: %02x\n", offset, data));
5949
5950   switch (offset & 0x03)
5951   {
5952      case 0:
5953         chr4_0(space->machine(), data >> 2, CHRROM);
5954         break;
5955      case 1:
5956         chr2_4(space->machine(), data >> 1, CHRROM);
5957         break;
5958      case 2:
5959         chr2_6(space->machine(), data >> 1 , CHRROM);
5960         break;
5961      case 3:
5962         prg8_89(space->machine(), data);
5963         break;
5964   }
5965}
5966
5967/*************************************************************
5968
5969 Open Corp DAOU306 board
5970
5971 Games: Metal Force (K)
5972
5973 iNES: mapper 156
5974
5975 In MESS: Supported.
5976
5977 *************************************************************/
5978
5979static WRITE8_HANDLER( daou306_w )
5980{
5981   LOG_MMC(("daou306_w, offset: %04x, data: %02x\n", offset, data));
5982
5983   switch (offset)
5984   {
5985      case 0x4000:
5986         chr1_0(space->machine(), data, CHRROM);
5987         break;
5988      case 0x4001:
5989         chr1_1(space->machine(), data, CHRROM);
5990         break;
5991      case 0x4002:
5992         chr1_2(space->machine(), data, CHRROM);
5993         break;
5994      case 0x4003:
5995         chr1_3(space->machine(), data, CHRROM);
5996         break;
5997      case 0x4008:
5998         chr1_4(space->machine(), data, CHRROM);
5999         break;
6000      case 0x4009:
6001         chr1_5(space->machine(), data, CHRROM);
6002         break;
6003      case 0x400a:
6004         chr1_6(space->machine(), data, CHRROM);
6005         break;
6006      case 0x400b:
6007         chr1_7(space->machine(), data, CHRROM);
6008         break;
6009      case 0x4010:
6010         prg16_89ab(space->machine(), data);
6011         break;
6012   }
6013}
6014
6015/*************************************************************
6016
6017 RCM GS2015 Board
6018
6019 Games: Bonza, Magic Jewelry 2
6020
6021 Very simple mapper: writes to 0x8000-0xffff sets prg32
6022 to offset and chr8 to offset>>1 (when chrrom is present)
6023
6024 iNES: mapper 216
6025
6026 In MESS: Supported.
6027
6028 *************************************************************/
6029
6030static WRITE8_HANDLER( gs2015_w )
6031{
6032   nes_state *state = space->machine().driver_data<nes_state>();
6033   LOG_MMC(("gs2015_w, offset: %04x, data: %02x\n", offset, data));
6034
6035   prg32(space->machine(), offset);
6036   chr8(space->machine(), offset >> 1, state->m_mmc_chr_source);
6037}
6038
6039/*************************************************************
6040
6041 Bootleg Board by RCM for Tetris Family
6042
6043 Games: Tetris Family 9 in 1, 20 in 1
6044
6045 Simple Mapper: prg/chr/nt are swapped depending on the offset
6046 of writes in 0x8000-0xffff. offset&0x80 set NT mirroring,
6047 when (offset&0x30) is 0,3 prg32 is set; when it is 1,2
6048 two 16k prg banks are set. See below for the values used in
6049 these banks.
6050
6051 iNES: mapper 61
6052
6053 In MESS: Supported.
6054
6055 *************************************************************/
6056
6057static WRITE8_HANDLER( rcm_tf_w )
6058{
6059   LOG_MMC(("rcm_tf_w, offset: %04x, data: %02x\n", offset, data));
6060
6061   switch (offset & 0x30)
6062   {
6063      case 0x00:
6064      case 0x30:
6065         prg32(space->machine(), offset & 0x0f);
6066         break;
6067      case 0x10:
6068      case 0x20:
6069         prg16_89ab(space->machine(), ((offset & 0x0f) << 1) | ((offset & 0x20) >> 4));
6070         prg16_cdef(space->machine(), ((offset & 0x0f) << 1) | ((offset & 0x20) >> 4));
6071         break;
6072   }
6073   set_nt_mirroring(space->machine(), BIT(data, 7) ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT);
6074}
6075
6076/*************************************************************
6077
6078 Bootleg Board by Rex Soft
6079
6080 Games: Dragon Ball Z 5, Dragon Ball Z Super
6081
6082 MMC3 clone
6083
6084 iNES: mapper 12
6085
6086 In MESS: Supported
6087
6088 *************************************************************/
6089
6090static WRITE8_HANDLER( rex_dbz_l_w )
6091{
6092   nes_state *state = space->machine().driver_data<nes_state>();
6093   LOG_MMC(("rex_dbz_l_w, offset: %04x, data: %02x\n", offset, data));
6094
6095   state->m_mmc_reg[0] = data;
6096   mmc3_set_chr(space->machine(), state->m_mmc_chr_source, state->m_mmc_chr_base, state->m_mmc_chr_mask);
6097}
6098
6099/* we would need to use this read handler in 0x6000-0x7fff as well */
6100static READ8_HANDLER( rex_dbz_l_r )
6101{
6102   LOG_MMC(("rex_dbz_l_r, offset: %04x\n", offset));
6103   return 0x01;
6104}
6105
6106static void rex_dbz_chr_cb( running_machine &machine, int start, int bank, int source )
6107{
6108   nes_state *state = machine.driver_data<nes_state>();
6109   int shift = (start < 4) ? 8 : 4;
6110
6111   bank |= ((state->m_mmc_reg[0] << shift) & 0x100);
6112   chr1_x(machine, start, bank, source);
6113}
6114
6115/*************************************************************
6116
6117 Rex Soft SL1632 Board
6118
6119 Games: Samurai Spirits
6120
6121 MMC3 clone
6122
6123 iNES: mapper 14
6124
6125 In MESS: Supported
6126
6127 *************************************************************/
6128
6129static void rex_sl1632_set_prg( running_machine &machine, int prg_base, int prg_mask )
6130{
6131   nes_state *state = machine.driver_data<nes_state>();
6132
6133   if (state->m_mmc_reg[0] & 0x02)
6134   {
6135      mmc3_set_prg(machine, prg_base, prg_mask);
6136   }
6137   else
6138   {
6139      prg8_89(machine, state->m_mmc_extra_bank[0]);
6140      prg8_ab(machine, state->m_mmc_extra_bank[1]);
6141      prg8_cd(machine, state->m_mmc_extra_bank[2]);
6142      prg8_ef(machine, state->m_mmc_extra_bank[3]);
6143   }
6144}
6145
6146static void rex_sl1632_set_chr( running_machine &machine, UINT8 chr, int chr_base, int chr_mask )
6147{
6148   nes_state *state = machine.driver_data<nes_state>();
6149   static const UINT8 conv_table[8] = {5, 5, 5, 5, 3, 3, 1, 1};
6150   UINT8 chr_page = (state->m_mmc3_latch & 0x80) >> 5;
6151   UINT8 bank[8];
6152   UINT8 chr_base2[8];
6153   int i;
6154
6155   if (state->m_mmc_reg[0] & 0x02)
6156   {
6157      for(i = 0; i < 8; i++)
6158      {
6159         bank[i] = state->m_mmc_vrom_bank[i];
6160         chr_base2[i] = chr_base | ((state->m_mmc_reg[0] << conv_table[i]) & 0x100);
6161      }
6162   }
6163   else
6164   {
6165      for(i = 0; i < 8; i++)
6166      {
6167         bank[i] = state->m_mmc_extra_bank[i + 4];   // first 4 state->m_mmc_extra_banks are PRG
6168         chr_base2[i] = chr_base;
6169      }
6170   }
6171
6172   chr1_x(machine, chr_page ^ 0, chr_base2[0] | (bank[0] & chr_mask), chr);
6173   chr1_x(machine, chr_page ^ 1, chr_base2[1] | (bank[1] & chr_mask), chr);
6174   chr1_x(machine, chr_page ^ 2, chr_base2[2] | (bank[2] & chr_mask), chr);
6175   chr1_x(machine, chr_page ^ 3, chr_base2[3] | (bank[3] & chr_mask), chr);
6176   chr1_x(machine, chr_page ^ 4, chr_base2[4] | (bank[4] & chr_mask), chr);
6177   chr1_x(machine, chr_page ^ 5, chr_base2[5] | (bank[5] & chr_mask), chr);
6178   chr1_x(machine, chr_page ^ 6, chr_base2[6] | (bank[6] & chr_mask), chr);
6179   chr1_x(machine, chr_page ^ 7, chr_base2[7] | (bank[7] & chr_mask), chr);
6180}
6181
6182static WRITE8_HANDLER( rex_sl1632_w )
6183{
6184   nes_state *state = space->machine().driver_data<nes_state>();
6185   UINT8 map14_helper1, map14_helper2, mmc_helper, cmd;
6186   LOG_MMC(("rex_sl1632_w, offset: %04x, data: %02x\n", offset, data));
6187
6188   if (offset == 0x2131)
6189   {
6190      state->m_mmc_reg[0] = data;
6191      rex_sl1632_set_prg(space->machine(), state->m_mmc_prg_base, state->m_mmc_prg_mask);
6192      rex_sl1632_set_chr(space->machine(), state->m_mmc_chr_source, state->m_mmc_chr_base, state->m_mmc_chr_mask);
6193
6194      if (!(state->m_mmc_reg[0] & 0x02))
6195         set_nt_mirroring(space->machine(), BIT(state->m_mmc_reg[1], 0) ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT);
6196   }
6197
6198   if (state->m_mmc_reg[0] & 0x02)
6199   {
6200      switch (offset & 0x6001)
6201      {
6202         case 0x0000:
6203            mmc_helper = state->m_mmc3_latch ^ data;
6204            state->m_mmc3_latch = data;
6205
6206            /* Has PRG Mode changed? */
6207            if (mmc_helper & 0x40)
6208               rex_sl1632_set_prg(space->machine(), state->m_mmc_prg_base, state->m_mmc_prg_mask);
6209
6210            /* Has CHR Mode changed? */
6211            if (mmc_helper & 0x80)
6212               rex_sl1632_set_chr(space->machine(), state->m_mmc_chr_source, state->m_mmc_chr_base, state->m_mmc_chr_mask);
6213            break;
6214
6215         case 0x0001:
6216            cmd = state->m_mmc3_latch & 0x07;
6217            switch (cmd)
6218            {
6219            case 0: case 1:   // these have to be changed due to the different way rex_sl1632_set_chr works (it handles 1k banks)!
6220               state->m_mmc_vrom_bank[2 * cmd] = data;
6221               state->m_mmc_vrom_bank[2 * cmd + 1] = data;
6222               rex_sl1632_set_chr(space->machine(), state->m_mmc_chr_source, state->m_mmc_chr_base, state->m_mmc_chr_mask);
6223               break;
6224            case 2: case 3: case 4: case 5:
6225               state->m_mmc_vrom_bank[cmd + 2] = data;
6226               rex_sl1632_set_chr(space->machine(), state->m_mmc_chr_source, state->m_mmc_chr_base, state->m_mmc_chr_mask);
6227               break;
6228            case 6:
6229            case 7:
6230               state->m_mmc_prg_bank[cmd - 6] = data;
6231               rex_sl1632_set_prg(space->machine(), state->m_mmc_prg_base, state->m_mmc_prg_mask);
6232               break;
6233            }
6234            break;
6235
6236         case 0x2000:
6237            set_nt_mirroring(space->machine(), BIT(state->m_mmc_reg[1], 0) ? PPU_MIRROR_VERT : PPU_MIRROR_HORZ);
6238            break;
6239
6240         default:
6241            txrom_w(space, offset, data);
6242            break;
6243      }
6244   }
6245   else if (offset >= 0x3000 && offset <= 0x6003 )
6246   {
6247      map14_helper1 = (offset & 0x01) << 2;
6248      offset = ((offset & 0x02) | (offset >> 10)) >> 1;
6249      map14_helper2 = ((offset + 2) & 0x07) + 4; // '+4' because first 4 state->m_mmc_extra_banks are for PRG!
6250      state->m_mmc_extra_bank[map14_helper2] = (state->m_mmc_extra_bank[map14_helper2] & (0xf0 >> map14_helper1)) | ((data & 0x0f) << map14_helper1);
6251      rex_sl1632_set_chr(space->machine(), state->m_mmc_chr_source, state->m_mmc_chr_base, state->m_mmc_chr_mask);
6252   }
6253   else
6254   {
6255      switch (offset & 0x7003)
6256      {
6257         case 0x0000:
6258         case 0x2000:
6259            state->m_mmc_extra_bank[offset >> 13] = data;
6260            rex_sl1632_set_prg(space->machine(), state->m_mmc_prg_base, state->m_mmc_prg_mask);
6261            break;
6262
6263         case 0x1000:
6264            state->m_mmc_reg[1] = data;
6265            set_nt_mirroring(space->machine(), BIT(state->m_mmc_reg[1], 0) ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT);
6266            break;
6267      }
6268   }
6269}
6270
6271/*************************************************************
6272
6273 Rumblestation Board
6274
6275 Games: Rumblestation 15 in 1
6276
6277 iNES: mapper 46
6278
6279 In MESS: Supported.
6280
6281 *************************************************************/
6282
6283static WRITE8_HANDLER( rumblestation_m_w )
6284{
6285   nes_state *state = space->machine().driver_data<nes_state>();
6286   LOG_MMC(("rumblestation_m_w, offset: %04x, data: %02x\n", offset, data));
6287
6288   state->m_mmc_prg_bank[0] = (state->m_mmc_prg_bank[0] & 0x01) | ((data & 0x0f) << 1);
6289   state->m_mmc_vrom_bank[0] = (state->m_mmc_vrom_bank[0] & 0x07) | ((data & 0xf0) >> 1);
6290   prg32(space->machine(), state->m_mmc_prg_bank[0]);
6291   chr8(space->machine(), state->m_mmc_vrom_bank[0], CHRROM);
6292}
6293
6294static WRITE8_HANDLER( rumblestation_w )
6295{
6296   nes_state *state = space->machine().driver_data<nes_state>();
6297   LOG_MMC(("rumblestation_w, offset: %04x, data: %02x\n", offset, data));
6298
6299   state->m_mmc_prg_bank[0] = (state->m_mmc_prg_bank[0] & ~0x01) | (data & 0x01);
6300   state->m_mmc_vrom_bank[0] = (state->m_mmc_vrom_bank[0] & ~0x07) | ((data & 0x70) >> 4);
6301   prg32(space->machine(), state->m_mmc_prg_bank[0]);
6302   chr8(space->machine(), state->m_mmc_vrom_bank[0], CHRROM);
6303}
6304
6305/*************************************************************
6306
6307 Sachen 74x374 bootleg boards
6308
6309 Games: Chess Academy, Chinese Checkers Jpn, Mahjong Academy,
6310 Olympic IQ, Poker II, Tasac [150], Poker III [243]
6311
6312 iNES: mappers 150 & 243
6313
6314 *************************************************************/
6315
6316static void sachen_set_mirror( running_machine &machine, UINT8 nt ) // used by mappers 137, 138, 139, 141
6317{
6318   switch (nt)
6319   {
6320      case 0:
6321      case 1:
6322         set_nt_mirroring(machine, nt ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT);
6323         break;
6324      case 2:
6325         set_nt_page(machine, 0, CIRAM, 0, 1);
6326         set_nt_page(machine, 1, CIRAM, 1, 1);
6327         set_nt_page(machine, 2, CIRAM, 1, 1);
6328         set_nt_page(machine, 3, CIRAM, 1, 1);
6329         break;
6330      case 3:
6331         set_nt_mirroring(machine, PPU_MIRROR_LOW);
6332         break;
6333      default:
6334         LOG_MMC(("Mapper set NT to invalid value %02x", nt));
6335         break;
6336   }
6337}
6338
6339static WRITE8_HANDLER( sachen_74x374_l_w )
6340{
6341   nes_state *state = space->machine().driver_data<nes_state>();
6342   LOG_MMC(("sachen_74x374_l_w, offset: %04x, data: %02x\n", offset, data));
6343
6344   /* write happens only if we are at 0x4100 + k * 0x200, but 0x4100 is offset = 0 */
6345   if (!(offset & 0x100))
6346   {
6347      if (!(offset & 0x01))
6348         state->m_mmc_latch1 = data & 0x07;
6349      else
6350      {
6351         switch (state->m_mmc_latch1)
6352         {
6353            case 0x02:
6354               state->m_mmc_vrom_bank[0] = (state->m_mmc_vrom_bank[0] & ~0x08) | ((data << 3) & 0x08);
6355               chr8(space->machine(), state->m_mmc_vrom_bank[0], CHRROM);
6356               prg32(space->machine(), data & 0x01);
6357               break;
6358            case 0x04:
6359               state->m_mmc_vrom_bank[0] = (state->m_mmc_vrom_bank[0] & ~0x04) | ((data << 2) & 0x04);
6360               chr8(space->machine(), state->m_mmc_vrom_bank[0], CHRROM);
6361               break;
6362            case 0x05:
6363               prg32(space->machine(), data & 0x07);
6364               break;
6365            case 0x06:
6366               state->m_mmc_vrom_bank[0] = (state->m_mmc_vrom_bank[0] & ~0x03) | ((data << 0) & 0x03);
6367               chr8(space->machine(), state->m_mmc_vrom_bank[0], CHRROM);
6368               break;
6369            case 0x07:
6370               sachen_set_mirror(space->machine(), (data >> 1) & 0x03);
6371               break;
6372            default:
6373               break;
6374         }
6375      }
6376   }
6377}
6378
6379static READ8_HANDLER( sachen_74x374_l_r )
6380{
6381   nes_state *state = space->machine().driver_data<nes_state>();
6382   LOG_MMC(("sachen_74x374_l_r, offset: %04x", offset));
6383
6384   /* read  happens only if we are at 0x4100 + k * 0x200, but 0x4100 is offset = 0 */
6385   if (!(offset & 0x100))
6386      return (~state->m_mmc_latch1 & 0x3f) /* ^ dips*/;   // we would need to check the Dips here
6387   else
6388      return 0;
6389}
6390
6391static WRITE8_HANDLER( sachen_74x374a_l_w )
6392{
6393   nes_state *state = space->machine().driver_data<nes_state>();
6394   LOG_MMC(("sachen_74x374a_l_w, offset: %04x, data: %02x\n", offset, data));
6395
6396   /* write happens only if we are at 0x4100 + k * 0x200, but 0x4100 is offset = 0 */
6397   if (!(offset & 0x100))
6398   {
6399      if (!(offset & 0x01))
6400         state->m_mmc_latch1 = data;
6401      else
6402      {
6403         switch (state->m_mmc_latch1 & 0x07)
6404         {
6405            case 0x00:
6406               prg32(space->machine(), 0);
6407               chr8(space->machine(), 3, CHRROM);
6408               break;
6409            case 0x02:
6410               state->m_mmc_vrom_bank[0] = (state->m_mmc_vrom_bank[0] & ~0x08) | ((data << 3) & 0x08);
6411               chr8(space->machine(), state->m_mmc_vrom_bank[0], CHRROM);
6412               break;
6413            case 0x04:
6414               state->m_mmc_vrom_bank[0] = (state->m_mmc_vrom_bank[0] & ~0x01) | ((data << 0) & 0x01);
6415               chr8(space->machine(), state->m_mmc_vrom_bank[0], CHRROM);
6416               break;
6417            case 0x05:
6418               prg32(space->machine(), data & 0x01);
6419               break;
6420            case 0x06:
6421               state->m_mmc_vrom_bank[0] = (state->m_mmc_vrom_bank[0] & ~0x06) | ((data << 1) & 0x06);
6422               chr8(space->machine(), state->m_mmc_vrom_bank[0], CHRROM);
6423               break;
6424            case 0x07:
6425               sachen_set_mirror(space->machine(), BIT(data, 0));
6426               break;
6427            default:
6428               break;
6429         }
6430      }
6431   }
6432}
6433
6434/*************************************************************
6435
6436 Sachen S8259 bootleg boards
6437
6438 iNES: mapper 141 (A), 138 (B), 139 (C), 137 (D)
6439
6440 *************************************************************/
6441
6442static void common_s8259_write_handler( address_space *space, offs_t offset, UINT8 data, int board )
6443{
6444   nes_state *state = space->machine().driver_data<nes_state>();
6445   UINT8 bank_helper1, bank_helper2, shift, add1, add2, add3;
6446
6447   /* write happens only if we are at 0x4100 + k * 0x200, but 0x4100 is offset = 0 */
6448   if (!(offset & 0x100))
6449   {
6450      if (!(offset & 0x01))
6451         state->m_mmc_latch1 = data & 0x07;
6452      else
6453      {
6454         state->m_sachen_reg[state->m_mmc_latch1] = data;
6455
6456         switch (state->m_mmc_latch1)
6457         {
6458            case 0x05:
6459               prg32(space->machine(), data);
6460               break;
6461            case 0x07:
6462               sachen_set_mirror(space->machine(), BIT(data, 0) ? 0 : (data >> 1) & 0x03);
6463               break;
6464            default:
6465               if (board == SACHEN_8259D)
6466               {
6467                  if (state->m_mmc_chr_source == CHRROM)
6468                  {
6469                     chr1_0(space->machine(), (state->m_sachen_reg[0] & 0x07), CHRROM);
6470                     chr1_1(space->machine(), (state->m_sachen_reg[1] & 0x07) | (state->m_sachen_reg[4] << 4 & 0x10), CHRROM);
6471                     chr1_2(space->machine(), (state->m_sachen_reg[2] & 0x07) | (state->m_sachen_reg[4] << 3 & 0x10), CHRROM);
6472                     chr1_3(space->machine(), (state->m_sachen_reg[3] & 0x07) | (state->m_sachen_reg[4] << 2 & 0x10) | (state->m_sachen_reg[6] << 3 & 0x08), CHRROM);
6473                  }
6474               }
6475               else
6476               {
6477                  bank_helper1 = state->m_sachen_reg[7] & 0x01;
6478                  bank_helper2 = (state->m_sachen_reg[4] & 0x07) << 3;
6479                  shift = (board == SACHEN_8259A) ? 1 : (board == SACHEN_8259C) ? 2 : 0;
6480                  add1 = (board == SACHEN_8259B) ? 0 : 1;
6481                  add2 = (board == SACHEN_8259C) ? 2 : 0;
6482                  add3 = (board == SACHEN_8259A) ? 1 : (board == SACHEN_8259C) ? 3 : 0;
6483
6484                  if (state->m_mmc_chr_source == CHRROM)
6485                  {
6486                     chr2_0(space->machine(), ((state->m_sachen_reg[bank_helper1 ? 0 : 0] & 0x07) | bank_helper2) << shift, CHRROM);
6487                     chr2_2(space->machine(), ((state->m_sachen_reg[bank_helper1 ? 0 : 1] & 0x07) | bank_helper2) << shift | add1, CHRROM);
6488                     chr2_4(space->machine(), ((state->m_sachen_reg[bank_helper1 ? 0 : 2] & 0x07) | bank_helper2) << shift | add2, CHRROM);
6489                     chr2_6(space->machine(), ((state->m_sachen_reg[bank_helper1 ? 0 : 3] & 0x07) | bank_helper2) << shift | add3, CHRROM);
6490                  }
6491               }
6492               break;
6493         }
6494      }
6495   }
6496}
6497
6498static WRITE8_HANDLER( s8259_l_w )
6499{
6500   nes_state *state = space->machine().driver_data<nes_state>();
6501   LOG_MMC(("s8259_w, type: %d, offset: %04x, data: %02x\n", state->m_pcb_id, offset, data));
6502
6503   common_s8259_write_handler(space, offset, data, state->m_pcb_id);
6504}
6505
6506static WRITE8_HANDLER( s8259_m_w )
6507{
6508   nes_state *state = space->machine().driver_data<nes_state>();
6509   LOG_MMC(("s8259_w, type: %d, offset: %04x, data: %02x\n", state->m_pcb_id, offset, data));
6510
6511   common_s8259_write_handler(space, (offset + 0x100) & 0xfff, data, state->m_pcb_id);
6512}
6513
6514
6515/*************************************************************
6516
6517 Sachen SA009 bootleg boards
6518
6519 Games: Pipe 5
6520
6521 iNES: mapper 160
6522
6523 In MESS: Supported.
6524
6525 *************************************************************/
6526
6527static WRITE8_HANDLER( sa009_l_w )
6528{
6529   nes_state *state = space->machine().driver_data<nes_state>();
6530   LOG_MMC(("sa009_l_w, offset: %04x, data: %02x\n", offset, data));
6531
6532   chr8(space->machine(), data, state->m_mmc_chr_source);
6533}
6534
6535/*************************************************************
6536
6537 Sachen SA0036 bootleg boards
6538
6539 Games: Taiwan Mahjong 16
6540
6541 iNES: mapper 149
6542
6543 In MESS: Supported.
6544
6545 *************************************************************/
6546
6547static WRITE8_HANDLER( sa0036_w )
6548{
6549   LOG_MMC(("sa0036_w, offset: %04x, data: %02x\n", offset, data));
6550
6551   chr8(space->machine(), data >> 7, CHRROM);
6552}
6553
6554/*************************************************************
6555
6556 Sachen SA0037 bootleg boards
6557
6558 Games: Mahjong World, Shisen Mahjong
6559
6560 iNES: mapper 148
6561
6562 In MESS: Supported.
6563
6564 *************************************************************/
6565
6566static WRITE8_HANDLER( sa0037_w )
6567{
6568   LOG_MMC(("sa0037_w, offset: %04x, data: %02x\n", offset, data));
6569
6570   prg32(space->machine(), data >> 3);
6571   chr8(space->machine(), data, CHRROM);
6572}
6573
6574/*************************************************************
6575
6576 Sachen SA72007 bootleg boards
6577
6578 Games: Sidewinder
6579
6580 iNES: mapper 145
6581
6582 In MESS: Supported.
6583
6584 *************************************************************/
6585
6586static WRITE8_HANDLER( sa72007_l_w )
6587{
6588   LOG_MMC(("sa72007_l_w, offset: %04x, data: %02x\n", offset, data));
6589
6590   /* only if we are at 0x4100 + k * 0x200, but 0x4100 is offset = 0 */
6591   if (!(offset & 0x100))
6592      chr8(space->machine(), data >> 7, CHRROM);
6593}
6594
6595/*************************************************************
6596
6597 Sachen SA72008 bootleg boards
6598
6599 Games: Jovial Race, Qi Wang
6600
6601 iNES: mapper 133
6602
6603 In MESS: Supported.
6604
6605 *************************************************************/
6606
6607static WRITE8_HANDLER( sa72008_l_w )
6608{
6609   LOG_MMC(("sa72008_l_w, offset: %04x, data: %02x\n", offset, data));
6610
6611   prg32(space->machine(), data >> 2);
6612   chr8(space->machine(), data, CHRROM);
6613}
6614
6615/*************************************************************
6616
6617 Sachen TCA-01 bootleg boards
6618
6619 iNES: mapper 143
6620
6621 Games: Dancing Blocks, Magic Mathematic
6622
6623 In MESS: Supported.
6624
6625 *************************************************************/
6626
6627static READ8_HANDLER( tca01_l_r )
6628{
6629   LOG_MMC(("tca01_l_r, offset: %04x\n", offset));
6630
6631   /* the address is read only if we are at 0x4100 + k * 0x200, but 0x4100 is offset = 0 */
6632   if (!(offset & 0x100))
6633      return (~offset & 0x3f) | 0x40;
6634   else
6635      return 0x00;
6636}
6637
6638/*************************************************************
6639
6640 Sachen TCU-01 bootleg boards
6641
6642 Games: Challenge of the Dragon, Chinese Kungfu
6643
6644 iNES: mapper 147
6645
6646 In MESS: Supported.
6647
6648 *************************************************************/
6649
6650static WRITE8_HANDLER( tcu01_l_w )
6651{
6652   LOG_MMC(("tcu01_l_w, offset: %04x, data: %02x\n", offset, data));
6653
6654   if ((offset & 0x103) == 0x002)
6655   {
6656      prg32(space->machine(), ((data >> 6) & 0x02) | ((data >> 2) & 0x01));
6657      chr8(space->machine(), data >> 3, CHRROM);
6658   }
6659}
6660
6661static WRITE8_HANDLER( tcu01_m_w )
6662{
6663   LOG_MMC(("tcu01_m_w, offset: %04x, data: %02x\n", offset, data));
6664
6665   tcu01_l_w(space, (offset + 0x100) & 0xfff, data);
6666}
6667
6668static WRITE8_HANDLER( tcu01_w )
6669{
6670   LOG_MMC(("tcu01_w, offset: %04x, data: %02x\n", offset, data));
6671
6672   tcu01_l_w(space, (offset + 0x100) & 0xfff, data);
6673}
6674
6675/*************************************************************
6676
6677 Sachen TCU-02 bootleg boards
6678
6679 Games: Mei Loi Siu Ji
6680
6681 iNES: mapper 136
6682
6683 In MESS: Supported.
6684
6685 *************************************************************/
6686
6687static WRITE8_HANDLER( tcu02_l_w )
6688{
6689   nes_state *state = space->machine().driver_data<nes_state>();
6690   LOG_MMC(("tcu02_l_w, offset: %04x, data: %02x\n", offset, data));
6691
6692   if ((offset & 0x103) == 0x002)
6693   {
6694      state->m_mmc_latch1 = (data & 0x30) | ((data + 3) & 0x0f);
6695      chr8(space->machine(), state->m_mmc_latch1, CHRROM);
6696   }
6697}
6698
6699static READ8_HANDLER( tcu02_l_r )
6700{
6701   nes_state *state = space->machine().driver_data<nes_state>();
6702   LOG_MMC(("tcu02_l_r, offset: %04x\n", offset));
6703
6704   if ((offset & 0x103) == 0x000)
6705      return state->m_mmc_latch1 | 0x40;
6706   else
6707      return 0x00;
6708}
6709
6710
6711/*************************************************************
6712
6713 Subor bootleg board Type 0
6714
6715 iNES: mapper 167
6716
6717 *************************************************************/
6718
6719static WRITE8_HANDLER( subor0_w )
6720{
6721   nes_state *state = space->machine().driver_data<nes_state>();
6722   UINT8 subor_helper1, subor_helper2;
6723   LOG_MMC(("subor0_w, offset: %04x, data: %02x\n", offset, data));
6724
6725   state->m_subor_reg[(offset >> 13) & 0x03] = data;
6726   subor_helper1 = ((state->m_subor_reg[0] ^ state->m_subor_reg[1]) << 1) & 0x20;
6727   subor_helper2 = ((state->m_subor_reg[2] ^ state->m_subor_reg[3]) << 0) & 0x1f;
6728
6729   if (state->m_subor_reg[1] & 0x08)
6730   {
6731      subor_helper1 += subor_helper2 & 0xfe;
6732      subor_helper2 = subor_helper1;
6733      subor_helper1 += 1;
6734   }
6735   else if (state->m_subor_reg[1] & 0x04)
6736   {
6737      subor_helper2 += subor_helper1;
6738      subor_helper1 = 0x1f;
6739   }
6740   else
6741   {
6742      subor_helper1 += subor_helper2;
6743      subor_helper2 = 0x20;
6744   }
6745
6746   prg16_89ab(space->machine(), subor_helper1);
6747   prg16_cdef(space->machine(), subor_helper2);
6748}
6749
6750/*************************************************************
6751
6752 Subor bootleg board Type 1
6753
6754 iNES: mapper 166
6755
6756 *************************************************************/
6757
6758static WRITE8_HANDLER( subor1_w )
6759{
6760   nes_state *state = space->machine().driver_data<nes_state>();
6761   UINT8 subor_helper1, subor_helper2;
6762   LOG_MMC(("subor1_w, offset: %04x, data: %02x\n", offset, data));
6763
6764   state->m_subor_reg[(offset >> 13) & 0x03] = data;
6765   subor_helper1 = ((state->m_subor_reg[0] ^ state->m_subor_reg[1]) << 1) & 0x20;
6766   subor_helper2 = ((state->m_subor_reg[2] ^ state->m_subor_reg[3]) << 0) & 0x1f;
6767
6768   if (state->m_subor_reg[1] & 0x08)
6769   {
6770      subor_helper1 += subor_helper2 & 0xfe;
6771      subor_helper2 = subor_helper1;
6772      subor_helper2 += 1;
6773   }
6774   else if (state->m_subor_reg[1] & 0x04)
6775   {
6776      subor_helper2 += subor_helper1;
6777      subor_helper1 = 0x1f;
6778   }
6779   else
6780   {
6781      subor_helper1 += subor_helper2;
6782      subor_helper2 = 0x07;
6783   }
6784
6785   prg16_89ab(space->machine(), subor_helper1);
6786   prg16_cdef(space->machine(), subor_helper2);
6787}
6788
6789/*************************************************************
6790
6791 Bootleg Board by Super Game
6792
6793 Games: Boogerman, Mortal Kombat III
6794
6795 MMC3 clone. Also, it probably needs a hack to support both
6796 variants (Boogerman & MK3).
6797
6798 iNES: mapper 215
6799
6800 In MESS: Preliminary support.
6801
6802 *************************************************************/
6803
6804static void sgame_boog_prg_cb( running_machine &machine, int start, int bank )
6805{
6806   nes_state *state = machine.driver_data<nes_state>();
6807   if (!(state->m_mmc_reg[0] & 0x80))   // if this is != 0 we should never even arrive here
6808   {
6809      if (state->m_mmc_reg[1] & 0x08)
6810         bank = (bank & 0x1f) | 0x20;
6811      else
6812         bank = (bank & 0x0f) | (state->m_mmc_reg[1] & 0x10);
6813
6814      prg8_x(machine, start, bank);
6815   }
6816}
6817
6818static void sgame_boog_chr_cb( running_machine &machine, int start, int bank, int source )
6819{
6820   nes_state *state = machine.driver_data<nes_state>();
6821
6822   if ((state->m_mmc_reg[1] & 0x04))
6823      bank |= 0x100;
6824   else
6825      bank = (bank & 0x7f) | ((state->m_mmc_reg[1] & 0x10) << 3);
6826
6827   chr1_x(machine, start, bank, source);
6828}
6829
6830static void sgame_boog_set_prg( running_machine &machine )
6831{
6832   nes_state *state = machine.driver_data<nes_state>();
6833   if (state->m_mmc_reg[0] & 0x80)
6834   {
6835      prg16_89ab(machine, (state->m_mmc_reg[0] & 0xf0) | (state->m_mmc_reg[1] & 0x10));
6836      prg16_cdef(machine, (state->m_mmc_reg[0] & 0xf0) | (state->m_mmc_reg[1] & 0x10));
6837   }
6838   else
6839      mmc3_set_prg(machine, state->m_mmc_prg_base, state->m_mmc_prg_mask);
6840}
6841
6842static WRITE8_HANDLER( sgame_boog_l_w )
6843{
6844   nes_state *state = space->machine().driver_data<nes_state>();
6845   LOG_MMC(("sgame_boog_l_w, offset: %04x, data: %02x\n", offset, data));
6846   offset += 0x100;
6847
6848   if (offset == 0x1000)
6849   {
6850      state->m_mmc_reg[0] = data;
6851      sgame_boog_set_prg(space->machine());
6852   }
6853   else if (offset == 0x1001)
6854   {
6855      state->m_mmc_reg[1] = data;
6856      mmc3_set_chr(space->machine(), state->m_mmc_chr_source, state->m_mmc_chr_base, state->m_mmc_chr_mask);
6857   }
6858   else if (offset == 0x1007)
6859   {
6860      state->m_mmc3_latch = 0;
6861      state->m_mmc_reg[2] = data;
6862      sgame_boog_set_prg(space->machine());
6863      mmc3_set_chr(space->machine(), state->m_mmc_chr_source, state->m_mmc_chr_base, state->m_mmc_chr_mask);
6864   }
6865}
6866
6867static WRITE8_HANDLER( sgame_boog_m_w )
6868{
6869   nes_state *state = space->machine().driver_data<nes_state>();
6870   LOG_MMC(("sgame_boog_m_w, offset: %04x, data: %02x\n", offset, data));
6871
6872   if (offset == 0x0000)
6873   {
6874      state->m_mmc_reg[0] = data;
6875      sgame_boog_set_prg(space->machine());
6876   }
6877   else if (offset == 0x0001)
6878   {
6879      state->m_mmc_reg[1] = data;
6880      mmc3_set_chr(space->machine(), state->m_mmc_chr_source, state->m_mmc_chr_base, state->m_mmc_chr_mask);
6881   }
6882   else if (offset == 0x0007)
6883   {
6884      state->m_mmc3_latch = 0;
6885      state->m_mmc_reg[2] = data;
6886      sgame_boog_set_prg(space->machine());
6887      mmc3_set_chr(space->machine(), state->m_mmc_chr_source, state->m_mmc_chr_base, state->m_mmc_chr_mask);
6888   }
6889}
6890
6891static WRITE8_HANDLER( sgame_boog_w )
6892{
6893   nes_state *state = space->machine().driver_data<nes_state>();
6894   static const UINT8 conv_table[8] = {0,2,5,3,6,1,7,4};
6895   LOG_MMC(("sgame_boog_w, offset: %04x, data: %02x\n", offset, data));
6896
6897   switch (offset & 0x6001)
6898   {
6899      case 0x0000:
6900         if (!state->m_mmc_reg[2])
6901            txrom_w(space, 0x0000, data);
6902         break;
6903
6904      case 0x0001:
6905         if (!state->m_mmc_reg[2])
6906            txrom_w(space, 0x0001, data);
6907         else if (state->m_mmc_reg[3] && ((state->m_mmc_reg[0] & 0x80) == 0 || (state->m_mmc_latch1 & 0x07) < 6))   // if we use the prg16 banks and cmd=6,7 DON'T enter!
6908         {
6909            state->m_mmc_reg[3] = 0;
6910            txrom_w(space, 0x0001, data);
6911         }
6912         break;
6913
6914      case 0x2000:
6915         if (!state->m_mmc_reg[2])
6916            txrom_w(space, 0x2000, data);
6917         else
6918         {
6919            data = (data & 0xc0) | conv_table[data & 0x07];
6920            state->m_mmc_reg[3] = 1;
6921            txrom_w(space, 0x0000, data);
6922            break;
6923         }
6924         break;
6925
6926      case 0x4000:
6927         if (!state->m_mmc_reg[2])
6928            txrom_w(space, 0x4000, data);
6929         else
6930            set_nt_mirroring(space->machine(), ((data >> 7) | data) & 0x01 ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT);
6931         break;
6932
6933      case 0x4001:
6934         if (!state->m_mmc_reg[2])
6935            txrom_w(space, 0x4001, data);
6936         else
6937            txrom_w(space, 0x6001, data);
6938         break;
6939
6940      case 0x6001:
6941         if (!state->m_mmc_reg[2])
6942            txrom_w(space, 0x6001, data);
6943         else
6944         {
6945            txrom_w(space, 0x4000, data);
6946            txrom_w(space, 0x4001, data);
6947         }
6948         break;
6949
6950      default:
6951         txrom_w(space, offset, data);
6952         break;
6953   }
6954}
6955
6956/*************************************************************
6957
6958 Bootleg Board by Super Game
6959
6960 Games: The Lion King
6961
6962 MMC3 clone.
6963
6964 iNES: mapper 114
6965
6966 In MESS: Supported.
6967
6968 *************************************************************/
6969
6970static WRITE8_HANDLER( sgame_lion_m_w )
6971{
6972   nes_state *state = space->machine().driver_data<nes_state>();
6973   LOG_MMC(("sgame_lion_m_w, offset: %04x, data: %02x\n", offset, data));
6974
6975   state->m_map114_reg = data;
6976
6977   if (state->m_map114_reg & 0x80)
6978   {
6979      prg16_89ab(space->machine(), data & 0x1f);
6980      prg16_cdef(space->machine(), data & 0x1f);
6981   }
6982   else
6983      mmc3_set_prg(space->machine(), state->m_mmc_prg_base, state->m_mmc_prg_mask);
6984
6985}
6986
6987static WRITE8_HANDLER( sgame_lion_w )
6988{
6989   nes_state *state = space->machine().driver_data<nes_state>();
6990   static const UINT8 conv_table[8] = {0, 3, 1, 5, 6, 7, 2, 4};
6991   LOG_MMC(("sgame_lion_w, offset: %04x, data: %02x\n", offset, data));
6992
6993   if (offset < 0x6000)
6994   {
6995      switch (offset & 0x6000)
6996      {
6997         case 0x0000:
6998            set_nt_mirroring(space->machine(), BIT(data, 0) ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT);
6999            break;
7000         case 0x2000:
7001            state->m_map114_reg_enabled = 1;
7002            data = (data & 0xc0) | conv_table[data & 0x07];
7003            txrom_w(space, 0x0000, data);
7004            break;
7005         case 0x4000:
7006            if (state->m_map114_reg_enabled && (state->m_map114_reg & 0x80) == 0)
7007            {
7008               state->m_map114_reg_enabled = 0;
7009               txrom_w(space, 0x0001, data);
7010            }
7011            break;
7012      }
7013   }
7014   else
7015   {
7016      switch (offset & 0x03)
7017      {
7018         case 0x02:
7019            txrom_w(space, 0x6000, data);
7020            break;
7021         case 0x03:
7022            txrom_w(space, 0x6001, data);
7023            txrom_w(space, 0x4000, data);
7024            txrom_w(space, 0x4001, data);
7025            break;
7026      }
7027   }
7028}
7029
7030/*************************************************************
7031
7032 Tengen 800008 Board
7033
7034 iNES: mapper 3?
7035
7036 In MESS: Supported.
7037
7038 *************************************************************/
7039
7040static WRITE8_HANDLER( tengen_800008_w )
7041{
7042   LOG_MMC(("tengen_800008_w, offset: %04x, data: %02x\n", offset, data));
7043
7044   prg32(space->machine(), data >> 3);
7045   chr8(space->machine(), data, CHRROM);
7046}
7047
7048/*************************************************************
7049
7050 Tengen 800032 Board
7051
7052 Games: Klax, Road Runner, Rolling Thunder, Shinobi, Skulls
7053 & Croosbones, Xybots
7054
7055 iNES: mapper 64
7056
7057 In MESS: Partially Supported.
7058
7059 *************************************************************/
7060
7061static void tengen_800032_irq( device_t *device, int scanline, int vblank, int blanked )
7062{
7063   nes_state *state = device->machine().driver_data<nes_state>();
7064   if (!state->m_IRQ_mode)   // we are in scanline mode!
7065   {
7066      if (scanline < PPU_BOTTOM_VISIBLE_SCANLINE)
7067      {
7068         if (!state->m_IRQ_reset)
7069         {
7070            if (!state->m_IRQ_count)
7071               state->m_IRQ_count = state->m_IRQ_count_latch;
7072            else
7073            {
7074               state->m_IRQ_count--;
7075               if (state->m_IRQ_enable && !blanked && !state->m_IRQ_count)
7076               {
7077                  LOG_MMC(("irq fired, scanline: %d (MAME %d, beam pos: %d)\n", scanline,
7078                         device->machine().primary_screen->vpos(), device->machine().primary_screen->hpos()));
7079                  device_set_input_line(state->m_maincpu, M6502_IRQ_LINE, HOLD_LINE);
7080               }
7081            }
7082         }
7083         else
7084         {
7085            state->m_IRQ_reset = 0;
7086            state->m_IRQ_count = state->m_IRQ_count_latch + 1;
7087         }
7088      }
7089   }
7090   /* otherwise, we are in CPU cycles mode --> decrement count of 114 every scanline
7091     --> in the meanwhile anything can have happened to IRQ_reset and we would not know
7092     --> Skulls and Crossbones does not show anything!! */
7093   else
7094   {
7095      //      if (!state->m_IRQ_reset)
7096      {
7097         if (state->m_IRQ_count <= 114)
7098            state->m_IRQ_count = state->m_IRQ_count_latch;
7099         else
7100         {
7101            state->m_IRQ_count -= 114;
7102            if (state->m_IRQ_enable && !blanked && (state->m_IRQ_count <= 114))
7103            {
7104               LOG_MMC(("irq fired, scanline: %d (MAME %d, beam pos: %d)\n", scanline,
7105                      device->machine().primary_screen->vpos(), device->machine().primary_screen->hpos()));
7106               device_set_input_line(state->m_maincpu, M6502_IRQ_LINE, HOLD_LINE);
7107            }
7108         }
7109      }
7110      //      else
7111      //      {
7112      //          state->m_IRQ_reset = 0;
7113      //          state->m_IRQ_count = state->m_IRQ_count_latch + 1;
7114      //      }
7115   }
7116}
7117
7118static void tengen_800032_set_prg( running_machine &machine )
7119{
7120   nes_state *state = machine.driver_data<nes_state>();
7121   UINT8 prg_mode = state->m_mmc_latch1 & 0x40;
7122
7123   prg8_89(machine, state->m_mmc_prg_bank[prg_mode ? 2: 0]);
7124   prg8_ab(machine, state->m_mmc_prg_bank[prg_mode ? 0: 1]);
7125   prg8_cd(machine, state->m_mmc_prg_bank[prg_mode ? 1: 2]);
7126}
7127
7128static void tengen_800032_set_chr( running_machine &machine )
7129{
7130   nes_state *state = machine.driver_data<nes_state>();
7131   UINT8 chr_page = (state->m_mmc_latch1 & 0x80) >> 5;
7132
7133   if (state->m_mmc_latch1 & 0x20)
7134   {
7135      chr1_x(machine, 0 ^ chr_page, state->m_mmc_vrom_bank[0], CHRROM);
7136      chr1_x(machine, 1 ^ chr_page, state->m_mmc_vrom_bank[8], CHRROM);
7137      chr1_x(machine, 2 ^ chr_page, state->m_mmc_vrom_bank[1], CHRROM);
7138      chr1_x(machine, 3 ^ chr_page, state->m_mmc_vrom_bank[9], CHRROM);
7139   }
7140   else
7141   {
7142      chr1_x(machine, 0 ^ chr_page, state->m_mmc_vrom_bank[0] & ~0x01, CHRROM);
7143      chr1_x(machine, 1 ^ chr_page, state->m_mmc_vrom_bank[0] |  0x01, CHRROM);
7144      chr1_x(machine, 2 ^ chr_page, state->m_mmc_vrom_bank[1] & ~0x01, CHRROM);
7145      chr1_x(machine, 3 ^ chr_page, state->m_mmc_vrom_bank[1] |  0x01, CHRROM);
7146   }
7147
7148   chr1_x(machine, 4 ^ chr_page, state->m_mmc_vrom_bank[2], CHRROM);
7149   chr1_x(machine, 5 ^ chr_page, state->m_mmc_vrom_bank[3], CHRROM);
7150   chr1_x(machine, 6 ^ chr_page, state->m_mmc_vrom_bank[4], CHRROM);
7151   chr1_x(machine, 7 ^ chr_page, state->m_mmc_vrom_bank[5], CHRROM);
7152}
7153
7154static WRITE8_HANDLER( tengen_800032_w )
7155{
7156   nes_state *state = space->machine().driver_data<nes_state>();
7157   UINT8 map64_helper, cmd;
7158   LOG_MMC(("tengen_800032_w, offset: %04x, data: %02x\n", offset, data));
7159
7160   switch (offset & 0x6001)
7161   {
7162      case 0x0000:
7163         map64_helper = state->m_mmc_latch1 ^ data;
7164         state->m_mmc_latch1 = data;
7165
7166         /* Has PRG Mode changed? */
7167         if (map64_helper & 0x40)
7168            tengen_800032_set_prg(space->machine());
7169
7170         /* Has CHR Mode changed? */
7171         if (map64_helper & 0xa0)
7172            tengen_800032_set_chr(space->machine());
7173         break;
7174
7175      case 0x0001:
7176         cmd = state->m_mmc_latch1 & 0x0f;
7177         switch (cmd)
7178      {
7179         case 0: case 1:
7180         case 2: case 3:
7181         case 4: case 5:
7182            state->m_mmc_vrom_bank[cmd] = data;
7183            tengen_800032_set_chr(space->machine());
7184            break;
7185         case 6: case 7:
7186            state->m_mmc_prg_bank[cmd - 6] = data;
7187            tengen_800032_set_prg(space->machine());
7188            break;
7189         case 8: case 9:
7190            state->m_mmc_vrom_bank[cmd - 2] = data;
7191            tengen_800032_set_chr(space->machine());
7192            break;
7193         case 0x0f:
7194            state->m_mmc_prg_bank[2] = data;
7195            tengen_800032_set_prg(space->machine());
7196            break;
7197      }
7198         break;
7199
7200      case 0x2000:
7201         set_nt_mirroring(space->machine(), BIT(data, 0) ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT);
7202         break;
7203
7204      case 0x4000:
7205         state->m_IRQ_count_latch = data;
7206         break;
7207
7208      case 0x4001: /* $c001 - IRQ scanline latch */
7209         state->m_IRQ_mode = data & 0x01;
7210         state->m_IRQ_reset = 1;
7211         break;
7212
7213      case 0x6000:
7214         state->m_IRQ_enable = 0;
7215         break;
7216
7217      case 0x6001:
7218         state->m_IRQ_enable = 1;
7219         break;
7220
7221      default:
7222         LOG_MMC(("Mapper 64 write. addr: %04x value: %02x\n", offset + 0x8000, data));
7223         break;
7224   }
7225}
7226
7227/*************************************************************
7228
7229 Tengen 800037 Board
7230
7231 Games: Alien Syndrome
7232
7233 iNES: mapper 158
7234
7235 In MESS: Very preliminary support.
7236
7237 *************************************************************/
7238
7239// probably wrong...
7240static void tengen_800037_set_mirror( running_machine &machine )
7241{
7242   nes_state *state = machine.driver_data<nes_state>();
7243   UINT8 nt_mode = state->m_mmc_latch1 & 0x80;
7244
7245   set_nt_page(machine, 0, ROM, state->m_mmc_vrom_bank[nt_mode ? 2 : 0], 0);
7246   set_nt_page(machine, 1, ROM, state->m_mmc_vrom_bank[nt_mode ? 3 : 0], 0);
7247   set_nt_page(machine, 2, ROM, state->m_mmc_vrom_bank[nt_mode ? 4 : 1], 0);
7248   set_nt_page(machine, 3, ROM, state->m_mmc_vrom_bank[nt_mode ? 5 : 1], 0);
7249}
7250
7251static WRITE8_HANDLER( tengen_800037_w )
7252{
7253   nes_state *state = space->machine().driver_data<nes_state>();
7254   UINT8 map158_helper, cmd;
7255   LOG_MMC(("tengen_800037_w, offset: %04x, data: %02x\n", offset, data));
7256
7257   switch (offset & 0x6001)
7258   {
7259      case 0x0000:
7260         map158_helper = state->m_mmc_latch1 ^ data;
7261         state->m_mmc_latch1 = data;
7262
7263         /* Has PRG Mode changed? */
7264         if (map158_helper & 0x40)
7265            tengen_800032_set_prg(space->machine());
7266
7267         /* Has CHR Mode changed? */
7268         if (map158_helper & 0xa0)
7269         {
7270            tengen_800032_set_chr(space->machine());
7271            tengen_800037_set_mirror(space->machine());
7272         }
7273         break;
7274
7275      case 0x0001:
7276         cmd = state->m_mmc_latch1 & 0x0f;
7277         switch (cmd)
7278      {
7279         case 0: case 1:
7280         case 2: case 3:
7281         case 4: case 5:
7282            state->m_mmc_vrom_bank[cmd] = data;
7283            tengen_800032_set_chr(space->machine());
7284            tengen_800037_set_mirror(space->machine());
7285            break;
7286         case 6: case 7:
7287            state->m_mmc_prg_bank[cmd - 6] = data;
7288            tengen_800032_set_prg(space->machine());
7289            break;
7290         case 8: case 9:
7291            state->m_mmc_vrom_bank[cmd - 2] = data;
7292            tengen_800032_set_chr(space->machine());
7293            tengen_800037_set_mirror(space->machine());
7294            break;
7295         case 0x0f:
7296            state->m_mmc_prg_bank[2] = data;
7297            tengen_800032_set_prg(space->machine());
7298            break;
7299      }
7300         break;
7301
7302      case 0x2000:
7303         break;
7304
7305      default:
7306         tengen_800032_w(space, offset, data);
7307         break;
7308   }
7309}
7310
7311/*************************************************************
7312
7313 Bootleg Board 22211 by TXC (Type A)
7314
7315 Games: Creatom
7316
7317 Info from NEStopia: this mapper features write to four
7318 registers (0x4100-0x4103). The third one is used to select
7319 PRG and CHR banks.
7320
7321 iNES: mapper 132
7322
7323 In MESS: Supported.
7324
7325 *************************************************************/
7326
7327static WRITE8_HANDLER( txc_22211_l_w )
7328{
7329   nes_state *state = space->machine().driver_data<nes_state>();
7330   LOG_MMC(("txc_22211_l_w, offset: %04x, data: %02x\n", offset, data));
7331
7332   if (offset < 4)
7333      state->m_txc_reg[offset & 0x03] = data;
7334}
7335
7336static READ8_HANDLER( txc_22211_l_r )
7337{
7338   nes_state *state = space->machine().driver_data<nes_state>();
7339   LOG_MMC(("txc_22211_l_r, offset: %04x\n", offset));
7340
7341   if (offset == 0x0000)
7342      return (state->m_txc_reg[1] ^ state->m_txc_reg[2]) | 0x40;
7343   else
7344      return 0x00;
7345}
7346
7347static WRITE8_HANDLER( txc_22211_w )
7348{
7349   nes_state *state = space->machine().driver_data<nes_state>();
7350   LOG_MMC(("txc_22211_w, offset: %04x, data: %02x\n", offset, data));
7351
7352   prg32(space->machine(), state->m_txc_reg[2] >> 2);
7353   chr8(space->machine(), state->m_txc_reg[2], CHRROM);
7354}
7355
7356/*************************************************************
7357
7358 Bootleg Board 22211 by TXC (Type B)
7359
7360 Games: 1991 Du Ma Racing
7361
7362 This mapper is basically the same as Type A. Only difference is
7363 in the way CHR banks are selected (see below)
7364
7365 iNES: mapper 172
7366
7367 In MESS: Supported.
7368
7369 *************************************************************/
7370
7371static WRITE8_HANDLER( txc_22211b_w )
7372{
7373   nes_state *state = space->machine().driver_data<nes_state>();
7374   LOG_MMC(("txc_22211b_w, offset: %04x, data: %02x\n", offset, data));
7375
7376   prg32(space->machine(), state->m_txc_reg[2] >> 2);
7377   chr8(space->machine(), (((data ^ state->m_txc_reg[2]) >> 3) & 0x02) | (((data ^ state->m_txc_reg[2]) >> 5) & 0x01), CHRROM);
7378}
7379
7380/*************************************************************
7381
7382 Bootleg Board 22211 by TXC (Type C)
7383
7384 Games: Mahjong Block, Xiao Ma Li
7385
7386 This mapper is basically the same as 132 too. Only difference is
7387 in 0x4100 reads which expect also bit 0 to be set
7388
7389 iNES: mapper 172
7390
7391 In MESS: Supported.
7392
7393 *************************************************************/
7394
7395static READ8_HANDLER( txc_22211c_l_r )
7396{
7397   nes_state *state = space->machine().driver_data<nes_state>();
7398   LOG_MMC(("txc_22211c_l_r, offset: %04x\n", offset));
7399
7400   if (offset == 0x0000)
7401      return (state->m_txc_reg[1] ^ state->m_txc_reg[2]) | 0x41;
7402   else
7403      return 0x00;
7404}
7405
7406/*************************************************************
7407
7408 Bootleg Board 'Thunder Warrior' by TXC
7409
7410 Games: Master Fighter II, Master Fighter 3, Thunder Warrior
7411
7412 MMC3 clone
7413
7414 iNES: mapper 189
7415
7416 In MESS: Supported.
7417
7418 *************************************************************/
7419
7420static WRITE8_HANDLER( txc_tw_l_w )
7421{
7422   LOG_MMC(("txctw_l_w, offset: %04x, data: %02x\n", offset, data));
7423
7424   prg32(space->machine(), (data >> 4) | data);
7425}
7426
7427static WRITE8_HANDLER( txc_tw_m_w )
7428{
7429   LOG_MMC(("txctw_m_w, offset: %04x, data: %04x\n", offset, data));
7430
7431   txc_tw_l_w(space, offset & 0xff, data);   // offset does not really count for this mapper
7432}
7433
7434/* writes to 0x8000-0xffff are like MMC3 but no PRG bankswitch (beacuse it is handled by low writes) */
7435static void txc_tw_prg_cb( running_machine &machine, int start, int bank )
7436{
7437   return;
7438}
7439
7440/*************************************************************
7441
7442 Bootleg Board 'Strike Wolf' by TXC
7443
7444 Games: Strike Wolf (also Policeman?? according to Nestopia)
7445
7446 iNES: mapper 36
7447
7448 Known Boards: Bootleg Board by TXC
7449
7450 In MESS: Supported.
7451
7452 *************************************************************/
7453
7454static WRITE8_HANDLER( txc_strikewolf_w )
7455{
7456   LOG_MMC(("txc_strikewolf_w, offset: %04x, data: %02x\n", offset, data));
7457
7458   if ((offset >= 0x400) && (offset < 0x7fff))
7459   {
7460      prg32(space->machine(), data >> 4);
7461      chr8(space->machine(), data & 0x0f, CHRROM);
7462   }
7463}
7464
7465/*************************************************************
7466
7467 Bootleg Board MXMDHTWO by TXC
7468
7469 Games: Commandos, Journey to the West, Ma Bu Mi Zhen &
7470 Qu Wei Cheng Yu Wu, Si Lu Chuan Qi
7471
7472 Simple Mapper: writes to 0x8000-0xffff sets the prg32 bank.
7473 Not sure if returning 0x50 for reads in 0x4100-0x5000 is correct.
7474
7475 iNES: mapper 241
7476
7477 In MESS: Supported.
7478
7479 *************************************************************/
7480
7481static READ8_HANDLER( txc_mxmdhtwo_l_r )
7482{
7483   return 0x50;
7484}
7485
7486static WRITE8_HANDLER( txc_mxmdhtwo_w )
7487{
7488   LOG_MMC(("txc_mxmdhtwo_w, offset: %04x, data: %02x\n", offset, data));
7489
7490   prg32(space->machine(), data);
7491}
7492
7493/*************************************************************
7494
7495 Waixing Board Type A
7496
7497 Games: Columbus - Ougon no Yoake (C), Ji Jia Zhan Shi,
7498 Jia A Fung Yun, Wei Luo Chuan Qi
7499
7500 This mapper is quite similar to MMC3, but with two differences:
7501 mirroring is not the same, and when VROM banks 8,9 are accessed
7502 they point to CHRRAM and not CHRROM.
7503
7504 iNES: mapper 74
7505
7506 In MESS: Supported
7507
7508 *************************************************************/
7509
7510/* MIRROR_LOW and MIRROR_HIGH are swapped! */
7511static void waixing_set_mirror( running_machine &machine, UINT8 nt )
7512{
7513   switch (nt)
7514   {
7515      case 0:
7516      case 1:
7517         set_nt_mirroring(machine, nt ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT);
7518         break;
7519      case 2:
7520         set_nt_mirroring(machine, PPU_MIRROR_LOW);
7521         break;
7522      case 3:
7523         set_nt_mirroring(machine, PPU_MIRROR_HIGH);
7524         break;
7525      default:
7526         LOG_MMC(("Mapper set NT to invalid value %02x", nt));
7527         break;
7528   }
7529}
7530
7531/* Luo Ke Ren X only works with this */
7532static void waixing_a_chr_cb( running_machine &machine, int start, int bank, int source )
7533{
7534   int chr_src = (bank <= 9) ? CHRRAM : CHRROM;
7535   chr1_x(machine, start, bank, chr_src);
7536}
7537
7538/* Ji Jia Zhan Shi only works with this */
7539static void waixing_a1_chr_cb( running_machine &machine, int start, int bank, int source )
7540{
7541   int chr_src = ((bank == 8) || (bank == 9)) ? CHRRAM : CHRROM;
7542   chr1_x(machine, start, bank, chr_src);
7543}
7544
7545static WRITE8_HANDLER( waixing_a_w )
7546{
7547   LOG_MMC(("waixing_a_w, offset: %04x, data: %02x\n", offset, data));
7548
7549   switch (offset & 0x6001)
7550   {
7551      case 0x2000:
7552         waixing_set_mirror(space->machine(), data);   //maybe data & 0x03?
7553         break;
7554
7555      case 0x2001:
7556         break;
7557
7558      default:
7559         txrom_w(space, offset, data);
7560         break;
7561   }
7562}
7563
7564/*************************************************************
7565
7566 Waixing Board Type B
7567
7568 Games: Sugoro Quest (C)
7569
7570 MMC3 clone. This is a minor modification of Mapper 74,
7571 in the sense that it is the same board except for the
7572 CHRRAM pages.
7573
7574 iNES: mapper 191
7575
7576 In MESS: Supported.
7577
7578 *************************************************************/
7579
7580static void waixing_b_chr_cb( running_machine &machine, int start, int bank, int source )
7581{
7582   int chr_src = BIT(bank, 7) ? CHRRAM : CHRROM;
7583   chr1_x(machine, start, bank, chr_src);
7584}
7585
7586/*************************************************************
7587
7588 Waixing Board Type C
7589
7590 Games: Ying Lie Qun Xia Zhuan, Young Chivalry
7591
7592 MMC3 clone. This is a minor modification of Mapper 74,
7593 in the sense that it is the same board except for the
7594 CHRRAM pages.
7595
7596 iNES: mapper 192
7597
7598 In MESS: Supported.
7599
7600 *************************************************************/
7601
7602static void waixing_c_chr_cb( running_machine &machine, int start, int bank, int source )
7603{
7604   int chr_src = ((bank == 0x08) || (bank == 0x09) || (bank == 0x0a) || (bank == 0x0b)) ? CHRRAM : CHRROM;
7605   chr1_x(machine, start, bank, chr_src);
7606}
7607
7608/*************************************************************
7609
7610 Waixing Board Type D
7611
7612 Games: Super Robot Taisen (C)
7613
7614 MMC3 clone. This is a minor modification of Mapper 74,
7615 in the sense that it is the same board except for the
7616 CHRRAM pages.
7617
7618 iNES: mapper 194
7619
7620 In MESS: Supported.
7621
7622 *************************************************************/
7623
7624static void waixing_d_chr_cb( running_machine &machine, int start, int bank, int source )
7625{
7626   int chr_src = (bank < 0x02) ? CHRRAM : CHRROM;
7627   chr1_x(machine, start, bank, chr_src);
7628}
7629
7630/*************************************************************
7631
7632 Waixing Board Type E
7633
7634 Games: Captain Tsubasa Vol. II (C), Chaos World, God
7635 Slayer (C), Zu Qiu Xiao Jiang
7636
7637 MMC3 clone. This is a minor modification of Mapper 74,
7638 in the sense that it is the same board except for the
7639 CHRRAM pages.
7640
7641 iNES: mapper 195
7642
7643 In MESS: Supported.
7644
7645 *************************************************************/
7646
7647static void waixing_e_chr_cb( running_machine &machine, int start, int bank, int source )
7648{
7649   int chr_src = (bank < 0x04) ? CHRRAM : CHRROM;
7650   chr1_x(machine, start, bank, chr_src);
7651}
7652
7653/*************************************************************
7654
7655 Waixing Board Type F
7656
7657 Games: Tenchi wo Kurau II (C)
7658
7659 MMC3 clone.
7660
7661 iNES: mapper 198
7662
7663 In MESS: Preliminary support.
7664
7665 *************************************************************/
7666
7667static WRITE8_HANDLER( waixing_f_w )
7668{
7669   nes_state *state = space->machine().driver_data<nes_state>();
7670   UINT8 cmd;
7671   LOG_MMC(("waixing_f_w, offset: %04x, data: %02x\n", offset, data));
7672
7673   switch (offset & 0x6001)
7674   {
7675      case 0x0001:
7676         cmd = state->m_mmc_latch1 & 0x07;
7677         if (cmd >= 6)
7678         {
7679            state->m_mmc_prg_bank[cmd - 6] = data & ((data > 0x3f) ? 0x4f : 0x3f);
7680            mmc3_set_prg(space->machine(), state->m_mmc_prg_base, state->m_mmc_prg_mask);
7681         }
7682         else
7683            waixing_a_w(space, offset, data);
7684         break;
7685
7686      default:
7687         waixing_a_w(space, offset, data);
7688         break;
7689   }
7690}
7691
7692/*************************************************************
7693
7694 Waixing Board Type G
7695
7696 Games: San Guo Zhi 2, Dragon Ball Z Gaiden (C), Dragon
7697 Ball Z II (C)
7698
7699 MMC3 clone
7700
7701 iNES: mapper 199
7702
7703 In MESS: Supported.
7704
7705 *************************************************************/
7706
7707static void waixing_g_chr_cb( running_machine &machine, int start, int bank, int source )
7708{
7709   int chr_src = (bank < 0x08) ? CHRRAM : CHRROM;
7710   chr1_x(machine, start, bank, chr_src);
7711}
7712
7713static void waixing_g_set_chr( running_machine &machine, int chr_base, int chr_mask )
7714{
7715   nes_state *state = machine.driver_data<nes_state>();
7716   UINT8 chr_page = (state->m_mmc_latch1 & 0x80) >> 5;
7717
7718   state->m_mmc3_chr_cb(machine, chr_page ^ 0, chr_base | (state->m_mmc_vrom_bank[0] & chr_mask), state->m_mmc_chr_source);
7719   state->m_mmc3_chr_cb(machine, chr_page ^ 1, chr_base | (state->m_mmc_vrom_bank[6] & chr_mask), state->m_mmc_chr_source);
7720   state->m_mmc3_chr_cb(machine, chr_page ^ 2, chr_base | (state->m_mmc_vrom_bank[1] & chr_mask), state->m_mmc_chr_source);
7721   state->m_mmc3_chr_cb(machine, chr_page ^ 3, chr_base | (state->m_mmc_vrom_bank[7] & chr_mask), state->m_mmc_chr_source);
7722   state->m_mmc3_chr_cb(machine, chr_page ^ 4, chr_base | (state->m_mmc_vrom_bank[2] & chr_mask), state->m_mmc_chr_source);
7723   state->m_mmc3_chr_cb(machine, chr_page ^ 5, chr_base | (state->m_mmc_vrom_bank[3] & chr_mask), state->m_mmc_chr_source);
7724   state->m_mmc3_chr_cb(machine, chr_page ^ 6, chr_base | (state->m_mmc_vrom_bank[4] & chr_mask), state->m_mmc_chr_source);
7725   state->m_mmc3_chr_cb(machine, chr_page ^ 7, chr_base | (state->m_mmc_vrom_bank[5] & chr_mask), state->m_mmc_chr_source);
7726}
7727
7728static WRITE8_HANDLER( waixing_g_w )
7729{
7730   nes_state *state = space->machine().driver_data<nes_state>();
7731   UINT8 MMC3_helper, cmd;
7732   LOG_MMC(("waixing_g_w, offset: %04x, data: %02x\n", offset, data));
7733
7734   switch (offset & 0x6001)
7735   {
7736      case 0x0000:
7737         MMC3_helper = state->m_mmc_latch1 ^ data;
7738         state->m_mmc_latch1 = data;
7739
7740         /* Has PRG Mode changed? */
7741         if (MMC3_helper & 0x40)
7742            mmc3_set_prg(space->machine(), state->m_mmc_prg_base, state->m_mmc_prg_mask);
7743
7744         /* Has CHR Mode changed? */
7745         if (MMC3_helper & 0x80)
7746            waixing_g_set_chr(space->machine(), state->m_mmc_chr_base, state->m_mmc_chr_mask);
7747         break;
7748
7749      case 0x0001:
7750         cmd = state->m_mmc_latch1 & 0x0f;
7751         switch (cmd)
7752         {
7753         case 0: case 1:   // these do not need to be separated: we take care of them in set_chr!
7754         case 2: case 3: case 4: case 5:
7755            state->m_mmc_vrom_bank[cmd] = data;
7756            waixing_g_set_chr(space->machine(), state->m_mmc_chr_base, state->m_mmc_chr_mask);
7757            break;
7758         case 6:
7759         case 7:
7760         case 8:
7761         case 9:
7762            state->m_mmc_prg_bank[cmd - 6] = data;
7763            mmc3_set_prg(space->machine(), state->m_mmc_prg_base, state->m_mmc_prg_mask);
7764            break;
7765         case 0x0a: case 0x0b:
7766            state->m_mmc_vrom_bank[cmd - 4] = data;
7767            waixing_g_set_chr(space->machine(), state->m_mmc_chr_base, state->m_mmc_chr_mask);
7768            break;
7769         }
7770         break;
7771
7772      default:
7773         waixing_a_w(space, offset, data);
7774         break;
7775   }
7776}
7777
7778/*************************************************************
7779
7780 Waixing Board Type H
7781
7782 Games: Ying Xiong Yuan Yi Jing Chuan Qi, Yong Zhe Dou E
7783 Long - Dragon Quest VII
7784
7785 MMC3 clone. More info to come.
7786
7787 iNES: mapper 245
7788
7789 In MESS: Supported.
7790
7791 *************************************************************/
7792
7793static void waixing_h_chr_cb( running_machine &machine, int start, int bank, int source )
7794{
7795   if (source == CHRROM)
7796      chr1_x(machine, start, bank, source);
7797}
7798
7799static WRITE8_HANDLER( waixing_h_w )
7800{
7801   nes_state *state = space->machine().driver_data<nes_state>();
7802   UINT8 cmd;
7803   LOG_MMC(("waixing_h_w, offset: %04x, data: %02x\n", offset, data));
7804
7805   switch (offset & 0x6001)
7806   {
7807      case 0x0001:
7808         cmd = state->m_mmc3_latch & 0x07;
7809         switch (cmd)
7810         {
7811         case 0:    // in this case we set prg_base in addition to state->m_mmc_vrom_bank!
7812            state->m_mmc_prg_base = (data << 5) & 0x40;
7813            state->m_mmc_prg_mask = 0x3f;
7814            mmc3_set_prg(space->machine(), state->m_mmc_prg_base, state->m_mmc_prg_mask);
7815            txrom_w(space, offset, data);
7816         default:
7817            txrom_w(space, offset, data);
7818            break;
7819         }
7820         break;
7821
7822      case 0x2001:
7823         break;
7824
7825      default:
7826         txrom_w(space, offset, data);
7827         break;
7828   }
7829}
7830
7831/*************************************************************
7832
7833 Waixing San Guo Zhi Board
7834
7835 Games: San Guo Zhi
7836
7837 This board uses Konami IRQ
7838
7839 iNES: mapper 252
7840
7841 In MESS: Unsupported.
7842
7843 *************************************************************/
7844
7845static WRITE8_HANDLER( waixing_sgz_w )
7846{
7847   nes_state *state = space->machine().driver_data<nes_state>();
7848   UINT8 mmc_helper, bank;
7849   LOG_MMC(("waixing_sgz_w, offset: %04x, data: %02x\n", offset, data));
7850
7851   switch (offset & 0x7000)
7852   {
7853      case 0x0000:
7854         prg8_89(space->machine(), data);
7855         break;
7856      case 0x2000:
7857         prg8_ab(space->machine(), data);
7858         break;
7859      case 0x3000:
7860      case 0x4000:
7861      case 0x5000:
7862      case 0x6000:
7863         bank = ((offset & 0x7000) - 0x3000) / 0x0800 + ((offset & 0x0008) >> 3);
7864         mmc_helper = offset & 0x04;
7865         if (mmc_helper)
7866            state->m_mmc_vrom_bank[bank] = (state->m_mmc_vrom_bank[bank] & 0x0f) | ((data & 0x0f) << 4);
7867         else
7868            state->m_mmc_vrom_bank[bank] = (state->m_mmc_vrom_bank[bank] & 0xf0) | (data & 0x0f);
7869         chr1_x(space->machine(), bank, state->m_mmc_vrom_bank[bank], CHRROM);
7870         break;
7871      case 0x7000:
7872         switch (offset & 0x0c)
7873         {
7874         case 0x00:
7875            state->m_IRQ_count_latch = (state->m_IRQ_count_latch & 0xf0) | (data & 0x0f);
7876            break;
7877         case 0x04:
7878            state->m_IRQ_count_latch = (state->m_IRQ_count_latch & 0x0f) | ((data & 0x0f) << 4);
7879            break;
7880         case 0x08:
7881            state->m_IRQ_enable = data & 0x02;
7882            state->m_IRQ_enable_latch = data & 0x01;
7883            if (data & 0x02)
7884               state->m_IRQ_count = state->m_IRQ_count_latch;
7885            break;
7886         case 0x0c:
7887            state->m_IRQ_enable = state->m_IRQ_enable_latch;
7888            break;
7889         }
7890         break;
7891   }
7892}
7893
7894
7895/*************************************************************
7896
7897 Waixing San Guo Zhong Lie Zhuan Board
7898
7899 Games: Fan Kong Jing Ying, San Guo Zhong Lie Zhuan, Xing
7900 Ji Zheng Ba
7901
7902 iNES: mapper 178
7903
7904 In MESS: Supported.
7905
7906 *************************************************************/
7907
7908static WRITE8_HANDLER( waixing_sgzlz_l_w )
7909{
7910   nes_state *state = space->machine().driver_data<nes_state>();
7911   LOG_MMC(("waixing_sgzlz_l_w, offset: %04x, data: %02x\n", offset, data));
7912
7913   switch (offset)
7914   {
7915      case 0x700:
7916         set_nt_mirroring(space->machine(), data ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT);
7917         break;
7918      case 0x701:
7919         state->m_mmc_latch1 = (state->m_mmc_latch1 & 0x0c) | ((data >> 1) & 0x03);
7920         prg32(space->machine(), state->m_mmc_latch1);
7921         break;
7922      case 0x702:
7923         state->m_mmc_latch1 = (state->m_mmc_latch1 & 0x03) | ((data << 2) & 0x0c);
7924         break;
7925   }
7926}
7927
7928/*************************************************************
7929
7930 Waixing Final Fantasy V Board
7931
7932 Games: Darkseed, Digital Dragon, Final Fantasy V, Pocket
7933 Monster Red
7934
7935 iNES: mapper 164
7936
7937 In MESS: Supported.
7938
7939 *************************************************************/
7940
7941static WRITE8_HANDLER( waixing_ffv_l_w )
7942{
7943   nes_state *state = space->machine().driver_data<nes_state>();
7944   UINT8 mmc_helper;
7945   LOG_MMC(("waixing_ffv_l_w, offset: %04x, data: %02x\n", offset, data));
7946   offset += 0x100; /* the checks work better on addresses */
7947
7948   if (0x1000 == (offset & 0x1200))
7949   {
7950      state->m_mmc_reg[BIT(offset, 8)] = data;
7951      mmc_helper = BIT(state->m_mmc_reg[1], 0) << 5;
7952      switch (state->m_mmc_reg[0] & 0x70)
7953      {
7954         case 0x00:
7955         case 0x20:
7956         case 0x40:
7957         case 0x60:
7958            prg16_89ab(space->machine(), mmc_helper | ((state->m_mmc_reg[0] >> 1) & 0x10) | (state->m_mmc_reg[0] & 0x0f));
7959            prg16_cdef(space->machine(), mmc_helper & 0x1f);
7960            break;
7961         case 0x50:
7962            prg32(space->machine(), (mmc_helper >> 1) | (state->m_mmc_reg[0] & 0x0f));
7963            break;
7964         case 0x70:
7965            prg16_89ab(space->machine(), mmc_helper | ((state->m_mmc_reg[0] << 1) & 0x10) | (state->m_mmc_reg[0] & 0x0f));
7966            prg16_cdef(space->machine(), mmc_helper & 0x1f);
7967            break;
7968      }
7969   }
7970}
7971
7972/*************************************************************
7973
7974 Waixing Zhan Shi Board
7975
7976 Games: Wai Xing Zhan Shi
7977
7978 Simple mapper: writes to 0x8000-0xffff sets prg32 banks to
7979 (offset>>3)&f. written data&3 sets the mirroring (with
7980 switched high/low compared to the standard one).
7981
7982 A crc check is required to support Dragon Quest VIII (which
7983 uses a slightly different board)
7984
7985 iNES: mapper 242
7986
7987 In MESS: Supported.
7988
7989 *************************************************************/
7990
7991static WRITE8_HANDLER( waixing_zs_w )
7992{
7993   LOG_MMC(("waixing_zs_w, offset: %04x, data: %02x\n", offset, data));
7994
7995   prg32(space->machine(), offset >> 3);
7996
7997   switch (data & 0x03)
7998   {
7999      case 0: set_nt_mirroring(space->machine(), PPU_MIRROR_VERT); break;
8000      case 1: set_nt_mirroring(space->machine(), PPU_MIRROR_HORZ); break;
8001      case 2: set_nt_mirroring(space->machine(), PPU_MIRROR_LOW); break;
8002      case 3: set_nt_mirroring(space->machine(), PPU_MIRROR_HIGH); break;
8003   }
8004}
8005
8006/*************************************************************
8007
8008 Waixing Dragon Quest VIII Board
8009
8010 Games: Dragon Quest VIII
8011
8012 Simple mapper: writes to 0x8000-0xffff sets prg32 banks to
8013 (offset>>3)&f.
8014
8015 iNES: mapper 242
8016
8017 In MESS: Supported.
8018
8019 *************************************************************/
8020
8021static WRITE8_HANDLER( waixing_dq8_w )
8022{
8023   LOG_MMC(("waixing_dq8_w, offset: %04x, data: %02x\n", offset, data));
8024
8025   prg32(space->machine(), offset >> 3);
8026}
8027
8028
8029/*************************************************************
8030
8031 Waixing PS2 board
8032
8033 Games: Bao Xiao Tien Guo, Bio Hazard, Pokemon Gold, Subor (R)
8034
8035 iNES: mapper 15
8036
8037 In MESS: Supported
8038
8039 *************************************************************/
8040
8041static WRITE8_HANDLER( waixing_ps2_w )
8042{
8043   UINT8 map15_flip = (data & 0x80) >> 7;
8044   UINT8 map15_helper = (data & 0x7f) << 1;
8045
8046   LOG_MMC(("waixing_ps2_w, offset: %04x, data: %02x\n", offset, data));
8047
8048   set_nt_mirroring(space->machine(), BIT(data, 6) ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT);
8049
8050   switch (offset & 0x0fff)
8051   {
8052      case 0x000:
8053         prg8_89(space->machine(), (map15_helper + 0) ^ map15_flip);
8054         prg8_ab(space->machine(), (map15_helper + 1) ^ map15_flip);
8055         prg8_cd(space->machine(), (map15_helper + 2) ^ map15_flip);
8056         prg8_ef(space->machine(), (map15_helper + 3) ^ map15_flip);
8057         break;
8058      case 0x001:
8059         map15_helper |= map15_flip;
8060         prg8_89(space->machine(), map15_helper);
8061         prg8_ab(space->machine(), map15_helper + 1);
8062         prg8_cd(space->machine(), map15_helper + 1);
8063         prg8_ef(space->machine(), map15_helper + 1);
8064         break;
8065      case 0x002:
8066         map15_helper |= map15_flip;
8067         prg8_89(space->machine(), map15_helper);
8068         prg8_ab(space->machine(), map15_helper);
8069         prg8_cd(space->machine(), map15_helper);
8070         prg8_ef(space->machine(), map15_helper);
8071         break;
8072      case 0x003:
8073         map15_helper |= map15_flip;
8074         prg8_89(space->machine(), map15_helper);
8075         prg8_ab(space->machine(), map15_helper + 1);
8076         prg8_cd(space->machine(), map15_helper);
8077         prg8_ef(space->machine(), map15_helper + 1);
8078         break;
8079   }
8080}
8081
8082/*************************************************************
8083
8084 Waixing Board with Security Chip
8085
8086 Games: Duo Bao Xiao Ying Hao - Guang Ming yu An Hei Chuan Shuo,
8087 Myth Struggle, San Shi Liu Ji, Shui Hu Zhuan
8088
8089 MMC3 clone
8090
8091 iNES: mapper 249
8092
8093 In MESS: Partially Supported.
8094
8095 *************************************************************/
8096
8097static void waixing_sec_prg_cb( running_machine &machine, int start, int bank )
8098{
8099   nes_state *state = machine.driver_data<nes_state>();
8100
8101   if (state->m_mmc_reg[0])
8102      bank = ((bank & 0x01)) | ((bank >> 3) & 0x02) | ((bank >> 1) & 0x04) | ((bank << 2) & 0x18);
8103
8104   prg8_x(machine, start, bank);
8105}
8106
8107static void waixing_sec_chr_cb( running_machine &machine, int start, int bank, int source )
8108{
8109   nes_state *state = machine.driver_data<nes_state>();
8110
8111   if (state->m_mmc_reg[0])
8112      bank = ((bank & 0x03)) | ((bank >> 1) & 0x04) | ((bank >> 4) & 0x08) |
8113            ((bank >> 2) & 0x10) | ((bank << 3) & 0x20) | ((bank << 2) & 0xc0);
8114
8115   chr1_x(machine, start, bank, source);
8116}
8117
8118static WRITE8_HANDLER( waixing_sec_l_w )
8119{
8120   nes_state *state = space->machine().driver_data<nes_state>();
8121   LOG_MMC(("waixing_sec_l_w, offset: %04x, data: %02x\n", offset, data));
8122
8123   offset += 0x100;
8124
8125   if (offset == 0x1000)
8126   {
8127      state->m_mmc_reg[0] = data & 0x02;
8128      mmc3_set_prg(space->machine(), state->m_mmc_prg_base, state->m_mmc_prg_mask);
8129      mmc3_set_chr(space->machine(), state->m_mmc_chr_source, state->m_mmc_chr_base, state->m_mmc_chr_mask);
8130   }
8131}
8132
8133/*************************************************************
8134
8135 Waixing SH2 Board
8136
8137 Games: Fire Emblem (C) and Fire Emblem Gaiden (C)
8138
8139 MMC3 clone with different access to CHR
8140
8141 iNES: mapper 165
8142
8143 In MESS: Partially Supported.
8144
8145 *************************************************************/
8146
8147static void waixing_sh2_chr_cb( running_machine &machine, int start, int bank, int source )
8148{
8149   nes_state *state = machine.driver_data<nes_state>();
8150
8151   chr4_0(machine, state->m_mmc_reg[0], state->m_mmc_reg[0] ? CHRRAM : CHRROM);
8152   chr4_4(machine, state->m_mmc_reg[1], state->m_mmc_reg[1] ? CHRRAM : CHRROM);
8153}
8154
8155READ8_HANDLER( waixing_sh2_chr_r )
8156{
8157   nes_state *state = space->machine().driver_data<nes_state>();
8158   int bank = offset >> 10;
8159   UINT8 val = state->m_chr_map[bank].access[offset & 0x3ff];   // this would be usual return value
8160   int chr_helper;
8161
8162   switch (offset & 0xff8)
8163   {
8164      case 0xfd0: chr_helper = (bank & 0x4) | 0x0; break;
8165      case 0xfe8: chr_helper = (bank & 0x4) | 0x2; break;
8166      default: return val;
8167   }
8168
8169   state->m_mmc_reg[offset >> 12] = chr_helper;
8170   if (offset & 0x1000)
8171      chr4_4(space->machine(), state->m_mmc_reg[1], state->m_mmc_reg[1] ? CHRRAM : CHRROM);
8172   else
8173      chr4_0(space->machine(), state->m_mmc_reg[0], state->m_mmc_reg[0] ? CHRRAM : CHRROM);
8174
8175   return val;
8176}
8177
8178/*************************************************************
8179
8180 Board UNL-8237
8181
8182 Games: Pocahontas 2
8183
8184 MMC3 clone
8185
8186 In MESS: Supported
8187
8188 *************************************************************/
8189
8190static void unl_8237_prg_cb( running_machine &machine, int start, int bank )
8191{
8192   nes_state *state = machine.driver_data<nes_state>();
8193
8194   if (!(state->m_mmc_reg[0] & 0x80))
8195      prg8_x(machine, start, bank);
8196}
8197
8198static void unl_8237_chr_cb( running_machine &machine, int start, int bank, int source )
8199{
8200   nes_state *state = machine.driver_data<nes_state>();
8201   bank |= ((state->m_mmc_reg[1] << 6) & 0x100);
8202
8203   chr1_x(machine, start, bank, source);
8204}
8205
8206static WRITE8_HANDLER( unl_8237_l_w )
8207{
8208   nes_state *state = space->machine().driver_data<nes_state>();
8209   LOG_MMC(("unl_8237_l_w offset: %04x, data: %02x\n", offset, data));
8210   offset += 0x100;
8211
8212   if (offset == 0x1000)
8213   {
8214      state->m_mmc_reg[0] = data;
8215      if (state->m_mmc_reg[0] & 0x80)
8216      {
8217         if (state->m_mmc_reg[0] & 0x20)
8218            prg32(space->machine(), (state->m_mmc_reg[0] & 0x0f) >> 1);
8219         else
8220         {
8221            prg16_89ab(space->machine(), state->m_mmc_reg[0] & 0x1f);
8222            prg16_cdef(space->machine(), state->m_mmc_reg[0] & 0x1f);
8223         }
8224      }
8225      else
8226         mmc3_set_prg(space->machine(), state->m_mmc_prg_base, state->m_mmc_prg_mask);
8227   }
8228
8229   if (offset == 0x1001)
8230   {
8231      state->m_mmc_reg[1] = data;
8232      mmc3_set_chr(space->machine(), state->m_mmc_chr_source, state->m_mmc_chr_base, state->m_mmc_chr_mask);
8233   }
8234}
8235
8236static WRITE8_HANDLER( unl_8237_w )
8237{
8238   nes_state *state = space->machine().driver_data<nes_state>();
8239   static const UINT8 conv_table[8] = {0, 2, 6, 1, 7, 3, 4, 5};
8240   LOG_MMC(("unl_8237_w offset: %04x, data: %02x\n", offset, data));
8241
8242   switch (offset & 0x7000)
8243   {
8244      case 0x0000:
8245      case 0x1000:
8246         set_nt_mirroring(space->machine(), (data | (data >> 7)) & 0x01 ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT);
8247         break;
8248
8249      case 0x2000:
8250      case 0x3000:
8251         state->m_mmc_reg[2] = 1;
8252         data = (data & 0xc0) | conv_table[data & 0x07];
8253         txrom_w(space, 0x0000, data);
8254         break;
8255
8256      case 0x4000:
8257      case 0x5000:
8258         if (state->m_mmc_reg[2])
8259         {
8260            state->m_mmc_reg[2] = 0;
8261            txrom_w(space, 0x0001, data);
8262         }
8263         break;
8264
8265      case 0x6000:
8266         break;
8267
8268      case 0x7000:
8269         txrom_w(space, 0x6001, data);
8270         txrom_w(space, 0x4000, data);
8271         txrom_w(space, 0x4001, data);
8272         break;
8273   }
8274}
8275
8276/*************************************************************
8277
8278 Board UNL-AX5705
8279
8280 Games: Super Mario Bros. Pocker Mali (Crayon Shin-chan pirate hack)
8281
8282 In MESS: Supported
8283
8284 *************************************************************/
8285
8286static void unl_ax5705_set_prg( running_machine &machine )
8287{
8288   nes_state *state = machine.driver_data<nes_state>();
8289   prg8_89(machine, state->m_mmc_prg_bank[0]);
8290   prg8_ab(machine, state->m_mmc_prg_bank[1]);
8291}
8292
8293static WRITE8_HANDLER( unl_ax5705_w )
8294{
8295   nes_state *state = space->machine().driver_data<nes_state>();
8296   UINT8 bank;
8297   LOG_MMC(("unl_ax5705_w offset: %04x, data: %02x\n", offset, data));
8298
8299   switch (offset & 0x700f)
8300   {
8301      case 0x0000:
8302         state->m_mmc_prg_bank[0] = (data & 0x05) | ((data & 0x08) >> 2) | ((data & 0x02) << 2);
8303         unl_ax5705_set_prg(space->machine());
8304         break;
8305      case 0x0008:
8306         set_nt_mirroring(space->machine(), BIT(data, 0) ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT);
8307         break;
8308      case 0x2000:
8309         state->m_mmc_prg_bank[1] = (data & 0x05) | ((data & 0x08) >> 2) | ((data & 0x02) << 2);
8310         unl_ax5705_set_prg(space->machine());
8311         break;
8312         /* CHR banks 0, 1, 4, 5 */
8313      case 0x2008:
8314      case 0x200a:
8315      case 0x4008:
8316      case 0x400a:
8317         bank = ((offset & 0x4000) ? 4 : 0) + ((offset & 0x0002) ? 1 : 0);
8318         state->m_mmc_vrom_bank[bank] = (state->m_mmc_vrom_bank[bank] & 0xf0) | (data & 0x0f);
8319         chr1_x(space->machine(), bank, state->m_mmc_vrom_bank[bank], CHRROM);
8320         break;
8321      case 0x2009:
8322      case 0x200b:
8323      case 0x4009:
8324      case 0x400b:
8325         bank = ((offset & 0x4000) ? 4 : 0) + ((offset & 0x0002) ? 1 : 0);
8326         state->m_mmc_vrom_bank[bank] = (state->m_mmc_vrom_bank[bank] & 0x0f) | ((data & 0x04) << 3) | ((data & 0x02) << 5) | ((data & 0x09) << 4);
8327         chr1_x(space->machine(), bank, state->m_mmc_vrom_bank[bank], CHRROM);
8328         break;
8329         /* CHR banks 2, 3, 6, 7 */
8330      case 0x4000:
8331      case 0x4002:
8332      case 0x6000:
8333      case 0x6002:
8334         bank = 2 + ((offset & 0x2000) ? 4 : 0) + ((offset & 0x0002) ? 1 : 0);
8335         state->m_mmc_vrom_bank[bank] = (state->m_mmc_vrom_bank[bank] & 0xf0) | (data & 0x0f);
8336         chr1_x(space->machine(), bank, state->m_mmc_vrom_bank[bank], CHRROM);
8337         break;
8338      case 0x4001:
8339      case 0x4003:
8340      case 0x6001:
8341      case 0x6003:
8342         bank = 2 + ((offset & 0x2000) ? 4 : 0) + ((offset & 0x0002) ? 1 : 0);
8343         state->m_mmc_vrom_bank[bank] = (state->m_mmc_vrom_bank[bank] & 0x0f) | ((data & 0x04) << 3) | ((data & 0x02) << 5) | ((data & 0x09) << 4);
8344         chr1_x(space->machine(), bank, state->m_mmc_vrom_bank[bank], CHRROM);
8345         break;
8346   }
8347}
8348
8349/*************************************************************
8350
8351 Board UNL-CC-21
8352
8353 Games: Mi Hun Che
8354
8355 In MESS: Supported
8356
8357 *************************************************************/
8358
8359static WRITE8_HANDLER( unl_cc21_w )
8360{
8361   LOG_MMC(("unl_cc21_w offset: %04x, data: %02x\n", offset, data));
8362
8363   set_nt_mirroring(space->machine(), BIT(data, 1) ? PPU_MIRROR_HIGH : PPU_MIRROR_LOW);
8364   chr8(space->machine(), (offset & 0x01), CHRROM);
8365}
8366
8367/*************************************************************
8368
8369 Board UNL-KOF97
8370
8371 Games: King of Fighters 97 (Rex Soft)
8372
8373 MMC3 clone
8374
8375 In MESS: Not working
8376
8377 *************************************************************/
8378
8379static UINT8 unl_kof97_unscramble( UINT8 data )
8380{
8381   return ((data >> 1) & 0x01) | ((data >> 4) & 0x02) | ((data << 2) & 0x04) | ((data >> 0) & 0xd8) | ((data << 3) & 0x20);
8382}
8383
8384static WRITE8_HANDLER( unl_kof97_w )
8385{
8386   LOG_MMC(("unl_kof97_w offset: %04x, data: %02x\n", offset, data));
8387
8388   /* Addresses 0x9000, 0xa000, 0xd000 & 0xf000 behaves differently than MMC3 */
8389   if (offset == 0x1000)
8390   {
8391      data = unl_kof97_unscramble(data);
8392      txrom_w(space, 0x0001, data);
8393   }
8394   else if (offset == 0x2000)
8395   {
8396      data = unl_kof97_unscramble(data);
8397      txrom_w(space, 0x0000, data);
8398   }
8399   else if (offset == 0x5000)
8400   {
8401      data = unl_kof97_unscramble(data);
8402      txrom_w(space, 0x4001, data);
8403   }
8404   else if (offset == 0x7000)
8405   {
8406      data = unl_kof97_unscramble(data);
8407      txrom_w(space, 0x6001, data);
8408   }
8409   else      /* Other addresses behaves like MMC3, up to unscrambling data */
8410   {
8411      switch (offset & 0x6001)
8412      {
8413         case 0x0000:
8414         case 0x0001:
8415         case 0x4000:
8416         case 0x4001:
8417         case 0x6000:
8418         case 0x6001:
8419         case 0x2000:   /* are these ever called?!? */
8420         case 0x2001:
8421            data = unl_kof97_unscramble(data);
8422            txrom_w(space, offset, data);
8423            break;
8424      }
8425   }
8426}
8427
8428/*************************************************************
8429
8430 Board UNL-T-230
8431
8432 Games: Dragon Ball Z IV (Unl)
8433
8434 In MESS: Supported
8435
8436 *************************************************************/
8437
8438static WRITE8_HANDLER( unl_t230_w )
8439{
8440   nes_state *state = space->machine().driver_data<nes_state>();
8441   UINT8 bank;
8442   LOG_MMC(("unl_t230_w offset: %04x, data: %02x\n", offset, data));
8443
8444   switch (offset & 0x700c)
8445   {
8446      case 0x0000:
8447         break;
8448      case 0x2000:
8449         prg16_89ab(space->machine(), data);
8450         break;
8451
8452      // the part below works like VRC-2. how was the original board wired up?
8453      // was there a VRC2? if so, we can use VRC-2 and add proper pin settings to xml!
8454      case 0x1000:
8455      case 0x1004:
8456      case 0x1008:
8457      case 0x100c:
8458         switch (data & 0x03)
8459         {
8460         case 0x00: set_nt_mirroring(space->machine(), PPU_MIRROR_VERT); break;
8461         case 0x01: set_nt_mirroring(space->machine(), PPU_MIRROR_HORZ); break;
8462         case 0x02: set_nt_mirroring(space->machine(), PPU_MIRROR_LOW); break;
8463         case 0x03: set_nt_mirroring(space->machine(), PPU_MIRROR_HIGH); break;
8464         }
8465         break;
8466
8467      case 0x3000:
8468      case 0x3004:
8469      case 0x3008:
8470      case 0x300c:
8471      case 0x4000:
8472      case 0x4004:
8473      case 0x4008:
8474      case 0x400c:
8475      case 0x5000:
8476      case 0x5004:
8477      case 0x5008:
8478      case 0x500c:
8479      case 0x6000:
8480      case 0x6004:
8481      case 0x6008:
8482      case 0x600c:
8483         bank = ((offset & 0x7000) - 0x3000) / 0x0800 + ((offset & 0x0008) >> 2);
8484         if (offset & 0x0004)
8485            state->m_mmc_vrom_bank[bank] = (state->m_mmc_vrom_bank[bank] & 0x0f) | (data << 4);
8486         else
8487            state->m_mmc_vrom_bank[bank] = (state->m_mmc_vrom_bank[bank] & 0xf0) | (data & 0x0f);
8488
8489         chr1_x(space->machine(), bank, state->m_mmc_vrom_bank[bank], state->m_mmc_chr_source);
8490         break;
8491      case 0x7000:
8492         state->m_IRQ_count_latch &= ~0x0f;
8493         state->m_IRQ_count_latch |= data & 0x0f;
8494         break;
8495      case 0x7004:
8496         state->m_IRQ_count_latch &= ~0xf0;
8497         state->m_IRQ_count_latch |= (data << 4) & 0xf0;
8498         break;
8499      case 0x7008:
8500         state->m_IRQ_mode = data & 0x04;   // currently not implemented: 0 = prescaler mode / 1 = CPU mode
8501         state->m_IRQ_enable = data & 0x02;
8502         state->m_IRQ_enable_latch = data & 0x01;
8503         if (data & 0x02)
8504            state->m_IRQ_count = state->m_IRQ_count_latch;
8505         break;
8506
8507      default:
8508         logerror("unl_t230_w uncaught offset: %04x value: %02x\n", offset, data);
8509         break;
8510   }
8511}
8512
8513/*************************************************************
8514
8515 Bootleg Board for KOF96
8516
8517 Games: The King of Fighters 96, Sonic 3D Blast 6, Street
8518 Fighter Zero 2
8519
8520 MMC3 clone
8521
8522 iNES: mapper 187
8523
8524 In MESS: Preliminary Support.
8525
8526 *************************************************************/
8527
8528static void kof96_prg_cb( running_machine &machine, int start, int bank )
8529{
8530   nes_state *state = machine.driver_data<nes_state>();
8531
8532   if (!(state->m_mmc_reg[0] & 0x80))
8533      prg8_x(machine, start, bank);
8534}
8535
8536static void kof96_chr_cb( running_machine &machine, int start, int bank, int source )
8537{
8538   nes_state *state = machine.driver_data<nes_state>();
8539   UINT8 chr_page = (state->m_mmc_latch1 & 0x80) >> 5;
8540
8541   if ((start & 0x04) == chr_page)
8542      bank |= 0x100;
8543
8544   chr1_x(machine, start, bank, source);
8545}
8546
8547static WRITE8_HANDLER( kof96_l_w )
8548{
8549   nes_state *state = space->machine().driver_data<nes_state>();
8550   UINT8 new_bank;
8551   LOG_MMC(("kof96_l_w, offset: %04x, data: %02x\n", offset, data));
8552   offset += 0x100;
8553
8554   if (offset == 0x1000)
8555   {
8556      state->m_mmc_reg[0] = data;
8557
8558      if (state->m_mmc_reg[0] & 0x80)
8559      {
8560         new_bank = (state->m_mmc_reg[0] & 0x1f);
8561
8562         if (state->m_mmc_reg[0] & 0x20)
8563            prg32(space->machine(), new_bank >> 2);
8564         else
8565         {
8566            prg16_89ab(space->machine(), new_bank);
8567            prg16_cdef(space->machine(), new_bank);
8568         }
8569      }
8570      else
8571         mmc3_set_prg(space->machine(), state->m_mmc_prg_base, state->m_mmc_prg_mask);
8572   }
8573
8574   if (offset >= 0x1000)
8575   {
8576      switch (data & 0x03)
8577      {
8578         case 0x00:
8579         case 0x01:
8580            state->m_mmc_reg[1] = 0x83;
8581            break;
8582         case 0x02:
8583            state->m_mmc_reg[1] = 0x42;
8584            break;
8585         case 0x03:
8586            state->m_mmc_reg[1] = 0x00;
8587            break;
8588      }
8589
8590   }
8591
8592   if (!state->m_mmc_reg[3] && offset > 0x1000)
8593   {
8594      state->m_mmc_reg[3] = 1;
8595      space->write_byte(0x4017, 0x40);
8596   }
8597}
8598
8599static READ8_HANDLER( kof96_l_r )
8600{
8601   nes_state *state = space->machine().driver_data<nes_state>();
8602   LOG_MMC(("kof96_l_r, offset: %04x\n", offset));
8603   offset += 0x100;
8604
8605   if (!(offset < 0x1000))
8606      return state->m_mmc_reg[1];
8607   else
8608      return 0;
8609}
8610
8611static WRITE8_HANDLER( kof96_w )
8612{
8613   nes_state *state = space->machine().driver_data<nes_state>();
8614   LOG_MMC(("kof96_w, offset: %04x, data: %02x\n", offset, data));
8615
8616   switch (offset & 0x6003)
8617   {
8618      case 0x0000:
8619         state->m_mmc_reg[2] = 1;
8620         txrom_w(space, 0x0000, data);
8621         break;
8622
8623      case 0x0001:
8624         if (state->m_mmc_reg[2])
8625            txrom_w(space, 0x0001, data);
8626         break;
8627
8628      case 0x0002:
8629         break;
8630
8631      case 0x0003:
8632         state->m_mmc_reg[2] = 0;
8633
8634         if (data == 0x28)
8635            prg8_cd(space->machine(), 0x17);
8636         else if (data == 0x2a)
8637            prg8_ab(space->machine(), 0x0f);
8638         break;
8639
8640      default:
8641         txrom_w(space, offset, data);
8642         break;
8643   }
8644}
8645
8646/*************************************************************
8647
8648 Bootleg Board for MK2
8649
8650 Games: Mortal Kombat II, Street Fighter III, Super Mario
8651 Kart Rider
8652
8653 This board uses an IRQ system very similar to MMC3. We indeed
8654 use mapper4_irq, but there is some small glitch!
8655
8656 iNES: mapper 91
8657
8658 In MESS: Supported.
8659
8660 *************************************************************/
8661
8662static WRITE8_HANDLER( mk2_m_w )
8663{
8664   nes_state *state = space->machine().driver_data<nes_state>();
8665   LOG_MMC(("mk2_m_w, offset: %04x, data: %02x\n", offset, data));
8666
8667   switch (offset & 0x1000)
8668   {
8669      case 0x0000:
8670         switch (offset & 0x03)
8671         {
8672         case 0x00: chr2_0(space->machine(), data, CHRROM); break;
8673         case 0x01: chr2_2(space->machine(), data, CHRROM); break;
8674         case 0x02: chr2_4(space->machine(), data, CHRROM); break;
8675         case 0x03: chr2_6(space->machine(), data, CHRROM); break;
8676         }
8677         break;
8678      case 0x1000:
8679         switch (offset & 0x03)
8680         {
8681         case 0x00: prg8_89(space->machine(), data); break;
8682         case 0x01: prg8_ab(space->machine(), data); break;
8683         case 0x02: state->m_IRQ_enable = 0; state->m_IRQ_count = 0; break;
8684         case 0x03: state->m_IRQ_enable = 1; state->m_IRQ_count = 7; break;
8685         }
8686         break;
8687      default:
8688         logerror("mk2_m_w uncaught addr: %04x value: %02x\n", offset + 0x6000, data);
8689         break;
8690   }
8691}
8692
8693/*************************************************************
8694
8695 Bootleg Board N625092
8696
8697 Games: 400 in 1, 700 in 1, 1000 in 1
8698
8699 iNES: mapper 221
8700
8701 In MESS: Supported.
8702
8703 *************************************************************/
8704
8705static void n625092_set_prg( running_machine &machine, UINT8 reg1, UINT8 reg2 )
8706{
8707   UINT8 map221_helper1, map221_helper2;
8708
8709   map221_helper1 = !(reg1 & 0x01) ? reg2 :
8710   (reg1 & 0x80) ? reg2 : (reg2 & 0x06) | 0x00;
8711   map221_helper2 = !(reg1 & 0x01) ? reg2 :
8712   (reg1 & 0x80) ? 0x07 : (reg2 & 0x06) | 0x01;
8713
8714   prg16_89ab(machine, map221_helper1 | ((reg1 & 0x70) >> 1));
8715   prg16_cdef(machine, map221_helper2 | ((reg1 & 0x70) >> 1));
8716}
8717
8718static WRITE8_HANDLER( n625092_w )
8719{
8720   nes_state *state = space->machine().driver_data<nes_state>();
8721   LOG_MMC(("n625092_w, offset: %04x, data: %02x\n", offset, data));
8722
8723   if (offset < 0x4000)
8724   {
8725      set_nt_mirroring(space->machine(), BIT(data, 0) ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT);
8726      offset = (offset >> 1) & 0xff;
8727
8728      if (state->m_mmc_latch1 != offset)
8729      {
8730         state->m_mmc_latch1 = offset;
8731         n625092_set_prg(space->machine(), state->m_mmc_latch1, state->m_mmc_latch2);
8732      }
8733   }
8734   else
8735   {
8736      offset &= 0x07;
8737
8738      if (state->m_mmc_latch2 != offset)
8739      {
8740         state->m_mmc_latch2 = offset;
8741         n625092_set_prg(space->machine(), state->m_mmc_latch1, state->m_mmc_latch2);
8742      }
8743   }
8744}
8745
8746/*************************************************************
8747
8748 SC-127 Board
8749
8750 Games: Wario World II (Kirby Hack)
8751
8752 iNES: mapper 35
8753
8754 In MESS: Supported
8755
8756 *************************************************************/
8757
8758static void sc127_irq( device_t *device, int scanline, int vblank, int blanked )
8759{
8760   nes_state *state = device->machine().driver_data<nes_state>();
8761
8762   if (scanline < PPU_BOTTOM_VISIBLE_SCANLINE && state->m_IRQ_enable)
8763   {
8764      state->m_IRQ_count--;
8765
8766      if (!blanked && (state->m_IRQ_count == 0))
8767      {
8768         LOG_MMC(("irq fired, scanline: %d (MAME %d, beam pos: %d)\n", scanline,
8769                device->machine().primary_screen->vpos(), device->machine().primary_screen->hpos()));
8770         device_set_input_line(state->m_maincpu, M6502_IRQ_LINE, HOLD_LINE);
8771         state->m_IRQ_enable = 0;
8772      }
8773   }
8774}
8775
8776static WRITE8_HANDLER( sc127_w )
8777{
8778   nes_state *state = space->machine().driver_data<nes_state>();
8779   LOG_MMC(("sc127_w, offset: %04x, data: %02x\n", offset, data));
8780
8781   switch (offset)
8782   {
8783      case 0x0000:
8784         prg8_89(space->machine(), data);
8785         break;
8786      case 0x0001:
8787         prg8_ab(space->machine(), data);
8788         break;
8789      case 0x0002:
8790         //      state->m_mmc_prg_bank[offset & 0x02] = data;
8791         prg8_cd(space->machine(), data);
8792         break;
8793      case 0x1000:
8794      case 0x1001:
8795      case 0x1002:
8796      case 0x1003:
8797      case 0x1004:
8798      case 0x1005:
8799      case 0x1006:
8800      case 0x1007:
8801         //      state->m_mmc_vrom_bank[offset & 0x07] = data;
8802         chr1_x(space->machine(), offset & 0x07, data, CHRROM);
8803         break;
8804      case 0x4002:
8805         state->m_IRQ_enable = 0;
8806         break;
8807      case 0x4003:
8808         state->m_IRQ_enable = 1;
8809         break;
8810      case 0x4005:
8811         state->m_IRQ_count = data;
8812         break;
8813      case 0x5001:
8814         set_nt_mirroring(space->machine(), BIT(data, 0) ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT);
8815         break;
8816   }
8817}
8818
8819/*************************************************************
8820
8821 Bootleg Board SMB2J
8822
8823 Games: Super Mario Bros. 2 Pirate (LF36)
8824
8825 iNES: mapper 43
8826
8827 In MESS: Supported? The only image I found is not working
8828 (not even in NEStopia).
8829
8830 *************************************************************/
8831
8832static WRITE8_HANDLER( smb2j_w )
8833{
8834   nes_state *state = space->machine().driver_data<nes_state>();
8835   int bank = (((offset >> 8) & 0x03) * 0x20) + (offset & 0x1f);
8836
8837   LOG_MMC(("smb2j_w, offset: %04x, data: %02x\n", offset, data));
8838
8839   set_nt_mirroring(space->machine(), (offset & 0x2000) ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT);
8840
8841   if (offset & 0x0800)
8842   {
8843      if (offset & 0x1000)
8844      {
8845         if (bank * 2 >= state->m_prg_chunks)
8846         {
8847            memory_set_bankptr(space->machine(), "bank3", state->m_wram);
8848            memory_set_bankptr(space->machine(), "bank4", state->m_wram);
8849         }
8850         else
8851         {
8852            LOG_MMC(("smb2j_w, selecting upper 16KB bank of #%02x\n", bank));
8853            prg16_cdef(space->machine(), 2 * bank + 1);
8854         }
8855      }
8856      else
8857      {
8858         if (bank * 2 >= state->m_prg_chunks)
8859         {
8860            memory_set_bankptr(space->machine(), "bank1", state->m_wram);
8861            memory_set_bankptr(space->machine(), "bank2", state->m_wram);
8862         }
8863         else
8864         {
8865            LOG_MMC(("smb2j_w, selecting lower 16KB bank of #%02x\n", bank));
8866            prg16_89ab(space->machine(), 2 * bank);
8867         }
8868      }
8869   }
8870   else
8871   {
8872      if (bank * 2 >= state->m_prg_chunks)
8873      {
8874         memory_set_bankptr(space->machine(), "bank1", state->m_wram);
8875         memory_set_bankptr(space->machine(), "bank2", state->m_wram);
8876         memory_set_bankptr(space->machine(), "bank3", state->m_wram);
8877         memory_set_bankptr(space->machine(), "bank4", state->m_wram);
8878      }
8879      else
8880      {
8881         LOG_MMC(("smb2j_w, selecting 32KB bank #%02x\n", bank));
8882         prg32(space->machine(), bank);
8883      }
8884   }
8885}
8886
8887/*************************************************************
8888
8889 BTL-SMB2B
8890
8891 Games: Super Mario Bros. 2 Pirate (Jpn version of SMB2)
8892
8893 This was marked as Alt. Levels. is it true?
8894
8895 iNES: mapper 50
8896
8897 In MESS: Supported.
8898
8899 *************************************************************/
8900
8901static void smb2jb_irq( device_t *device, int scanline, int vblank, int blanked )
8902{
8903   nes_state *state = device->machine().driver_data<nes_state>();
8904   if (state->m_IRQ_enable)
8905   {
8906      if (state->m_IRQ_count < 0x1000)
8907      {
8908         if ((0x1000 - state->m_IRQ_count) <= 114)
8909            device_set_input_line(state->m_maincpu, M6502_IRQ_LINE, HOLD_LINE);
8910         else
8911            state->m_IRQ_count += 114;
8912      }
8913      else
8914         state->m_IRQ_count += 114;
8915
8916      state->m_IRQ_count &= 0xffff;   // according to docs is 16bit counter -> it wraps only after 0xffff
8917   }
8918}
8919
8920static WRITE8_HANDLER( smb2jb_l_w )
8921{
8922   nes_state *state = space->machine().driver_data<nes_state>();
8923   UINT8 prg;
8924   LOG_MMC(("smb2jb_l_w, offset: %04x, data: %02x\n", offset, data));
8925   offset += 0x100;
8926
8927   switch (offset & 0x160)
8928   {
8929      case 0x020:
8930         prg = (data & 0x08) | ((data & 0x06) >> 1) | ((data & 0x01) << 2);
8931         prg8_cd(space->machine(), prg);
8932         break;
8933      case 0x120:
8934         state->m_IRQ_enable = data & 0x01;
8935         break;
8936   }
8937}
8938
8939/* This goes to 0x4020-0x403f */
8940WRITE8_HANDLER( smb2jb_extra_w )
8941{
8942   UINT8 prg;
8943   LOG_MMC(("smb2jb_extra_w, offset: %04x, data: %02x\n", offset, data));
8944
8945   prg = (data & 0x08) | ((data & 0x06) >> 1) | ((data & 0x01) << 2);
8946   prg8_cd(space->machine(), prg);
8947}
8948
8949/*************************************************************
8950
8951 Bootleg Board for Super Fighter III
8952
8953 MMC3 clone
8954
8955 iNES: mapper 197
8956
8957 In MESS: Supported.
8958
8959 *************************************************************/
8960
8961static void unl_sf3_set_chr( running_machine &machine, UINT8 chr_source, int chr_base, int chr_mask )
8962{
8963   nes_state *state = machine.driver_data<nes_state>();
8964   chr4_0(machine, chr_base | ((state->m_mmc_vrom_bank[0] >> 1) & chr_mask), chr_source);
8965   chr2_4(machine, chr_base | (state->m_mmc_vrom_bank[1] & chr_mask), chr_source);
8966   chr2_6(machine, chr_base | (state->m_mmc_vrom_bank[2] & chr_mask), chr_source);
8967}
8968
8969static WRITE8_HANDLER( unl_sf3_w )
8970{
8971   nes_state *state = space->machine().driver_data<nes_state>();
8972   UINT8 mmc_helper, cmd;
8973   LOG_MMC(("unl_sf3_w, offset: %04x, data: %02x\n", offset, data));
8974
8975   switch (offset & 0x6001)
8976   {
8977      case 0x0000:
8978         mmc_helper = state->m_mmc3_latch ^ data;
8979         state->m_mmc3_latch = data;
8980
8981         /* Has PRG Mode changed? */
8982         if (mmc_helper & 0x40)
8983            mmc3_set_prg(space->machine(), state->m_mmc_prg_base, state->m_mmc_prg_mask);
8984
8985         /* Has CHR Mode changed? */
8986         if (mmc_helper & 0x80)
8987            unl_sf3_set_chr(space->machine(), state->m_mmc_chr_source, state->m_mmc_chr_base, state->m_mmc_chr_mask);
8988         break;
8989
8990      case 0x0001:
8991         cmd = state->m_mmc3_latch & 0x0f;
8992         switch (cmd)
8993         {
8994         case 0: case 2: case 4:
8995            state->m_mmc_vrom_bank[cmd >> 1] = data;
8996            unl_sf3_set_chr(space->machine(), state->m_mmc_chr_source, state->m_mmc_chr_base, state->m_mmc_chr_mask);
8997            break;
8998         case 6:
8999         case 7:
9000            state->m_mmc_prg_bank[cmd - 6] = data;
9001            mmc3_set_prg(space->machine(), state->m_mmc_prg_base, state->m_mmc_prg_mask);
9002            break;
9003         }
9004         break;
9005
9006      default:
9007         txrom_w(space, offset, data);
9008         break;
9009   }
9010}
9011
9012/*************************************************************
9013
9014 Bootleg Board for Xiao Zhuan Yuan
9015
9016 Games: Shu Qi Yu - Zhi Li Xiao Zhuan Yuan
9017
9018 Very simple mapper: writes to 0x5ff1 set prg32 (to data>>1),
9019 while writes to 0x5ff2 set chr8
9020
9021 iNES: mapper 176
9022
9023 In MESS: Supported.
9024
9025 *************************************************************/
9026
9027static WRITE8_HANDLER( unl_xzy_l_w )
9028{
9029   LOG_MMC(("unl_xzy_l_w, offset: %04x, data: %02x\n", offset, data));
9030
9031   switch (offset)
9032   {
9033      case 0x1ef1:   /* 0x5ff1 */
9034         prg32(space->machine(), data >> 1);
9035         break;
9036      case 0x1ef2:   /* 0x5ff2 */
9037         chr8(space->machine(), data, CHRROM);
9038         break;
9039   }
9040}
9041
9042/*************************************************************
9043
9044 Board UNL-RACERMATE
9045
9046 In MESS: *VERY* preliminary support. Also, it seems that this
9047 board saves to battery the CHRRAM!!!
9048
9049 *************************************************************/
9050
9051static void racmate_update_banks( running_machine &machine )
9052{
9053   nes_state *state = machine.driver_data<nes_state>();
9054   chr4_4(machine, state->m_mmc_latch1 & 0x0f, state->m_mmc_chr_source);
9055   prg16_89ab(machine, state->m_mmc_latch1 >> 1);
9056}
9057
9058static WRITE8_HANDLER( unl_racmate_w )
9059{
9060   nes_state *state = space->machine().driver_data<nes_state>();
9061   LOG_MMC(("unl_racmate_w offset: %04x, data: %02x\n", offset, data));
9062
9063   if (offset == 0x3000)
9064   {
9065      state->m_mmc_latch1 = data;
9066      racmate_update_banks(space->machine());
9067   }
9068}
9069
9070/*************************************************************
9071
9072        BOOTLEG CART VERSIONS OF FDS GAMES
9073
9074 *************************************************************/
9075
9076/*************************************************************
9077
9078 BTL-SUPERBROS11
9079
9080 Games: Super Mario Bros. 11, Super Mario Bros. 17
9081
9082 This acts basically like a MMC3 with different use of write
9083 address.
9084
9085 iNES: mapper 196
9086
9087 In MESS: Supported.
9088
9089 *************************************************************/
9090
9091static WRITE8_HANDLER( btl_smb11_w )
9092{
9093   LOG_MMC(("btl_smb11_w, offset: %04x, data: %02x\n", offset, data));
9094
9095   txrom_w(space, (offset & 0x6000) | ((offset & 0x04) >> 2), data);
9096}
9097
9098/*************************************************************
9099
9100 BTL-MARIOBABY
9101
9102 Games: Mario Baby, Ai Senshi Nicol
9103
9104 iNES: mapper 42
9105
9106 In MESS: Supported.
9107
9108 *************************************************************/
9109
9110// is the code fine for ai senshi nicol?!?
9111static WRITE8_HANDLER( btl_mariobaby_w )
9112{
9113   nes_state *state = space->machine().driver_data<nes_state>();
9114   LOG_MMC(("btl_mariobaby_w, offset: %04x, data: %02x\n", offset, data));
9115
9116   if (offset >= 0x7000)
9117   {
9118      switch (offset & 0x03)
9119      {
9120         case 0x00:
9121            prg8_67(space->machine(), data);
9122            break;
9123         case 0x01:
9124            set_nt_mirroring(space->machine(), BIT(data, 3) ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT);
9125            break;
9126         case 0x02:
9127            /* Check if IRQ is being enabled */
9128            if (!state->m_IRQ_enable && (data & 0x02))
9129            {
9130               state->m_IRQ_enable = 1;
9131               state->m_irq_timer->adjust(downcast<cpu_device *>(state->m_maincpu)->cycles_to_attotime(24576));
9132            }
9133            if (!(data & 0x02))
9134            {
9135               state->m_IRQ_enable = 0;
9136               state->m_irq_timer->adjust(attotime::never);
9137            }
9138            break;
9139      }
9140   }
9141}
9142
9143/*************************************************************
9144
9145 BTL-SMB2A
9146
9147 Games: Super Mario Bros. 2 Pirate (Jpn version of SMB2)
9148
9149 iNES: mapper 40
9150
9151 In MESS: Supported.
9152
9153 *************************************************************/
9154
9155static void btl_smb2a_irq( device_t *device, int scanline, int vblank, int blanked )
9156{
9157   nes_state *state = device->machine().driver_data<nes_state>();
9158
9159   if (state->m_IRQ_enable)
9160   {
9161      if ((0xfff - state->m_IRQ_count) <= 114)
9162      {
9163         state->m_IRQ_count = (state->m_IRQ_count + 1) & 0xfff;
9164         state->m_IRQ_enable = 0;
9165         device_set_input_line(state->m_maincpu, M6502_IRQ_LINE, HOLD_LINE);
9166      }
9167      else
9168         state->m_IRQ_count += 114;
9169   }
9170}
9171
9172static WRITE8_HANDLER( btl_smb2a_w )
9173{
9174   nes_state *state = space->machine().driver_data<nes_state>();
9175   LOG_MMC(("btl_smb2a_w, offset: %04x, data: %02x\n", offset, data));
9176
9177   switch (offset & 0x6000)
9178   {
9179      case 0x0000:
9180         state->m_IRQ_enable = 0;
9181         state->m_IRQ_count = 0;
9182         break;
9183      case 0x2000:
9184         state->m_IRQ_enable = 1;
9185         break;
9186      case 0x6000:
9187         prg8_cd(space->machine(), data);
9188         break;
9189   }
9190}
9191
9192/*************************************************************
9193
9194 WHIRLWIND-2706
9195
9196 Games: Meikyuu Jiin Dababa (FDS conversion)
9197
9198 iNES: mapper 108
9199
9200 In MESS: Supported.
9201
9202 *************************************************************/
9203
9204static WRITE8_HANDLER( whirl2706_w )
9205{
9206   LOG_MMC(("whirl2706_w, offset: %04x, data: %02x\n", offset, data));
9207   prg8_67(space->machine(), data);
9208}
9209
9210/*************************************************************
9211
9212 Bootleg Board used for FDS conversion
9213
9214 Games: Tobidase Daisakusen (FDS conversion)
9215
9216 iNES: mapper 120
9217
9218 In MESS: Partially Supported.
9219
9220 *************************************************************/
9221
9222static WRITE8_HANDLER( btl_tobi_l_w )
9223{
9224   LOG_MMC(("btl_tobi_l_w, offset: %04x, data: %02x\n", offset, data));
9225   offset += 0x100;
9226
9227   if ((offset & 0x43c0) == 0x41c0)
9228      prg8_67(space->machine(), data & 0x07);
9229}
9230
9231/*************************************************************
9232
9233 BTL-SMB3
9234
9235 Games: Super Mario Bros. 3 Pirate
9236
9237 iNES: mapper 106
9238
9239 In MESS: Supported.
9240
9241 *************************************************************/
9242
9243static void btl_smb3_irq( device_t *device, int scanline, int vblank, int blanked )
9244{
9245   nes_state *state = device->machine().driver_data<nes_state>();
9246
9247   if (state->m_IRQ_enable)
9248   {
9249      if ((0xffff - state->m_IRQ_count) < 114)
9250      {
9251         device_set_input_line(state->m_maincpu, M6502_IRQ_LINE, HOLD_LINE);
9252         state->m_IRQ_enable = 0;
9253      }
9254
9255      state->m_IRQ_count = (state->m_IRQ_count + 114) & 0xffff;
9256   }
9257}
9258
9259static WRITE8_HANDLER( btl_smb3_w )
9260{
9261   nes_state *state = space->machine().driver_data<nes_state>();
9262   LOG_MMC(("btl_smb3_w, offset: %04x, data: %02x\n", offset, data));
9263   switch (offset & 0x0f)
9264   {
9265      case 0x00:
9266      case 0x02:
9267         chr1_x(space->machine(), offset & 0x07, data & 0xfe, CHRROM);
9268         break;
9269      case 0x01:
9270      case 0x03:
9271         chr1_x(space->machine(), offset & 0x07, data | 0x01, CHRROM);
9272         break;
9273      case 0x04: case 0x05:
9274      case 0x06: case 0x07:
9275         chr1_x(space->machine(), offset & 0x07, data, CHRROM);
9276         break;
9277      case 0x08:
9278         prg8_89(space->machine(), data | 0x10);
9279         break;
9280      case 0x09:
9281         prg8_ab(space->machine(), data);
9282         break;
9283      case 0x0a:
9284         prg8_cd(space->machine(), data);
9285         break;
9286      case 0x0b:
9287         prg8_ef(space->machine(), data | 0x10);
9288         break;
9289      case 0x0c:
9290         set_nt_mirroring(space->machine(), BIT(data, 0) ?  PPU_MIRROR_HORZ : PPU_MIRROR_VERT);
9291         break;
9292      case 0x0d:
9293         state->m_IRQ_count = 0;
9294         state->m_IRQ_enable = 0;
9295         break;
9296      case 0x0e:
9297         state->m_IRQ_count = (state->m_IRQ_count & 0xff00) | data;
9298         break;
9299      case 0x0f:
9300         state->m_IRQ_count = (state->m_IRQ_count & 0x00ff) | (data << 8);
9301         state->m_IRQ_enable = 1;
9302         break;
9303   }
9304}
9305
9306/*************************************************************
9307
9308 BTL-DRAGONNINJA
9309
9310 Games: Dragon Ninja (Bootleg), Super Mario Bros. 8
9311
9312 iNES: mapper 222
9313
9314 In MESS: Unsupported.
9315
9316 *************************************************************/
9317
9318/* Scanline based IRQ ? */
9319static void btl_dn_irq( device_t *device, int scanline, int vblank, int blanked )
9320{
9321   nes_state *state = device->machine().driver_data<nes_state>();
9322   if (scanline < PPU_BOTTOM_VISIBLE_SCANLINE)
9323   {
9324      if (!state->m_IRQ_count || ++state->m_IRQ_count < 240)
9325         return;
9326
9327      state->m_IRQ_count = 0;
9328      LOG_MMC(("irq fired, scanline: %d (MAME %d, beam pos: %d)\n", scanline,
9329             device->machine().primary_screen->vpos(), device->machine().primary_screen->hpos()));
9330      device_set_input_line(state->m_maincpu, M6502_IRQ_LINE, HOLD_LINE);
9331   }
9332}
9333
9334static WRITE8_HANDLER( btl_dn_w )
9335{
9336   nes_state *state = space->machine().driver_data<nes_state>();
9337   UINT8 bank;
9338   LOG_MMC(("btl_dn_w, offset: %04x, data: %02x\n", offset, data));
9339
9340   switch (offset & 0x7003)
9341   {
9342      case 0x0000:
9343         prg8_89(space->machine(), data);
9344         break;
9345      case 0x1000:
9346         set_nt_mirroring(space->machine(), BIT(data, 0) ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT);
9347         break;
9348      case 0x2000:
9349         prg8_ab(space->machine(), data);
9350         break;
9351      case 0x3000:
9352      case 0x3002:
9353      case 0x4000:
9354      case 0x4002:
9355      case 0x5000:
9356      case 0x5002:
9357      case 0x6000:
9358      case 0x6002:
9359         bank = ((offset & 0x7000) - 0x3000) / 0x0800 + ((offset & 0x0002) >> 3);
9360         chr1_x(space->machine(), bank, data, CHRROM);
9361         break;
9362      case 0x7000:
9363         state->m_IRQ_count = data;
9364         break;
9365   }
9366}
9367
9368/*************************************************************
9369
9370 BTL-PIKACHUY2K
9371
9372 Games: Pikachu Y2k
9373
9374 iNES: mapper 254
9375
9376 In MESS:
9377
9378 *************************************************************/
9379
9380static WRITE8_HANDLER( btl_pika_y2k_w )
9381{
9382   nes_state *state = space->machine().driver_data<nes_state>();
9383   LOG_MMC(("btl_pika_y2k_w, offset: %04x, data: %02x\n", offset, data));
9384
9385   switch (offset & 0x6001)
9386   {
9387      case 0x2001:
9388         state->m_mmc_latch2 = data;
9389         break;
9390
9391      case 0x2000:
9392         state->m_mmc_reg[0] = 0;
9393      default:
9394         txrom_w(space, offset, data);
9395         break;
9396   }
9397}
9398
9399// strange WRAM usage: it is protected at start, and gets unprotected after the first write to 0xa000
9400static WRITE8_HANDLER( btl_pika_y2k_m_w )
9401{
9402   nes_state *state = space->machine().driver_data<nes_state>();
9403   LOG_MMC(("btl_pika_y2k_m_w, offset: %04x, data: %02x\n", offset, data));
9404
9405   state->m_wram[offset] = data;
9406}
9407
9408static READ8_HANDLER( btl_pika_y2k_m_r )
9409{
9410   nes_state *state = space->machine().driver_data<nes_state>();
9411   LOG_MMC(("btl_pika_y2k_m_r, offset: %04x\n", offset));
9412
9413   return   state->m_wram[offset] ^ (state->m_mmc_latch2 & state->m_mmc_reg[0]);
9414}
9415
9416/*************************************************************
9417
9418          MULTICART
9419
9420 *************************************************************/
9421
9422/*************************************************************
9423
9424 Board BMC-FK23C
9425
9426 In MESS: partially supported (still to sort initial banking
9427 for many games)
9428
9429 *************************************************************/
9430
9431#if 0
9432static void fk23c_prg_cb( running_machine &machine, int start, int bank )
9433{
9434   nes_state *state = machine.driver_data<nes_state>();
9435
9436   if (((state->m_mmc_reg[0] & 0x07) - 3) > 1 && (!(state->m_mmc_reg[3] & 0x02) || start < 2))
9437   {
9438      if (state->m_mmc_reg[0] & 0x03)
9439         bank = (bank & (0x3f >> (state->m_mmc_reg[0] & 0x03))) | (state->m_mmc_reg[1] << 1);
9440
9441      prg8_x(machine, start, bank);
9442   }
9443}
9444
9445static void fk23c_chr_cb( running_machine &machine, int start, int bank, int source )
9446{
9447   nes_state *state = machine.driver_data<nes_state>();
9448
9449   if (!(state->m_mmc_reg[0] & 0x40) && (!(state->m_mmc_reg[3] & 0x02) || (start != 1 && start != 3)))
9450      chr1_x(machine, start, ((state->m_mmc_reg[2] & 0x7f) << 3) | bank, source);
9451}
9452
9453#endif
9454
9455static void fk23c_prg_cb( running_machine &machine, int start, int bank )
9456{
9457   nes_state *state = machine.driver_data<nes_state>();
9458   UINT8 mask = (0x3f >> (state->m_mmc_reg[0] & 0x03));
9459
9460   if ((state->m_mmc_reg[0] & 0x07) < 3)
9461   {
9462      if (!(state->m_mmc_reg[0] & 0x03))
9463         bank = (bank & mask) | ((state->m_mmc_reg[1]  & (0x7f ^ mask)) << 1);
9464
9465      prg8_x(machine, start, bank);
9466   }
9467}
9468
9469static void fk23c_chr_cb( running_machine &machine, int start, int bank, int source )
9470{
9471   nes_state *state = machine.driver_data<nes_state>();
9472
9473   if (!(state->m_mmc_reg[0] & 0x40) && (!(state->m_mmc_reg[3] & 0x02) || (start != 1 && start != 3)))
9474      chr1_x(machine, start, ((state->m_mmc_reg[2] & 0x7f) << 3) | bank, source);
9475}
9476
9477static void fk23c_set_prg( running_machine &machine )
9478{
9479   nes_state *state = machine.driver_data<nes_state>();
9480
9481   if ((state->m_mmc_reg[0] & 0x07) == 4)
9482      prg32(machine, (state->m_mmc_reg[1] & 0x7f) >> 1);
9483   else if ((state->m_mmc_reg[0] & 0x07) == 3)
9484   {
9485      prg16_89ab(machine, state->m_mmc_reg[1] & 0x7f);
9486      prg16_cdef(machine, state->m_mmc_reg[1] & 0x7f);
9487   }
9488   else
9489   {
9490      if (state->m_mmc_reg[3] & 0x02)
9491      {
9492         prg8_cd(machine, state->m_mmc_reg[4]);
9493         prg8_ef(machine, state->m_mmc_reg[5]);
9494      }
9495
9496      mmc3_set_prg(machine, state->m_mmc_prg_base, state->m_mmc_prg_mask);
9497   }
9498}
9499
9500static void fk23c_set_chr( running_machine &machine )
9501{
9502   nes_state *state = machine.driver_data<nes_state>();
9503
9504   if (state->m_mmc_reg[0] & 0x40)
9505      chr8(machine, state->m_mmc_reg[2] | state->m_mmc_cmd1, state->m_mmc_chr_source);
9506   else
9507   {
9508      if (state->m_mmc_reg[3] & 0x02)
9509      {
9510         int base = (state->m_mmc_reg[2] & 0x7f) << 3;
9511         chr1_x(machine, 1, base | state->m_mmc_reg[6], state->m_mmc_chr_source);
9512         chr1_x(machine, 3, base | state->m_mmc_reg[7], state->m_mmc_chr_source);
9513      }
9514
9515      mmc3_set_chr(machine, state->m_mmc_chr_source, state->m_mmc_chr_base, state->m_mmc_chr_mask);
9516   }
9517}
9518
9519static WRITE8_HANDLER( fk23c_l_w )
9520{
9521   nes_state *state = space->machine().driver_data<nes_state>();
9522   LOG_MMC(("fk23c_l_w, offset: %04x, data: %02x\n", offset, data));
9523   offset += 0x100;
9524
9525   if (offset >= 0x1000)
9526   {
9527      if (offset & (1 << 4))   // here it should be (4 + state->m_mmc_dipsetting)
9528      {
9529         state->m_mmc_reg[offset & 0x03] = data;
9530
9531         fk23c_set_prg(space->machine());
9532         fk23c_set_chr(space->machine());
9533      }
9534   }
9535}
9536
9537static WRITE8_HANDLER( fk23c_w )
9538{
9539   nes_state *state = space->machine().driver_data<nes_state>();
9540   LOG_MMC(("fk23c_w, offset: %04x, data: %02x\n", offset, data));
9541
9542   if (state->m_mmc_reg[0] & 0x40)
9543   {
9544      if (state->m_mmc_reg[0] & 0x30)
9545         state->m_mmc_cmd1 = 0;
9546      else
9547      {
9548         state->m_mmc_cmd1 = data & 0x03;
9549         fk23c_set_chr(space->machine());
9550      }
9551   }
9552   else
9553   {
9554      switch (offset & 0x6001)
9555      {
9556         case 0x0001:
9557            if ((state->m_mmc_reg[3] & 0x02) && (state->m_mmc3_latch & 0x08))
9558            {
9559               state->m_mmc_reg[4 | (state->m_mmc3_latch & 0x03)] = data;
9560               fk23c_set_prg(space->machine());
9561               fk23c_set_chr(space->machine());
9562            }
9563            else
9564               txrom_w(space, offset, data);
9565            break;
9566
9567         case 0x2000:
9568            set_nt_mirroring(space->machine(), data ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT);
9569            break;
9570
9571         default:
9572            txrom_w(space, offset, data);
9573            break;
9574      }
9575   }
9576}
9577
9578
9579/*************************************************************
9580
9581 Board BMC-64IN1NOREPEAT
9582
9583 Games: 64-in-1 Y2K
9584
9585 In MESS: Supported
9586
9587 *************************************************************/
9588
9589static void bmc_64in1nr_set_prg( running_machine &machine )
9590{
9591   nes_state *state = machine.driver_data<nes_state>();
9592   UINT8 helper1 = (state->m_mmc_reg[1] & 0x1f);
9593   UINT8 helper2 = (helper1 << 1) | ((state->m_mmc_reg[1] & 0x40) >> 6);
9594
9595   if (state->m_mmc_reg[0] & 0x80)
9596   {
9597      if (state->m_mmc_reg[1] & 0x80)
9598         prg32(machine, helper1);
9599      else
9600      {
9601         prg16_89ab(machine, helper2);
9602         prg16_cdef(machine, helper2);
9603      }
9604   }
9605   else
9606      prg16_cdef(machine, helper2);
9607}
9608
9609static WRITE8_HANDLER( bmc_64in1nr_l_w )
9610{
9611   nes_state *state = space->machine().driver_data<nes_state>();
9612   LOG_MMC(("bmc_64in1nr_l_w offset: %04x, data: %02x\n", offset, data));
9613   offset += 0x100;
9614
9615   switch (offset)
9616   {
9617      case 0x1000:
9618      case 0x1001:
9619      case 0x1002:
9620      case 0x1003:
9621         state->m_mmc_reg[offset & 0x03] = data;
9622         bmc_64in1nr_set_prg(space->machine());
9623         chr8(space->machine(), ((state->m_mmc_reg[0] >> 1) & 0x03) | (state->m_mmc_reg[2] << 2), CHRROM);
9624         break;
9625   }
9626   if (offset == 0x1000)   /* reg[0] also sets mirroring */
9627      set_nt_mirroring(space->machine(), BIT(data, 5) ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT);
9628}
9629
9630static WRITE8_HANDLER( bmc_64in1nr_w )
9631{
9632   nes_state *state = space->machine().driver_data<nes_state>();
9633   LOG_MMC(("bmc_64in1nr_w offset: %04x, data: %02x\n", offset, data));
9634
9635   state->m_mmc_reg[3] = data;   // reg[3] is currently unused?!?
9636}
9637
9638/*************************************************************
9639
9640 Board BMC-190IN1
9641
9642 Games: 190-in-1
9643
9644 In MESS: Supported
9645
9646 *************************************************************/
9647
9648static WRITE8_HANDLER( bmc_190in1_w )
9649{
9650   LOG_MMC(("bmc_190in1_w offset: %04x, data: %02x\n", offset, data));
9651
9652   set_nt_mirroring(space->machine(), BIT(data, 0) ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT);
9653   offset >>= 2;
9654   prg16_89ab(space->machine(), offset);
9655   prg16_cdef(space->machine(), offset);
9656   chr8(space->machine(), offset, CHRROM);
9657}
9658
9659/*************************************************************
9660
9661 Board BMC-A65AS
9662
9663 Games: 3-in-1 (N068)
9664
9665 In MESS: Supported
9666
9667 *************************************************************/
9668
9669static WRITE8_HANDLER( bmc_a65as_w )
9670{
9671   UINT8 helper = (data & 0x30) >> 1;
9672   LOG_MMC(("bmc_a65as_w offset: %04x, data: %02x\n", offset, data));
9673
9674   if (data & 0x80)
9675      set_nt_mirroring(space->machine(), BIT(data, 5) ? PPU_MIRROR_HIGH : PPU_MIRROR_LOW);
9676   else
9677      set_nt_mirroring(space->machine(), BIT(data, 3) ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT);
9678
9679   if (data & 0x40)
9680      prg32(space->machine(), data >> 1);
9681   else
9682   {
9683      prg16_89ab(space->machine(), helper | (data & 0x07));
9684      prg16_cdef(space->machine(), helper | 0x07);
9685   }
9686}
9687
9688/*************************************************************
9689
9690 Board BMC-GS2004
9691
9692 Games: Tetris Family 6-in-1
9693
9694 In MESS: Preliminary Support. It also misses WRAM handling
9695 (we need reads from 0x6000-0x7fff)
9696
9697 *************************************************************/
9698
9699static WRITE8_HANDLER( bmc_gs2004_w )
9700{
9701   LOG_MMC(("bmc_gs2004_w offset: %04x, data: %02x\n", offset, data));
9702
9703   prg32(space->machine(), data);
9704}
9705
9706/*************************************************************
9707
9708 Board BMC-GS2013
9709
9710 Games: Tetris Family 12-in-1
9711
9712 In MESS: Preliminary Support. It also misses WRAM handling
9713 (we need reads from 0x6000-0x7fff)
9714
9715 *************************************************************/
9716
9717static WRITE8_HANDLER( bmc_gs2013_w )
9718{
9719   LOG_MMC(("bmc_gs2013_w offset: %04x, data: %02x\n", offset, data));
9720
9721   if (data & 0x08)
9722      prg32(space->machine(), data & 0x09);
9723   else
9724      prg32(space->machine(), data & 0x07);
9725}
9726
9727/*************************************************************
9728
9729 Board BMC-SUPER24IN1SC03
9730
9731 Games: Super 24-in-1
9732
9733 In MESS: Partially Supported
9734
9735 *************************************************************/
9736
9737static void bmc_s24in1sc03_prg_cb( running_machine &machine, int start, int bank )
9738{
9739   nes_state *state = machine.driver_data<nes_state>();
9740   static const UINT8 masks[8] = {0x3f, 0x1f, 0x0f, 0x01, 0x03, 0x00, 0x00, 0x00};
9741   int prg_base = state->m_mmc_reg[1] << 1;
9742   int prg_mask = masks[state->m_mmc_reg[0] & 0x07];
9743
9744   bank = prg_base | (bank & prg_mask);
9745   prg8_x(machine, start, bank);
9746}
9747
9748static void bmc_s24in1sc03_chr_cb( running_machine &machine, int start, int bank, int source )
9749{
9750   nes_state *state = machine.driver_data<nes_state>();
9751   UINT8 chr = BIT(state->m_mmc_reg[0], 5) ? CHRRAM : CHRROM;
9752   int chr_base = (state->m_mmc_reg[2] << 3) & 0xf00;
9753
9754   chr1_x(machine, start, chr_base | bank, chr);
9755}
9756
9757static WRITE8_HANDLER( bmc_s24in1sc03_l_w )
9758{
9759   nes_state *state = space->machine().driver_data<nes_state>();
9760   LOG_MMC(("bmc_s24in1sc03_l_w offset: %04x, data: %02x\n", offset, data));
9761   offset += 0x100;
9762
9763   if (offset == 0x1ff0)
9764   {
9765      state->m_mmc_reg[0] = data;
9766      mmc3_set_chr(space->machine(), state->m_mmc_chr_source, state->m_mmc_chr_base, state->m_mmc_chr_mask);
9767      mmc3_set_prg(space->machine(), state->m_mmc_prg_base, state->m_mmc_prg_mask);
9768   }
9769
9770   if (offset == 0x1ff1)
9771   {
9772      state->m_mmc_reg[1] = data;
9773      mmc3_set_prg(space->machine(), state->m_mmc_prg_base, state->m_mmc_prg_mask);
9774   }
9775
9776   if (offset == 0x1ff2)
9777   {
9778      state->m_mmc_reg[2] = data;
9779      mmc3_set_chr(space->machine(), state->m_mmc_chr_source, state->m_mmc_chr_base, state->m_mmc_chr_mask);
9780   }
9781}
9782
9783/*************************************************************
9784
9785 Board BMC-T-262
9786
9787 Games: 4-in-1 (D-010), 8-in-1 (A-020)
9788
9789 In MESS: Supported
9790
9791 *************************************************************/
9792
9793static WRITE8_HANDLER( bmc_t262_w )
9794{
9795   nes_state *state = space->machine().driver_data<nes_state>();
9796   UINT8 mmc_helper;
9797   LOG_MMC(("bmc_t262_w offset: %04x, data: %02x\n", offset, data));
9798
9799   if (state->m_mmc_latch2 || offset == 0)
9800   {
9801      state->m_mmc_latch1 = (state->m_mmc_latch1 & 0x38) | (data & 0x07);
9802      prg16_89ab(space->machine(), state->m_mmc_latch1);
9803   }
9804   else
9805   {
9806      state->m_mmc_latch2 = 1;
9807      set_nt_mirroring(space->machine(), BIT(data, 1) ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT);
9808      mmc_helper = ((offset >> 3) & 0x20) | ((offset >> 2) & 0x18);
9809      state->m_mmc_latch1 = mmc_helper | (state->m_mmc_latch1 & 0x07);
9810      prg16_89ab(space->machine(), state->m_mmc_latch1);
9811      prg16_cdef(space->machine(), mmc_helper | 0x07);
9812   }
9813}
9814
9815/*************************************************************
9816
9817 Board BMC-WS
9818
9819 Games: Super 40-in-1
9820
9821 In MESS: Partially Supported (some games, like Galaxian, have
9822 issues)
9823
9824 *************************************************************/
9825
9826static WRITE8_HANDLER( bmc_ws_m_w )
9827{
9828   nes_state *state = space->machine().driver_data<nes_state>();
9829   UINT8 mmc_helper;
9830   LOG_MMC(("bmc_ws_m_w offset: %04x, data: %02x\n", offset, data));
9831
9832   if (offset < 0x1000)
9833   {
9834      switch (offset & 0x01)
9835      {
9836         case 0:
9837            if (!state->m_mmc_latch1)
9838            {
9839               state->m_mmc_latch1 = data & 0x20;
9840               set_nt_mirroring(space->machine(), BIT(data, 4) ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT);
9841               mmc_helper = (~data & 0x08) >> 3;
9842               prg16_89ab(space->machine(), data & ~mmc_helper);
9843               prg16_cdef(space->machine(), data |  mmc_helper);
9844            }
9845            break;
9846         case 1:
9847            if (!state->m_mmc_latch1)
9848            {
9849               chr8(space->machine(), data, CHRROM);
9850            }
9851            break;
9852      }
9853   }
9854}
9855
9856/*************************************************************
9857
9858 BMC-NOVELDIAMOND and BMC-999999in1
9859
9860 Unknown Bootleg Multigame Board
9861 Games: I only found 'Novel Diamond 999999-in-1.unf' using
9862 this mapper (hence the code is used for BMC_NOVELDIAMOND
9863 board). The code is included here in case a mapper 54
9864 dump arises.
9865
9866 iNES: mappers 54 and 213
9867
9868 In MESS: Partial Support.
9869
9870 *************************************************************/
9871
9872// Are this correct or should they work the same?
9873static WRITE8_HANDLER( novel1_w )
9874{
9875   LOG_MMC(("novel1_w, offset: %04x, data: %02x\n", offset, data));
9876
9877   prg32(space->machine(), offset & 0x03);
9878   chr8(space->machine(), offset & 0x07, CHRROM);
9879}
9880
9881static WRITE8_HANDLER( novel2_w )
9882{
9883   LOG_MMC(("novel2_w, offset: %04x, data: %02x\n", offset, data));
9884
9885   prg32(space->machine(), offset >> 1);
9886   chr8(space->machine(), offset >> 3, CHRROM);
9887}
9888
9889/*************************************************************
9890
9891 Board BMC-GKA
9892
9893 Unknown Bootleg Multigame Board
9894 Games: 6 in 1, 54 in 1, 106 in 1
9895
9896 iNES: mapper 57
9897
9898 In MESS: Supported.
9899
9900 *************************************************************/
9901
9902static WRITE8_HANDLER( bmc_gka_w )
9903{
9904   nes_state *state = space->machine().driver_data<nes_state>();
9905   LOG_MMC(("bmc_gka_w, offset: %04x, data: %02x\n", offset, data));
9906
9907   if (offset & 0x0800)
9908      state->m_mmc_latch2 = data;
9909   else
9910      state->m_mmc_latch1 = data;
9911
9912   if (state->m_mmc_latch2 & 0x80)
9913      prg32(space->machine(), 2 | (state->m_mmc_latch2 >> 6));
9914   else
9915   {
9916      prg16_89ab(space->machine(), (state->m_mmc_latch2 >> 5) & 0x03);
9917      prg16_cdef(space->machine(), (state->m_mmc_latch2 >> 5) & 0x03);
9918   }
9919
9920   set_nt_mirroring(space->machine(), (state->m_mmc_latch2 & 0x08) ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT);
9921
9922   chr8(space->machine(), (state->m_mmc_latch1 & 0x03) | (state->m_mmc_latch2 & 0x07) | ((state->m_mmc_latch2 & 0x10) >> 1), CHRROM);
9923}
9924
9925
9926/*************************************************************
9927
9928 Board UNL-STUDYNGAME
9929
9930 Games: Study n Game 32 in 1
9931
9932 iNES: mapper 39
9933
9934 In MESS: Partially Supported (problems with PRG bankswitch,
9935 only keyboard exercise work).
9936
9937 *************************************************************/
9938
9939static WRITE8_HANDLER( sng32_w )
9940{
9941   LOG_MMC(("sng32_w, offset: %04x, data: %02x\n", offset, data));
9942   prg32(space->machine(), data);
9943}
9944
9945/*************************************************************
9946
9947 Board BMC-GKB
9948
9949 Unknown Bootleg Multigame Board
9950 Games: 68 in 1, 73 in 1, 98 in 1
9951
9952 iNES: mapper 58
9953
9954 In MESS: Supported.
9955
9956 *************************************************************/
9957
9958static WRITE8_HANDLER( bmc_gkb_w )
9959{
9960   nes_state *state = space->machine().driver_data<nes_state>();
9961   UINT8 bank = (offset & 0x40) ? 0 : 1;
9962   LOG_MMC(("bmc_gkb_w, offset: %04x, data: %02x\n", offset, data));
9963
9964   prg16_89ab(space->machine(), offset & ~bank);
9965   prg16_cdef(space->machine(), offset | bank);
9966   chr8(space->machine(), offset >> 3, state->m_mmc_chr_source);
9967   set_nt_mirroring(space->machine(), BIT(data, 7) ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT);
9968}
9969
9970/*************************************************************
9971
9972 BMC-SUPER-700IN1
9973
9974 Unknown Bootleg Multigame Board
9975 Games: Super 700 in 1
9976
9977 iNES: mapper 62
9978
9979 In MESS: Supported.
9980
9981 *************************************************************/
9982
9983static WRITE8_HANDLER( bmc_super700in1_w )
9984{
9985   LOG_MMC(("bmc_super700in1_w, offset :%04x, data: %02x\n", offset, data));
9986
9987   chr8(space->machine(), ((offset & 0x1f) << 2) | (data & 0x03), CHRROM);
9988
9989   if (offset & 0x20)
9990   {
9991      prg16_89ab(space->machine(), (offset & 0x40) | ((offset >> 8) & 0x3f));
9992      prg16_cdef(space->machine(), (offset & 0x40) | ((offset >> 8) & 0x3f));
9993   }
9994   else
9995   {
9996      prg32(space->machine(), ((offset & 0x40) | ((offset >> 8) & 0x3f)) >> 1);
9997   }
9998
9999   set_nt_mirroring(space->machine(), BIT(data, 7) ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT);
10000}
10001
10002/*************************************************************
10003
10004 BMC-36IN1
10005
10006 Unknown Bootleg Multigame Board
10007 Games: 36 in 1, 1200 in 1
10008
10009 iNES: mapper 200
10010
10011 In MESS: Supported.
10012
10013 *************************************************************/
10014
10015static WRITE8_HANDLER( bmc_36in1_w )
10016{
10017   LOG_MMC(("bmc_36in1_w, offset: %04x, data: %02x\n", offset, data));
10018
10019   prg16_89ab(space->machine(), offset & 0x07);
10020   prg16_cdef(space->machine(), offset & 0x07);
10021   chr8(space->machine(), offset & 0x07, CHRROM);
10022
10023   set_nt_mirroring(space->machine(), BIT(data, 3) ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT);
10024}
10025
10026/*************************************************************
10027
10028 BMC-21IN1
10029
10030 Unknown Bootleg Multigame Board
10031 Games: 8 in 1, 21 in 1
10032
10033 iNES: mapper 201
10034
10035 In MESS: Supported.
10036
10037 *************************************************************/
10038
10039static WRITE8_HANDLER( bmc_21in1_w )
10040{
10041   LOG_MMC(("bmc_21in1_w, offset: %04x, data: %02x\n", offset, data));
10042
10043   prg32(space->machine(), offset & 0x03);
10044   chr8(space->machine(), offset & 0x03, CHRROM);
10045}
10046
10047/*************************************************************
10048
10049 BMC-150IN1
10050
10051 Unknown Bootleg Multigame Board
10052 Games: 150 in 1
10053
10054 iNES: mapper 202
10055
10056 In MESS: Supported.
10057
10058 *************************************************************/
10059
10060static WRITE8_HANDLER( bmc_150in1_w )
10061{
10062   int bank = (offset >> 1) & 0x07;
10063
10064   LOG_MMC(("bmc_150in1_w, offset: %04x, data: %02x\n", offset, data));
10065
10066   prg16_89ab(space->machine(), bank);
10067   prg16_cdef(space->machine(), bank + (((bank & 0x06) == 0x06) ? 1 : 0));
10068   chr8(space->machine(), bank, CHRROM);
10069
10070   set_nt_mirroring(space->machine(), BIT(data, 0) ? PPU_MIRROR_HORZ: PPU_MIRROR_VERT);
10071}
10072
10073/*************************************************************
10074
10075 BMC-35IN1
10076
10077 Unknown Bootleg Multigame Board
10078 Games: 35 in 1
10079
10080 iNES: mapper 203
10081
10082 In MESS: Supported.
10083
10084 *************************************************************/
10085
10086static WRITE8_HANDLER( bmc_35in1_w )
10087{
10088   LOG_MMC(("bmc_35in1_w, offset: %04x, data: %02x\n", offset, data));
10089
10090   prg16_89ab(space->machine(), (data >> 2) & 0x03);
10091   prg16_cdef(space->machine(), (data >> 2) & 0x03);
10092   chr8(space->machine(), data & 0x03, CHRROM);
10093}
10094
10095/*************************************************************
10096
10097 BMC-64IN1
10098
10099 Unknown Bootleg Multigame Board
10100 Games: 64 in 1
10101
10102 iNES: mapper 204
10103
10104 In MESS: Supported.
10105
10106 *************************************************************/
10107
10108static WRITE8_HANDLER( bmc_64in1_w )
10109{
10110   int bank = (offset >> 1) & (offset >> 2) & 0x01;
10111
10112   LOG_MMC(("bmc_64in1_w, offset: %04x, data: %02x\n", offset, data));
10113
10114   prg16_89ab(space->machine(), offset & ~bank);
10115   prg16_cdef(space->machine(), offset | bank);
10116   chr8(space->machine(), offset & ~bank, CHRROM);
10117
10118   set_nt_mirroring(space->machine(), BIT(data, 4) ? PPU_MIRROR_HORZ: PPU_MIRROR_VERT);
10119}
10120
10121/*************************************************************
10122
10123 BMC-15IN1
10124
10125 Unknown Bootleg Multigame Board
10126 Games: 3 in 1, 15 in 1
10127
10128 iNES: mapper 205, MMC3 clone
10129
10130 In MESS: Supported.
10131
10132 *************************************************************/
10133
10134static WRITE8_HANDLER( bmc_15in1_m_w )
10135{
10136   nes_state *state = space->machine().driver_data<nes_state>();
10137   LOG_MMC(("bmc_15in1_m_w, offset: %04x, data: %02x\n", offset, data));
10138
10139   if (offset & 0x0800)
10140   {
10141      state->m_mmc_prg_base = (data & 0x03) << 4;
10142      state->m_mmc_prg_mask = (data & 0x02) ? 0x0f : 0x1f;
10143      state->m_mmc_chr_base = (data & 0x03) << 7;
10144      state->m_mmc_chr_mask = (data & 0x02) ? 0x7f : 0xff;
10145      mmc3_set_prg(space->machine(), state->m_mmc_prg_base, state->m_mmc_prg_mask);
10146      mmc3_set_chr(space->machine(), state->m_mmc_chr_source, state->m_mmc_chr_base, state->m_mmc_chr_mask);
10147   }
10148}
10149
10150/*************************************************************
10151
10152 BMC-SUPERHIK_300IN1
10153
10154 Unknown Bootleg Multigame Board
10155 Games: 100000 in 1, Super HIK 300 in 1, 1997 in 1
10156
10157 iNES: mapper 212
10158
10159 In MESS: Supported.
10160
10161 *************************************************************/
10162
10163static WRITE8_HANDLER( bmc_hik300_w )
10164{
10165   LOG_MMC(("bmc_hik300_w, offset: %04x, data: %02x\n", offset, data));
10166
10167   set_nt_mirroring(space->machine(), BIT(data, 3) ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT);
10168   chr8(space->machine(), offset, CHRROM);
10169
10170   if (offset < 0x4000)
10171   {
10172      prg16_89ab(space->machine(), offset);
10173      prg16_cdef(space->machine(), offset);
10174   }
10175   else
10176      prg32(space->machine(), offset >> 1);
10177}
10178
10179/*************************************************************
10180
10181 BMC-SUPERGUN-20IN1
10182
10183 Unknown Bootleg Multigame Board
10184 Games: Super Gun 20 in 1
10185
10186 iNES: mapper 214
10187
10188 In MESS: Supported.
10189
10190 *************************************************************/
10191
10192static WRITE8_HANDLER( supergun20in1_w )
10193{
10194   LOG_MMC(("supergun20in1_w, offset: %04x, data: %02x\n", offset, data));
10195
10196   prg16_89ab(space->machine(), offset >> 2);
10197   prg16_cdef(space->machine(), offset >> 2);
10198   chr8(space->machine(), offset, CHRROM);
10199}
10200
10201/*************************************************************
10202
10203 BMC-72IN1
10204
10205 Unknown Bootleg Multigame Board
10206 Games: 72 in 1, 115 in 1 and other multigame carts
10207
10208 iNES: mapper 225
10209
10210 In MESS: Supported.
10211
10212 *************************************************************/
10213
10214static WRITE8_HANDLER( bmc_72in1_w )
10215{
10216   int hi_bank;
10217   int size_16;
10218   int bank;
10219
10220   LOG_MMC(("bmc_72in1_w, offset: %04x, data: %02x\n", offset, data));
10221
10222   chr8(space->machine(), offset, CHRROM);
10223   set_nt_mirroring(space->machine(), (offset & 0x2000) ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT);
10224
10225   hi_bank = offset & 0x40;
10226   size_16 = offset & 0x1000;
10227   bank = (offset & 0xf80) >> 7;
10228   if (size_16)
10229   {
10230      bank <<= 1;
10231      if (hi_bank)
10232         bank ++;
10233
10234      prg16_89ab(space->machine(), bank);
10235      prg16_cdef(space->machine(), bank);
10236   }
10237   else
10238      prg32(space->machine(), bank);
10239}
10240
10241/*************************************************************
10242
10243 BMC-76IN1
10244
10245 Unknown Bootleg Multigame Board
10246 Games: 76 in 1, Super 42 in 1
10247
10248 iNES: mapper 226
10249
10250 In MESS: Supported.
10251
10252 *************************************************************/
10253
10254// does this work for super42in1 as well?!?
10255static WRITE8_HANDLER( bmc_76in1_w )
10256{
10257   nes_state *state = space->machine().driver_data<nes_state>();
10258   int hi_bank;
10259   int size_16;
10260   int bank;
10261
10262   LOG_MMC(("bmc_76in1_w, offset: %04x, data: %02x\n", offset, data));
10263
10264   if (offset & 0x01)
10265      state->m_mmc_latch2 = data;
10266   else
10267      state->m_mmc_latch1 = data;
10268
10269   set_nt_mirroring(space->machine(), BIT(state->m_mmc_latch1, 6) ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT);
10270
10271   hi_bank = state->m_mmc_latch1 & 0x01;
10272   size_16 = state->m_mmc_latch1 & 0x20;
10273   bank = ((state->m_mmc_latch1 & 0x1e) >> 1) | ((state->m_mmc_latch1 & 0x80) >> 3) | ((state->m_mmc_latch2 & 0x01) << 5);
10274
10275   if (size_16)
10276   {
10277      bank <<= 1;
10278      if (hi_bank)
10279         bank ++;
10280
10281      prg16_89ab(space->machine(), bank);
10282      prg16_cdef(space->machine(), bank);
10283   }
10284   else
10285      prg32(space->machine(), bank);
10286}
10287
10288/*************************************************************
10289
10290 BMC-1200IN1
10291
10292 Unknown Bootleg Multigame Board
10293 Games: 1200 in 1, 295 in 1, 76 in 1
10294
10295 iNES: mapper 227
10296
10297 In MESS: Supported.
10298
10299 *************************************************************/
10300
10301static WRITE8_HANDLER( bmc_1200in1_w )
10302{
10303   int hi_bank;
10304   int size_32;
10305   int bank;
10306
10307   LOG_MMC(("bmc_1200in1_w, offset: %04x, data: %02x\n", offset, data));
10308
10309   hi_bank = offset & 0x04;
10310   size_32 = offset & 0x01;
10311   bank = ((offset & 0x78) >> 3) | ((offset & 0x0100) >> 4);
10312   if (!size_32)
10313   {
10314      bank <<= 1;
10315      if (hi_bank)
10316         bank ++;
10317
10318      prg16_89ab(space->machine(), bank);
10319      prg16_cdef(space->machine(), bank);
10320   }
10321   else
10322      prg32(space->machine(), bank);
10323
10324   if (!(offset & 0x80))
10325   {
10326      if (offset & 0x200)
10327         prg16_cdef(space->machine(), ((bank << 1) & 0x38) + 7);
10328      else
10329         prg16_cdef(space->machine(), ((bank << 1) & 0x38));
10330   }
10331
10332   set_nt_mirroring(space->machine(), BIT(data, 1) ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT);
10333}
10334
10335/*************************************************************
10336
10337 BMC-31IN1
10338
10339 Unknown Bootleg Multigame Board
10340 Games: 31 in 1
10341
10342 iNES: mapper 229
10343
10344 In MESS: Supported.
10345
10346 *************************************************************/
10347
10348static WRITE8_HANDLER( bmc_31in1_w )
10349{
10350   LOG_MMC(("bmc_31in1_w, offset: %04x, data: %02x\n", offset, data));
10351
10352   set_nt_mirroring(space->machine(), BIT(data, 5) ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT);
10353   chr8(space->machine(), offset, CHRROM);
10354
10355   if ((offset & 0x1e) == 0)
10356   {
10357      prg16_89ab(space->machine(), 0);
10358      prg16_89ab(space->machine(), 1);
10359   }
10360   else
10361   {
10362      prg16_89ab(space->machine(), offset & 0x1f);
10363      prg16_89ab(space->machine(), offset & 0x1f);
10364   }
10365}
10366
10367/*************************************************************
10368
10369 BMC-22GAMES
10370
10371 Unknown Bootleg Multigame Board
10372 Games: 22 in 1
10373
10374 iNES: mapper 230
10375
10376 In MESS: Partially Supported. It would need a reset
10377 to work (not possible yet)
10378
10379 *************************************************************/
10380
10381static WRITE8_HANDLER( bmc_22g_w )
10382{
10383   LOG_MMC(("bmc_22g_w, offset: %04x, data: %02x\n", offset, data));
10384
10385   if (1)   // this should flip at reset
10386   {
10387      prg16_89ab(space->machine(), data & 0x07);
10388   }
10389   else
10390   {
10391      if (data & 0x20)
10392      {
10393         prg16_89ab(space->machine(), (data & 0x1f) + 8);
10394         prg16_cdef(space->machine(), (data & 0x1f) + 8);
10395      }
10396      else
10397      {
10398         prg16_89ab(space->machine(), (data & 0x1f) + 8);
10399         prg16_cdef(space->machine(), (data & 0x1f) + 9);
10400      }
10401      set_nt_mirroring(space->machine(), BIT(data, 6) ? PPU_MIRROR_VERT : PPU_MIRROR_HORZ);
10402   }
10403}
10404
10405/*************************************************************
10406
10407 BMC-20IN1
10408
10409 Unknown Bootleg Multigame Board
10410 Games: 20 in 1
10411
10412 iNES: mapper 231
10413
10414 In MESS: Supported.
10415
10416 *************************************************************/
10417
10418static WRITE8_HANDLER( bmc_20in1_w )
10419{
10420   LOG_MMC(("bmc_20in1_w, offset: %04x, data: %02x\n", offset, data));
10421
10422   set_nt_mirroring(space->machine(), BIT(data, 7) ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT);
10423
10424   prg16_89ab(space->machine(), (offset & 0x1e));
10425   prg16_cdef(space->machine(), (offset & 0x1e) | ((offset & 0x20) ? 1 : 0));
10426}
10427
10428/*************************************************************
10429
10430 BMC-110IN1
10431
10432 Known Boards: Unknown Bootleg Board
10433 Games: 110 in 1
10434
10435 iNES: mapper 255
10436
10437 In MESS: Preliminary support.
10438
10439 *************************************************************/
10440
10441static WRITE8_HANDLER( bmc_110in1_w )
10442{
10443   UINT8 map255_helper1 = (offset >> 12) ? 0 : 1;
10444   UINT8 map255_helper2 = ((offset >> 8) & 0x40) | ((offset >> 6) & 0x3f);
10445
10446   LOG_MMC(("bmc_110in1_w, offset: %04x, data: %02x\n", offset, data));
10447
10448   set_nt_mirroring(space->machine(), (offset & 0x2000) ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT);
10449   prg16_89ab(space->machine(), map255_helper1 & ~map255_helper2);
10450   prg16_cdef(space->machine(), map255_helper1 | map255_helper2);
10451   chr8(space->machine(), ((offset >> 8) & 0x40) | (offset & 0x3f), CHRROM);
10452}
10453
10454/*************************************************************
10455
10456 BMC-SUPERBIG-7IN1
10457
10458 Known Boards: Unknown Multigame Bootleg Board
10459 Games: Kunio 8 in 1, Super Big 7 in 1
10460
10461 iNES: mapper 44
10462
10463 In MESS: Supported. It also uses mmc3_irq.
10464
10465 *************************************************************/
10466
10467static WRITE8_HANDLER( bmc_sbig7_w )
10468{
10469   nes_state *state = space->machine().driver_data<nes_state>();
10470   UINT8 page;
10471   LOG_MMC(("bmc_sbig7_w, offset: %04x, data: %02x\n", offset, data));
10472
10473   switch (offset & 0x6001)
10474   {
10475      case 0x2001: /* $a001 - Select 128K ROM/VROM base (0..5) or last 256K ROM/VRAM base (6) */
10476         page = (data & 0x07);
10477         if (page > 6)
10478            page = 6;
10479
10480         state->m_mmc_prg_base = page << 4;
10481         state->m_mmc_prg_mask = (page > 5) ? 0x1f : 0x0f;
10482         state->m_mmc_chr_base = page << 7;
10483         state->m_mmc_chr_mask = (page > 5) ? 0xff : 0x7f;
10484         mmc3_set_prg(space->machine(), state->m_mmc_prg_base, state->m_mmc_prg_mask);
10485         mmc3_set_chr(space->machine(), state->m_mmc_chr_source, state->m_mmc_chr_base, state->m_mmc_chr_mask);
10486         break;
10487
10488      default:
10489         txrom_w(space, offset, data);
10490         break;
10491   }
10492}
10493
10494/*************************************************************
10495
10496 BMC-HIK8IN1
10497
10498 Known Boards: Unknown Multigame Bootleg Board
10499 Games: Street Fighter V, various multigame carts
10500
10501 iNES: mapper 45
10502
10503 In MESS: Supported. It also uses mmc3_irq.
10504
10505 *************************************************************/
10506
10507static WRITE8_HANDLER( bmc_hik8_m_w )
10508{
10509   nes_state *state = space->machine().driver_data<nes_state>();
10510   LOG_MMC(("bmc_hik8_m_w, offset: %04x, data: %02x\n", offset, data));
10511
10512   /* This bit is the "register lock". Once register are locked, writes go to WRAM
10513     and there is no way to unlock them (except by resetting the machine) */
10514   if ((state->m_mmc_reg[3] & 0x40) && state->m_wram != NULL)
10515      state->m_wram[offset] = data;
10516   else
10517   {
10518      state->m_mmc_reg[state->m_mmc_count] = data;
10519      state->m_mmc_count = (state->m_mmc_count + 1) & 0x03;
10520
10521      if (!state->m_mmc_count)
10522      {
10523         LOG_MMC(("bmc_hik8_m_w, command completed %02x %02x %02x %02x\n", state->m_mmc_reg[3],
10524                state->m_mmc_reg[2], state->m_mmc_reg[1], state->m_mmc_reg[0]));
10525
10526         state->m_mmc_prg_base = state->m_mmc_reg[1];
10527         state->m_mmc_prg_mask = 0x3f ^ (state->m_mmc_reg[3] & 0x3f);
10528         state->m_mmc_chr_base = ((state->m_mmc_reg[2] & 0xf0) << 4) | state->m_mmc_reg[0];
10529         if (BIT(state->m_mmc_reg[2], 3))
10530            state->m_mmc_chr_mask = (1 << ((state->m_mmc_reg[2] & 7) + 1)) - 1;
10531         else if (state->m_mmc_reg[2])
10532            state->m_mmc_chr_mask = 0;
10533         else
10534            state->m_mmc_chr_mask = 0xff;   // i.e. we use the vrom_bank with no masking
10535
10536         mmc3_set_prg(space->machine(), state->m_mmc_prg_base, state->m_mmc_prg_mask);
10537         mmc3_set_chr(space->machine(), state->m_mmc_chr_source, state->m_mmc_chr_base, state->m_mmc_chr_mask);
10538      }
10539   }
10540}
10541
10542/*************************************************************
10543
10544 BMC-SUPERHIK-4IN1
10545
10546 Known Boards: Unknown Multigame Bootleg Board
10547 Games: Super HIK 4 in 1
10548
10549 iNES: mapper 49
10550
10551 In MESS: Supported. It also uses mmc3_irq.
10552
10553 *************************************************************/
10554
10555static WRITE8_HANDLER( bmc_hik4in1_m_w )
10556{
10557   nes_state *state = space->machine().driver_data<nes_state>();
10558   LOG_MMC(("bmc_hik4in1_m_w, offset: %04x, data: %02x\n", offset, data));
10559
10560   /* mid writes only work when WRAM is enabled. not sure if I should
10561     change the condition to state->m_mmc_latch2==0x80 (i.e. what is the effect of
10562     the read-only bit?) */
10563   if (state->m_mmc3_wram_protect & 0x80)
10564   {
10565      if (data & 0x01)   /* if this is 0, then we have 32k PRG blocks */
10566      {
10567         state->m_mmc_prg_base = (data & 0xc0) >> 2;
10568         state->m_mmc_prg_mask = 0x0f;
10569         mmc3_set_prg(space->machine(), state->m_mmc_prg_base, state->m_mmc_prg_mask);
10570      }
10571      else
10572         prg32(space->machine(), (data & 0x30) >> 4);
10573
10574      state->m_mmc_chr_base = (data & 0xc0) << 1;
10575      state->m_mmc_chr_mask = 0x7f;
10576      mmc3_set_chr(space->machine(), state->m_mmc_chr_source, state->m_mmc_chr_base, state->m_mmc_chr_mask);
10577   }
10578}
10579
10580/*************************************************************
10581
10582 BMC-BALLGAMES-11IN1
10583
10584 Known Boards: Unknown Multigame Bootleg Board
10585 Games: 11 in 1 Ball Games
10586
10587 iNES: mapper 51
10588
10589 In MESS: Partially Supported.
10590
10591 *************************************************************/
10592
10593static void bmc_ball11_set_banks( running_machine &machine )
10594{
10595   nes_state *state = machine.driver_data<nes_state>();
10596   set_nt_mirroring(machine, (state->m_mmc_reg[0] == 3) ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT);
10597
10598   if (state->m_mmc_reg[0] & 0x01)
10599   {
10600      prg32(machine, state->m_mmc_reg[1]);
10601   }
10602   else
10603   {
10604      prg16_89ab(machine, (state->m_mmc_reg[1] << 1) | (state->m_mmc_reg[0] >> 1));
10605      prg16_cdef(machine, (state->m_mmc_reg[1] << 1) | 0x07);
10606   }
10607}
10608
10609static WRITE8_HANDLER( bmc_ball11_m_w )
10610{
10611   nes_state *state = space->machine().driver_data<nes_state>();
10612
10613   LOG_MMC(("bmc_ball11_m_w, offset: %04x, data: %02x\n", offset, data));
10614
10615   state->m_mmc_reg[0] = ((data >> 1) & 0x01) | ((data >> 3) & 0x02);
10616   bmc_ball11_set_banks(space->machine());
10617}
10618
10619static WRITE8_HANDLER( bmc_ball11_w )
10620{
10621   nes_state *state = space->machine().driver_data<nes_state>();
10622
10623   LOG_MMC(("bmc_ball11_w, offset: %04x, data: %02x\n", offset, data));
10624
10625   switch (offset & 0x6000)
10626   {
10627      case 0x4000:   // here we also update reg[0] upper bit
10628         state->m_mmc_reg[0] = (state->m_mmc_reg[0] & 0x01) | ((data >> 3) & 0x02);
10629      case 0x0000:
10630      case 0x2000:
10631      case 0x6000:
10632         state->m_mmc_reg[1] = data & 0x0f;
10633         bmc_ball11_set_banks(space->machine());
10634         break;
10635   }
10636}
10637
10638/*************************************************************
10639
10640 BMC-MARIOPARTY-7IN1
10641
10642 Known Boards: Unknown Multigame Bootleg Board
10643 Games: Mario 7 in 1
10644
10645 MMC3 clone
10646
10647 iNES: mapper 52
10648
10649 In MESS: Supported.
10650
10651 *************************************************************/
10652
10653static WRITE8_HANDLER( bmc_mario7in1_m_w )
10654{
10655   nes_state *state = space->machine().driver_data<nes_state>();
10656   UINT8 map52_helper1, map52_helper2;
10657   LOG_MMC(("bmc_mario7in1_m_w, offset: %04x, data: %02x\n", offset, data));
10658
10659   /* mid writes only work when WRAM is enabled. not sure if I should
10660     change the condition to state->m_mmc_latch2==0x80 (i.e. what is the effect of
10661     the read-only bit?) and it only can happen once! */
10662   if ((state->m_mmc3_wram_protect & 0x80) && !state->m_map52_reg_written)
10663   {
10664      map52_helper1 = (data & 0x08);
10665      map52_helper2 = (data & 0x40);
10666
10667      state->m_mmc_prg_base = map52_helper1 ? ((data & 0x07) << 4) : ((data & 0x06) << 4);
10668      state->m_mmc_prg_mask = map52_helper1 ? 0x0f : 0x1f;
10669      state->m_mmc_chr_base = ((data & 0x20) << 4) | ((data & 0x04) << 6) | (map52_helper2 ? ((data & 0x10) << 3) : 0);
10670      state->m_mmc_chr_mask = map52_helper2 ? 0x7f : 0xff;
10671      mmc3_set_prg(space->machine(), state->m_mmc_prg_base, state->m_mmc_prg_mask);
10672      mmc3_set_chr(space->machine(), state->m_mmc_chr_source, state->m_mmc_chr_base, state->m_mmc_chr_mask);
10673
10674      state->m_map52_reg_written = 1;
10675   }
10676   else
10677      state->m_wram[offset] = data;
10678}
10679
10680/*************************************************************
10681
10682 BMC-GOLDENCARD-6IN1
10683
10684 Known Boards: Unknown Bootleg Multigame Board
10685 Games: Golden Card 6 in 1
10686
10687 MMC3 clone
10688
10689 iNES: mapper 217
10690
10691 In MESS: Supported.
10692
10693 *************************************************************/
10694
10695// remove mask & base parameters!
10696static void bmc_gc6in1_set_prg( running_machine &machine, int prg_base, int prg_mask )
10697{
10698   nes_state *state = machine.driver_data<nes_state>();
10699   state->m_mmc_prg_base = (state->m_mmc_reg[1] & 0x08) ? 0 : (state->m_mmc_reg[1] & 0x10);
10700   state->m_mmc_prg_mask = (state->m_mmc_reg[1] & 0x08) ? 0x1f : 0x0f;
10701
10702   state->m_mmc_prg_base |= ((state->m_mmc_reg[1] & 0x03) << 5);
10703
10704   mmc3_set_prg(machine, state->m_mmc_prg_base, state->m_mmc_prg_mask);
10705}
10706
10707static void bmc_gc6in1_set_chr( running_machine &machine, UINT8 chr )
10708{
10709   nes_state *state = machine.driver_data<nes_state>();
10710   UINT8 chr_page = (state->m_mmc_latch1 & 0x80) >> 5;
10711   int chr_base = (state->m_mmc_reg[1] & 0x08) ? 0x00 : ((state->m_mmc_reg[1] & 0x10) << 3);
10712   int chr_mask = (state->m_mmc_reg[1] & 0x08) ? 0xff : 0x7f;
10713
10714   chr_base |= ((state->m_mmc_reg[1] & 0x03) << 8);
10715
10716   chr1_x(machine, chr_page ^ 0, chr_base | ((state->m_mmc_vrom_bank[0] & ~0x01) & chr_mask), chr);
10717   chr1_x(machine, chr_page ^ 1, chr_base | ((state->m_mmc_vrom_bank[0] |  0x01) & chr_mask), chr);
10718   chr1_x(machine, chr_page ^ 2, chr_base | ((state->m_mmc_vrom_bank[1] & ~0x01) & chr_mask), chr);
10719   chr1_x(machine, chr_page ^ 3, chr_base | ((state->m_mmc_vrom_bank[1] |  0x01) & chr_mask), chr);
10720   chr1_x(machine, chr_page ^ 4, chr_base | (state->m_mmc_vrom_bank[2] & chr_mask), chr);
10721   chr1_x(machine, chr_page ^ 5, chr_base | (state->m_mmc_vrom_bank[3] & chr_mask), chr);
10722   chr1_x(machine, chr_page ^ 6, chr_base | (state->m_mmc_vrom_bank[4] & chr_mask), chr);
10723   chr1_x(machine, chr_page ^ 7, chr_base | (state->m_mmc_vrom_bank[5] & chr_mask), chr);
10724}
10725
10726static WRITE8_HANDLER( bmc_gc6in1_l_w )
10727{
10728   nes_state *state = space->machine().driver_data<nes_state>();
10729   UINT8 bank;
10730   LOG_MMC(("bmc_gc6in1_l_w, offset: %04x, data: %02x\n", offset, data));
10731   offset += 0x100;
10732
10733   if (offset == 0x1000)
10734   {
10735      state->m_mmc_reg[0] = data;
10736      if (data & 0x80)
10737      {
10738         bank = (data & 0x0f) | ((state->m_mmc_reg[1] & 0x03) << 4);
10739         prg16_89ab(space->machine(), bank);
10740         prg16_cdef(space->machine(), bank);
10741      }
10742      else
10743         bmc_gc6in1_set_prg(space->machine(), state->m_mmc_prg_base, state->m_mmc_prg_mask);
10744   }
10745   else if (offset == 0x1001)
10746   {
10747      state->m_mmc_reg[1] = data;
10748      bmc_gc6in1_set_prg(space->machine(), state->m_mmc_prg_base, state->m_mmc_prg_mask);
10749   }
10750   else if (offset == 0x1007)
10751   {
10752      state->m_mmc_reg[2] = data;
10753   }
10754}
10755
10756static WRITE8_HANDLER( bmc_gc6in1_w )
10757{
10758   nes_state *state = space->machine().driver_data<nes_state>();
10759   UINT8 mmc_helper, cmd;
10760   static const UINT8 conv_table[8] = {0, 6, 3, 7, 5, 2, 4, 1};
10761   LOG_MMC(("bmc_gc6in1_w, offset: %04x, data: %02x\n", offset, data));
10762
10763   if (!state->m_mmc_reg[2]) // in this case we act like MMC3, only with alt prg/chr handlers
10764   {
10765      switch (offset & 0x6001)
10766      {
10767         case 0x0000:
10768            mmc_helper = state->m_mmc3_latch ^ data;
10769            state->m_mmc3_latch = data;
10770
10771            /* Has PRG Mode changed? */
10772            if (mmc_helper & 0x40)
10773               bmc_gc6in1_set_prg(space->machine(), state->m_mmc_prg_base, state->m_mmc_prg_mask);
10774
10775            /* Has CHR Mode changed? */
10776            if (mmc_helper & 0x80)
10777               bmc_gc6in1_set_chr(space->machine(), state->m_mmc_chr_source);
10778            break;
10779
10780         case 0x0001:
10781            cmd = state->m_mmc3_latch & 0x07;
10782            switch (cmd)
10783         {
10784            case 0: case 1:   // these do not need to be separated: we take care of them in set_chr!
10785            case 2: case 3: case 4: case 5:
10786               state->m_mmc_vrom_bank[cmd] = data;
10787               bmc_gc6in1_set_chr(space->machine(), state->m_mmc_chr_source);
10788               break;
10789            case 6:
10790            case 7:
10791               state->m_mmc_prg_bank[cmd - 6] = data;
10792               bmc_gc6in1_set_prg(space->machine(), state->m_mmc_prg_base, state->m_mmc_prg_mask);
10793               break;
10794         }
10795            break;
10796
10797         default:
10798            txrom_w(space, offset, data);
10799            break;
10800      }
10801   }
10802   else
10803   {
10804      switch (offset & 0x6001)
10805      {
10806         case 0x0000:
10807            txrom_w(space, 0x4000, data);
10808            break;
10809
10810         case 0x0001:
10811            data = (data & 0xc0) | conv_table[data & 0x07];
10812            mmc_helper = state->m_mmc3_latch ^ data;
10813            state->m_mmc3_latch = data;
10814
10815            /* Has PRG Mode changed? */
10816            if (mmc_helper & 0x40)
10817               bmc_gc6in1_set_prg(space->machine(), state->m_mmc_prg_base, state->m_mmc_prg_mask);
10818
10819            /* Has CHR Mode changed? */
10820            if (mmc_helper & 0x80)
10821               bmc_gc6in1_set_chr(space->machine(), state->m_mmc_chr_source);
10822
10823            state->m_mmc_reg[3] = 1;
10824            break;
10825
10826         case 0x2000:
10827            cmd = state->m_mmc3_latch & 0x07;
10828            if (state->m_mmc_reg[3])
10829            {
10830               state->m_mmc_reg[3] = 0;
10831               switch (cmd)
10832               {
10833                  case 0: case 1:   // these do not need to be separated: we take care of them in set_chr!
10834                  case 2: case 3: case 4: case 5:
10835                     state->m_mmc_vrom_bank[cmd] = data;
10836                     bmc_gc6in1_set_chr(space->machine(), state->m_mmc_chr_source);
10837                     break;
10838                  case 6:
10839                  case 7:
10840                     state->m_mmc_prg_bank[cmd - 6] = data;
10841                     bmc_gc6in1_set_prg(space->machine(), state->m_mmc_prg_base, state->m_mmc_prg_mask);
10842                     break;
10843               }
10844            }
10845            break;
10846
10847
10848         case 0x2001:
10849            set_nt_mirroring(space->machine(), BIT(data, 0) ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT);
10850            break;
10851
10852         default:
10853            txrom_w(space, offset, data);
10854            break;
10855      }
10856   }
10857}
10858
10859/*************************************************************
10860
10861 BMC-FAMILY-4646B
10862
10863 Known Boards: Unknown Multigame Bootleg Board (4646B)
10864 Games: 2 in 1 - Family Kid & Aladdin 4
10865
10866 MMC3 clone
10867
10868 iNES: mapper 134
10869
10870 In MESS: Supported.
10871
10872 *************************************************************/
10873
10874static WRITE8_HANDLER( bmc_family4646_m_w )
10875{
10876   nes_state *state = space->machine().driver_data<nes_state>();
10877   LOG_MMC(("bmc_family4646_m_w, offset: %04x, data: %02x\n", offset, data));
10878
10879   if (offset == 0x01)
10880   {
10881      state->m_mmc_prg_base = (data & 0x02) << 4;
10882      state->m_mmc_prg_mask = 0x1f;
10883      state->m_mmc_chr_base = (data & 0x20) << 3;
10884      state->m_mmc_chr_mask = 0xff;
10885      mmc3_set_prg(space->machine(), state->m_mmc_prg_base, state->m_mmc_prg_mask);
10886      mmc3_set_chr(space->machine(), state->m_mmc_chr_source, state->m_mmc_chr_base, state->m_mmc_chr_mask);
10887   }
10888}
10889
10890/*************************************************************
10891
10892 BMC-VT5201
10893
10894 *************************************************************/
10895
10896static WRITE8_HANDLER( bmc_vt5201_w )
10897{
10898   nes_state *state = space->machine().driver_data<nes_state>();
10899   LOG_MMC(("bmc_vt5201_w, offset: %04x, data: %02x\n", offset, data));
10900
10901   state->m_mmc_latch1 = BIT(offset, 8);
10902
10903   // not sure about this mirroring bit!!
10904   // without it TN 95 in 1 has glitches in Lunar Ball; with it TN 95 in 1 has glitches in Galaxian!
10905   set_nt_mirroring(space->machine(), BIT(data, 3) ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT);
10906   if (BIT(offset, 7))
10907   {
10908      prg16_89ab(space->machine(), (offset >> 4) & 0x07);
10909      prg16_cdef(space->machine(), (offset >> 4) & 0x07);
10910   }
10911   else
10912      prg32(space->machine(), (offset >> 5) & 0x03);
10913   chr8(space->machine(), offset, CHRROM);
10914}
10915
10916static READ8_HANDLER( bmc_vt5201_r )
10917{
10918   nes_state *state = space->machine().driver_data<nes_state>();
10919   LOG_MMC(("bmc_vt5201_r, offset: %04x\n", offset));
10920   //  state->m_mmc_dipsetting = input_port_read(space->machine(), "CARTDIPS");
10921
10922   if (state->m_mmc_latch1)
10923      return state->m_mmc_dipsetting; // cart mode, depending on the Dip Switches (always zero atm, given we have no way to add cart-based DIPs)
10924   else
10925      return mmc_hi_access_rom(space->machine(), offset);
10926}
10927
10928/*************************************************************
10929
10930 BMC-BS-5
10931
10932 Games: a few 4 in 1 multicarts
10933
10934 *************************************************************/
10935
10936static void bmc_bs5_update_banks( running_machine &machine )
10937{
10938   nes_state *state = machine.driver_data<nes_state>();
10939
10940   prg8_89(machine, state->m_mmc_prg_bank[0]);
10941   prg8_ab(machine, state->m_mmc_prg_bank[1]);
10942   prg8_cd(machine, state->m_mmc_prg_bank[2]);
10943   prg8_ef(machine, state->m_mmc_prg_bank[3]);
10944   chr2_0(machine, state->m_mmc_vrom_bank[0], CHRROM);
10945   chr2_2(machine, state->m_mmc_vrom_bank[1], CHRROM);
10946   chr2_4(machine, state->m_mmc_vrom_bank[2], CHRROM);
10947   chr2_6(machine, state->m_mmc_vrom_bank[3], CHRROM);
10948}
10949
10950static WRITE8_HANDLER( bmc_bs5_w )
10951{
10952   nes_state *state = space->machine().driver_data<nes_state>();
10953   UINT8 bs5_helper = (offset & 0xc00) >> 10;
10954   LOG_MMC(("bmc_bs5_w, offset: %04x, data: %02x\n", offset, data));
10955//  state->m_mmc_dipsetting = input_port_read(space->machine(), "CARTDIPS");
10956
10957   switch (offset & 0x7000)
10958   {
10959      case 0x0000:
10960         state->m_mmc_vrom_bank[bs5_helper] = offset & 0x1f;
10961         break;
10962      case 0x2000:
10963         if (BIT(offset, state->m_mmc_dipsetting + 4))   // mmc_dipsetting is always zero atm, given we have no way to add cart-based DIPs
10964            state->m_mmc_prg_bank[bs5_helper] = offset & 0x0f;
10965         break;
10966   }
10967   bmc_bs5_update_banks(space->machine());
10968}
10969
10970/*************************************************************
10971
10972 BMC-810544-C-A1
10973
10974 Games: 200-in-1 Elfland
10975
10976 *************************************************************/
10977
10978static WRITE8_HANDLER( bmc_810544_w )
10979{
10980   UINT8 bank = (offset >> 7);
10981   LOG_MMC(("bmc_810544_w, offset: %04x, data: %02x\n", offset, data));
10982
10983   if (!BIT(offset, 6))
10984   {
10985      prg16_89ab(space->machine(), (bank << 1) | BIT(offset, 5));
10986      prg16_cdef(space->machine(), (bank << 1) | BIT(offset, 5));
10987   }
10988   else
10989      prg32(space->machine(), bank);
10990
10991   set_nt_mirroring(space->machine(), BIT(offset, 4) ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT);
10992
10993   chr8(space->machine(), offset & 0x0f, CHRROM);
10994}
10995
10996/*************************************************************
10997
10998 BMC-NTD-03
10999
11000 *************************************************************/
11001
11002static WRITE8_HANDLER( bmc_ntd03_w )
11003{
11004   UINT8 pbank, cbank;
11005   LOG_MMC(("bmc_ntd03_w, offset: %04x, data: %02x\n", offset, data));
11006
11007   pbank = (offset >> 10) & 0x1e;
11008   cbank = ((offset & 0x300) >> 5) | (offset & 0x07);
11009
11010   if (BIT(offset, 7))
11011   {
11012      prg16_89ab(space->machine(), pbank | BIT(offset, 6));
11013      prg16_cdef(space->machine(), pbank | BIT(offset, 6));
11014   }
11015   else
11016      prg32(space->machine(), pbank >> 1);
11017
11018   set_nt_mirroring(space->machine(), BIT(offset, 10) ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT);
11019
11020   chr8(space->machine(), cbank, CHRROM);
11021}
11022
11023/*************************************************************
11024
11025 BMC-GHOSTBUSTERS63IN1
11026
11027 in MESS: only preliminar support
11028
11029 *************************************************************/
11030
11031static void bmc_gb63_update( running_machine &machine )
11032{
11033   nes_state *state = machine.driver_data<nes_state>();
11034
11035   set_nt_mirroring(machine, BIT(state->m_mmc_reg[0], 6) ? PPU_MIRROR_VERT : PPU_MIRROR_HORZ);
11036
11037   if (BIT(state->m_mmc_reg[0], 5))
11038   {
11039      prg16_89ab(machine, state->m_mmc_reg[0] & 0x1f);   // FIXME: here probably we could also have PRGRAM, depending on mmc_latch1!
11040      prg16_cdef(machine, state->m_mmc_reg[0] & 0x1f);   // FIXME: here probably we could also have PRGRAM, depending on mmc_latch1!
11041   }
11042   else
11043      prg32(machine, (state->m_mmc_reg[0] & 0x1f) >> 1);   // FIXME: here probably we could also have PRGRAM, depending on mmc_latch1!
11044
11045   if (BIT(state->m_mmc_reg[1], 2))
11046      chr8(machine, 0, CHRRAM);
11047//  else
11048//      chr8(machine, 0, CHRROM);
11049}
11050
11051static WRITE8_HANDLER( bmc_gb63_w )
11052{
11053   nes_state *state = space->machine().driver_data<nes_state>();
11054   LOG_MMC(("bmc_gb63_w, offset: %04x, data: %02x\n", offset, data));
11055
11056   state->m_mmc_reg[offset & 1] = data;
11057   state->m_mmc_latch1 = BIT(state->m_mmc_reg[0], 7) | (BIT(state->m_mmc_reg[1], 0) << 1);
11058
11059}
11060
11061static READ8_HANDLER( bmc_gb63_r )
11062{
11063   nes_state *state = space->machine().driver_data<nes_state>();
11064   LOG_MMC(("bmc_gb63_r, offset: %04x\n", offset));
11065   //  state->m_mmc_dipsetting = input_port_read(space->machine(), "CARTDIPS");
11066
11067   if (state->m_mmc_latch1 == 1)
11068      return 0xff;   // open bus
11069   else
11070      return mmc_hi_access_rom(space->machine(), offset);
11071}
11072
11073/*************************************************************
11074
11075 UNL-EDU2000
11076
11077 *************************************************************/
11078
11079static WRITE8_HANDLER( edu2k_w )
11080{
11081   LOG_MMC(("edu2k_w, offset: %04x, data: %02x\n", offset, data));
11082
11083   prg32(space->machine(), data & 0x1f);
11084   wram_bank(space->machine(), (data & 0xc0) >> 6, NES_WRAM);
11085}
11086
11087/*************************************************************
11088
11089 UNL-H2288
11090
11091 *************************************************************/
11092
11093static void h2288_prg_cb( running_machine &machine, int start, int bank )
11094{
11095   nes_state *state = machine.driver_data<nes_state>();
11096
11097   if (!(state->m_mmc_reg[0] & 0x40))
11098      prg8_x(machine, start, bank);
11099}
11100
11101static WRITE8_HANDLER( h2288_l_w )
11102{
11103   nes_state *state = space->machine().driver_data<nes_state>();
11104   LOG_MMC(("h2288_l_w offset: %04x, data: %02x\n", offset, data));
11105   offset += 0x100;
11106
11107   if (offset >= 0x1800)
11108   {
11109      state->m_mmc_reg[offset & 1] = data;
11110      if (state->m_mmc_reg[0] & 0x40)
11111      {
11112         UINT8 helper1 = (state->m_mmc_reg[0] & 0x05) | ((state->m_mmc_reg[0] >> 2) & 0x0a);
11113         UINT8 helper2 = BIT(state->m_mmc_reg[0], 1);
11114         prg16_89ab(space->machine(), helper1 & ~helper2);
11115         prg16_cdef(space->machine(), helper1 |  helper2);
11116      }
11117      else
11118         mmc3_set_prg(space->machine(), state->m_mmc_prg_base, state->m_mmc_prg_mask);
11119   }
11120}
11121
11122static READ8_HANDLER( h2288_l_r )
11123{
11124   LOG_MMC(("h2288_l_r offset: %04x\n", offset));
11125   offset += 0x100;
11126
11127   if (offset >= 0x1000)
11128   {
11129      int helper = offset >> 8;
11130      if (offset & 1)
11131         return helper | 0x01;
11132      else
11133         return helper ^ 0x01;
11134   }
11135
11136   return 0;
11137}
11138
11139static WRITE8_HANDLER( h2288_w )
11140{
11141   static const UINT8 conv_table[8] = {0, 3, 1, 5, 6, 7, 2, 4};
11142   LOG_MMC(("h2288_w, offset: %04x, data: %02x\n", offset, data));
11143
11144   switch (offset & 0x6001)
11145   {
11146      case 0x0000:
11147         txrom_w(space, 0x0000, (data & 0xc0) | conv_table[data & 0x07]);
11148         break;
11149
11150      default:
11151         txrom_w(space, offset, data);
11152         break;
11153   }
11154}
11155
11156/*************************************************************
11157
11158 UNL-SHJY3
11159
11160 *************************************************************/
11161
11162/* I think the IRQ should only get fired if enough CPU cycles have passed, but we don't implement (yet) this part */
11163static void shjy3_irq( device_t *device, int scanline, int vblank, int blanked )
11164{
11165   nes_state *state = device->machine().driver_data<nes_state>();
11166   if (state->m_IRQ_enable & 0x02)
11167   {
11168      if (state->m_IRQ_count == 0xff)
11169      {
11170         state->m_IRQ_count = state->m_IRQ_count_latch;
11171         state->m_IRQ_enable = state->m_IRQ_enable | ((state->m_IRQ_enable & 0x01) << 1);
11172         device_set_input_line(state->m_maincpu, M6502_IRQ_LINE, HOLD_LINE);
11173      }
11174      else
11175         state->m_IRQ_count++;
11176   }
11177}
11178
11179static void shjy3_update( running_machine &machine )
11180{
11181   nes_state *state = machine.driver_data<nes_state>();
11182   int i;
11183
11184   prg8_89(machine, state->m_mmc_prg_bank[0]);
11185   prg8_ab(machine, state->m_mmc_prg_bank[1]);
11186
11187   for (i = 0; i < 8; i++)
11188   {
11189      UINT8 chr_bank = state->m_mmc_vrom_bank[i] | (state->m_mmc_extra_bank[i] << 4);
11190      if (state->m_mmc_vrom_bank[i] == 0xc8)
11191      {
11192         state->m_mmc_latch1 = 0;
11193         continue;
11194      }
11195      else if (state->m_mmc_vrom_bank[i] == 0x88)
11196      {
11197         state->m_mmc_latch1 = 1;
11198         continue;
11199      }
11200      if ((state->m_mmc_vrom_bank[i] == 4 || state->m_mmc_vrom_bank[i] == 5) && !state->m_mmc_latch1)
11201         chr1_x(machine, i, chr_bank & 1, CHRRAM);
11202      else
11203         chr1_x(machine, i, chr_bank, CHRROM);
11204   }
11205}
11206
11207static WRITE8_HANDLER( shjy3_w )
11208{
11209   nes_state *state = space->machine().driver_data<nes_state>();
11210   UINT8 mmc_helper, shift;
11211   LOG_MMC(("shjy3_w, offset: %04x, data: %02x\n", offset, data));
11212
11213   if (offset >= 0x3000 && offset <= 0x600c)
11214   {
11215      mmc_helper = ((offset & 8) | (offset >> 8)) >> 3;
11216      mmc_helper += 2;
11217      mmc_helper &= 7;
11218      shift = offset & 4;
11219
11220      state->m_mmc_vrom_bank[mmc_helper] = (state->m_mmc_vrom_bank[mmc_helper] & (0xf0 >> shift)) | ((data & 0x0f) << shift);
11221      if (shift)
11222         state->m_mmc_extra_bank[mmc_helper] = data >> 4;
11223   }
11224   else
11225   {
11226      switch (offset)
11227      {
11228         case 0x0010:
11229            state->m_mmc_prg_bank[0] = data;
11230            break;
11231         case 0x2010:
11232            state->m_mmc_prg_bank[1] = data;
11233            break;
11234         case 0x1400:
11235            switch (data & 0x03)
11236            {
11237               case 0: set_nt_mirroring(space->machine(), PPU_MIRROR_VERT); break;
11238               case 1: set_nt_mirroring(space->machine(), PPU_MIRROR_HORZ); break;
11239               case 2: set_nt_mirroring(space->machine(), PPU_MIRROR_LOW); break;
11240               case 3: set_nt_mirroring(space->machine(), PPU_MIRROR_HIGH); break;
11241            }
11242            break;
11243         case 0x7000:
11244            state->m_IRQ_count_latch = (state->m_IRQ_count_latch & 0xf0) | (data & 0x0f);
11245            break;
11246         case 0x7004:
11247            state->m_IRQ_count_latch = (state->m_IRQ_count_latch & 0x0f) | ((data & 0x0f) << 4);
11248            break;
11249         case 0x7008:
11250            state->m_IRQ_enable = data & 0x03;
11251            if (state->m_IRQ_enable & 0x02)
11252               state->m_IRQ_count = state->m_IRQ_count_latch;
11253            break;
11254      }
11255   }
11256   shjy3_update(space->machine());
11257}
11258
11259/*************************************************************
11260
11261 UNL-603-5052
11262
11263 MMC3 + protection access in 0x4020 - 0x7fff
11264
11265 in MESS: Partial support
11266
11267 *************************************************************/
11268
11269WRITE8_HANDLER( unl_6035052_extra_w )
11270{
11271   nes_state *state = space->machine().driver_data<nes_state>();
11272   LOG_MMC(("unl_6035052_extra_w, offset: %04x, data: %02x\n", offset, data));
11273   state->m_mmc_latch1 = data & 0x03;
11274   if (state->m_mmc_latch1 == 1)
11275      state->m_mmc_latch1 = 2;
11276}
11277
11278READ8_HANDLER( unl_6035052_extra_r )
11279{
11280   nes_state *state = space->machine().driver_data<nes_state>();
11281   LOG_MMC(("unl_6035052_extra_r, offset: %04x\n", offset));
11282   return state->m_mmc_latch1;
11283}
11284
11285
11286/*************************************************************
11287
11288 BMC-POWERJOY
11289
11290 *************************************************************/
11291
11292static void pjoy84_prg_cb( running_machine &machine, int start, int bank )
11293{
11294   nes_state *state = machine.driver_data<nes_state>();
11295   UINT8 flip = (state->m_mmc3_latch & 0x40) ? 2 : 0;
11296
11297   if (!(state->m_mmc_reg[3] & 0x03))
11298      prg8_x(machine, start, bank);
11299   else if (start == flip)
11300   {
11301      if ((state->m_mmc_reg[3] & 0x03) == 0x03)
11302         prg32(machine, bank >> 2);
11303      else
11304      {
11305         prg16_89ab(machine, bank >> 1);
11306         prg16_cdef(machine, bank >> 1);
11307      }
11308   }
11309}
11310
11311static void pjoy84_chr_cb( running_machine &machine, int start, int bank, int source )
11312{
11313   nes_state *state = machine.driver_data<nes_state>();
11314
11315   if (!(state->m_mmc_reg[3] & 0x10))
11316      chr1_x(machine, start, bank, source);
11317}
11318
11319INLINE void pjoy84_set_base_mask( running_machine &machine )
11320{
11321   nes_state *state = machine.driver_data<nes_state>();
11322
11323   state->m_mmc_prg_base = ((state->m_mmc_reg[0] & (0x06 | BIT(state->m_mmc_reg[0], 6))) << 4) |
11324                  (BIT(state->m_mmc_reg[0], 4) << 7);
11325
11326   state->m_mmc_chr_base = ((~state->m_mmc_reg[0] << 0) & 0x080 & state->m_mmc_reg[2]) |
11327                  ((state->m_mmc_reg[0] << 4) & 0x080 & state->m_mmc_reg[0]) |
11328                  ((state->m_mmc_reg[0] << 3) & 0x100) |
11329                  ((state->m_mmc_reg[0] << 5) & 0x200);
11330
11331   state->m_mmc_prg_mask = BIT(state->m_mmc_reg[0], 6) ? 0x0f : 0x1f;
11332   state->m_mmc_chr_mask = BIT(state->m_mmc_reg[0], 7) ? 0x7f : 0xff;
11333}
11334
11335static WRITE8_HANDLER( pjoy84_m_w )
11336{
11337   nes_state *state = space->machine().driver_data<nes_state>();
11338   LOG_MMC(("pjoy84_m_w offset: %04x, data: %02x\n", offset, data));
11339
11340   switch (offset & 0x03)
11341   {
11342      case 0x00:
11343      case 0x03:
11344         if (state->m_mmc_reg[3] & 0x80)
11345            return;   // else we act as if offset & 3 = 1,2
11346      case 0x01:
11347      case 0x02:
11348         state->m_mmc_reg[offset & 0x03] = data;
11349         pjoy84_set_base_mask(space->machine());
11350         if (state->m_mmc_reg[3] & 0x10)
11351            chr8(space->machine(), (state->m_mmc_chr_base >> 3) | (state->m_mmc_reg[2] & 0x0f), state->m_mmc_chr_source);
11352         else
11353            mmc3_set_chr(space->machine(), state->m_mmc_chr_source, state->m_mmc_chr_base, state->m_mmc_chr_mask);
11354         mmc3_set_prg(space->machine(), state->m_mmc_prg_base, state->m_mmc_prg_mask);
11355         break;
11356   }
11357}
11358
11359/*************************************************************
11360
11361 SOMERI TEAM
11362
11363 iNES: mapper 116
11364
11365 Emulation note about regs in MESS: currently,
11366 - state->m_mmc_cmd1 represent the board mode
11367 - state->m_mmc_reg[n] for n=0,1,2,3 represent the MMC1 regs
11368 - state->m_mmc_prg_bank[n] for n=0,...,3 represent the MMC3 PRG banks
11369 - state->m_mmc_vrom_bank[n] for n=0,...,5 represent the MMC3 CHR banks
11370 - state->m_mmc_prg_bank[n] for n=4,5 represent the VRC2 PRG banks
11371 - state->m_mmc_vrom_bank[n] for n=6,...,13 represent the VRC2 CHR banks
11372
11373 In MESS: Preliminary support
11374
11375 *************************************************************/
11376
11377// MMC1 Mode emulation
11378static void someri_mmc1_set_prg( running_machine &machine )
11379{
11380   nes_state *state = machine.driver_data<nes_state>();
11381   UINT8 prg_mode = state->m_mmc_reg[0] & 0x0c;
11382   UINT8 prg_offset = state->m_mmc_reg[1] & 0x10;
11383
11384   switch (prg_mode)
11385   {
11386      case 0x00:
11387      case 0x04:
11388         prg32(machine, (prg_offset + state->m_mmc_reg[3]) >> 1);
11389         break;
11390      case 0x08:
11391         prg16_89ab(machine, prg_offset + 0);
11392         prg16_cdef(machine, prg_offset + state->m_mmc_reg[3]);
11393         break;
11394      case 0x0c:
11395         prg16_89ab(machine, prg_offset + state->m_mmc_reg[3]);
11396         prg16_cdef(machine, prg_offset + 0x0f);
11397         break;
11398   }
11399}
11400
11401static void someri_mmc1_set_chr( running_machine &machine )
11402{
11403   nes_state *state = machine.driver_data<nes_state>();
11404   UINT8 chr_mode = BIT(state->m_mmc_reg[0], 4);
11405
11406   if (chr_mode)
11407   {
11408      chr4_0(machine, state->m_mmc_reg[1] & 0x1f, state->m_mmc_chr_source);
11409      chr4_4(machine, state->m_mmc_reg[2] & 0x1f, state->m_mmc_chr_source);
11410   }
11411   else
11412      chr8(machine, (state->m_mmc_reg[1] & 0x1f) >> 1, state->m_mmc_chr_source);
11413}
11414
11415static WRITE8_HANDLER( someri_mmc1_w )
11416{
11417   nes_state *state = space->machine().driver_data<nes_state>();
11418
11419   assert(state->m_mmc_cmd1 == 2);
11420
11421   if (data & 0x80)
11422   {
11423      state->m_mmc1_count = 0;
11424      state->m_mmc1_latch = 0;
11425
11426      state->m_mmc_reg[0] |= 0x0c;
11427      someri_mmc1_set_prg(space->machine());
11428      return;
11429   }
11430
11431   if (state->m_mmc1_count < 5)
11432   {
11433      if (state->m_mmc1_count == 0) state->m_mmc1_latch = 0;
11434      state->m_mmc1_latch >>= 1;
11435      state->m_mmc1_latch |= (data & 0x01) ? 0x10 : 0x00;
11436      state->m_mmc1_count++;
11437   }
11438
11439   if (state->m_mmc1_count == 5)
11440   {
11441      switch (offset & 0x6000)
11442      {
11443         case 0x0000:
11444            state->m_mmc_reg[0] = state->m_mmc1_latch;
11445            switch (state->m_mmc_reg[0] & 0x03)
11446            {
11447            case 0: set_nt_mirroring(space->machine(), PPU_MIRROR_LOW); break;
11448            case 1: set_nt_mirroring(space->machine(), PPU_MIRROR_HIGH); break;
11449            case 2: set_nt_mirroring(space->machine(), PPU_MIRROR_VERT); break;
11450            case 3: set_nt_mirroring(space->machine(), PPU_MIRROR_HORZ); break;
11451            }
11452            someri_mmc1_set_chr(space->machine());
11453            someri_mmc1_set_prg(space->machine());
11454            break;
11455         case 0x2000:
11456            state->m_mmc_reg[1] = state->m_mmc1_latch;
11457            someri_mmc1_set_chr(space->machine());
11458            someri_mmc1_set_prg(space->machine());
11459            break;
11460         case 0x4000:
11461            state->m_mmc_reg[2] = state->m_mmc1_latch;
11462            someri_mmc1_set_chr(space->machine());
11463            break;
11464         case 0x6000:
11465            state->m_mmc_reg[3] = state->m_mmc1_latch;
11466            someri_mmc1_set_prg(space->machine());
11467            break;
11468      }
11469
11470      state->m_mmc1_count = 0;
11471   }
11472}
11473
11474// MMC3 Mode emulation
11475static WRITE8_HANDLER( someri_mmc3_w )
11476{
11477   nes_state *state = space->machine().driver_data<nes_state>();
11478   UINT8 mmc_helper, cmd;
11479
11480   assert(state->m_mmc_cmd1 == 1);
11481   switch (offset & 0x6001)
11482   {
11483      case 0x0000:
11484         mmc_helper = state->m_mmc3_latch ^ data;
11485         state->m_mmc3_latch = data;
11486
11487         if (mmc_helper & 0x40)
11488            mmc3_set_prg(space->machine(), state->m_mmc_prg_base, state->m_mmc_prg_mask);
11489
11490         if (mmc_helper & 0x80)
11491            mmc3_set_chr(space->machine(), state->m_mmc_chr_source, state->m_mmc_chr_base, state->m_mmc_chr_mask);
11492         break;
11493
11494      case 0x0001:
11495         cmd = state->m_mmc3_latch & 0x07;
11496         switch (cmd)
11497         {
11498         case 0: case 1:
11499         case 2: case 3: case 4: case 5:
11500            state->m_mmc_vrom_bank[cmd] = data;
11501            mmc3_set_chr(space->machine(), state->m_mmc_chr_source, state->m_mmc_chr_base, state->m_mmc_chr_mask);
11502            break;
11503         case 6:
11504         case 7:
11505            state->m_mmc_prg_bank[cmd - 6] = data;
11506            mmc3_set_prg(space->machine(), state->m_mmc_prg_base, state->m_mmc_prg_mask);
11507            break;
11508         }
11509         break;
11510
11511      case 0x2000:
11512         set_nt_mirroring(space->machine(), BIT(data, 0) ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT);
11513         break;
11514      case 0x2001: break;
11515      case 0x4000: state->m_IRQ_count_latch = data; break;
11516      case 0x4001: state->m_IRQ_count = 0; break;
11517      case 0x6000: state->m_IRQ_enable = 0; break;
11518      case 0x6001: state->m_IRQ_enable = 1; break;
11519   }
11520}
11521
11522// VRC2 Mode emulation
11523static WRITE8_HANDLER( someri_vrc2_w )
11524{
11525   nes_state *state = space->machine().driver_data<nes_state>();
11526   UINT8 bank, shift;
11527
11528   assert(state->m_mmc_cmd1 == 0);
11529
11530   if (offset < 0x1000)
11531   {
11532      state->m_mmc_prg_bank[4] = data;
11533      prg8_89(space->machine(), state->m_mmc_prg_bank[4]);
11534   }
11535   else if (offset < 0x2000)
11536   {
11537      switch (data & 0x03)
11538      {
11539         case 0x00: set_nt_mirroring(space->machine(), PPU_MIRROR_VERT); break;
11540         case 0x01: set_nt_mirroring(space->machine(), PPU_MIRROR_HORZ); break;
11541         case 0x02: set_nt_mirroring(space->machine(), PPU_MIRROR_LOW); break;
11542         case 0x03: set_nt_mirroring(space->machine(), PPU_MIRROR_HIGH); break;
11543      }
11544   }
11545   else if (offset < 0x3000)
11546   {
11547      state->m_mmc_prg_bank[5] = data;
11548      prg8_ab(space->machine(), state->m_mmc_prg_bank[5]);
11549   }
11550   else if (offset < 0x7000)
11551   {
11552      bank = ((offset & 0x7000) - 0x3000) / 0x0800 + BIT(offset, 1);
11553      shift = BIT(offset, 2) * 4;
11554      data = (data & 0x0f) << shift;
11555      state->m_mmc_vrom_bank[6 + bank] = data | state->m_mmc_chr_base;
11556      chr1_x(space->machine(), bank, state->m_mmc_vrom_bank[6 + bank], CHRROM);
11557   }
11558}
11559
11560static WRITE8_HANDLER( someri_w )
11561{
11562   nes_state *state = space->machine().driver_data<nes_state>();
11563   LOG_MMC(("someri_w mode %d, offset: %04x, data: %02x\n", state->m_mmc_cmd1, offset, data));
11564
11565   switch (state->m_mmc_cmd1)
11566   {
11567      case 0x00: someri_vrc2_w(space, offset, data); break;
11568      case 0x01: someri_mmc3_w(space, offset, data); break;
11569      case 0x02: someri_mmc1_w(space, offset, data); break;
11570   }
11571}
11572
11573static void someri_mode_update( running_machine &machine )
11574{
11575   nes_state *state = machine.driver_data<nes_state>();
11576   int i;
11577
11578   switch (state->m_mmc_cmd1)
11579   {
11580      case 0x00:
11581         prg8_89(machine, state->m_mmc_prg_bank[4]);
11582         prg8_ab(machine, state->m_mmc_prg_bank[5]);
11583         for (i = 0; i < 8; i++)
11584            chr1_x(machine, i, state->m_mmc_vrom_bank[6 + i], CHRROM);
11585         break;
11586      case 0x01:
11587         mmc3_set_prg(machine, state->m_mmc_prg_base, state->m_mmc_prg_mask);
11588         mmc3_set_chr(machine, state->m_mmc_chr_source, state->m_mmc_chr_base, state->m_mmc_chr_mask);
11589         break;
11590      case 0x02:
11591         someri_mmc1_set_prg(machine);
11592         someri_mmc1_set_chr(machine);
11593         break;
11594   }
11595}
11596
11597static WRITE8_HANDLER( someri_l_w )
11598{
11599   nes_state *state = space->machine().driver_data<nes_state>();
11600   LOG_MMC(("someri_l_w, offset: %04x, data: %02x\n", offset, data));
11601   offset += 0x100;
11602
11603   if (offset & 0x100)
11604   {
11605      state->m_mmc_cmd1 = data & 0x03;
11606      state->m_mmc_chr_base = ((state->m_mmc_cmd1 & 0x04) << 6);
11607      if (state->m_mmc_cmd1 != 1)
11608         state->m_IRQ_enable = 0;
11609      someri_mode_update(space->machine());
11610   }
11611}
11612
11613#ifdef UNUSED_FUNCTION
11614/*************************************************************
11615
11616 FUJIYA Board - mapper 170 according to NEStopia
11617
11618 Which games are supposed to use this?
11619
11620 *************************************************************/
11621
11622static WRITE8_HANDLER( fujiya_m_w )
11623{
11624   nes_state *state = space->machine().driver_data<nes_state>();
11625   LOG_MMC(("fujiya_m_w, offset: %04x, data: %02x\n", offset, data));
11626   offset += 0x6000;
11627
11628   if (offset == 0x6502 || offset == 0x7000)
11629      state->m_mmc_latch1 = (data & 0x40) << 1;
11630}
11631
11632static READ8_HANDLER( fujiya_m_r )
11633{
11634   nes_state *state = space->machine().driver_data<nes_state>();
11635   LOG_MMC(("fujiya_m_r, offset: %04x\n", offset));
11636   offset += 0x6000;
11637
11638   if (offset == 0x7001 || offset == 0x7777)
11639      return state->m_mmc_latch1 | ((offset >> 8) & 0x7f);
11640
11641   return 0;
11642}
11643#endif
11644
11645
11646
11647
11648typedef void (*nes_ppu_latch)(device_t *device, offs_t offset);
11649
11650struct nes_memory_accessor
11651{
11652   write8_space_func write;
11653   const char        *write_name;
11654   read8_space_func  read;
11655   const char        *read_name;
11656};
11657
11658typedef struct _nes_pcb_intf  nes_pcb_intf;
11659struct _nes_pcb_intf
11660{
11661   int                     mmc_pcb;
11662   nes_memory_accessor     mmc_l;  /* $4100-$5fff read/write routines */
11663   nes_memory_accessor     mmc_m;  /* $6000-$7fff read/write routines */
11664   nes_memory_accessor     mmc_h;  /* $8000-$ffff read/write routines */
11665   nes_ppu_latch           mmc_ppu_latch;
11666   ppu2c0x_scanline_cb      mmc_scanline;
11667   ppu2c0x_hblank_cb      mmc_hblank;
11668};
11669
11670#define NES_NOACCESS \
11671{FUNC_NULL, FUNC_NULL}
11672
11673#define NES_READONLY(a) \
11674{FUNC_NULL, FUNC(a)}
11675
11676#define NES_WRITEONLY(a) \
11677{FUNC(a), FUNC_NULL}
11678
11679static WRITE8_HANDLER( dummy_l_w )
11680{
11681   logerror("write access, offset: %04x, data: %02x\n", offset + 0x4100, data);
11682}
11683
11684static WRITE8_HANDLER( dummy_m_w )
11685{
11686   logerror("write access, offset: %04x, data: %02x\n", offset + 0x6000, data);
11687}
11688
11689static WRITE8_HANDLER( dummy_w )
11690{
11691   logerror("write access, offset: %04x, data: %02x\n", offset + 0x8000, data);
11692}
11693
11694static READ8_HANDLER( dummy_l_r )
11695{
11696   logerror("read access, offset: %04x\n", offset + 0x4100);
11697   return 0x00;
11698}
11699
11700static READ8_HANDLER( dummy_m_r )
11701{
11702   logerror("read access, offset: %04x\n", offset + 0x6000);
11703   return 0x00;
11704}
11705
11706static READ8_HANDLER( dummy_r )
11707{
11708   logerror("read access, offset: %04x\n", offset + 0x8000);
11709   return 0x00;
11710}
11711
11712static const nes_pcb_intf nes_intf_list[] =
11713{
11714   { STD_NROM,             NES_NOACCESS, NES_NOACCESS, NES_NOACCESS,                         NULL, NULL, NULL },
11715   { HVC_FAMBASIC,         NES_NOACCESS, NES_NOACCESS, NES_NOACCESS,                         NULL, NULL, NULL },
11716   { GG_NROM,              NES_NOACCESS, NES_NOACCESS, NES_NOACCESS,                         NULL, NULL, NULL },
11717   { STD_UXROM,            NES_NOACCESS, NES_NOACCESS, NES_WRITEONLY(uxrom_w),               NULL, NULL, NULL },
11718   { STD_UN1ROM,           NES_NOACCESS, NES_NOACCESS, NES_WRITEONLY(un1rom_w),              NULL, NULL, NULL },
11719   { STD_CPROM,            NES_NOACCESS, NES_NOACCESS, NES_WRITEONLY(cprom_w),               NULL, NULL, NULL },
11720   { STD_CNROM,            NES_NOACCESS, NES_NOACCESS, NES_WRITEONLY(cnrom_w),               NULL, NULL, NULL },
11721   { BANDAI_PT554,         NES_NOACCESS, NES_WRITEONLY(bandai_pt554_m_w), NES_WRITEONLY(cnrom_w), NULL, NULL, NULL },
11722   { STD_AXROM,            NES_NOACCESS, NES_NOACCESS, NES_WRITEONLY(axrom_w),               NULL, NULL, NULL },
11723   { STD_PXROM,            NES_NOACCESS, NES_NOACCESS, NES_WRITEONLY(pxrom_w),               mmc2_latch, NULL, NULL },
11724   { STD_FXROM,            NES_NOACCESS, NES_NOACCESS, NES_WRITEONLY(fxrom_w),               mmc2_latch, NULL, NULL },
11725   { STD_BXROM,            NES_NOACCESS, NES_NOACCESS, NES_WRITEONLY(bxrom_w),               NULL, NULL, NULL },
11726   { STD_GXROM,            NES_NOACCESS, NES_NOACCESS, NES_WRITEONLY(gxrom_w),               NULL, NULL, NULL },
11727   { STD_MXROM,            NES_NOACCESS, NES_NOACCESS, NES_WRITEONLY(gxrom_w),               NULL, NULL, NULL },
11728   { STD_NXROM,            NES_NOACCESS, NES_NOACCESS, NES_WRITEONLY(ntbrom_w),              NULL, NULL, NULL },
11729   { SUNSOFT_DCS,          NES_NOACCESS, NES_NOACCESS, NES_WRITEONLY(ntbrom_w),              NULL, NULL, NULL },
11730   { STD_JXROM,            NES_NOACCESS, NES_NOACCESS, NES_WRITEONLY(jxrom_w),               NULL, NULL, jxrom_irq },
11731   { STD_SXROM,            NES_NOACCESS, NES_NOACCESS, NES_WRITEONLY(sxrom_w),               NULL, NULL, NULL },
11732   { STD_SOROM,            NES_NOACCESS, NES_NOACCESS, NES_WRITEONLY(sxrom_w),               NULL, NULL, NULL },
11733   { STD_SXROM_A,          NES_NOACCESS, NES_NOACCESS, NES_WRITEONLY(sxrom_w),               NULL, NULL, NULL },
11734   { STD_SOROM_A,          NES_NOACCESS, NES_NOACCESS, NES_WRITEONLY(sxrom_w),               NULL, NULL, NULL },
11735   { STD_TXROM,            NES_NOACCESS, NES_NOACCESS, NES_WRITEONLY(txrom_w),               NULL, NULL, mmc3_irq },
11736   { STD_TVROM,            NES_NOACCESS, NES_NOACCESS, NES_WRITEONLY(txrom_w),               NULL, NULL, mmc3_irq },
11737   { STD_TKROM,            NES_NOACCESS, NES_NOACCESS, NES_WRITEONLY(txrom_w),               NULL, NULL, mmc3_irq },
11738   { STD_HKROM,            NES_NOACCESS, {FUNC(hkrom_m_w), FUNC(hkrom_m_r)}, NES_WRITEONLY(hkrom_w),     NULL, NULL, mmc3_irq },
11739   { STD_TQROM,            NES_NOACCESS, NES_NOACCESS, NES_WRITEONLY(tqrom_w),               NULL, NULL, mmc3_irq },
11740   { STD_TXSROM,           NES_NOACCESS, NES_NOACCESS, NES_WRITEONLY(txsrom_w),              NULL, NULL, mmc3_irq },
11741   { STD_DXROM,            NES_NOACCESS, NES_NOACCESS, NES_WRITEONLY(dxrom_w),               NULL, NULL, NULL },
11742   { STD_DRROM,            NES_NOACCESS, NES_NOACCESS, NES_WRITEONLY(dxrom_w),               NULL, NULL, NULL },
11743   { NAMCOT_34X3,          NES_NOACCESS, NES_NOACCESS, NES_WRITEONLY(dxrom_w),               NULL, NULL, NULL },
11744   { NAMCOT_3425,          NES_NOACCESS, NES_NOACCESS, NES_WRITEONLY(namcot3425_w),          NULL, NULL, NULL },
11745   { NAMCOT_3446,          NES_NOACCESS, NES_NOACCESS, NES_WRITEONLY(namcot3446_w),          NULL, NULL, NULL },
11746   { NAMCOT_3453,          NES_NOACCESS, NES_NOACCESS, NES_WRITEONLY(namcot3453_w),          NULL, NULL, NULL },
11747   { STD_EXROM,            {FUNC(exrom_l_w), FUNC(exrom_l_r)}, NES_NOACCESS, NES_NOACCESS,               NULL, NULL, mmc5_irq },
11748   { NES_QJ,               NES_NOACCESS, NES_WRITEONLY(qj_m_w), NES_WRITEONLY(txrom_w),      NULL, NULL, mmc3_irq },
11749   { PAL_ZZ,               NES_NOACCESS, NES_WRITEONLY(zz_m_w), NES_WRITEONLY(txrom_w),      NULL, NULL, mmc3_irq },
11750   { UXROM_CC,             NES_NOACCESS, NES_NOACCESS, NES_WRITEONLY(uxrom_cc_w),            NULL, NULL, NULL },
11751   //
11752   { DIS_74X139X74,        NES_NOACCESS, NES_WRITEONLY(dis_74x139x74_m_w), NES_NOACCESS,     NULL, NULL, NULL },
11753   { DIS_74X377,           NES_NOACCESS, NES_NOACCESS, NES_WRITEONLY(dis_74x377_w),          NULL, NULL, NULL },
11754   { DIS_74X161X161X32,    NES_NOACCESS, NES_NOACCESS, NES_WRITEONLY(dis_74x161x161x32_w),   NULL, NULL, NULL },
11755   { DIS_74X161X138,       NES_NOACCESS, NES_WRITEONLY(dis_74x161x138_m_w), NES_NOACCESS,    NULL, NULL, NULL },
11756   { BANDAI_LZ93,          NES_NOACCESS, NES_WRITEONLY(lz93d50_m_w), NES_WRITEONLY(lz93d50_w), NULL, NULL, bandai_lz_irq },
11757   { BANDAI_LZ93EX,        NES_NOACCESS, NES_WRITEONLY(lz93d50_m_w), NES_WRITEONLY(lz93d50_w), NULL, NULL, bandai_lz_irq },
11758   { BANDAI_FCG,           NES_NOACCESS, NES_WRITEONLY(lz93d50_m_w), NES_WRITEONLY(lz93d50_w), NULL, NULL, bandai_lz_irq },
11759   { BANDAI_DATACH,        NES_NOACCESS, NES_WRITEONLY(lz93d50_m_w), NES_WRITEONLY(lz93d50_w), NULL, NULL, bandai_lz_irq },
11760   { BANDAI_JUMP2,         NES_NOACCESS, NES_NOACCESS, NES_WRITEONLY(fjump2_w),              NULL, NULL, bandai_lz_irq },
11761   { BANDAI_KARAOKE,       NES_NOACCESS, NES_NOACCESS, NES_WRITEONLY(bandai_ks_w),           NULL, NULL, NULL },
11762   { BANDAI_OEKAKIDS,      NES_NOACCESS, NES_NOACCESS, NES_WRITEONLY(bandai_ok_w),           NULL, NULL, NULL },
11763   { IREM_G101,            NES_NOACCESS, NES_NOACCESS, NES_WRITEONLY(g101_w),                NULL, NULL, NULL },
11764   { IREM_LROG017,         NES_NOACCESS, NES_NOACCESS, NES_WRITEONLY(lrog017_w),             NULL, NULL, NULL },
11765   { IREM_H3001,           NES_NOACCESS, NES_NOACCESS, NES_WRITEONLY(h3001_w),               NULL, NULL, h3001_irq },
11766   { IREM_TAM_S1,          NES_NOACCESS, NES_NOACCESS, NES_WRITEONLY(tam_s1_w),              NULL, NULL, NULL },
11767   { IREM_HOLYDIV,         NES_NOACCESS, NES_NOACCESS, NES_WRITEONLY(irem_hd_w),             NULL, NULL, NULL },
11768   { JALECO_SS88006,       NES_NOACCESS, NES_NOACCESS, NES_WRITEONLY(ss88006_w),             NULL, NULL, ss88006_irq },
11769   { JALECO_JF11,          NES_NOACCESS, NES_WRITEONLY(jf11_m_w), NES_NOACCESS,              NULL, NULL, NULL },
11770   { JALECO_JF13,          NES_NOACCESS, NES_WRITEONLY(jf13_m_w), NES_NOACCESS,              NULL, NULL, NULL },
11771   { JALECO_JF16,          NES_NOACCESS, NES_NOACCESS, NES_WRITEONLY(jf16_w),                NULL, NULL, NULL },
11772   { JALECO_JF17,          NES_NOACCESS, NES_NOACCESS, NES_WRITEONLY(jf17_w),                NULL, NULL, NULL },
11773   { JALECO_JF19,          NES_NOACCESS, NES_NOACCESS, NES_WRITEONLY(jf19_w),                NULL, NULL, NULL },
11774   { KONAMI_VRC1,          NES_NOACCESS, NES_NOACCESS, NES_WRITEONLY(konami_vrc1_w),         NULL, NULL, NULL },
11775   { KONAMI_VRC2,          NES_NOACCESS, NES_NOACCESS, NES_WRITEONLY(konami_vrc2_w),         NULL, NULL, NULL },
11776   { KONAMI_VRC3,          NES_NOACCESS, NES_NOACCESS, NES_WRITEONLY(konami_vrc3_w),         NULL, NULL, konami_irq },
11777   { KONAMI_VRC4,          NES_NOACCESS, NES_NOACCESS, NES_WRITEONLY(konami_vrc4_w),         NULL, NULL, konami_irq },
11778   { KONAMI_VRC6,          NES_NOACCESS, NES_NOACCESS, NES_WRITEONLY(konami_vrc6_w),         NULL, NULL, konami_irq },
11779   { KONAMI_VRC7,          NES_NOACCESS, NES_NOACCESS, NES_WRITEONLY(konami_vrc7_w),         NULL, NULL, konami_irq },
11780   { NAMCOT_163,           {FUNC(namcot163_l_w), FUNC(namcot163_l_r) }, NES_NOACCESS, NES_WRITEONLY(namcot163_w), NULL, NULL, namcot_irq },
11781   { SUNSOFT_1,            NES_NOACCESS, NES_WRITEONLY(sunsoft1_m_w), NES_NOACCESS,          NULL, NULL, NULL },
11782   { SUNSOFT_2,            NES_NOACCESS, NES_NOACCESS, NES_WRITEONLY(sunsoft2_w),            NULL, NULL, NULL },
11783   { SUNSOFT_3,            NES_NOACCESS, NES_NOACCESS, NES_WRITEONLY(sunsoft3_w),            NULL, NULL, sunsoft3_irq },
11784   { TAITO_TC0190FMC,      NES_NOACCESS, NES_NOACCESS, NES_WRITEONLY(tc0190fmc_w),           NULL, NULL, NULL },
11785   { TAITO_TC0190FMCP,     NES_NOACCESS, NES_NOACCESS, NES_WRITEONLY(tc0190fmc_p16_w),       NULL, NULL, mmc3_irq },
11786   { TAITO_X1_005,         NES_NOACCESS, {FUNC(x1005_m_w), FUNC(x1005_m_r)}, NES_NOACCESS,               NULL, NULL, NULL },
11787   { TAITO_X1_005_A,       NES_NOACCESS, {FUNC(x1005a_m_w), FUNC(x1005_m_r)}, NES_NOACCESS,              NULL, NULL, NULL },
11788   { TAITO_X1_017,         NES_NOACCESS, {FUNC(x1017_m_w), FUNC(x1017_m_r)}, NES_NOACCESS,               NULL, NULL, NULL },
11789   //
11790   { AGCI_50282,           NES_NOACCESS, NES_NOACCESS, NES_WRITEONLY(agci_50282_w),          NULL, NULL, NULL },
11791   { ACTENT_ACT52,         NES_NOACCESS, NES_NOACCESS, NES_WRITEONLY(ae_act52_w),            NULL, NULL, NULL },
11792   { AVE_NINA01,           NES_NOACCESS, NES_WRITEONLY(nina01_m_w), NES_NOACCESS,            NULL, NULL, NULL },
11793   { AVE_NINA06,           NES_WRITEONLY(nina06_l_w), NES_NOACCESS, NES_NOACCESS,            NULL, NULL, NULL },
11794   { CNE_DECATHLON,        NES_NOACCESS, NES_NOACCESS, NES_WRITEONLY(cne_decathl_w),         NULL, NULL, NULL },
11795   { CNE_FSB,              NES_NOACCESS, NES_WRITEONLY(cne_fsb_m_w), NES_NOACCESS,           NULL, NULL, NULL },
11796   { CNE_SHLZ,             NES_WRITEONLY(cne_shlz_l_w), NES_NOACCESS, NES_NOACCESS,          NULL, NULL, NULL },
11797   { CALTRON_6IN1,         NES_NOACCESS, NES_WRITEONLY(caltron6in1_m_w), NES_WRITEONLY(caltron6in1_w),      NULL, NULL, NULL },
11798   { CAMERICA_BF9093,      NES_NOACCESS, NES_NOACCESS, NES_WRITEONLY(bf9093_w),              NULL, NULL, NULL },
11799   { CAMERICA_BF9097,      NES_NOACCESS, NES_NOACCESS, NES_WRITEONLY(bf9093_w),              NULL, NULL, NULL },
11800   { CAMERICA_BF9096,      NES_NOACCESS, NES_WRITEONLY(bf9096_w), NES_WRITEONLY(bf9096_w),   NULL, NULL, NULL },
11801   { CAMERICA_GOLDENFIVE,  NES_NOACCESS, NES_NOACCESS, NES_WRITEONLY(golden5_w),             NULL, NULL, NULL },
11802   { CONY_BOARD,           {FUNC(cony_l_w), FUNC(cony_l_r)}, NES_NOACCESS, NES_WRITEONLY(cony_w),        NULL, NULL, sunsoft3_irq },
11803   { DREAMTECH_BOARD,      NES_WRITEONLY(dreamtech_l_w), NES_NOACCESS, NES_NOACCESS,         NULL, NULL, NULL },
11804   { FUTUREMEDIA_BOARD,    NES_NOACCESS, NES_NOACCESS, NES_WRITEONLY(futuremedia_w),         NULL, NULL, futuremedia_irq },
11805   { FUKUTAKE_BOARD,       {FUNC(fukutake_l_w), FUNC(fukutake_l_r)}, NES_NOACCESS, NES_NOACCESS,         NULL, NULL, NULL },
11806   { GOUDER_37017,         {FUNC(gouder_sf4_l_w), FUNC(gouder_sf4_l_r)}, NES_NOACCESS, NES_WRITEONLY(txrom_w), NULL, NULL, mmc3_irq },
11807   { HENGEDIANZI_BOARD,    NES_NOACCESS, NES_NOACCESS, NES_WRITEONLY(henggedianzi_w),        NULL, NULL, NULL },
11808   { HENGEDIANZI_XJZB,     NES_WRITEONLY(heng_xjzb_l_w), NES_NOACCESS, NES_WRITEONLY(heng_xjzb_w), NULL, NULL, NULL },
11809   { HES6IN1_BOARD,        NES_WRITEONLY(hes6in1_l_w), NES_NOACCESS, NES_NOACCESS,           NULL, NULL, NULL },
11810   { HES_BOARD,            NES_WRITEONLY(hes_l_w), NES_NOACCESS, NES_NOACCESS,               NULL, NULL, NULL },
11811   { HOSENKAN_BOARD,       NES_NOACCESS, NES_NOACCESS, NES_WRITEONLY(hosenkan_w),            NULL, NULL, mmc3_irq },
11812   { KAISER_KS7058,        NES_NOACCESS, NES_NOACCESS, NES_WRITEONLY(ks7058_w),              NULL, NULL, NULL },
11813   { KAISER_KS7022,        NES_NOACCESS, NES_NOACCESS, {FUNC(ks7022_w), FUNC(ks7022_r)},                 NULL, NULL, NULL },
11814   { KAISER_KS7032,        NES_NOACCESS, NES_NOACCESS, NES_WRITEONLY(ks7032_w),              NULL, NULL, ks7032_irq },
11815   { KAISER_KS202,         NES_NOACCESS, NES_NOACCESS, NES_WRITEONLY(ks202_w),               NULL, NULL, ks7032_irq },
11816   { KAISER_KS7017,      NES_WRITEONLY(ks7017_l_w), NES_NOACCESS, NES_NOACCESS,            NULL, NULL, mmc_fds_irq },
11817   { KAY_PANDAPRINCE,      {FUNC(kay_pp_l_w), FUNC(kay_pp_l_r)}, NES_NOACCESS, NES_WRITEONLY(kay_pp_w),  NULL, NULL, mmc3_irq },
11818   { KASING_BOARD,         NES_NOACCESS, NES_WRITEONLY(kasing_m_w), NES_WRITEONLY(txrom_w),  NULL, NULL, mmc3_irq },
11819   { SACHEN_74LS374,       {FUNC(sachen_74x374_l_w), FUNC(sachen_74x374_l_r)}, NES_NOACCESS, NES_NOACCESS, NULL, NULL, NULL },
11820   { SACHEN_74LS374_A,     NES_WRITEONLY(sachen_74x374a_l_w), NES_NOACCESS, NES_NOACCESS,    NULL, NULL, NULL },
11821   { SACHEN_8259A,         NES_WRITEONLY(s8259_l_w), NES_WRITEONLY(s8259_m_w), NES_NOACCESS, NULL, NULL, NULL },
11822   { SACHEN_8259B,         NES_WRITEONLY(s8259_l_w), NES_WRITEONLY(s8259_m_w), NES_NOACCESS, NULL, NULL, NULL },
11823   { SACHEN_8259C,         NES_WRITEONLY(s8259_l_w), NES_WRITEONLY(s8259_m_w), NES_NOACCESS, NULL, NULL, NULL },
11824   { SACHEN_8259D,         NES_WRITEONLY(s8259_l_w), NES_WRITEONLY(s8259_m_w), NES_NOACCESS, NULL, NULL, NULL },
11825   { SACHEN_SA009,         NES_WRITEONLY(sa009_l_w), NES_NOACCESS, NES_NOACCESS,             NULL, NULL, NULL },
11826   { SACHEN_SA0036,        NES_NOACCESS, NES_NOACCESS, NES_WRITEONLY(sa0036_w),              NULL, NULL, NULL },
11827   { SACHEN_SA0037,        NES_NOACCESS, NES_NOACCESS, NES_WRITEONLY(sa0037_w),              NULL, NULL, NULL },
11828   { SACHEN_SA72007,       NES_WRITEONLY(sa72007_l_w), NES_NOACCESS, NES_NOACCESS,           NULL, NULL, NULL },
11829   { SACHEN_SA72008,       NES_WRITEONLY(sa72008_l_w), NES_NOACCESS, NES_NOACCESS,           NULL, NULL, NULL },
11830   { SACHEN_TCA01,         NES_READONLY(tca01_l_r), NES_NOACCESS, NES_NOACCESS,              NULL, NULL, NULL },
11831   { SACHEN_TCU01,         NES_WRITEONLY(tcu01_l_w), NES_WRITEONLY(tcu01_m_w), NES_WRITEONLY(tcu01_w), NULL, NULL, NULL },
11832   { SACHEN_TCU02,         {FUNC(tcu02_l_w), FUNC(tcu02_l_r)}, NES_NOACCESS, NES_NOACCESS,               NULL, NULL, NULL },
11833   { SUBOR_TYPE0,          NES_NOACCESS, NES_NOACCESS, NES_WRITEONLY(subor0_w),              NULL, NULL, NULL },
11834   { SUBOR_TYPE1,          NES_NOACCESS, NES_NOACCESS, NES_WRITEONLY(subor1_w),              NULL, NULL, NULL },
11835   { MAGICSERIES_MD,       NES_NOACCESS, NES_NOACCESS, NES_WRITEONLY(magics_md_w),           NULL, NULL, NULL },
11836   { NANJING_BOARD,        {FUNC(nanjing_l_w), FUNC(nanjing_l_r)}, NES_NOACCESS, NES_NOACCESS,           NULL, NULL, nanjing_irq },
11837   { NITRA_TDA,            NES_NOACCESS, NES_NOACCESS, NES_WRITEONLY(nitra_w),               NULL, NULL, mmc3_irq },
11838   { NTDEC_ASDER,          NES_NOACCESS, NES_NOACCESS, NES_WRITEONLY(ntdec_asder_w),         NULL, NULL, NULL },
11839   { NTDEC_FIGHTINGHERO,   NES_NOACCESS, NES_WRITEONLY(ntdec_fh_m_w), NES_NOACCESS,          NULL, NULL, NULL },
11840   { OPENCORP_DAOU306,     NES_NOACCESS, NES_NOACCESS, NES_WRITEONLY(daou306_w),             NULL, NULL, NULL },
11841   { RCM_GS2015,           NES_NOACCESS, NES_NOACCESS, NES_WRITEONLY(gs2015_w),              NULL, NULL, NULL },
11842   { RCM_TETRISFAMILY,     NES_NOACCESS, NES_NOACCESS, NES_WRITEONLY(rcm_tf_w),              NULL, NULL, NULL },
11843   { REXSOFT_DBZ5,         {FUNC(rex_dbz_l_w), FUNC(rex_dbz_l_r)}, NES_READONLY(rex_dbz_l_r), NES_WRITEONLY(txrom_w), NULL, NULL, mmc3_irq },
11844   { REXSOFT_SL1632,       NES_NOACCESS, NES_NOACCESS, NES_WRITEONLY(rex_sl1632_w),          NULL, NULL, mmc3_irq },
11845   { RUMBLESTATION_BOARD,  NES_NOACCESS, NES_WRITEONLY(rumblestation_m_w), NES_WRITEONLY(rumblestation_w),      NULL, NULL, NULL },
11846   { SOMERI_SL12,          NES_WRITEONLY(someri_l_w), NES_NOACCESS, NES_WRITEONLY(someri_w), NULL, NULL, mmc3_irq },
11847   { SUPERGAME_BOOGERMAN,  NES_WRITEONLY(sgame_boog_l_w), NES_WRITEONLY(sgame_boog_m_w), NES_WRITEONLY(sgame_boog_w), NULL, NULL, mmc3_irq },
11848   { SUPERGAME_LIONKING,   NES_NOACCESS, NES_WRITEONLY(sgame_lion_m_w), NES_WRITEONLY(sgame_lion_w), NULL, NULL, mmc3_irq },
11849   { TENGEN_800008,        NES_NOACCESS, NES_NOACCESS, NES_WRITEONLY(tengen_800008_w),       NULL, NULL, NULL },
11850   { TENGEN_800032,        NES_NOACCESS, NES_NOACCESS, NES_WRITEONLY(tengen_800032_w),       NULL, NULL, tengen_800032_irq },
11851   { TENGEN_800037,        NES_NOACCESS, NES_NOACCESS, NES_WRITEONLY(tengen_800037_w),       NULL, NULL, tengen_800032_irq },
11852   { TXC_22211A,           {FUNC(txc_22211_l_w), FUNC(txc_22211_l_r)}, NES_NOACCESS, NES_WRITEONLY(txc_22211_w), NULL, NULL, NULL },
11853   { TXC_22211B,           {FUNC(txc_22211_l_w), FUNC(txc_22211_l_r)}, NES_NOACCESS, NES_WRITEONLY(txc_22211b_w), NULL, NULL, NULL },
11854   { TXC_22211C,           {FUNC(txc_22211_l_w), FUNC(txc_22211c_l_r)}, NES_NOACCESS, NES_WRITEONLY(txc_22211_w), NULL, NULL, NULL },
11855   { TXC_TW,               NES_WRITEONLY(txc_tw_l_w), NES_WRITEONLY(txc_tw_m_w), NES_WRITEONLY(txrom_w), NULL, NULL, mmc3_irq },
11856   { TXC_STRIKEWOLF,       NES_NOACCESS, NES_NOACCESS, NES_WRITEONLY(txc_strikewolf_w),      NULL, NULL, NULL },
11857   { TXC_MXMDHTWO,         NES_READONLY(txc_mxmdhtwo_l_r), NES_NOACCESS, NES_WRITEONLY(txc_mxmdhtwo_w), NULL, NULL, NULL },
11858   { WAIXING_TYPE_A,       NES_NOACCESS, NES_NOACCESS, NES_WRITEONLY(waixing_a_w),           NULL, NULL, mmc3_irq },
11859   { WAIXING_TYPE_A_1,     NES_NOACCESS, NES_NOACCESS, NES_WRITEONLY(waixing_a_w),           NULL, NULL, mmc3_irq },
11860   { WAIXING_TYPE_B,       NES_NOACCESS, NES_NOACCESS, NES_WRITEONLY(waixing_a_w),           NULL, NULL, mmc3_irq },
11861   { WAIXING_TYPE_C,       NES_NOACCESS, NES_NOACCESS, NES_WRITEONLY(waixing_a_w),           NULL, NULL, mmc3_irq },
11862   { WAIXING_TYPE_D,       NES_NOACCESS, NES_NOACCESS, NES_WRITEONLY(waixing_a_w),           NULL, NULL, mmc3_irq },
11863   { WAIXING_TYPE_E,       NES_NOACCESS, NES_NOACCESS, NES_WRITEONLY(waixing_a_w),           NULL, NULL, mmc3_irq },
11864   { WAIXING_TYPE_F,       NES_NOACCESS, NES_NOACCESS, NES_WRITEONLY(waixing_f_w),           NULL, NULL, mmc3_irq },
11865   { WAIXING_TYPE_G,       NES_NOACCESS, NES_NOACCESS, NES_WRITEONLY(waixing_g_w),           NULL, NULL, mmc3_irq },
11866   { WAIXING_TYPE_H,       NES_NOACCESS, NES_NOACCESS, NES_WRITEONLY(waixing_h_w),           NULL, NULL, mmc3_irq },
11867   { WAIXING_TYPE_I,       NES_NOACCESS, NES_NOACCESS, NES_WRITEONLY(txrom_w),               NULL, NULL, mmc3_irq },   // this is MMC3 + possibly additional WRAM added in 0x5000-0x5fff
11868   { WAIXING_TYPE_J,       NES_NOACCESS, NES_NOACCESS, NES_WRITEONLY(txrom_w),               NULL, NULL, mmc3_irq },   // this is MMC3 + possibly additional WRAM added in 0x5000-0x5fff
11869   { WAIXING_SGZ,          NES_NOACCESS, NES_NOACCESS, NES_WRITEONLY(waixing_sgz_w),         NULL, NULL, konami_irq },
11870   { WAIXING_SGZLZ,        NES_WRITEONLY(waixing_sgzlz_l_w), NES_NOACCESS, NES_NOACCESS,     NULL, NULL, NULL },
11871   { WAIXING_FFV,          NES_WRITEONLY(waixing_ffv_l_w), NES_NOACCESS, NES_NOACCESS,       NULL, NULL, NULL },
11872   { WAIXING_ZS,           NES_NOACCESS, NES_NOACCESS, NES_WRITEONLY(waixing_zs_w),          NULL, NULL, NULL },
11873   { WAIXING_DQ8,          NES_NOACCESS, NES_NOACCESS, NES_WRITEONLY(waixing_dq8_w),         NULL, NULL, NULL },
11874   { WAIXING_SECURITY,     NES_WRITEONLY(waixing_sec_l_w), NES_NOACCESS, NES_WRITEONLY(txrom_w), NULL, NULL, mmc3_irq },
11875   { WAIXING_SH2,          NES_NOACCESS, NES_NOACCESS, NES_WRITEONLY(txrom_w),               NULL, NULL, mmc3_irq },   // this is MMC3 + possibly additional WRAM added in 0x5000-0x5fff
11876   { WAIXING_PS2,          NES_NOACCESS, NES_NOACCESS, NES_WRITEONLY(waixing_ps2_w),         NULL, NULL, NULL },
11877   { UNL_8237,             NES_WRITEONLY(unl_8237_l_w), NES_NOACCESS, NES_WRITEONLY(unl_8237_w),      NULL, NULL, mmc3_irq },
11878   { UNL_AX5705,           NES_NOACCESS, NES_NOACCESS, NES_WRITEONLY(unl_ax5705_w),          NULL, NULL, NULL },
11879   { UNL_CC21,             NES_NOACCESS, NES_NOACCESS, NES_WRITEONLY(unl_cc21_w),            NULL, NULL, NULL },
11880   { UNL_KOF97,            NES_NOACCESS, NES_NOACCESS, NES_WRITEONLY(unl_kof97_w),           NULL, NULL, mmc3_irq },
11881   { UNL_T230,             NES_NOACCESS, NES_NOACCESS, NES_WRITEONLY(unl_t230_w),            NULL, NULL, konami_irq },
11882   { UNL_KOF96,            {FUNC(kof96_l_w), FUNC(kof96_l_r)}, NES_NOACCESS, NES_WRITEONLY(kof96_w),     NULL, NULL, mmc3_irq },
11883   { UNL_MK2,              NES_NOACCESS, NES_WRITEONLY(mk2_m_w), NES_NOACCESS,               NULL, NULL, mmc3_irq },
11884   { UNL_N625092,          NES_NOACCESS, NES_NOACCESS, NES_WRITEONLY(n625092_w),             NULL, NULL, NULL },
11885   { UNL_SC127,            NES_NOACCESS, NES_NOACCESS, NES_WRITEONLY(sc127_w),               NULL, NULL, sc127_irq },
11886   { UNL_SMB2J,            NES_NOACCESS, NES_NOACCESS, NES_WRITEONLY(smb2j_w),               NULL, NULL, NULL },
11887   { UNL_SUPERFIGHTER3,    NES_NOACCESS, NES_NOACCESS, NES_WRITEONLY(unl_sf3_w),             NULL, NULL, mmc3_irq },
11888   { UNL_XZY,              NES_WRITEONLY(unl_xzy_l_w), NES_NOACCESS, NES_NOACCESS,           NULL, NULL, NULL },
11889   { UNL_RACERMATE,        NES_NOACCESS, NES_NOACCESS, NES_WRITEONLY(unl_racmate_w),         NULL, NULL, NULL },
11890   { UNL_STUDYNGAME,       NES_NOACCESS, NES_NOACCESS, NES_WRITEONLY(sng32_w),               NULL, NULL, NULL },
11891   { UNL_603_5052,         {FUNC(unl_6035052_extra_w), FUNC(unl_6035052_extra_r)}, {FUNC(unl_6035052_extra_w), FUNC(unl_6035052_extra_r)}, NES_WRITEONLY(txrom_w), NULL, NULL, mmc3_irq },
11892   { UNL_EDU2K,            NES_NOACCESS, NES_NOACCESS, NES_WRITEONLY(edu2k_w),               NULL, NULL, NULL },
11893   { UNL_SHJY3,            NES_NOACCESS, NES_NOACCESS, NES_WRITEONLY(shjy3_w),               NULL, NULL, shjy3_irq },
11894   { UNL_H2288,            {FUNC(h2288_l_w), FUNC(h2288_l_r)}, NES_NOACCESS, NES_WRITEONLY(h2288_w),     NULL, NULL, mmc3_irq },
11895   //
11896   { BTL_AISENSHINICOL,    NES_NOACCESS, NES_NOACCESS, NES_WRITEONLY(btl_mariobaby_w),       NULL, NULL, NULL },
11897   { BTL_DRAGONNINJA,      NES_NOACCESS, NES_NOACCESS, NES_WRITEONLY(btl_dn_w),              NULL, NULL, btl_dn_irq },
11898   { BTL_MARIOBABY,        NES_NOACCESS, NES_NOACCESS, NES_WRITEONLY(btl_mariobaby_w),       NULL, NULL, NULL },
11899   { BTL_SMB2A,            NES_NOACCESS, NES_NOACCESS, NES_WRITEONLY(btl_smb2a_w),           NULL, NULL, btl_smb2a_irq },
11900   { BTL_SMB2B,            NES_WRITEONLY(smb2jb_l_w), NES_NOACCESS, NES_NOACCESS,            NULL, NULL, smb2jb_irq },
11901   { BTL_SMB3,             NES_NOACCESS, NES_NOACCESS, NES_WRITEONLY(btl_smb3_w),            NULL, NULL, btl_smb3_irq },
11902   { BTL_SUPERBROS11,      NES_NOACCESS, NES_NOACCESS, NES_WRITEONLY(btl_smb11_w),           NULL, NULL, mmc3_irq },
11903   { BTL_TOBIDASE,         NES_WRITEONLY(btl_tobi_l_w), NES_NOACCESS, NES_NOACCESS,          NULL, NULL, NULL },
11904   { BTL_PIKACHUY2K,       NES_NOACCESS, {FUNC(btl_pika_y2k_m_w), FUNC(btl_pika_y2k_m_r)}, NES_WRITEONLY(btl_pika_y2k_w),  NULL, NULL, mmc3_irq },
11905   { WHIRLWIND_2706,       NES_NOACCESS, NES_NOACCESS, NES_WRITEONLY(whirl2706_w),           NULL, NULL, NULL },
11906   //
11907   { BMC_190IN1,           NES_NOACCESS, NES_NOACCESS, NES_WRITEONLY(bmc_190in1_w),          NULL, NULL, NULL },
11908   { BMC_A65AS,            NES_NOACCESS, NES_NOACCESS, NES_WRITEONLY(bmc_a65as_w),           NULL, NULL, NULL },
11909   { BMC_GS2004,           NES_NOACCESS, NES_NOACCESS, NES_WRITEONLY(bmc_gs2004_w),          NULL, NULL, NULL },
11910   { BMC_GS2013,           NES_NOACCESS, NES_NOACCESS, NES_WRITEONLY(bmc_gs2013_w),          NULL, NULL, NULL },
11911   { BMC_NOVELDIAMOND,     NES_NOACCESS, NES_NOACCESS, NES_WRITEONLY(novel1_w),              NULL, NULL, NULL },
11912   { BMC_9999999IN1,       NES_NOACCESS, NES_NOACCESS, NES_WRITEONLY(novel2_w),              NULL, NULL, NULL },
11913   { BMC_T262,             NES_NOACCESS, NES_NOACCESS, NES_WRITEONLY(bmc_t262_w),            NULL, NULL, NULL },
11914   { BMC_WS,               NES_NOACCESS, NES_WRITEONLY(bmc_ws_m_w), NES_NOACCESS,            NULL, NULL, NULL },
11915   { BMC_GKA,              NES_NOACCESS, NES_NOACCESS, NES_WRITEONLY(bmc_gka_w),             NULL, NULL, NULL },
11916   { BMC_GKB,              NES_NOACCESS, NES_NOACCESS, NES_WRITEONLY(bmc_gkb_w),             NULL, NULL, NULL },
11917   { BMC_SUPER_700IN1,     NES_NOACCESS, NES_NOACCESS, NES_WRITEONLY(bmc_super700in1_w),     NULL, NULL, NULL },
11918   { BMC_36IN1,            NES_NOACCESS, NES_NOACCESS, NES_WRITEONLY(bmc_36in1_w),           NULL, NULL, NULL },
11919   { BMC_21IN1,            NES_NOACCESS, NES_NOACCESS, NES_WRITEONLY(bmc_21in1_w),           NULL, NULL, NULL },
11920   { BMC_150IN1,           NES_NOACCESS, NES_NOACCESS, NES_WRITEONLY(bmc_150in1_w),          NULL, NULL, NULL },
11921   { BMC_35IN1,            NES_NOACCESS, NES_NOACCESS, NES_WRITEONLY(bmc_35in1_w),           NULL, NULL, NULL },
11922   { BMC_64IN1,            NES_NOACCESS, NES_NOACCESS, NES_WRITEONLY(bmc_64in1_w),           NULL, NULL, NULL },
11923   { BMC_SUPERHIK_300IN1,  NES_NOACCESS, NES_NOACCESS, NES_WRITEONLY(bmc_hik300_w),          NULL, NULL, NULL },
11924   { BMC_SUPERGUN_20IN1,   NES_NOACCESS, NES_NOACCESS, NES_WRITEONLY(supergun20in1_w),       NULL, NULL, NULL },
11925   { BMC_72IN1,            NES_NOACCESS, NES_NOACCESS, NES_WRITEONLY(bmc_72in1_w),           NULL, NULL, NULL },
11926   { BMC_76IN1,            NES_NOACCESS, NES_NOACCESS, NES_WRITEONLY(bmc_76in1_w),           NULL, NULL, NULL },
11927   { BMC_SUPER_42IN1,      NES_NOACCESS, NES_NOACCESS, NES_WRITEONLY(bmc_76in1_w),           NULL, NULL, NULL },
11928   { BMC_1200IN1,          NES_NOACCESS, NES_NOACCESS, NES_WRITEONLY(bmc_1200in1_w),         NULL, NULL, NULL },
11929   { BMC_31IN1,            NES_NOACCESS, NES_NOACCESS, NES_WRITEONLY(bmc_31in1_w),           NULL, NULL, NULL },
11930   { BMC_22GAMES,          NES_NOACCESS, NES_NOACCESS, NES_WRITEONLY(bmc_22g_w),             NULL, NULL, NULL },
11931   { BMC_20IN1,            NES_NOACCESS, NES_NOACCESS, NES_WRITEONLY(bmc_20in1_w),           NULL, NULL, NULL },
11932   { BMC_110IN1,           NES_NOACCESS, NES_NOACCESS, NES_WRITEONLY(bmc_110in1_w),          NULL, NULL, NULL },
11933   { BMC_64IN1NR,          NES_WRITEONLY(bmc_64in1nr_l_w), NES_NOACCESS, NES_WRITEONLY(bmc_64in1nr_w), NULL, NULL, NULL },
11934   { BMC_S24IN1SC03,       NES_WRITEONLY(bmc_s24in1sc03_l_w), NES_NOACCESS, NES_WRITEONLY(txrom_w), NULL, NULL, mmc3_irq },
11935   { BMC_HIK8IN1,          NES_NOACCESS, NES_WRITEONLY(bmc_hik8_m_w), NES_WRITEONLY(txrom_w), NULL, NULL, mmc3_irq },
11936   { BMC_SUPERHIK_4IN1,    NES_NOACCESS, NES_WRITEONLY(bmc_hik4in1_m_w), NES_WRITEONLY(txrom_w), NULL, NULL, mmc3_irq },
11937   { BMC_SUPERBIG_7IN1,    NES_NOACCESS, NES_NOACCESS, NES_WRITEONLY(bmc_sbig7_w),           NULL, NULL, mmc3_irq },
11938   { BMC_MARIOPARTY_7IN1,  NES_NOACCESS, NES_WRITEONLY(bmc_mario7in1_m_w), NES_WRITEONLY(txrom_w), NULL, NULL, mmc3_irq },
11939   { BMC_FAMILY_4646B,     NES_NOACCESS, NES_WRITEONLY(bmc_family4646_m_w), NES_WRITEONLY(txrom_w), NULL, NULL, mmc3_irq },
11940   { BMC_15IN1,            NES_NOACCESS, NES_WRITEONLY(bmc_15in1_m_w), NES_WRITEONLY(txrom_w), NULL, NULL, mmc3_irq },
11941   { BMC_BALLGAMES_11IN1,  NES_NOACCESS, NES_WRITEONLY(bmc_ball11_m_w), NES_WRITEONLY(bmc_ball11_w), NULL, NULL, NULL },
11942   { BMC_GOLDENCARD_6IN1,  NES_WRITEONLY(bmc_gc6in1_l_w), NES_NOACCESS, NES_WRITEONLY(bmc_gc6in1_w), NULL, NULL, mmc3_irq },
11943   { BMC_VT5201,           NES_NOACCESS, NES_NOACCESS, {FUNC(bmc_vt5201_w), FUNC(bmc_vt5201_r)},         NULL, NULL, NULL },
11944   { BMC_BENSHENG_BS5,     NES_NOACCESS, NES_NOACCESS, NES_WRITEONLY(bmc_bs5_w),             NULL, NULL, NULL },
11945   { BMC_810544,           NES_NOACCESS, NES_NOACCESS, NES_WRITEONLY(bmc_810544_w),          NULL, NULL, NULL },
11946   { BMC_NTD_03,           NES_NOACCESS, NES_NOACCESS, NES_WRITEONLY(bmc_ntd03_w),           NULL, NULL, NULL },
11947   { BMC_G63IN1,           NES_NOACCESS, NES_NOACCESS, {FUNC(bmc_gb63_w), FUNC(bmc_gb63_r)},             NULL, NULL, NULL },
11948   { BMC_FK23C,            NES_WRITEONLY(fk23c_l_w), NES_NOACCESS, NES_WRITEONLY(fk23c_w),   NULL, NULL, mmc3_irq },
11949   { BMC_FK23CA,           NES_WRITEONLY(fk23c_l_w), NES_NOACCESS, NES_WRITEONLY(fk23c_w),   NULL, NULL, mmc3_irq },
11950   { BMC_PJOY84,           NES_NOACCESS, NES_WRITEONLY(pjoy84_m_w), NES_WRITEONLY(txrom_w),  NULL, NULL, mmc3_irq },
11951   //
11952   { FFE_MAPPER6,          NES_WRITEONLY(mapper6_l_w), NES_NOACCESS, NES_WRITEONLY(mapper6_w), NULL, NULL, ffe_irq },
11953   { FFE_MAPPER8,          NES_NOACCESS, NES_NOACCESS, NES_WRITEONLY(mapper8_w),             NULL, NULL, NULL },
11954   { FFE_MAPPER17,         NES_WRITEONLY(mapper17_l_w), NES_NOACCESS, NES_NOACCESS,          NULL, NULL, ffe_irq },
11955   // for debug and development
11956   { UNKNOWN_BOARD,        {FUNC(dummy_l_w), FUNC(dummy_l_r)}, {FUNC(dummy_m_w), FUNC(dummy_m_r)}, {FUNC(dummy_w), FUNC(dummy_r)}, NULL, NULL, NULL },
11957   //
11958   { UNSUPPORTED_BOARD,    NES_NOACCESS, NES_NOACCESS, NES_NOACCESS,                         NULL, NULL, NULL },
11959   //
11960};
11961
11962const nes_pcb_intf *nes_pcb_intf_lookup( int pcb_id )
11963{
11964   int i;
11965   for (i = 0; i < ARRAY_LENGTH(nes_intf_list); i++)
11966   {
11967      if (nes_intf_list[i].mmc_pcb == pcb_id)
11968         return &nes_intf_list[i];
11969   }
11970   return NULL;
11971}
11972
11973void pcb_handlers_setup( running_machine &machine )
11974{
11975   nes_state *state = machine.driver_data<nes_state>();
11976   const nes_pcb_intf *intf = nes_pcb_intf_lookup(state->m_pcb_id);
11977   device_t *ppu = machine.device("ppu");
11978
11979   if (intf == NULL)
11980      fatalerror("Missing PCB interface\n");
11981
11982   if (intf)
11983   {
11984      state->m_mmc_write_low = intf->mmc_l.write;
11985      state->m_mmc_write_low_name = intf->mmc_l.write_name;
11986      state->m_mmc_write_mid = intf->mmc_m.write;
11987      state->m_mmc_write_mid_name = intf->mmc_m.write_name;
11988      state->m_mmc_write = intf->mmc_h.write;
11989      state->m_mmc_write_name = intf->mmc_h.write_name;
11990      state->m_mmc_read_low = intf->mmc_l.read;
11991      state->m_mmc_read_low_name = intf->mmc_l.read_name;
11992      state->m_mmc_read_mid = intf->mmc_m.read;   // in progress
11993      state->m_mmc_read_mid_name = intf->mmc_m.read_name;
11994      state->m_mmc_read = intf->mmc_h.read;   // in progress
11995      state->m_mmc_read_name = intf->mmc_h.read_name;
11996      ppu2c0x_set_latch(ppu, intf->mmc_ppu_latch);
11997   }
11998   else
11999   {
12000      logerror("PCB %d is not yet supported, defaulting to no mapper.\n", state->m_pcb_id);
12001      state->m_mmc_write_low = NULL;
12002      state->m_mmc_write_mid = NULL;
12003      state->m_mmc_write = NULL;
12004      state->m_mmc_read_low = NULL;
12005      state->m_mmc_read_mid = NULL;   // in progress
12006      state->m_mmc_read = NULL;   // in progress
12007      ppu2c0x_set_latch(ppu, NULL);
12008   }
12009
12010   state->m_mmc3_prg_cb = prg8_x;
12011   state->m_mmc3_chr_cb = chr1_x;
12012
12013   switch (state->m_pcb_id)
12014   {
12015      case STD_TXSROM:
12016         state->m_mmc3_chr_cb = txsrom_chr_cb;
12017         break;
12018      case GOUDER_37017:
12019         state->m_mmc3_prg_cb = gouder_sf4_prg_cb;
12020         break;
12021      case KASING_BOARD:
12022         state->m_mmc3_prg_cb = kasing_prg_cb;
12023         break;
12024      case REXSOFT_DBZ5:
12025         state->m_mmc3_chr_cb = rex_dbz_chr_cb;
12026         break;
12027      case TXC_TW:
12028         state->m_mmc3_prg_cb = txc_tw_prg_cb;
12029         break;
12030      case WAIXING_TYPE_A:
12031         state->m_mmc3_chr_cb = waixing_a_chr_cb;
12032         break;
12033      case WAIXING_TYPE_A_1:
12034         state->m_mmc3_chr_cb = waixing_a1_chr_cb;
12035         break;
12036      case WAIXING_TYPE_B:
12037         state->m_mmc3_chr_cb = waixing_b_chr_cb;
12038         break;
12039      case WAIXING_TYPE_C:
12040         state->m_mmc3_chr_cb = waixing_c_chr_cb;
12041         break;
12042      case WAIXING_TYPE_D:
12043         state->m_mmc3_chr_cb = waixing_d_chr_cb;
12044         break;
12045      case WAIXING_TYPE_E:
12046         state->m_mmc3_chr_cb = waixing_e_chr_cb;
12047         break;
12048      case WAIXING_TYPE_G:
12049         state->m_mmc3_chr_cb = waixing_g_chr_cb;
12050         break;
12051      case WAIXING_TYPE_H:
12052         state->m_mmc3_chr_cb = waixing_h_chr_cb;
12053         break;
12054      case WAIXING_SECURITY:
12055         state->m_mmc3_prg_cb = waixing_sec_prg_cb;
12056         state->m_mmc3_chr_cb = waixing_sec_chr_cb;
12057         break;
12058      case WAIXING_SH2:
12059         state->m_mmc3_chr_cb = waixing_sh2_chr_cb;
12060         break;
12061      case UNL_8237:
12062         state->m_mmc3_prg_cb = unl_8237_prg_cb;
12063         state->m_mmc3_chr_cb = unl_8237_chr_cb;
12064         break;
12065      case UNL_H2288:
12066         state->m_mmc3_prg_cb = h2288_prg_cb;
12067         break;
12068      case SUPERGAME_BOOGERMAN:
12069         state->m_mmc3_prg_cb = sgame_boog_prg_cb;
12070         state->m_mmc3_chr_cb = sgame_boog_chr_cb;
12071         break;
12072      case UNL_KOF96:
12073         state->m_mmc3_prg_cb = kof96_prg_cb;
12074         state->m_mmc3_chr_cb = kof96_chr_cb;
12075         break;
12076      case KAY_PANDAPRINCE:
12077         state->m_mmc3_prg_cb = kay_pp_prg_cb;
12078         state->m_mmc3_chr_cb = kay_pp_chr_cb;
12079         break;
12080      case BMC_FK23C:
12081         state->m_mmc3_prg_cb = fk23c_prg_cb;
12082         state->m_mmc3_chr_cb = fk23c_chr_cb;
12083         break;
12084      case BMC_S24IN1SC03:
12085         state->m_mmc3_prg_cb = bmc_s24in1sc03_prg_cb;
12086         state->m_mmc3_chr_cb = bmc_s24in1sc03_chr_cb;
12087         break;
12088      case BMC_PJOY84:
12089         state->m_mmc3_prg_cb = pjoy84_prg_cb;
12090         state->m_mmc3_chr_cb = pjoy84_chr_cb;
12091         break;
12092   }
12093}
12094
12095/*************************************************************
12096
12097 pcb_initialize
12098
12099 Initialize all the necessary registers and quantities for
12100 emulation of each board
12101
12102 *************************************************************/
12103
12104/* this is used by many boards (MMC3, MMC6 + most MMC3 pirate clone boards) */
12105static void mmc3_common_initialize( running_machine &machine, int prg_mask, int chr_mask, int IRQ_type )
12106{
12107   nes_state *state = machine.driver_data<nes_state>();
12108
12109   state->m_mmc3_alt_irq = IRQ_type;      // later MMC3 boards seem to use MMC6-type IRQ... more investigations are in progress at NESDev...
12110   state->m_mmc_prg_bank[0] = state->m_mmc_prg_bank[2] = 0xfe;   // prg_bank[2] & prg_bank[3] remain always the same in most MMC3 variants
12111   state->m_mmc_prg_bank[1] = state->m_mmc_prg_bank[3] = 0xff;   // but some pirate clone mappers change them after writing certain registers
12112   state->m_mmc3_latch = 0;
12113   state->m_mmc3_wram_protect = 0x80;
12114   state->m_mmc_prg_base = state->m_mmc_chr_base = 0;
12115   state->m_mmc_prg_mask = prg_mask;
12116   state->m_mmc_chr_mask = chr_mask;
12117   mmc3_set_prg(machine, state->m_mmc_prg_base, state->m_mmc_prg_mask);
12118   mmc3_set_chr(machine, state->m_mmc_chr_source, state->m_mmc_chr_base, state->m_mmc_chr_mask);
12119}
12120
12121// WIP code
12122static int pcb_initialize( running_machine &machine, int idx )
12123{
12124   nes_state *state = machine.driver_data<nes_state>();
12125   int err = 0, i;
12126
12127   /* basic PRG config */
12128   prg32(machine, 0);
12129
12130   /* some boards will not use this, but directly CHRROM (resp. CHRRAM) if the board only has VROM (resp. VRAM) */
12131   state->m_mmc_chr_source = state->m_chr_chunks ? CHRROM : CHRRAM;
12132   chr8(machine, 0, state->m_mmc_chr_source);
12133
12134   /* Here, we init a few helpers: 4 prg banks and 16 chr banks - some mappers use them */
12135   for (i = 0; i < 4; i++)
12136      state->m_mmc_prg_bank[i] = 0;
12137   for (i = 0; i < 16; i++)
12138      state->m_mmc_vrom_bank[i] = 0;
12139   for (i = 0; i < 16; i++)
12140      state->m_mmc_extra_bank[i] = 0;
12141
12142   state->m_mmc_latch1 = 0;
12143   state->m_mmc_latch2 = 0;
12144
12145   /* Finally, we init IRQ-related quantities. */
12146   state->m_IRQ_enable = state->m_IRQ_enable_latch = 0;
12147   state->m_IRQ_count = state->m_IRQ_count_latch = 0;
12148   state->m_IRQ_toggle = 0;
12149
12150   switch (idx)
12151   {
12152         /* many boards only needs PRG to point at first 32k and CHR at first 8k */
12153      case STD_NROM:   // mapper 0
12154      case HVC_FAMBASIC:
12155      case GG_NROM:
12156      case UXROM_CC:   // mapper 180
12157      case STD_CNROM:   // mapper 3, 185
12158      case BANDAI_PT554:
12159      case TENGEN_800008:
12160      case STD_BXROM:   // mapper 34
12161      case STD_GXROM:   // mapper 66
12162      case STD_MXROM:
12163      case BANDAI_OEKAKIDS:   // mapper 96
12164      case JALECO_JF11:   // mapper 140
12165      case JALECO_JF13:   // mapper 86
12166      case JALECO_JF19:   // mapper 92
12167      case DIS_74X377:   // mapper 11
12168      case DIS_74X161X138:   // mapper 38
12169      case CALTRON_6IN1:   // mapper 41
12170      case TXC_STRIKEWOLF:   // mapper 36
12171      case UNL_STUDYNGAME:   // mapper 39
12172      case RUMBLESTATION_BOARD:   // mapper 46
12173      case BMC_GKB:   // mapper 58
12174      case RCM_TETRISFAMILY:   // mapper 61
12175      case BMC_SUPER_700IN1:   // mapper 62
12176      case MAGICSERIES_MD:   // mapper 107
12177      case HES_BOARD:   // mapper 113
12178      case HES6IN1_BOARD:   // mapper 113
12179      case SACHEN_SA72008:   // mapper 133
12180      case SACHEN_TCU02:   // mapper 136
12181      case SACHEN_SA72007:   // mapper 145
12182      case SACHEN_TCU01:   // mapper 147
12183      case SACHEN_SA009:   // mapper 160
12184      case SACHEN_SA0037:   // mapper 148
12185      case SACHEN_SA0036:   // mapper 149
12186      case AGCI_50282:   // mapper 144
12187      case KAISER_KS7058:   // mapper 171
12188      case HENGEDIANZI_BOARD:   // mapper 177
12189      case WAIXING_SGZLZ:   // mapper 178
12190      case HENGEDIANZI_XJZB:   // mapper 179
12191      case BMC_21IN1:   // mapper 201
12192      case BMC_9999999IN1:   // mapper 213
12193      case RCM_GS2015:   // mapper 216
12194      case BMC_72IN1:   // mapper 225
12195      case BMC_76IN1:   // mapper 226
12196      case BMC_SUPER_42IN1:   // mapper 226
12197      case ACTENT_ACT52:   // mapper 228
12198      case CNE_SHLZ:   // mapper 240
12199      case TXC_MXMDHTWO:   // mapper 241
12200      case WAIXING_ZS:   // mapper 242
12201      case WAIXING_DQ8:   // mapper 242
12202      case CNE_DECATHLON:   // mapper 244
12203      case UNL_CC21:
12204      case BMC_VT5201:
12205      case BMC_WS:
12206      case UNL_EDU2K:
12207         break;
12208
12209         /* other boards need additional initialization */
12210      case STD_UXROM:   // mapper 2
12211      case STD_UN1ROM:   // mapper 94
12212      case STD_JXROM:      // mapper 69
12213      case SUNSOFT_5B:
12214      case SUNSOFT_FME7:
12215      case NAMCOT_3425:   // mapper 95
12216      case DIS_74X139X74:   // mapper 87
12217      case DIS_74X161X161X32:   // mapper 152 & 70
12218      case BANDAI_LZ93:   // mapper 16, 157
12219      case BANDAI_LZ93EX:   // same + EEPROM
12220      case BANDAI_DATACH:
12221      case BANDAI_FCG:
12222      case IREM_HOLYDIV:   // mapper 78
12223      case IREM_G101:   // mapper 32
12224      case IREM_H3001:   // mapper 65
12225      case JALECO_SS88006:   // mapper 18
12226      case JALECO_JF16:   // mapper 78
12227      case JALECO_JF17:   // mapper 72
12228      case KONAMI_VRC1:   // mapper 75
12229      case KONAMI_VRC2:
12230      case KONAMI_VRC3:   // mapper 73
12231      case KONAMI_VRC4:
12232      case KONAMI_VRC6:
12233      case SUNSOFT_3:   // mapper 67
12234      case TAITO_TC0190FMC:   // mapper 33
12235      case TAITO_TC0190FMCP:   // mapper 48
12236      case TAITO_X1_005:   // mapper 80
12237      case TAITO_X1_005_A:   // mapper 207
12238      case TAITO_X1_017:   // mapper 82
12239      case NTDEC_ASDER:   // mapper 112
12240      case FUTUREMEDIA_BOARD:   // mapper 117
12241      case BTL_DRAGONNINJA:   // mapper 222
12242      case WAIXING_SGZ:   // mapper 252
12243      case UNL_T230:
12244      case BMC_NTD_03:
12245      case KAISER_KS7022:
12246      case UNL_SHJY3:
12247      case KAISER_KS7017:
12248      case KAISER_KS7032:
12249      case KAISER_KS202:
12250         prg16_89ab(machine, 0);
12251         prg16_cdef(machine, state->m_prg_chunks - 1);
12252         break;
12253
12254      case STD_CPROM:   // mapper 13
12255         chr4_0(machine, 0, CHRRAM);
12256         chr4_4(machine, 0, CHRRAM);
12257         break;
12258      case STD_AXROM:   // mapper 7
12259         set_nt_mirroring(machine, PPU_MIRROR_LOW);
12260         break;
12261      case STD_SXROM:   // mapper 1, 155
12262      case STD_SOROM:
12263      case STD_SXROM_A:
12264      case STD_SOROM_A:
12265         state->m_mmc1_latch = 0;
12266         state->m_mmc1_count = 0;
12267         state->m_mmc_reg[0] = 0x0f;
12268         state->m_mmc_reg[1] = state->m_mmc_reg[2] = state->m_mmc_reg[3] = 0;
12269         state->m_mmc1_reg_write_enable = 1;
12270         set_nt_mirroring(machine, PPU_MIRROR_HORZ);
12271         mmc1_set_chr(machine);
12272         mmc1_set_prg(machine);
12273         if (state->m_battery || state->m_wram)
12274            wram_bank(machine, 0, (idx == STD_SOROM) ? NES_WRAM : NES_BATTERY);
12275         break;
12276      case STD_PXROM:   // mapper 9
12277         state->m_mmc_reg[0] = state->m_mmc_reg[2] = 0;
12278         state->m_mmc_reg[1] = state->m_mmc_reg[3] = 0;
12279         state->m_mmc_latch1 = state->m_mmc_latch2 = 0xfe;
12280         prg8_89(machine, 0);
12281         prg8_ab(machine, (state->m_prg_chunks << 1) - 3);
12282         prg8_cd(machine, (state->m_prg_chunks << 1) - 2);
12283         prg8_ef(machine, (state->m_prg_chunks << 1) - 1);
12284         break;
12285      case STD_FXROM: // mapper 10
12286         state->m_mmc_reg[0] = state->m_mmc_reg[2] = 0;
12287         state->m_mmc_reg[1] = state->m_mmc_reg[3] = 0;
12288         state->m_mmc_latch1 = state->m_mmc_latch2 = 0xfe;
12289         prg16_89ab(machine, 0);
12290         prg16_cdef(machine, state->m_prg_chunks - 1);
12291         break;
12292      case STD_TXROM:   // mapper 4
12293      case STD_TVROM:
12294      case STD_TKROM:
12295      case REXSOFT_DBZ5:   // mapper 12
12296      case WAIXING_TYPE_A:   // mapper 74
12297      case WAIXING_TYPE_A_1:
12298      case STD_TXSROM:   // mapper 118
12299      case STD_TQROM:   // mapper 119
12300      case WAIXING_SH2:   // mapper 165
12301      case WAIXING_TYPE_B:   // mapper 191
12302      case WAIXING_TYPE_C:   // mapper 192
12303      case WAIXING_TYPE_D:   // mapper 194
12304      case WAIXING_TYPE_E:   // mapper 195
12305      case WAIXING_TYPE_H:   // mapper 245
12306      case BTL_SUPERBROS11:   // mapper 196
12307      case UNL_H2288:      // mapper 123
12308      case UNL_KOF97:
12309      case UNL_603_5052:
12310      case NITRA_TDA:   // mapper 250
12311         if (state->m_four_screen_vram)   // only TXROM and DXROM have 4-screen mirroring
12312         {
12313            set_nt_page(machine, 0, CART_NTRAM, 0, 1);
12314            set_nt_page(machine, 1, CART_NTRAM, 1, 1);
12315            set_nt_page(machine, 2, CART_NTRAM, 2, 1);
12316            set_nt_page(machine, 3, CART_NTRAM, 3, 1);
12317         }
12318         mmc3_common_initialize(machine, 0xff, 0xff, 0);
12319         break;
12320      case STD_HKROM:   // MMC6 (basically the same as TxROM, but alt IRQ behaviour)
12321         mmc3_common_initialize(machine, 0xff, 0xff, 1);
12322         state->m_mmc6_reg = 0xf0;
12323         state->m_mmc_latch2 = 0;   // this is used differently here compared to MMC3
12324         break;
12325      case PAL_ZZ:   // mapper 37
12326         mmc3_common_initialize(machine, 0x07, 0x7f, 0);
12327         break;
12328      case NES_QJ:   // mapper 47
12329         mmc3_common_initialize(machine, 0x0f, 0x7f, 0);
12330         break;
12331      case STD_EXROM:   // mapper 5
12332         state->m_MMC5_rom_bank_mode = 3;
12333         state->m_MMC5_vrom_bank_mode = 0;
12334         state->m_MMC5_vram_protect = 0;
12335         state->m_mmc5_high_chr = 0;
12336         state->m_mmc5_vram_control = 0;
12337         state->m_mmc5_split_scr = 0;
12338         memset(state->m_MMC5_vrom_bank, 0, ARRAY_LENGTH(state->m_MMC5_vrom_bank));
12339         state->m_mmc5_prg_mode = 3;
12340         state->m_mmc5_last_chr_a = 1;
12341         state->m_mmc5_prg_regs[0] = 0xfc;
12342         state->m_mmc5_prg_regs[1] = 0xfd;
12343         state->m_mmc5_prg_regs[2] = 0xfe;
12344         state->m_mmc5_prg_regs[3] = 0xff;
12345         memset(state->m_mmc5_vrom_regA, ~0, ARRAY_LENGTH(state->m_mmc5_vrom_regA));
12346         memset(state->m_mmc5_vrom_regB, ~0, ARRAY_LENGTH(state->m_mmc5_vrom_regB));
12347         prg16_89ab(machine, state->m_prg_chunks - 2);
12348         prg16_cdef(machine, state->m_prg_chunks - 1);
12349         break;
12350      case STD_NXROM:      // mapper 68
12351      case SUNSOFT_DCS:      // mapper 68
12352         state->m_mmc_reg[0] = 0;
12353         prg16_89ab(machine, 0);
12354         prg16_cdef(machine, state->m_prg_chunks - 1);
12355         break;
12356      case NAMCOT_34X3:   // mapper 88
12357      case STD_DXROM:   // mapper 206
12358      case STD_DRROM:
12359         if (state->m_four_screen_vram)   // only TXROM and DXROM have 4-screen mirroring
12360         {
12361            set_nt_page(machine, 0, CART_NTRAM, 0, 1);
12362            set_nt_page(machine, 1, CART_NTRAM, 1, 1);
12363            set_nt_page(machine, 2, CART_NTRAM, 2, 1);
12364            set_nt_page(machine, 3, CART_NTRAM, 3, 1);
12365         }
12366      case NAMCOT_3453:   // mapper 154
12367         prg16_89ab(machine, state->m_prg_chunks - 2);
12368         prg16_cdef(machine, state->m_prg_chunks - 1);
12369         break;
12370      case NAMCOT_3446:   // mapper 76
12371         prg8_89(machine, 0);
12372         prg8_ab(machine, 1);
12373         prg16_cdef(machine, state->m_prg_chunks - 1);
12374         chr2_0(machine, 0, CHRROM);
12375         chr2_2(machine, 1, CHRROM);
12376         chr2_4(machine, 2, CHRROM);
12377         chr2_6(machine, 3, CHRROM);
12378         break;
12379      case BANDAI_JUMP2:   // mapper 153
12380         for (i = 0; i < 8; i++)
12381            state->m_mmc_reg[i] = 0;
12382         prg16_89ab(machine, 0);
12383         prg16_cdef(machine, state->m_prg_chunks - 1);
12384         fjump2_set_prg(machine);
12385         break;
12386      case BANDAI_KARAOKE:   // mapper 188
12387         prg16_89ab(machine, 0);
12388         prg16_cdef(machine, (state->m_prg_chunks - 1) ^ 0x08);
12389         break;
12390      case IREM_LROG017:   // mapper 77
12391         chr2_2(machine, 0, CHRROM);
12392         chr2_4(machine, 1, CHRROM);
12393         chr2_6(machine, 2, CHRROM);
12394         break;
12395      case IREM_TAM_S1:   // mapper 97
12396         prg16_89ab(machine, state->m_prg_chunks - 1);
12397         prg16_cdef(machine, 0);
12398         break;
12399      case KONAMI_VRC7:   // mapper 85
12400         prg8_89(machine, 0);
12401         prg8_ab(machine, 0);
12402         prg8_cd(machine, 0);
12403         prg8_ef(machine, 0xff);
12404         break;
12405      case NAMCOT_163:   // mapper 19
12406         prg16_89ab(machine, 0);
12407         prg16_cdef(machine, state->m_prg_chunks - 1);
12408         set_nt_mirroring(machine, PPU_MIRROR_VERT);
12409         break;
12410      case SUNSOFT_1:   // mapper 184
12411      case SUNSOFT_2:   // mapper 89 & 93
12412         prg16_89ab(machine, 0);
12413         prg16_cdef(machine, state->m_prg_chunks - 1);
12414         if (!state->m_hard_mirroring)
12415            set_nt_mirroring(machine, PPU_MIRROR_LOW);
12416         break;
12417
12418         // mapper 14
12419      case REXSOFT_SL1632:
12420         state->m_mmc_extra_bank[2] = 0xfe;
12421         state->m_mmc_extra_bank[3] = 0xff;
12422         state->m_mmc_extra_bank[0] = state->m_mmc_extra_bank[1] = state->m_mmc_extra_bank[4] = state->m_mmc_extra_bank[5] = state->m_mmc_extra_bank[6] = 0;
12423         state->m_mmc_extra_bank[7] = state->m_mmc_extra_bank[8] = state->m_mmc_extra_bank[9] = state->m_mmc_extra_bank[0xa] = state->m_mmc_extra_bank[0xb] = 0;
12424         state->m_mmc_reg[0] = state->m_mmc_reg[1] = 0;
12425         mmc3_common_initialize(machine, 0xff, 0xff, 0);
12426         break;
12427         // mapper 15
12428      case WAIXING_PS2:
12429         set_nt_mirroring(machine, PPU_MIRROR_VERT);
12430         break;
12431
12432         // mapper 35
12433      case UNL_SC127:
12434         // mapper 42
12435      case BTL_MARIOBABY:
12436      case BTL_AISENSHINICOL:
12437         prg32(machine, 0xff);
12438         break;
12439
12440         // mapper 40
12441      case BTL_SMB2A:
12442         prg8_67(machine, 0xfe);
12443         prg8_89(machine, 0xfc);
12444         prg8_ab(machine, 0xfd);
12445         prg8_cd(machine, 0xfe);
12446         prg8_ef(machine, 0xff);
12447         break;
12448
12449         // mapper 43
12450      case UNL_SMB2J:
12451         if (state->m_battery)
12452            memset(state->m_battery_ram, 0x2000, 0xff);
12453         else if (state->m_prg_ram)
12454            memset(state->m_wram, 0x2000, 0xff);
12455         break;
12456         // mapper 44
12457      case BMC_SUPERBIG_7IN1:
12458         // mapper 49
12459      case BMC_SUPERHIK_4IN1:
12460         mmc3_common_initialize(machine, 0x0f, 0x7f, 0);
12461         break;
12462         // mapper 45
12463      case BMC_HIK8IN1:
12464         state->m_mmc_reg[0] = state->m_mmc_reg[1] = state->m_mmc_reg[2] = state->m_mmc_reg[3] = 0;
12465         mmc3_common_initialize(machine, 0x3f, 0xff, 0);
12466         break;
12467
12468         // mapper 50
12469      case BTL_SMB2B:
12470         prg8_67(machine, 0x0f);
12471         prg8_89(machine, 0x08);
12472         prg8_ab(machine, 0x09);
12473         prg8_cd(machine, 0);
12474         prg8_ef(machine, 0x0b);
12475         break;
12476         // mapper 51
12477      case BMC_BALLGAMES_11IN1:
12478         state->m_mmc_reg[0] = 0x01;
12479         state->m_mmc_reg[1] = 0x00;
12480         bmc_ball11_set_banks(machine);
12481         break;
12482         // mapper 52
12483      case BMC_MARIOPARTY_7IN1:
12484         state->m_map52_reg_written = 0;
12485         mmc3_common_initialize(machine, 0x1f, 0xff, 0);
12486         break;
12487         // mapper 54
12488      case BMC_NOVELDIAMOND:
12489         set_nt_mirroring(machine, PPU_MIRROR_VERT);
12490         break;
12491         // mapper 57
12492      case BMC_GKA:
12493         prg16_89ab(machine, 0);
12494         prg16_cdef(machine, 0);
12495         break;
12496
12497         // mapper 64
12498      case TENGEN_800032:
12499         // mapper 158
12500      case TENGEN_800037:
12501         prg16_89ab(machine, state->m_prg_chunks - 1);
12502         prg16_cdef(machine, state->m_prg_chunks - 1);
12503         break;
12504         // mapper 71
12505      case CAMERICA_BF9097:
12506         set_nt_mirroring(machine, PPU_MIRROR_HORZ);
12507      case CAMERICA_BF9093:
12508         prg32(machine, 0xff);
12509         break;
12510
12511         // mapper 79 (& 146)
12512      case AVE_NINA06:
12513         set_nt_mirroring(machine, PPU_MIRROR_HORZ);
12514         break;
12515
12516         // mapper 83
12517      case CONY_BOARD:
12518         state->m_mapper83_reg[9] = 0x0f;
12519         prg8_cd(machine, 0x1e);
12520         prg8_ef(machine, 0x1f);
12521         break;
12522
12523         // mapper 91
12524      case UNL_MK2:
12525         set_nt_mirroring(machine, PPU_MIRROR_VERT);
12526         prg16_89ab(machine, state->m_prg_chunks - 1);
12527         prg16_cdef(machine, state->m_prg_chunks - 1);
12528         break;
12529
12530         // mapper 104
12531      case CAMERICA_GOLDENFIVE:
12532         prg16_89ab(machine, 0x00);
12533         prg16_cdef(machine, 0x0f);
12534         break;
12535         // mapper 106
12536      case BTL_SMB3:
12537         prg8_89(machine, (state->m_prg_chunks << 1) - 1);
12538         prg8_ab(machine, 0);
12539         prg8_cd(machine, 0);
12540         prg8_ef(machine, (state->m_prg_chunks << 1) - 1);
12541         break;
12542
12543         // mapper 108
12544      case WHIRLWIND_2706:
12545         prg32(machine, 0xff);
12546         break;
12547
12548         // mapper 114
12549      case SUPERGAME_LIONKING:
12550         state->m_map114_reg = state->m_map114_reg_enabled = 0;
12551         mmc3_common_initialize(machine, 0xff, 0xff, 0);
12552         break;
12553         // mapper 115
12554      case KASING_BOARD:
12555         state->m_mmc_reg[0] = 0;
12556         mmc3_common_initialize(machine, 0xff, 0xff, 0);
12557         break;
12558         // mapper 116
12559      case SOMERI_SL12:
12560         state->m_mmc_prg_base = state->m_mmc_chr_base = 0;
12561         state->m_mmc_prg_mask = 0xff;
12562         state->m_mmc_chr_mask = 0xff;
12563         state->m_mmc_cmd1 = 2; // mode
12564         state->m_mmc3_latch = 0;
12565         state->m_mmc3_wram_protect = 0;
12566         // MMC1 regs
12567         state->m_mmc1_count = 0;
12568         state->m_mmc_reg[0] = 0x0c;
12569         state->m_mmc_reg[1] = 0x00;
12570         state->m_mmc_reg[2] = 0x00;
12571         state->m_mmc_reg[3] = 0x00;
12572         // MMC3 regs
12573         state->m_mmc_prg_bank[0] = 0x3c;
12574         state->m_mmc_prg_bank[1] = 0x3d;
12575         state->m_mmc_prg_bank[2] = 0xfe;
12576         state->m_mmc_prg_bank[3] = 0xff;
12577         state->m_mmc_vrom_bank[0] = 0x00;
12578         state->m_mmc_vrom_bank[1] = 0x01;
12579         state->m_mmc_vrom_bank[2] = 0x04;
12580         state->m_mmc_vrom_bank[3] = 0x05;
12581         state->m_mmc_vrom_bank[4] = 0x06;
12582         state->m_mmc_vrom_bank[5] = 0x07;
12583         // VRC2 regs
12584         state->m_mmc_prg_bank[4] = 0x00;
12585         state->m_mmc_prg_bank[5] = 0x01;
12586         for (i = 0; i < 8; ++i)
12587            state->m_mmc_vrom_bank[6 + i] = i;
12588         someri_mode_update(machine);
12589         break;
12590
12591         // mapper 120
12592      case BTL_TOBIDASE:
12593         prg32(machine, 2);
12594         break;
12595
12596         // mapper 121
12597      case KAY_PANDAPRINCE:
12598         state->m_mmc_reg[5] = state->m_mmc_reg[6] = state->m_mmc_reg[7] = 0;
12599         mmc3_common_initialize(machine, 0xff, 0xff, 0);
12600         break;
12601
12602         // mapper 126
12603      case BMC_PJOY84:
12604         mmc3_common_initialize(machine, 0xff, 0xff, 0);
12605         state->m_mmc_reg[0] = state->m_mmc_reg[1] = state->m_mmc_reg[2] = state->m_mmc_reg[3] = 0;
12606         pjoy84_set_base_mask(machine);
12607         mmc3_set_chr(machine, state->m_mmc_chr_source, state->m_mmc_chr_base, state->m_mmc_chr_mask);
12608         mmc3_set_prg(machine, state->m_mmc_prg_base, state->m_mmc_prg_mask);
12609         break;
12610
12611         // mapper 132
12612      case TXC_22211A:
12613         // mapper 172
12614      case TXC_22211B:
12615         // mapper 173
12616      case TXC_22211C:
12617         state->m_txc_reg[0] = state->m_txc_reg[1] = state->m_txc_reg[2] = state->m_txc_reg[3] = 0;
12618         break;
12619
12620         // mapper 134
12621      case BMC_FAMILY_4646B:
12622         mmc3_common_initialize(machine, 0x1f, 0xff, 0);
12623         break;
12624
12625         // mapper 137
12626      case SACHEN_8259D:
12627         chr8(machine, state->m_chr_chunks - 1, CHRROM);
12628         set_nt_mirroring(machine, PPU_MIRROR_VERT);
12629         break;
12630         // mapper 138
12631      case SACHEN_8259B:
12632         // mapper 139
12633      case SACHEN_8259C:
12634         // mapper 141
12635      case SACHEN_8259A:
12636         // mapper 150
12637      case SACHEN_74LS374:
12638         set_nt_mirroring(machine, PPU_MIRROR_VERT);
12639         break;
12640         // mapper 143
12641      case SACHEN_TCA01:
12642         prg16_89ab(machine, 0);
12643         prg16_cdef(machine, 1);
12644         break;
12645
12646         // mapper 156
12647      case OPENCORP_DAOU306:
12648         prg16_89ab(machine, state->m_prg_chunks - 2);
12649         prg16_cdef(machine, state->m_prg_chunks - 1);
12650         set_nt_mirroring(machine, PPU_MIRROR_LOW);
12651         break;
12652         // mapper 163
12653      case NANJING_BOARD:
12654         state->m_mmc_count = 0xff;
12655         state->m_mmc_reg[0] = 0xff;
12656         state->m_mmc_reg[1] = 0;
12657         prg16_89ab(machine, state->m_prg_chunks - 2);
12658         prg16_cdef(machine, state->m_prg_chunks - 1);
12659         break;
12660         // mapper 164
12661      case WAIXING_FFV:
12662         prg16_89ab(machine, 0);
12663         prg16_cdef(machine, 0x1f);
12664         break;
12665         // mapper 166
12666      case SUBOR_TYPE1:
12667         state->m_subor_reg[0] = state->m_subor_reg[1] = state->m_subor_reg[2] = state->m_subor_reg[3] = 0;
12668         prg16_89ab(machine, 0);
12669         prg16_cdef(machine, 0x07);
12670         break;
12671         // mapper 167
12672      case SUBOR_TYPE0:
12673         state->m_subor_reg[0] = state->m_subor_reg[1] = state->m_subor_reg[2] = state->m_subor_reg[3] = 0;
12674         prg16_89ab(machine, 0);
12675         prg16_cdef(machine, 0x20);
12676         break;
12677
12678         // mapper 176
12679      case UNL_XZY:
12680         // mapper 182
12681      case HOSENKAN_BOARD:
12682         prg32(machine, (state->m_prg_chunks - 1) >> 1);
12683         break;
12684
12685      case FUKUTAKE_BOARD:   // mapper 186
12686         prg16_89ab(machine, 0);
12687         prg16_cdef(machine, 0);
12688         break;
12689
12690         // mapper 187
12691      case UNL_KOF96:
12692         state->m_mmc_reg[0] = state->m_mmc_reg[1] = state->m_mmc_reg[2] = state->m_mmc_reg[3] = 0;
12693         mmc3_common_initialize(machine, 0xff, 0xff, 0);
12694         break;
12695         // mapper 189
12696      case TXC_TW:
12697         state->m_mmc_latch1 = 0;
12698         state->m_mmc_latch2 = 0x80;
12699         state->m_mmc_chr_base = 0;
12700         state->m_mmc_chr_mask = 0xff;
12701         mmc3_set_chr(machine, state->m_mmc_chr_source, state->m_mmc_chr_base, state->m_mmc_chr_mask);
12702         break;
12703         // mapper 193
12704      case NTDEC_FIGHTINGHERO:
12705         prg32(machine, (state->m_prg_chunks - 1) >> 1);
12706         set_nt_mirroring(machine, PPU_MIRROR_VERT);
12707         break;
12708         // mapper 197
12709      case UNL_SUPERFIGHTER3:
12710         mmc3_common_initialize(machine, 0xff, 0xff, 0);
12711         unl_sf3_set_chr(machine, state->m_mmc_chr_source, state->m_mmc_chr_base, state->m_mmc_chr_mask);
12712         break;
12713         // mapper 198
12714      case WAIXING_TYPE_F:
12715         mmc3_common_initialize(machine, 0xff, 0xff, 0);
12716         state->m_mmc_prg_bank[0] = 0x00;
12717         state->m_mmc_prg_bank[1] = 0x01;
12718         state->m_mmc_prg_bank[2] = 0x4e;
12719         state->m_mmc_prg_bank[3] = 0x4f;
12720         mmc3_set_prg(machine, state->m_mmc_prg_base, state->m_mmc_prg_mask);
12721         break;
12722         // mapper 199
12723      case WAIXING_TYPE_G:
12724         mmc3_common_initialize(machine, 0xff, 0xff, 0);
12725         state->m_mmc_prg_bank[0] = 0x00;
12726         state->m_mmc_prg_bank[1] = 0x01;
12727         state->m_mmc_prg_bank[2] = 0x3e;
12728         state->m_mmc_prg_bank[3] = 0x3f;
12729         mmc3_set_prg(machine, state->m_mmc_prg_base, state->m_mmc_prg_mask);
12730         state->m_mmc_vrom_bank[0] = 0x00;
12731         state->m_mmc_vrom_bank[1] = 0x02;
12732         state->m_mmc_vrom_bank[2] = 0x04;
12733         state->m_mmc_vrom_bank[3] = 0x05;
12734         state->m_mmc_vrom_bank[4] = 0x06;
12735         state->m_mmc_vrom_bank[5] = 0x07;
12736         state->m_mmc_vrom_bank[6] = 0x01;
12737         state->m_mmc_vrom_bank[7] = 0x03;
12738         waixing_g_set_chr(machine, state->m_mmc_chr_base, state->m_mmc_chr_mask);
12739         break;
12740
12741         // mapper 200
12742      case BMC_36IN1:
12743         prg16_89ab(machine, state->m_prg_chunks - 1);
12744         prg16_cdef(machine, state->m_prg_chunks - 1);
12745         break;
12746
12747         // mapper 202
12748      case BMC_150IN1:
12749         // mapper 203
12750      case BMC_35IN1:
12751         // mapper 204
12752      case BMC_64IN1:
12753         // mapper 214
12754      case BMC_SUPERGUN_20IN1:
12755         prg16_89ab(machine, 0);
12756         prg16_cdef(machine, 0);
12757         break;
12758         // mapper 205
12759      case BMC_15IN1:
12760         mmc3_common_initialize(machine, 0x1f, 0xff, 0);
12761         state->m_mmc_prg_base = 0x10;   // this board has a diff prg_base
12762         mmc3_set_prg(machine, state->m_mmc_prg_base, state->m_mmc_prg_mask);
12763         break;
12764
12765         // mapper 208
12766      case GOUDER_37017:
12767         state->m_mmc_reg[0] = state->m_mmc_reg[1] = state->m_mmc_reg[2] = state->m_mmc_reg[3] = state->m_mmc_reg[4] = 0;
12768         mmc3_common_initialize(machine, 0xff, 0xff, 0);
12769         break;
12770         // mapper 212
12771      case BMC_SUPERHIK_300IN1:
12772         chr8(machine, 0xff, CHRROM);
12773         prg32(machine, 0xff);
12774         break;
12775
12776         // mapper 215
12777      case SUPERGAME_BOOGERMAN:
12778         state->m_mmc_reg[0] = 0x00;
12779         state->m_mmc_reg[1] = 0xff;
12780         state->m_mmc_reg[2] = 0x04;
12781         state->m_mmc_reg[3] = 0;
12782         mmc3_common_initialize(machine, 0x1f, 0xff, 0);
12783         sgame_boog_set_prg(machine);
12784         mmc3_set_chr(machine, state->m_mmc_chr_source, state->m_mmc_chr_base, state->m_mmc_chr_mask);
12785         break;
12786
12787         // mapper 217
12788      case BMC_GOLDENCARD_6IN1:
12789         mmc3_common_initialize(machine, 0xff, 0xff, 0);
12790         state->m_mmc_reg[0] = 0x00;
12791         state->m_mmc_reg[1] = 0xff;
12792         state->m_mmc_reg[2] = 0x03;
12793         state->m_mmc_reg[3] = 0;
12794         bmc_gc6in1_set_prg(machine, state->m_mmc_prg_base, state->m_mmc_prg_mask);
12795         bmc_gc6in1_set_chr(machine, state->m_mmc_chr_source);
12796         break;
12797         // mapper 221
12798      case UNL_N625092:
12799         prg16_89ab(machine, 0);
12800         prg16_cdef(machine, 0);
12801         break;
12802
12803         // mapper 223?
12804      case WAIXING_TYPE_I:
12805         mmc3_common_initialize(machine, 0xff, 0xff, 0);
12806         state->m_mmc3_wram_protect = 0;
12807         break;
12808
12809         // mapper 224?
12810      case WAIXING_TYPE_J:
12811         mmc3_common_initialize(machine, 0xff, 0xff, 0);
12812         state->m_mmc_prg_bank[0] = 0x01;
12813         state->m_mmc_prg_bank[1] = 0x02;
12814         state->m_mmc_prg_bank[2] = 0x7e;
12815         state->m_mmc_prg_bank[3] = 0x7f;
12816         mmc3_set_prg(machine, state->m_mmc_prg_base, state->m_mmc_prg_mask);
12817         break;
12818
12819         // mapper 227
12820      case BMC_1200IN1:
12821         prg16_89ab(machine, 0);
12822         prg16_cdef(machine, 0);
12823         break;
12824
12825         // mapper 229
12826      case BMC_31IN1:
12827         prg16_89ab(machine, 0);
12828         prg16_cdef(machine, 1);
12829         set_nt_mirroring(machine, PPU_MIRROR_VERT);
12830         break;
12831         // mapper 230
12832      case BMC_22GAMES:
12833         prg16_89ab(machine, 0);
12834         prg16_cdef(machine, 7);
12835         break;
12836         // mapper 231
12837      case BMC_20IN1:
12838         prg16_89ab(machine, 0);
12839         prg16_cdef(machine, state->m_prg_chunks - 1);
12840         set_nt_mirroring(machine, PPU_MIRROR_VERT);
12841         break;
12842         // mapper 232
12843      case CAMERICA_BF9096:
12844         state->m_mmc_latch1 = 0x18;
12845         state->m_mmc_latch2 = 0x00;
12846         bf9096_set_prg(machine);
12847         break;
12848
12849         // mapper 243
12850      case SACHEN_74LS374_A:
12851         state->m_mmc_vrom_bank[0] = 3;
12852         chr8(machine, 3, CHRROM);
12853         set_nt_mirroring(machine, PPU_MIRROR_VERT);
12854         break;
12855
12856         // mapper 246
12857      case CNE_FSB:
12858         prg32(machine, 0xff);
12859         break;
12860         // mapper 249
12861      case WAIXING_SECURITY:
12862         state->m_mmc_reg[0] = 0;
12863         mmc3_common_initialize(machine, 0xff, 0xff, 0);
12864         break;
12865
12866         // mapper 254
12867      case BTL_PIKACHUY2K:
12868         state->m_mmc_reg[0] = 0xff;
12869         mmc3_common_initialize(machine, 0xff, 0xff, 0);
12870         break;
12871
12872         // mapper 255
12873      case BMC_110IN1:
12874         prg16_89ab(machine, 0);
12875         prg16_cdef(machine, 1);
12876         set_nt_mirroring(machine, PPU_MIRROR_VERT);
12877         break;
12878
12879         // UNIF only
12880      case BMC_64IN1NR:
12881         state->m_mmc_reg[0] = 0x80;
12882         state->m_mmc_reg[1] = 0x43;
12883         state->m_mmc_reg[2] = state->m_mmc_reg[3] = 0;
12884         bmc_64in1nr_set_prg(machine);
12885         set_nt_mirroring(machine, PPU_MIRROR_VERT);
12886         break;
12887      case BMC_190IN1:
12888         prg16_89ab(machine, 0);
12889         prg16_cdef(machine, 0);
12890         break;
12891      case BMC_A65AS:
12892         prg16_89ab(machine, 0);
12893         prg16_cdef(machine, 7);
12894         set_nt_mirroring(machine, PPU_MIRROR_VERT);
12895         break;
12896      case BMC_GS2004:
12897      case BMC_GS2013:
12898         prg32(machine, 0xff);
12899         break;
12900      case BMC_S24IN1SC03:
12901         state->m_mmc_reg[0] = 0x24;
12902         state->m_mmc_reg[1] = 0x9f;
12903         state->m_mmc_reg[2] = 0;
12904         mmc3_common_initialize(machine, 0xff, 0xff, 0);
12905         break;
12906      case BMC_T262:
12907         state->m_mmc_latch1 = 0;
12908         state->m_mmc_latch2 = 0;
12909         prg16_89ab(machine, 0);
12910         prg16_cdef(machine, 7);
12911         break;
12912      case DREAMTECH_BOARD:
12913         prg16_89ab(machine, 0);
12914         prg16_cdef(machine, 8);
12915         break;
12916      case UNL_8237:
12917         state->m_mmc_reg[0] = state->m_mmc_reg[1] = state->m_mmc_reg[2] = 0;
12918         mmc3_common_initialize(machine, 0xff, 0xff, 0);
12919         break;
12920      case UNL_AX5705:
12921         state->m_mmc_prg_bank[0] = 0;
12922         state->m_mmc_prg_bank[1] = 1;
12923         prg8_89(machine, state->m_mmc_prg_bank[0]);
12924         prg8_ab(machine, state->m_mmc_prg_bank[1]);
12925         prg8_cd(machine, 0xfe);
12926         prg8_ef(machine, 0xff);
12927         break;
12928      case UNL_RACERMATE:
12929         chr4_0(machine, 0, state->m_mmc_chr_source);
12930         chr4_4(machine, 0, state->m_mmc_chr_source);
12931         prg16_89ab(machine, 0);
12932         prg16_cdef(machine, state->m_prg_chunks - 1);
12933         break;
12934
12935      case BMC_BENSHENG_BS5:
12936         state->m_mmc_prg_bank[0] = 0xff;
12937         state->m_mmc_prg_bank[1] = 0xff;
12938         state->m_mmc_prg_bank[2] = 0xff;
12939         state->m_mmc_prg_bank[3] = 0xff;
12940         bmc_bs5_update_banks(machine);
12941         break;
12942
12943      case BMC_810544:
12944         prg16_89ab(machine, 0);
12945         prg16_cdef(machine, 0);
12946         set_nt_mirroring(machine, PPU_MIRROR_VERT);
12947         break;
12948
12949      case BMC_G63IN1:
12950         bmc_gb63_update(machine);
12951         break;
12952
12953      case BMC_FK23C:
12954         state->m_mmc_reg[0] = 4;
12955         state->m_mmc_reg[1] = 0xff;
12956         state->m_mmc_reg[2] = state->m_mmc_reg[3] = 0;
12957         state->m_mmc_reg[4] = state->m_mmc_reg[5] = state->m_mmc_reg[6] = state->m_mmc_reg[7] = 0xff;
12958         mmc3_common_initialize(machine, 0xff, 0xff, 0);
12959         fk23c_set_prg(machine);
12960         fk23c_set_chr(machine);
12961         break;
12962
12963      case BMC_FK23CA:
12964         state->m_mmc_reg[0] = state->m_mmc_reg[1] = state->m_mmc_reg[2] = state->m_mmc_reg[3] = 0;
12965         state->m_mmc_reg[4] = state->m_mmc_reg[5] = state->m_mmc_reg[6] = state->m_mmc_reg[7] = 0xff;
12966         mmc3_common_initialize(machine, 0xff, 0xff, 0);
12967         fk23c_set_prg(machine);
12968         fk23c_set_chr(machine);
12969         break;
12970
12971
12972      case FFE_MAPPER6:
12973         prg16_89ab(machine, 0);
12974         prg16_cdef(machine, 7);
12975         break;
12976      case FFE_MAPPER8:
12977         prg32(machine, 0);
12978         break;
12979      case FFE_MAPPER17:
12980         prg16_89ab(machine, 0);
12981         prg16_cdef(machine, state->m_prg_chunks - 1);
12982         break;
12983
12984      case UNSUPPORTED_BOARD:
12985      default:
12986         /* Mapper not supported */
12987         err = 2;
12988         break;
12989   }
12990
12991   return err;
12992}
12993
12994/*************************************************************
12995
12996 nes_pcb_reset
12997
12998 Resets the mmc bankswitch areas to their defaults.
12999 It returns a value "err" that indicates if it was
13000 successful. Possible values for err are:
13001
13002 0 = success
13003 1 = no pcb found
13004 2 = pcb not supported
13005
13006 *************************************************************/
13007
13008int nes_pcb_reset( running_machine &machine )
13009{
13010   nes_state *state = machine.driver_data<nes_state>();
13011   int err = 0;
13012   const nes_pcb_intf *intf = nes_pcb_intf_lookup(state->m_pcb_id);
13013
13014   if (intf == NULL)
13015      fatalerror("Missing PCB interface\n");
13016
13017   /* Set the mapper irq callback */
13018   ppu2c0x_set_scanline_callback(state->m_ppu, intf ? intf->mmc_scanline : NULL);
13019   ppu2c0x_set_hblank_callback(state->m_ppu, intf ? intf->mmc_hblank : NULL);
13020
13021   err = pcb_initialize(machine, state->m_pcb_id);
13022
13023   return err;
13024}
src/mame/machine/aescart.c
r11531r11532
1/**********************************************************************
2
3    aescart.c
4
5    Neo-Geo AES cartridge management
6    R. Belmont, 2009
7
8    Based on ti99cart.c by Michael Zapf
9
10    We leave the support in place for multiple slots in case MAME
11    uses this at some future point for MVS multi-cart.
12
13*********************************************************************/
14#include "emu.h"
15#include "aescart.h"
16#include "imagedev/cartslot.h"
17#include "imagedev/multcart.h"
18#include "includes/neogeo.h"
19
20typedef int assmfct(running_machine &machine, device_t *);
21
22enum
23{
24   AESCART_FCT_ASSM = DEVINFO_FCT_DEVICE_SPECIFIC,
25   AESCART_FCT_DISASSM
26};
27
28struct _aes_multicart_t
29{
30   /* Reserves space for all cartridges. This is also used in the legacy
31       cartridge system, but only for slot 0. */
32   aescartridge_t cartridge[AES_NUMBER_OF_CARTRIDGE_SLOTS];
33
34   /* Determines which slot is currently active. This value is changed when there
35    are accesses to other GROM base addresses. */
36   int active_slot;
37
38   /* Used in order to enforce a special slot. This value is retrieved
39       from the dipswitch setting. A value of -1 means automatic, that is,
40       the grom base switch is used. Values 0 .. max refer to the
41       respective slot. */
42   int fixed_slot;
43
44   /* Holds the highest index of a cartridge being plugged in plus one.
45       If we only have one cartridge inserted, we don't want to get a
46       selection option, so we just mirror the memory contents. */
47   int next_free_slot;
48
49   /* Counts the number of slots which currently contain legacy format
50       cartridge images. */
51   int legacy_slots;
52
53   /* Counts the number of slots which currently contain new format
54       cartridge images. */
55   int multi_slots;
56};
57typedef struct _aes_multicart_t aes_multicart_t;
58
59#define AUTO -1
60
61/* Access to the pcb. Contained in the token of the pcb instance. */
62struct _aes_pcb_t
63{
64   /* Link up to the cartridge structure which contains this pcb. */
65   aescartridge_t *cartridge;
66
67   /* Function to assemble this cartridge. */
68   assmfct   *assemble;
69
70   /* Function to disassemble this cartridge. */
71   assmfct   *disassemble;
72};
73typedef struct _aes_pcb_t aes_pcb_t;
74
75INLINE aes_multicart_t *get_safe_token(device_t *device)
76{
77   assert(device != NULL);
78   assert(device->type() == AES_MULTICART);
79
80   return (aes_multicart_t *)downcast<legacy_device_base *>(device)->token();
81}
82
83INLINE aes_pcb_t *get_safe_pcb_token(device_t *device)
84{
85   assert(device != NULL);
86   assert(device->type() == AES_CARTRIDGE_PCB_NONE || device->type() == AES_CARTRIDGE_PCB_STD);
87
88   return (aes_pcb_t *)downcast<legacy_device_base *>(device)->token();
89}
90
91INLINE cartslot_t *get_safe_cartslot_token(device_t *device)
92{
93   assert(device != NULL);
94   assert(device->type() == CARTSLOT);
95
96   return (cartslot_t *)downcast<legacy_device_base *>(device)->token();
97}
98
99/*
100    Find the index of the cartridge name. We assume the format
101    <name><number>, i.e. the number is the longest string from the right
102    which can be interpreted as a number.
103*/
104static int get_index_from_tagname(device_t *image)
105{
106   const char *tag = image->tag();
107   int maxlen = strlen(tag);
108   int i;
109   for (i=maxlen-1; i >=0; i--)
110      if (tag[i] < 48 || tag[i] > 57) break;
111
112   return atoi(tag+i+1);
113}
114
115/*
116    Common routine to assemble cartridges from resources.
117*/
118static aescartridge_t *assemble_common(running_machine &machine, device_t *cartslot)
119{
120   /* Pointer to the cartridge structure. */
121   aescartridge_t *cartridge;
122   device_t *cartsys = cartslot->owner();
123   aes_multicart_t *cartslots = get_safe_token(cartsys);
124   UINT8 *socketcont, *romrgn;
125   int reslength, i, blockofs;
126   char sprname1[16], sprname2[16];
127
128   int slotnumber = get_index_from_tagname(cartslot)-1;
129   assert(slotnumber>=0 && slotnumber<AES_NUMBER_OF_CARTRIDGE_SLOTS);
130
131   /* There is a cartridge in this slot, check the maximum slot number. */
132   if (cartslots->next_free_slot <= slotnumber)
133   {
134      cartslots->next_free_slot = slotnumber+1;
135   }
136   cartridge = &cartslots->cartridge[slotnumber];
137
138   // check for up to 4 program ROMs
139   romrgn = (UINT8 *)machine.region("maincpu")->base();
140   blockofs = 0;
141   for (i = 0; i < 4; i++)
142   {
143      sprintf(sprname1, "p%d", i+1);
144
145      socketcont = (UINT8*)cartslot_get_socket(cartslot, sprname1);
146      reslength = cartslot_get_resource_length(cartslot, sprname1);
147
148      if (socketcont != NULL)
149      {
150         memcpy(romrgn+blockofs, socketcont, reslength);
151         blockofs += reslength;
152      }
153   }
154
155   // 1 m1 ROM
156   socketcont = (UINT8*)cartslot_get_socket(cartslot, "m1");
157   reslength = cartslot_get_resource_length(cartslot, "m1");
158   if (socketcont != NULL)
159   {
160      romrgn = (UINT8 *)machine.region("audiocpu")->base();
161
162      memcpy(romrgn, socketcont, reslength);
163      // mirror (how does this really work?)
164      memcpy(romrgn+0x10000, socketcont, reslength);
165   }
166
167   // up to 8 YM sample ROMs
168   romrgn = (UINT8 *)machine.region("ymsnd")->base();
169   blockofs = 0;
170   for (i = 0; i < 8; i++)
171   {
172      sprintf(sprname1, "v1%d", i+1);
173
174      socketcont = (UINT8*)cartslot_get_socket(cartslot, sprname1);
175      reslength = cartslot_get_resource_length(cartslot, sprname1);
176
177      if (socketcont != NULL)
178      {
179         memcpy(romrgn+blockofs, socketcont, reslength);
180         blockofs += reslength;
181      }
182   }
183
184   // up to 8 YM delta-T sample ROMs
185   romrgn = (UINT8 *)machine.region("ymsnd.deltat")->base();
186   blockofs = 0;
187   for (i = 0; i < 8; i++)
188   {
189      sprintf(sprname1, "v2%d", i+1);
190
191      socketcont = (UINT8*)cartslot_get_socket(cartslot, sprname1);
192      reslength = cartslot_get_resource_length(cartslot, sprname1);
193
194      if (socketcont != NULL)
195      {
196         memcpy(romrgn+blockofs, socketcont, reslength);
197         blockofs += reslength;
198      }
199   }
200
201   // 1 s1 ROM
202   socketcont = (UINT8*)cartslot_get_socket(cartslot, "s1");
203   reslength = cartslot_get_resource_length(cartslot, "s1");
204   if (socketcont != NULL)
205   {
206      romrgn = (UINT8 *)machine.region("fixed")->base();
207
208      memcpy(romrgn, socketcont, reslength);
209   }
210
211   // up to 8 sprite ROMs in byte-interleaved pairs
212   romrgn = (UINT8 *)machine.region("sprites")->base();
213   blockofs = 0;
214   for (i = 0; i < 8; i+=2)
215   {
216      UINT8 *spr1, *spr2;
217      int j;
218
219      sprintf(sprname1, "c%d", i+1);
220      sprintf(sprname2, "c%d", i+2);
221
222      spr1 = (UINT8*)cartslot_get_socket(cartslot, sprname1);
223      spr2 = (UINT8*)cartslot_get_socket(cartslot, sprname2);
224      reslength = cartslot_get_resource_length(cartslot, sprname1);
225
226      if ((spr1) && (spr2))
227      {
228         for (j = 0; j < reslength; j++)
229         {
230            romrgn[blockofs + (j*2)] = spr1[j];
231            romrgn[blockofs + (j*2) + 1] = spr2[j];
232         }
233
234         blockofs += reslength*2;
235      }
236   }
237
238   return cartridge;
239}
240
241static void set_pointers(device_t *pcb, int index)
242{
243   device_t *cartsys = pcb->owner()->owner();
244   aes_multicart_t *cartslots = get_safe_token(cartsys);
245   aes_pcb_t *pcb_def = get_safe_pcb_token(pcb);
246
247   pcb_def->assemble = (assmfct *)downcast<const legacy_cart_slot_device_base *>(pcb)->get_legacy_fct(AESCART_FCT_ASSM);
248   pcb_def->disassemble = (assmfct *)downcast<const legacy_cart_slot_device_base *>(pcb)->get_legacy_fct(AESCART_FCT_DISASSM);
249
250   pcb_def->cartridge = &cartslots->cartridge[index];
251   pcb_def->cartridge->pcb = pcb;
252}
253
254/*****************************************************************************
255  Cartridge type: None
256    This PCB device is just a pseudo device; the legacy mode is handled
257    by dedicated functions.
258******************************************************************************/
259static DEVICE_START(aes_pcb_none)
260{
261   /* device is aes_cartslot:cartridge:pcb */
262//  printf("DEVICE_START(aes_pcb_none), tag of device=%s\n", device->tag());
263   set_pointers(device, get_index_from_tagname(device->owner())-1);
264}
265
266/*****************************************************************************
267  Cartridge type: Standard
268    Most cartridges are built in this type. This includes word-swapped program,
269    z80 program, YM samples, delta-T samples, sprites, and sfix.
270******************************************************************************/
271
272static DEVICE_START(aes_pcb_std)
273{
274   /* device is aes_cartslot:cartridge:pcb */
275//  printf("DEVICE_START(aes_pcb_std), tag of device=%s\n", device->tag());
276   set_pointers(device, get_index_from_tagname(device->owner())-1);
277}
278
279/*
280    The standard cartridge assemble routine. We just call the common
281    function here.
282*/
283static int assemble_std(running_machine &machine, device_t *image)
284{
285//  aescartridge_t *cart;
286//  printf("assemble_std, %s\n", image->tag);
287   /*cart = */assemble_common(machine, image);
288
289   return IMAGE_INIT_PASS;
290}
291
292/*
293    Removes pointers and restores the state before plugging in the
294    cartridge.
295    The pointer to the location after the last cartridge is adjusted.
296    As it seems, we can use the same function for the disassembling of all
297    cartridge types.
298*/
299static int disassemble_std(device_t *image)
300{
301//  int slotnumber;
302//  int i;
303//  aescartridge_t *cart;
304//  device_t *cartsys = image->owner();
305//  aes_multicart_t *cartslots = (aes_multicart_t *)cartsys->token;
306
307//  slotnumber = get_index_from_tagname(image)-1;
308//  printf("Disassemble cartridge %d\n", slotnumber);
309#if 0
310   /* Search the highest remaining cartridge. */
311   cartslots->next_free_slot = 0;
312   for (i=AES_NUMBER_OF_CARTRIDGE_SLOTS-1; i >= 0; i--)
313   {
314      if (i != slotnumber)
315      {
316         if (0) //!slot_is_empty(cartsys, i))    (for future use?)
317         {
318            cartslots->next_free_slot = i+1;
319//              printf("Setting new next_free_slot to %d\n", cartslots->next_free_slot);
320            break;
321         }
322      }
323   }
324#endif
325   /* Do we have RAM? If so, swap the bytes (undo the BIG_ENDIANIZE) */
326//  cart = &cartslots->cartridge[slotnumber];
327
328//  clear_slot(cartsys, slotnumber);
329
330   return IMAGE_INIT_PASS;
331}
332
333/*****************************************************************************
334  Device metadata
335******************************************************************************/
336
337static DEVICE_GET_INFO(aes_cart_common)
338{
339   switch(state)
340   {
341      /* --- the following bits of info are returned as 64-bit signed integers --- */
342      case DEVINFO_INT_TOKEN_BYTES:
343         info->i = sizeof(aes_pcb_t);
344         break;
345      case DEVINFO_INT_INLINE_CONFIG_BYTES:
346         info->i = 0;
347         break;
348
349      /* --- the following bits of info are returned as pointers to functions --- */
350      case DEVINFO_FCT_START:
351         info->start = DEVICE_START_NAME(aes_pcb_std);
352         break;
353      case DEVINFO_FCT_STOP:
354         /* Nothing */
355         break;
356      case DEVINFO_FCT_RESET:
357         /* Nothing */
358         break;
359
360      case AESCART_FCT_ASSM:
361         info->f = (genf *) assemble_std;
362         break;
363
364      case AESCART_FCT_DISASSM:
365         info->f = (genf *) disassemble_std;
366         break;
367
368      /* --- the following bits of info are returned as NULL-terminated strings --- */
369      case DEVINFO_STR_NAME:
370         strcpy(info->s, "AES standard cartridge pcb");
371         break;
372      case DEVINFO_STR_FAMILY:
373         strcpy(info->s, "AES cartridge pcb");
374         break;
375      case DEVINFO_STR_VERSION:
376         strcpy(info->s, "1.0");
377         break;
378      case DEVINFO_STR_SOURCE_FILE:
379         strcpy(info->s, __FILE__);
380         break;
381      case DEVINFO_STR_CREDITS:
382         /* Nothing */
383         break;
384   }
385}
386
387DEVICE_GET_INFO(aes_cartridge_pcb_none)
388{
389   switch(state)
390   {
391      case DEVINFO_FCT_START:
392         info->start = DEVICE_START_NAME(aes_pcb_none);
393         break;
394
395      case DEVINFO_STR_NAME:
396         strcpy(info->s, "AES empty cartridge");
397         break;
398
399      default:
400         DEVICE_GET_INFO_CALL(aes_cart_common);
401         break;
402   }
403}
404
405DEVICE_GET_INFO(aes_cartridge_pcb_std)
406{
407   DEVICE_GET_INFO_CALL(aes_cart_common);
408}
409
410/*****************************************************************************
411  The cartridge handling of the multi-cartridge system.
412  Every cartridge contains a PCB device. The memory handlers delegate the calls
413  to the respective handlers of the cartridges.
414******************************************************************************/
415/*
416    Initialize a cartridge. Each cartridge contains a PCB device.
417*/
418static DEVICE_START( aes_cartridge )
419{
420   cartslot_t *cart = get_safe_cartslot_token(device);
421
422   /* find the PCB device */
423   cart->pcb_device = device->subdevice(TAG_PCB);
424}
425
426// handle protected carts
427static void install_protection(device_image_interface& image)
428{
429   neogeo_state *state = image.device().machine().driver_data<neogeo_state>();
430   const char *crypt_feature = image.get_feature( "crypt" );
431
432   if(crypt_feature == NULL)
433      return;
434
435   if(strcmp(crypt_feature,"fatfury2_prot") == 0)
436   {
437      fatfury2_install_protection(image.device().machine());
438      logerror("Installed Fatal Fury 2 protection\n");
439   }
440   if(strcmp(crypt_feature,"kof99_crypt") == 0)
441   {
442      kof99_decrypt_68k(image.device().machine());
443      state->m_fixed_layer_bank_type = 1;
444      kof99_neogeo_gfx_decrypt(image.device().machine(), 0x00);
445      kof99_install_protection(image.device().machine());
446      logerror("Decrypted KOF99 code and graphics.\n");
447   }
448   if(strcmp(crypt_feature,"mslug3_crypt") == 0)
449   {
450      state->m_fixed_layer_bank_type = 1;
451      kof99_neogeo_gfx_decrypt(image.device().machine(), 0xad);
452      logerror("Decrypted Metal Slug 3 graphics\n");
453   }
454   if(strcmp(crypt_feature,"matrim_crypt") == 0)
455   {
456      matrim_decrypt_68k(image.device().machine());
457      neo_pcm2_swap(image.device().machine(), 1);
458      state->m_fixed_layer_bank_type = 2;
459      neogeo_cmc50_m1_decrypt(image.device().machine());
460      kof2000_neogeo_gfx_decrypt(image.device().machine(), 0x6a);
461      logerror("Decrypted Matrimelee code, sound and graphics\n");
462   }
463   if(strcmp(crypt_feature,"svc_crypt") == 0)
464   {
465      svc_px_decrypt(image.device().machine());
466      neo_pcm2_swap(image.device().machine(), 3);
467      state->m_fixed_layer_bank_type = 2;
468      neogeo_cmc50_m1_decrypt(image.device().machine());
469      kof2000_neogeo_gfx_decrypt(image.device().machine(), 0x57);
470      install_pvc_protection(image.device().machine());
471      logerror("Decrypted SvC code, sound and graphics.\n");
472   }
473   if(strcmp(crypt_feature,"samsho5_crypt") == 0)
474   {
475      samsho5_decrypt_68k(image.device().machine());
476      neo_pcm2_swap(image.device().machine(), 4);
477      state->m_fixed_layer_bank_type = 1;
478      neogeo_cmc50_m1_decrypt(image.device().machine());
479      kof2000_neogeo_gfx_decrypt(image.device().machine(), 0x0f);
480      logerror("Decrypted Samurai Shodown V code, sound and graphics.\n");
481   }
482   if(strcmp(crypt_feature,"kof2000_crypt") == 0)
483   {
484      kof2000_decrypt_68k(image.device().machine());
485      state->m_fixed_layer_bank_type = 2;
486      neogeo_cmc50_m1_decrypt(image.device().machine());
487      kof2000_neogeo_gfx_decrypt(image.device().machine(), 0x00);
488      kof2000_install_protection(image.device().machine());
489      logerror("Decrypted KOF2000 code, sound and graphics.\n");
490   }
491   if(strcmp(crypt_feature,"kof2001_crypt") == 0)
492   {
493      state->m_fixed_layer_bank_type = 1;
494      kof2000_neogeo_gfx_decrypt(image.device().machine(), 0x1e);
495      neogeo_cmc50_m1_decrypt(image.device().machine());
496      logerror("Decrypted KOF2001 code and graphics.\n");
497   }
498   if(strcmp(crypt_feature,"kof2002_crypt") == 0)
499   {
500      kof2002_decrypt_68k(image.device().machine());
501      neo_pcm2_swap(image.device().machine(), 0);
502      neogeo_cmc50_m1_decrypt(image.device().machine());
503      kof2000_neogeo_gfx_decrypt(image.device().machine(), 0xec);
504      logerror("Decrypted KOF2002 code, sound and graphics.\n");
505   }
506   if(strcmp(crypt_feature,"mslug4_crypt") == 0)
507   {
508      state->m_fixed_layer_bank_type = 1; /* USA violent content screen is wrong -- not a bug, confirmed on real hardware! */
509      neogeo_cmc50_m1_decrypt(image.device().machine());
510      kof2000_neogeo_gfx_decrypt(image.device().machine(), 0x31);
511      neo_pcm2_snk_1999(image.device().machine(), 8);
512      logerror("Decrypted Metal Slug 4 code, sound and graphics.\n");
513   }
514   if(strcmp(crypt_feature,"mslug5_crypt") == 0)
515   {
516      mslug5_decrypt_68k(image.device().machine());
517      neo_pcm2_swap(image.device().machine(), 2);
518      state->m_fixed_layer_bank_type = 1;
519      neogeo_cmc50_m1_decrypt(image.device().machine());
520      kof2000_neogeo_gfx_decrypt(image.device().machine(), 0x19);
521      install_pvc_protection(image.device().machine());
522      logerror("Decrypted Metal Slug 5 code and graphics, and installed protection routines.\n");
523   }
524   if(strcmp(crypt_feature,"kof2003_crypt") == 0)
525   {
526      kof2003h_decrypt_68k(image.device().machine());
527      neo_pcm2_swap(image.device().machine(), 5);
528      state->m_fixed_layer_bank_type = 2;
529      neogeo_cmc50_m1_decrypt(image.device().machine());
530      kof2000_neogeo_gfx_decrypt(image.device().machine(), 0x9d);
531      install_pvc_protection(image.device().machine());
532      logerror("Decrypted KOF2003 code and graphicss, and installed protection routines.\n");
533   }
534   if(strcmp(crypt_feature,"samsho5s_crypt") == 0)
535   {
536      samsh5sp_decrypt_68k(image.device().machine());
537      neo_pcm2_swap(image.device().machine(), 6);
538      state->m_fixed_layer_bank_type = 1;
539      neogeo_cmc50_m1_decrypt(image.device().machine());
540      kof2000_neogeo_gfx_decrypt(image.device().machine(), 0x0d);
541   }
542}
543
544/*
545    Load the cartridge image files. Apart from reading, we set pointers
546    to the image files so that during runtime we do not need search
547    operations.
548*/
549static DEVICE_IMAGE_LOAD( aes_cartridge )
550{
551   device_t *pcbdev = cartslot_get_pcb(image);
552   aes_pcb_t *pcb;
553   cartslot_t *cart;
554   multicart_open_error me;
555   UINT32 size;
556   device_t* ym = image.device().machine().device("ymsnd");
557
558   // first check software list
559   if(image.software_entry() != NULL)
560   {
561      // create memory regions
562      size = image.get_software_region_length("maincpu");
563      image.device().machine().region_free("maincpu");
564      image.device().machine().region_alloc("maincpu",size,1, ENDIANNESS_LITTLE);
565      memcpy(image.device().machine().region("maincpu")->base(),image.get_software_region("maincpu"),size);
566      size = image.get_software_region_length("fixed");
567      image.device().machine().region_free("fixed");
568      image.device().machine().region_alloc("fixed",size,1, ENDIANNESS_LITTLE);
569      memcpy(image.device().machine().region("fixed")->base(),image.get_software_region("fixed"),size);
570      size = image.get_software_region_length("audiocpu");
571      image.device().machine().region_free("audiocpu");
572      image.device().machine().region_alloc("audiocpu",size,1, ENDIANNESS_LITTLE);
573      memcpy(image.device().machine().region("audiocpu")->base(),image.get_software_region("audiocpu"),size);
574      size = image.get_software_region_length("ymsnd");
575      image.device().machine().region_free("ymsnd");
576      image.device().machine().region_alloc("ymsnd",size,1, ENDIANNESS_LITTLE);
577      memcpy(image.device().machine().region("ymsnd")->base(),image.get_software_region("ymsnd"),size);
578      if(image.get_software_region("ymsnd.deltat") != NULL)
579      {
580         size = image.get_software_region_length("ymsnd.deltat");
581         image.device().machine().region_free("ymsnd.deltat");
582         image.device().machine().region_alloc("ymsnd.deltat",size,1, ENDIANNESS_LITTLE);
583         memcpy(image.device().machine().region("ymsnd.deltat")->base(),image.get_software_region("ymsnd.deltat"),size);
584      }
585      else
586         image.device().machine().region_free("ymsnd.deltat");  // removing the region will fix sound glitches in non-Delta-T games
587      ym->reset();
588      size = image.get_software_region_length("sprites");
589      image.device().machine().region_free("sprites");
590      image.device().machine().region_alloc("sprites",size,1, ENDIANNESS_LITTLE);
591      memcpy(image.device().machine().region("sprites")->base(),image.get_software_region("sprites"),size);
592      if(image.get_software_region("audiocrypt") != NULL)  // encrypted Z80 code
593      {
594         size = image.get_software_region_length("audiocrypt");
595         image.device().machine().region_alloc("audiocrypt",size,1, ENDIANNESS_LITTLE);
596         memcpy(image.device().machine().region("audiocrypt")->base(),image.get_software_region("audiocrypt"),size);
597      }
598
599      // setup cartridge ROM area
600      image.device().machine().device("maincpu")->memory().space(AS_PROGRAM)->install_read_bank(0x000080,0x0fffff,"cart_rom");
601      memory_set_bankptr(image.device().machine(),"cart_rom",&image.device().machine().region("maincpu")->base()[0x80]);
602
603      // handle possible protection
604      install_protection(image);
605
606      return IMAGE_INIT_PASS;
607   }
608
609   if (pcbdev == NULL)
610      fatalerror("Error loading multicart: no pcb found.");
611
612   /* If we are here, we have a multicart. */
613   pcb = get_safe_pcb_token(pcbdev);
614   cart = get_safe_cartslot_token(&image.device());
615
616   /* try opening this as a multicart */
617   /* This line requires that cartslot_t be included in cartslot.h,
618    otherwise one cannot make use of multicart handling within such a
619    custom LOAD function. */
620   me = multicart_open(image.device().machine().options(), image.filename(), image.device().machine().system().name, MULTICART_FLAGS_LOAD_RESOURCES, &cart->mc);
621
622   /* Now that we have loaded the image files, let the PCB put them all
623    together. This means we put the images in a structure which allows
624    for a quick access by the memory handlers. Every PCB defines an
625    own assembly method. */
626    if (me != MCERR_NONE)
627      fatalerror("Error loading multicart: %s", multicart_error_text(me));
628
629   return pcb->assemble(pcbdev->machine(), image);
630}
631
632/*
633    This is called when the cartridge is unplugged (or the emulator is
634    stopped).
635*/
636static DEVICE_IMAGE_UNLOAD( aes_cartridge )
637{
638   device_t *pcbdev;
639
640   if (downcast<legacy_device_base *>(&image.device())->token() == NULL)
641   {
642      /* This means something went wrong during the pcb
643           identification (e.g. one of the cartridge files was not
644           found). We do not need to (and cannot) unload
645           the cartridge. */
646      return;
647   }
648   pcbdev = cartslot_get_pcb(image);
649
650   if (pcbdev != NULL)
651   {
652      aes_pcb_t *pcb = get_safe_pcb_token(pcbdev);
653      cartslot_t *cart = get_safe_cartslot_token(&image.device());
654
655      //  printf("unload\n");
656      if (cart->mc != NULL)
657      {
658         /* Remove pointers and de-big-endianize RAM contents. */
659         pcb->disassemble(pcbdev->machine(), image);
660
661         /* Close the multicart; all RAM resources will be
662               written to disk */
663         multicart_close(pcbdev->machine().options(), cart->mc);
664         cart->mc = NULL;
665      }
666//      else
667//          fatalerror("Lost pointer to multicart in cartridge. Report bug.");
668   }
669}
670
671/*****************************************************************************
672  The overall multi-cartridge slot system. It contains instances of
673  cartridges which contain PCB devices. The memory handlers delegate the calls
674  to the respective handlers of the cartridges.
675
676  Note that the term "multi-cartridge system" and "multicart" are not the same:
677  A "multicart" may contain multiple resources, organized on a PCB. The multi-
678  cart system may thus host multiple multicarts.
679
680  Actually, the name of the device should be changed (however, the device name
681  length is limited)
682******************************************************************************/
683/*
684    Instantiation of a multicart system for the Neo Geo AES.
685*/
686static DEVICE_START(aes_multicart)
687{
688   int i;
689//  printf("DEVICE_START(aes_multicart)\n");
690   aes_multicart_t *cartslots = get_safe_token(device);
691
692   /* Save this in the shortcut; we don't want to look for it each time
693       that we have a memory access. And currently we do not plan for
694       multiple multicart instances. */
695   cartslots->active_slot = 0;
696   cartslots->next_free_slot = 0;
697
698   for (i=0; i < AES_NUMBER_OF_CARTRIDGE_SLOTS; i++)
699   {
700      cartslots->cartridge[i].pcb = NULL;
701   }
702
703   cartslots->multi_slots = 0;
704
705   /* The cartslot system is initialized now. The cartridges themselves
706       need to check whether their parts are available. */
707}
708
709static DEVICE_STOP(aes_multicart)
710{
711//  printf("DEVICE_STOP(aes_multicart)\n");
712}
713
714static MACHINE_CONFIG_FRAGMENT(aes_multicart)
715   MCFG_CARTSLOT_ADD("cartridge1")
716   MCFG_CARTSLOT_EXTENSION_LIST("rpk,bin")
717   MCFG_CARTSLOT_PCBTYPE(0, "none", AES_CARTRIDGE_PCB_NONE)
718   MCFG_CARTSLOT_PCBTYPE(1, "standard", AES_CARTRIDGE_PCB_STD)
719
720   MCFG_CARTSLOT_START(aes_cartridge)
721   MCFG_CARTSLOT_LOAD(aes_cartridge)
722   MCFG_CARTSLOT_UNLOAD(aes_cartridge)
723   MCFG_CARTSLOT_INTERFACE("aes_cart")
724   MCFG_CARTSLOT_MANDATORY
725MACHINE_CONFIG_END
726
727
728DEVICE_GET_INFO(aes_multicart)
729{
730   switch (state)
731   {
732      /* --- the following bits of info are returned as pointers to data --- */
733      case DEVINFO_PTR_MACHINE_CONFIG:
734         info->machine_config = MACHINE_CONFIG_NAME(aes_multicart); break;
735
736      /* --- the following bits of info are returned as NULL-terminated strings --- */
737      case DEVINFO_STR_NAME:
738         strcpy(info->s, "AES Cartridge handler");
739         break;
740
741      case DEVINFO_INT_TOKEN_BYTES: /* private storage, automatically allocated */
742         info->i = sizeof(aes_multicart_t);
743         break;
744
745      case DEVINFO_STR_FAMILY:
746         strcpy(info->s, "Cartridge slot");
747         break;
748      case DEVINFO_STR_VERSION:
749         strcpy(info->s, "1.0");
750         break;
751      case DEVINFO_STR_SOURCE_FILE:
752         strcpy(info->s, __FILE__);
753         break;
754      /* --- the following bits of info are returned as pointers to functions --- */
755      case DEVINFO_FCT_START:
756         info->start = DEVICE_START_NAME(aes_multicart);
757         break;
758      case DEVINFO_FCT_STOP:
759         info->stop = DEVICE_STOP_NAME(aes_multicart);
760         break;
761      case DEVINFO_FCT_RESET:
762         /* Nothing */
763         break;
764   }
765}
766
767DEFINE_LEGACY_CART_SLOT_DEVICE(AES_MULTICART, aes_multicart);
768DEFINE_LEGACY_CART_SLOT_DEVICE(AES_CARTRIDGE_PCB_NONE, aes_cartridge_pcb_none);
769DEFINE_LEGACY_CART_SLOT_DEVICE(AES_CARTRIDGE_PCB_STD, aes_cartridge_pcb_std);
src/mame/machine/aescart.h
r11531r11532
1/*********************************************************************
2
3    aescart.h
4
5    AES cartridge management
6
7*********************************************************************/
8
9#ifndef __AESCART_H__
10#define __AESCART_H__
11
12#include "image.h"
13#include "imagedev/cartslot.h"
14
15DECLARE_LEGACY_CART_SLOT_DEVICE(AES_MULTICART, aes_multicart);
16DECLARE_LEGACY_CART_SLOT_DEVICE(AES_CARTRIDGE_PCB_NONE, aes_cartridge_pcb_none);
17DECLARE_LEGACY_CART_SLOT_DEVICE(AES_CARTRIDGE_PCB_STD, aes_cartridge_pcb_std);
18
19/* There's only 1 slot in an AES */
20#define AES_NUMBER_OF_CARTRIDGE_SLOTS 1
21
22/* Generic AES cartridge structure. */
23struct _aescartridge_t
24{
25   /* PCB device associated to this cartridge. If NULL, the slot is empty. */
26   device_t *pcb;
27};
28typedef struct _aescartridge_t aescartridge_t;
29
30#define MCFG_AES_CARTRIDGE_ADD(_tag) \
31   MCFG_DEVICE_ADD(_tag, AES_MULTICART, 0)
32
33#endif /* __AESCART_H__ */
src/mame/machine/amigacd.c
r11531r11532
1/***************************************************************************
2
3    Amiga CD-ROM controller emulation
4
5Notes:
6Many thanks to Toni Wilen for all the help and information about the
7DMAC controller.
8
9***************************************************************************/
10
11
12#include "emu.h"
13#include "includes/amiga.h"
14#include "amigacd.h"
15#include "machine/6525tpi.h"
16#include "machine/6526cia.h"
17#include "machine/wd33c93.h"
18#include "imagedev/chd_cd.h"
19#include "machine/matsucd.h"
20
21
22#define VERBOSE_DMAC 0
23
24#define LOG(x) do { if (VERBOSE_DMAC) logerror x; } while (0)
25
26/* constants */
27#define CD_SECTOR_TIME      (1000/((300*1024)/2048))   /* 2X CDROM sector time in msec (300KBps) */
28
29/***************************************************************************
30
31    DMAC
32
33***************************************************************************/
34
35/*
36 * value to go into DAWR
37 */
38#define DAWR_ATZSC      3       /* according to A3000T service-manual */
39
40/*
41 * bits defined for CNTR
42 */
43#define CNTR_TCEN       (1<<7)  /* Terminal Count Enable */
44#define CNTR_PREST      (1<<6)  /* Perp Reset (not implemented :-((( ) */
45#define CNTR_PDMD       (1<<5)  /* Perp Device Mode Select (1=SCSI,0=XT/AT) */
46#define CNTR_INTEN      (1<<4)  /* Interrupt Enable */
47#define CNTR_DDIR       (1<<3)  /* Device Direction. 1==rd host, wr to perp */
48
49/*
50 * bits defined for ISTR
51 */
52#define ISTR_INTX       (1<<8)  /* XT/AT Interrupt pending */
53#define ISTR_INT_F      (1<<7)  /* Interrupt Follow */
54#define ISTR_INTS       (1<<6)  /* SCSI Peripheral Interrupt */
55#define ISTR_E_INT      (1<<5)  /* End-Of-Process Interrupt */
56#define ISTR_INT_P      (1<<4)  /* Interrupt Pending */
57#define ISTR_UE_INT     (1<<3)  /* Under-Run FIFO Error Interrupt */
58#define ISTR_OE_INT     (1<<2)  /* Over-Run FIFO Error Interrupt */
59#define ISTR_FF_FLG     (1<<1)  /* FIFO-Full Flag */
60#define ISTR_FE_FLG     (1<<0)  /* FIFO-Empty Flag */
61
62typedef struct
63{
64   UINT16      istr;      /* Interrupt Status Register (R) */
65   UINT16      cntr;      /* Control Register (RW) */
66   UINT32      wtc;      /* Word Transfer Count Register (RW) */
67   UINT32      acr;      /* Address Count Register (RW) */
68   UINT16      dawr;      /* DACK Width Register (W) */
69   emu_timer *dma_timer;
70} _dmac_data;
71
72static _dmac_data dmac_data;
73
74static void check_interrupts( running_machine &machine )
75{
76   /* if interrupts are disabled, bail */
77   if ( (dmac_data.cntr & CNTR_INTEN) == 0 )
78      return;
79
80   /* if no interrupts are pending, bail */
81   if ( (dmac_data.istr & ISTR_INT_P) == 0 )
82      return;
83
84   /* otherwise, generate the IRQ */
85   amiga_custom_w(machine.device("maincpu")->memory().space(AS_PROGRAM), REG_INTREQ, 0x8000 | INTENA_PORTS, 0xffff);
86}
87
88static TIMER_CALLBACK(dmac_dma_proc)
89{
90   amiga_state *state = machine.driver_data<amiga_state>();
91   while( dmac_data.wtc > 0 )
92   {
93      UINT16   dat16;
94      UINT8   dat8;
95
96      if ( matsucd_get_next_byte( &dat8 ) < 0 )
97         break;
98
99      dat16 = dat8;
100
101      if ( matsucd_get_next_byte( &dat8 ) < 0 )
102         break;
103
104      dat16 <<= 8;
105      dat16 |= dat8;
106
107      (*state->m_chip_ram_w)(state, dmac_data.acr, dat16);
108
109      dmac_data.acr += 2;
110      dmac_data.wtc--;
111   }
112
113   if ( dmac_data.wtc > 0 )
114   {
115      matsucd_read_next_block();
116      dmac_data.dma_timer->adjust(attotime::from_msec( CD_SECTOR_TIME ));
117   }
118   else
119   {
120      dmac_data.istr |= ISTR_INT_P | ISTR_E_INT;
121      check_interrupts( machine );
122   }
123}
124
125static READ16_HANDLER( amiga_dmac_r )
126{
127   offset &= 0xff;
128
129   switch( offset )
130   {
131      case 0x20:
132      {
133         UINT8   v = dmac_data.istr;
134         LOG(( "DMAC: PC=%08x - ISTR Read(%04x)\n", cpu_get_pc(&space->device()), dmac_data.istr ));
135
136         dmac_data.istr &= ~0x0f;
137         return v;
138      }
139      break;
140
141      case 0x21:
142      {
143         LOG(( "DMAC: PC=%08x - CNTR Read(%04x)\n", cpu_get_pc(&space->device()), dmac_data.cntr ));
144         return dmac_data.cntr;
145      }
146      break;
147
148      case 0x40:   /* wtc hi */
149      {
150         LOG(( "DMAC: PC=%08x - WTC HI Read\n", cpu_get_pc(&space->device()) ));
151         return (dmac_data.wtc >> 16);
152      }
153      break;
154
155      case 0x41:   /* wtc lo */
156      {
157         LOG(( "DMAC: PC=%08x - WTC LO Read\n", cpu_get_pc(&space->device()) ));
158         return dmac_data.wtc;
159      }
160      break;
161
162      case 0x42:   /* acr hi */
163      {
164         LOG(( "DMAC: PC=%08x - ACR HI Read\n", cpu_get_pc(&space->device()) ));
165         return (dmac_data.acr >> 16);
166      }
167      break;
168
169      case 0x43:   /* acr lo */
170      {
171         LOG(( "DMAC: PC=%08x - ACR LO Read\n", cpu_get_pc(&space->device()) ));
172         return dmac_data.acr;
173      }
174      break;
175
176      case 0x48:   /* wd33c93 SCSI expansion */
177      case 0x49:
178      {
179         LOG(( "DMAC: PC=%08x - WD33C93 Read(%d)\n", cpu_get_pc(&space->device()), offset & 1 ));
180         return 0x00;   /* Not available without SCSI expansion */
181      }
182      break;
183
184      case 0x50:
185      {
186         LOG(( "DMAC: PC=%08x - CDROM RESP Read\n", cpu_get_pc(&space->device()) ));
187         return matsucd_response_r(space->machine());
188      }
189      break;
190
191      case 0x51:   /* XT IO */
192      case 0x52:
193      case 0x53:
194      {
195         LOG(( "DMAC: PC=%08x - XT IO Read(%d)\n", cpu_get_pc(&space->device()), (offset & 3)-1 ));
196         return 0xff;
197      }
198      break;
199
200      case 0x58:   /* TPI6525 */
201      case 0x59:
202      case 0x5A:
203      case 0x5B:
204      case 0x5C:
205      case 0x5D:
206      case 0x5E:
207      case 0x5F:
208      case 0x60:
209      case 0x61:
210      case 0x62:
211      case 0x63:
212      case 0x64:
213      case 0x65:
214      case 0x66:
215      case 0x67:
216      {
217         device_t *tpi = space->machine().device("tpi6525");
218         LOG(( "DMAC: PC=%08x - TPI6525 Read(%d)\n", cpu_get_pc(&space->device()), (offset - 0x58) ));
219         return tpi6525_r(tpi, offset - 0x58);
220      }
221      break;
222
223      case 0x70:   /* DMA start strobe */
224      {
225         LOG(( "DMAC: PC=%08x - DMA Start Strobe\n", cpu_get_pc(&space->device()) ));
226         dmac_data.dma_timer->adjust(attotime::from_msec( CD_SECTOR_TIME ));
227      }
228      break;
229
230      case 0x71:   /* DMA stop strobe */
231      {
232         LOG(( "DMAC: PC=%08x - DMA Stop Strobe\n", cpu_get_pc(&space->device()) ));
233         dmac_data.dma_timer->reset(  );
234      }
235      break;
236
237      case 0x72:   /* Clear IRQ strobe */
238      {
239         LOG(( "DMAC: PC=%08x - IRQ Clear Strobe\n", cpu_get_pc(&space->device()) ));
240         dmac_data.istr &= ~ISTR_INT_P;
241      }
242      break;
243
244      case 0x74:   /* Flush strobe */
245      {
246         LOG(( "DMAC: PC=%08x - Flush Strobe\n", cpu_get_pc(&space->device()) ));
247         dmac_data.istr |= ISTR_FE_FLG;
248      }
249      break;
250
251      default:
252         logerror( "DMAC-READ: PC=%08x, offset = %02x\n", cpu_get_pc(&space->device()), offset );
253      break;
254   }
255
256   return 0;
257}
258
259static WRITE16_HANDLER( amiga_dmac_w )
260{
261   offset &= 0xff;
262
263   switch( offset )
264   {
265      case 0x21:   /* control write */
266      {
267         LOG(( "DMAC: PC=%08x - CNTR Write(%04x)\n", cpu_get_pc(&space->device()), data ));
268         dmac_data.cntr = data;
269         check_interrupts(space->machine());
270      }
271      break;
272
273      case 0x40:   /* wtc hi */
274      {
275         LOG(( "DMAC: PC=%08x - WTC HI Write - data = %04x\n", cpu_get_pc(&space->device()), data ));
276         dmac_data.wtc &= 0x0000ffff;
277         dmac_data.wtc |= ((UINT32)data) << 16;
278      }
279      break;
280
281      case 0x41:   /* wtc lo */
282      {
283         LOG(( "DMAC: PC=%08x - WTC LO Write - data = %04x\n", cpu_get_pc(&space->device()), data ));
284         dmac_data.wtc &= 0xffff0000;
285         dmac_data.wtc |= data;
286      }
287      break;
288
289      case 0x42:   /* acr hi */
290      {
291         LOG(( "DMAC: PC=%08x - ACR HI Write - data = %04x\n", cpu_get_pc(&space->device()), data ));
292         dmac_data.acr &= 0x0000ffff;
293         dmac_data.acr |= ((UINT32)data) << 16;
294      }
295      break;
296
297      case 0x43:   /* acr lo */
298      {
299         LOG(( "DMAC: PC=%08x - ACR LO Write - data = %04x\n", cpu_get_pc(&space->device()), data ));
300         dmac_data.acr &= 0xffff0000;
301         dmac_data.acr |= data;
302      }
303      break;
304
305      case 0x47:   /* dawr */
306      {
307         LOG(( "DMAC: PC=%08x - DAWR Write - data = %04x\n", cpu_get_pc(&space->device()), data ));
308         dmac_data.dawr = data;
309      }
310      break;
311
312      case 0x48:   /* wd33c93 SCSI expansion */
313      case 0x49:
314      {
315         LOG(( "DMAC: PC=%08x - WD33C93 Write(%d) - data = %04x\n", cpu_get_pc(&space->device()), offset & 1, data ));
316         /* Not available without SCSI expansion */
317      }
318      break;
319
320      case 0x50:
321      {
322         LOG(( "DMAC: PC=%08x - CDROM CMD Write - data = %04x\n", cpu_get_pc(&space->device()), data ));
323         matsucd_command_w(space->machine(), data );
324      }
325      break;
326
327      case 0x58:   /* TPI6525 */
328      case 0x59:
329      case 0x5A:
330      case 0x5B:
331      case 0x5C:
332      case 0x5D:
333      case 0x5E:
334      case 0x5F:
335      case 0x60:
336      case 0x61:
337      case 0x62:
338      case 0x63:
339      case 0x64:
340      case 0x65:
341      case 0x66:
342      case 0x67:
343      {
344         device_t *tpi = space->machine().device("tpi6525");
345         LOG(( "DMAC: PC=%08x - TPI6525 Write(%d) - data = %04x\n", cpu_get_pc(&space->device()), (offset - 0x58), data ));
346         tpi6525_w(tpi, offset - 0x58, data);
347      }
348      break;
349
350      case 0x70:   /* DMA start strobe */
351      {
352         LOG(( "DMAC: PC=%08x - DMA Start Strobe\n", cpu_get_pc(&space->device()) ));
353         dmac_data.dma_timer->adjust(attotime::from_msec( CD_SECTOR_TIME ));
354      }
355      break;
356
357      case 0x71:   /* DMA stop strobe */
358      {
359         LOG(( "DMAC: PC=%08x - DMA Stop Strobe\n", cpu_get_pc(&space->device()) ));
360         dmac_data.dma_timer->reset(  );
361      }
362      break;
363
364      case 0x72:   /* Clear IRQ strobe */
365      {
366         LOG(( "DMAC: PC=%08x - IRQ Clear Strobe\n", cpu_get_pc(&space->device()) ));
367         dmac_data.istr &= ~ISTR_INT_P;
368      }
369      break;
370
371      case 0x74:   /* Flush Strobe */
372      {
373         LOG(( "DMAC: PC=%08x - Flush Strobe\n", cpu_get_pc(&space->device()) ));
374         dmac_data.istr |= ISTR_FE_FLG;
375      }
376      break;
377
378      default:
379         logerror( "DMAC-WRITE: PC=%08x, offset = %02x, data = %04x\n", cpu_get_pc(&space->device()), offset, data );
380      break;
381   }
382}
383
384/***************************************************************************
385
386    Autoconfig
387
388***************************************************************************/
389
390static void   dmac_install(running_machine &machine, offs_t base)
391{
392   address_space *space = machine.device("maincpu")->memory().space(AS_PROGRAM);
393   space->install_legacy_read_handler(base, base + 0xFFFF, FUNC(amiga_dmac_r));
394   space->install_legacy_write_handler(base, base + 0xFFFF, FUNC(amiga_dmac_w));
395}
396
397static void   dmac_uninstall(running_machine &machine, offs_t base)
398{
399   address_space *space = machine.device("maincpu")->memory().space(AS_PROGRAM);
400   space->unmap_readwrite(base, base + 0xFFFF);
401}
402
403static const amiga_autoconfig_device dmac_device =
404{
405   0,            /* link into free memory list */
406   0,            /* ROM vector offset valid */
407   0,            /* multiple devices on card */
408   1,            /* number of 64k pages */
409   3,            /* product number (DMAC) */
410   0,            /* prefer 8MB address space */
411   0,            /* can be shut up */
412   0x0202,         /* manufacturers number (Commodore) */
413   0,            /* serial number */
414   0,            /* ROM vector offset */
415   NULL,         /* interrupt control read */
416   NULL,         /* interrupt control write */
417   dmac_install,   /* memory installation */
418   dmac_uninstall   /* memory uninstallation */
419};
420
421/***************************************************************************
422
423    TPI6525
424
425***************************************************************************/
426
427READ8_DEVICE_HANDLER( amigacd_tpi6525_portc_r )
428{
429   int   ret = 0;
430
431   if ( (tpi6525_get_ddr_c(device) & 0x04) == 0 ) /* if pin 2 is set to input */
432   {
433      ret |= matsucd_stch_r() ? 0x00 : 0x04;   /* read status change signal */
434   }
435
436   if ( (tpi6525_get_ddr_c(device) & 0x08) == 0 ) /* if pin 3 is set to input */
437      ret |= matsucd_sten_r() ? 0x08 : 0x00;   /* read enable signal */
438
439   return ret;
440}
441
442WRITE8_DEVICE_HANDLER( amigacd_tpi6525_portb_w )
443{
444   if ( tpi6525_get_ddr_b(device) & 0x01 ) /* if pin 0 is set to output */
445      matsucd_cmd_w( data & 1 ); /* write to the /CMD signal */
446
447   if ( tpi6525_get_ddr_b(device) & 0x02 ) /* if pin 1 is set to output */
448      matsucd_enable_w( data & 2 ); /* write to the /ENABLE signal */
449}
450
451static emu_timer *tp6525_delayed_timer;
452
453static TIMER_CALLBACK(tp6525_delayed_irq)
454{
455   amiga_state *state = machine.driver_data<amiga_state>();
456   (void)param;
457
458   if ( (CUSTOM_REG(REG_INTREQ) & INTENA_PORTS) == 0 )
459   {
460      amiga_custom_w(machine.device("maincpu")->memory().space(AS_PROGRAM), REG_INTREQ, 0x8000 | INTENA_PORTS, 0xffff);
461   }
462   else
463   {
464      tp6525_delayed_timer->adjust(attotime::from_msec(1));
465   }
466}
467
468static void amigacd_tpi6525_irq_trampoline(device_t *device, int level)
469{
470   amiga_state *state = device->machine().driver_data<amiga_state>();
471   LOG(( "TPI6525 Interrupt: level = %d\n", level ));
472
473   if ( level )
474   {
475      if ( (CUSTOM_REG(REG_INTREQ) & INTENA_PORTS) == 0 )
476      {
477         amiga_custom_w(device->machine().device("maincpu")->memory().space(AS_PROGRAM), REG_INTREQ, 0x8000 | INTENA_PORTS, 0xffff);
478      }
479      else
480      {
481         /* we *have to* deliver the irq, so if we can't, delay it and try again later */
482         tp6525_delayed_timer->adjust(attotime::from_msec(1));
483      }
484   }
485}
486
487WRITE_LINE_DEVICE_HANDLER( amigacd_tpi6525_irq )
488{
489   amigacd_tpi6525_irq_trampoline(device, state);
490}
491
492static void cdrom_status_enabled( running_machine &machine, int level )
493{
494   device_t *tpi = machine.device("tpi6525");
495
496   /* PC3 on the 6525 */
497   tpi6525_i3_w(tpi, level);
498}
499
500static void cdrom_status_change( running_machine &machine, int level )
501{
502   device_t *tpi = machine.device("tpi6525");
503
504   /* invert */
505   level = level ? 0 : 1;
506
507   /* PC2 on the 6525 */
508   tpi6525_i2_w(tpi, level);
509}
510
511static void cdrom_subcode_ready( running_machine &machine, int level )
512{
513   device_t *tpi = machine.device("tpi6525");
514
515   /* PC1 on the 6525 */
516   tpi6525_i1_w(tpi, level);
517}
518
519MACHINE_START( amigacd )
520{
521   /* initialize the dmac */
522   memset( &dmac_data, 0, sizeof( dmac_data ) );
523
524   dmac_data.dma_timer = machine.scheduler().timer_alloc(FUNC(dmac_dma_proc));
525   tp6525_delayed_timer = machine.scheduler().timer_alloc(FUNC(tp6525_delayed_irq));
526
527   /* set up DMAC with autoconfig */
528   amiga_add_autoconfig( machine, &dmac_device );
529
530   matsucd_init( machine.device("cdrom"), "cdda" );
531}
532
533MACHINE_RESET( amigacd )
534{
535   /* initialize the cdrom */
536   matsucd_set_status_enabled_callback( cdrom_status_enabled );
537   matsucd_set_status_changed_callback( cdrom_status_change );
538   matsucd_set_subcode_ready_callback( cdrom_subcode_ready );
539}
src/mame/machine/nes.c
r11531r11532
1#include "emu.h"
2#include "crsshair.h"
3#include "hash.h"
4#include "cpu/m6502/m6502.h"
5#include "video/ppu2c0x.h"
6#include "includes/nes.h"
7#include "machine/nes_mmc.h"
8#include "imagedev/cartslot.h"
9#include "imagedev/flopdrv.h"
10#include "hashfile.h"
11
12/***************************************************************************
13    CONSTANTS
14***************************************************************************/
15
16/* Set to dump info about the inputs to the errorlog */
17#define LOG_JOY      0
18
19/* Set to generate prg & chr files when the cart is loaded */
20#define SPLIT_PRG   0
21#define SPLIT_CHR   0
22
23/***************************************************************************
24    FUNCTION PROTOTYPES
25***************************************************************************/
26
27static void init_nes_core(running_machine &machine);
28static void nes_machine_stop(running_machine &machine);
29static READ8_HANDLER(nes_fds_r);
30static WRITE8_HANDLER(nes_fds_w);
31static void fds_irq(device_t *device, int scanline, int vblank, int blanked);
32
33/***************************************************************************
34    FUNCTIONS
35***************************************************************************/
36
37static void init_nes_core( running_machine &machine )
38{
39   nes_state *state = machine.driver_data<nes_state>();
40   address_space *space = machine.device("maincpu")->memory().space(AS_PROGRAM);
41   static const char *const bank_names[] = { "bank1", "bank2", "bank3", "bank4" };
42   int prg_banks = (state->m_prg_chunks == 1) ? (2 * 2) : (state->m_prg_chunks * 2);
43   int i;
44
45   /* We set these here in case they weren't set in the cart loader */
46   state->m_rom = machine.region("maincpu")->base();
47   state->m_vrom = machine.region("gfx1")->base();
48   state->m_vram = machine.region("gfx2")->base();
49   state->m_ciram = machine.region("gfx3")->base();
50
51   /* Brutal hack put in as a consequence of the new memory system; we really need to fix the NES code */
52   space->install_readwrite_bank(0x0000, 0x07ff, 0, 0x1800, "bank10");
53
54   machine.device("ppu")->memory().space(AS_PROGRAM)->install_legacy_readwrite_handler(0, 0x1fff, FUNC(nes_chr_r), FUNC(nes_chr_w));
55   machine.device("ppu")->memory().space(AS_PROGRAM)->install_legacy_readwrite_handler(0x2000, 0x3eff, FUNC(nes_nt_r), FUNC(nes_nt_w));
56
57   memory_set_bankptr(machine, "bank10", state->m_rom);
58
59   /* If there is Disk Expansion and no cart has been loaded, setup memory accordingly */
60   if (state->m_disk_expansion && state->m_pcb_id == NO_BOARD)
61   {
62      /* If we are loading a disk we have already filled state->m_fds_data and we don't want to overwrite it,
63         if we are loading a cart image identified as mapper 20 (probably wrong mapper...) we need to alloc
64         memory for use in nes_fds_r/nes_fds_w. Same goes for allocation of fds_ram (used for bank2)  */
65      if (state->m_fds_data == NULL)
66      {
67         UINT32 size = machine.region("maincpu")->bytes() - 0x10000;
68         state->m_fds_data = auto_alloc_array_clear(machine, UINT8, size);
69         memcpy(state->m_fds_data, state->m_rom, size);   // copy in fds_data the cart PRG
70      }
71      if (state->m_fds_ram == NULL)
72         state->m_fds_ram = auto_alloc_array(machine, UINT8, 0x8000);
73
74      space->install_legacy_read_handler(0x4030, 0x403f, FUNC(nes_fds_r));
75      space->install_read_bank(0x6000, 0xdfff, "bank2");
76      space->install_read_bank(0xe000, 0xffff, "bank1");
77
78      space->install_legacy_write_handler(0x4020, 0x402f, FUNC(nes_fds_w));
79      space->install_write_bank(0x6000, 0xdfff, "bank2");
80
81      memory_set_bankptr(machine, "bank1", &state->m_rom[0xe000]);
82      memory_set_bankptr(machine, "bank2", state->m_fds_ram);
83      return;
84   }
85
86   /* Set up the mapper callbacks */
87   pcb_handlers_setup(machine);
88
89   /* Set up the memory handlers for the mapper */
90   space->install_read_bank(0x8000, 0x9fff, "bank1");
91   space->install_read_bank(0xa000, 0xbfff, "bank2");
92   space->install_read_bank(0xc000, 0xdfff, "bank3");
93   space->install_read_bank(0xe000, 0xffff, "bank4");
94   space->install_readwrite_bank(0x6000, 0x7fff, "bank5");
95
96   /* configure banks 1-4 */
97   for (i = 0; i < 4; i++)
98   {
99      memory_configure_bank(machine, bank_names[i], 0, prg_banks, machine.region("maincpu")->base() + 0x10000, 0x2000);
100      // some mappers (e.g. MMC5) can map PRG RAM in  0x8000-0xffff as well
101      if (state->m_prg_ram)
102         memory_configure_bank(machine, bank_names[i], prg_banks, state->m_wram_size / 0x2000, state->m_wram, 0x2000);
103      // however, at start we point to PRG ROM
104      memory_set_bank(machine, bank_names[i], i);
105      state->m_prg_bank[i] = i;
106   }
107
108   /* bank 5 configuration is more delicate, since it can have PRG RAM, PRG ROM or SRAM mapped to it */
109   /* we first map PRG ROM banks, then the battery bank (if a battery is present), and finally PRG RAM (state->m_wram) */
110   memory_configure_bank(machine, "bank5", 0, prg_banks, machine.region("maincpu")->base() + 0x10000, 0x2000);
111   state->m_battery_bank5_start = prg_banks;
112   state->m_prgram_bank5_start = prg_banks;
113   state->m_empty_bank5_start = prg_banks;
114
115   /* add battery ram, but only if there's no trainer since they share overlapping memory. */
116   if (state->m_battery && !state->m_trainer)
117   {
118      UINT32 bank_size = (state->m_battery_size > 0x2000) ? 0x2000 : state->m_battery_size;
119      int bank_num = (state->m_battery_size > 0x2000) ? state->m_battery_size / 0x2000 : 1;
120      memory_configure_bank(machine, "bank5", prg_banks, bank_num, state->m_battery_ram, bank_size);
121      state->m_prgram_bank5_start += bank_num;
122      state->m_empty_bank5_start += bank_num;
123   }
124   /* add prg ram. */
125   if (state->m_prg_ram)
126   {
127      memory_configure_bank(machine, "bank5", state->m_prgram_bank5_start, state->m_wram_size / 0x2000, state->m_wram, 0x2000);
128      state->m_empty_bank5_start += state->m_wram_size / 0x2000;
129   }
130
131   memory_configure_bank(machine, "bank5", state->m_empty_bank5_start, 1, state->m_rom + 0x6000, 0x2000);
132
133   /* if we have any additional PRG RAM, point bank5 to its first bank */
134   if (state->m_battery || state->m_prg_ram)
135      state->m_prg_bank[4] = state->m_battery_bank5_start;
136   else
137      state->m_prg_bank[4] = state->m_empty_bank5_start; // or shall we point to "maincpu" region at 0x6000? point is that we should never access this region if no sram or wram is present!
138
139   memory_set_bank(machine, "bank5", state->m_prg_bank[4]);
140
141   if (state->m_four_screen_vram)
142   {
143      state->m_extended_ntram = auto_alloc_array(machine, UINT8, 0x2000);
144      state->save_pointer(NAME(state->m_extended_ntram), 0x2000);
145   }
146
147   // there are still some quirk about writes to bank5... I hope to fix them soon. (mappers 34,45,52,246 have both mid_w and WRAM-->check)
148   if (state->m_mmc_write_mid)
149      space->install_legacy_write_handler(0x6000, 0x7fff, state->m_mmc_write_mid,state->m_mmc_write_mid_name);
150   if (state->m_mmc_write)
151      space->install_legacy_write_handler(0x8000, 0xffff, state->m_mmc_write, state->m_mmc_write_name);
152
153   // In fact, we also allow single pcbs to overwrite the bank read handlers defined above,
154   // because some pcbs (mainly pirate ones) require protection values to be read instead of
155   // the expected ROM banks: these handlers, though, must take care of the ROM access as well
156   if (state->m_mmc_read_mid)
157      space->install_legacy_read_handler(0x6000, 0x7fff, state->m_mmc_read_mid,state->m_mmc_read_mid_name);
158   if (state->m_mmc_read)
159      space->install_legacy_read_handler(0x8000, 0xffff, state->m_mmc_read,state->m_mmc_read_name);
160
161   // install additional handlers
162   if (state->m_pcb_id == BTL_SMB2B || state->m_mapper == 50)
163   {
164      space->install_legacy_write_handler(0x4020, 0x403f, FUNC(smb2jb_extra_w));
165      space->install_legacy_write_handler(0x40a0, 0x40bf, FUNC(smb2jb_extra_w));
166   }
167
168   if (state->m_pcb_id == KAISER_KS7017)
169   {
170      space->install_legacy_read_handler(0x4030, 0x4030, FUNC(ks7017_extra_r));
171      space->install_legacy_write_handler(0x4020, 0x40ff, FUNC(ks7017_extra_w));
172   }
173
174   if (state->m_pcb_id == UNL_603_5052)
175   {
176      space->install_legacy_read_handler(0x4020, 0x40ff, FUNC(unl_6035052_extra_r));
177      space->install_legacy_write_handler(0x4020, 0x40ff, FUNC(unl_6035052_extra_w));
178   }
179
180   if (state->m_pcb_id == WAIXING_SH2)
181      machine.device("ppu")->memory().space(AS_PROGRAM)->install_legacy_read_handler(0, 0x1fff, FUNC(waixing_sh2_chr_r));
182}
183
184// to be probably removed (it does nothing since a long time)
185int nes_ppu_vidaccess( device_t *device, int address, int data )
186{
187   return data;
188}
189
190MACHINE_RESET( nes )
191{
192   nes_state *state = machine.driver_data<nes_state>();
193
194   /* Reset the mapper variables. Will also mark the char-gen ram as dirty */
195   if (state->m_disk_expansion && state->m_pcb_id == NO_BOARD)
196      ppu2c0x_set_hblank_callback(state->m_ppu, fds_irq);
197   else
198      nes_pcb_reset(machine);
199
200   /* Reset the serial input ports */
201   state->m_in_0.shift = 0;
202   state->m_in_1.shift = 0;
203
204   machine.device("maincpu")->reset();
205}
206
207static TIMER_CALLBACK( nes_irq_callback )
208{
209   nes_state *state = machine.driver_data<nes_state>();
210   device_set_input_line(state->m_maincpu, M6502_IRQ_LINE, HOLD_LINE);
211   state->m_irq_timer->adjust(attotime::never);
212}
213
214static void nes_banks_restore(nes_state *state)
215{
216   memory_set_bank(state->machine(), "bank1", state->m_prg_bank[0]);
217   memory_set_bank(state->machine(), "bank2", state->m_prg_bank[1]);
218   memory_set_bank(state->machine(), "bank3", state->m_prg_bank[2]);
219   memory_set_bank(state->machine(), "bank4", state->m_prg_bank[3]);
220   memory_set_bank(state->machine(), "bank5", state->m_prg_bank[4]);
221}
222
223static void nes_state_register( running_machine &machine )
224{
225   nes_state *state = machine.driver_data<nes_state>();
226
227   state->save_item(NAME(state->m_prg_bank));
228
229   state->save_item(NAME(state->m_MMC5_floodtile));
230   state->save_item(NAME(state->m_MMC5_floodattr));
231   state->save_item(NAME(state->m_mmc5_vram_control));
232
233   state->save_item(NAME(state->m_nes_vram_sprite));
234   state->save_item(NAME(state->m_last_frame_flip));
235
236   // shared mapper variables
237   state->save_item(NAME(state->m_IRQ_enable));
238   state->save_item(NAME(state->m_IRQ_enable_latch));
239   state->save_item(NAME(state->m_IRQ_count));
240   state->save_item(NAME(state->m_IRQ_count_latch));
241   state->save_item(NAME(state->m_IRQ_toggle));
242   state->save_item(NAME(state->m_IRQ_reset));
243   state->save_item(NAME(state->m_IRQ_status));
244   state->save_item(NAME(state->m_IRQ_mode));
245   state->save_item(NAME(state->m_mult1));
246   state->save_item(NAME(state->m_mult2));
247   state->save_item(NAME(state->m_mmc_chr_source));
248   state->save_item(NAME(state->m_mmc_cmd1));
249   state->save_item(NAME(state->m_mmc_cmd2));
250   state->save_item(NAME(state->m_mmc_count));
251   state->save_item(NAME(state->m_mmc_prg_base));
252   state->save_item(NAME(state->m_mmc_prg_mask));
253   state->save_item(NAME(state->m_mmc_chr_base));
254   state->save_item(NAME(state->m_mmc_chr_mask));
255   state->save_item(NAME(state->m_mmc_prg_bank));
256   state->save_item(NAME(state->m_mmc_vrom_bank));
257   state->save_item(NAME(state->m_mmc_extra_bank));
258
259   state->save_item(NAME(state->m_fds_motor_on));
260   state->save_item(NAME(state->m_fds_door_closed));
261   state->save_item(NAME(state->m_fds_current_side));
262   state->save_item(NAME(state->m_fds_head_position));
263   state->save_item(NAME(state->m_fds_status0));
264   state->save_item(NAME(state->m_fds_read_mode));
265   state->save_item(NAME(state->m_fds_write_reg));
266   state->save_item(NAME(state->m_fds_last_side));
267   state->save_item(NAME(state->m_fds_count));
268
269   state->save_pointer(NAME(state->m_wram), state->m_wram_size);
270   if (state->m_battery)
271      state->save_pointer(NAME(state->m_battery_ram), state->m_battery_size);
272
273   machine.save().register_postload(save_prepost_delegate(FUNC(nes_banks_restore), state));
274}
275
276MACHINE_START( nes )
277{
278   nes_state *state = machine.driver_data<nes_state>();
279
280   init_nes_core(machine);
281   machine.add_notifier(MACHINE_NOTIFY_EXIT, machine_notify_delegate(FUNC(nes_machine_stop),&machine));
282
283   state->m_maincpu = machine.device("maincpu");
284   state->m_ppu = machine.device("ppu");
285   state->m_sound = machine.device("nessound");
286   state->m_cart = machine.device("cart");
287
288   state->m_irq_timer = machine.scheduler().timer_alloc(FUNC(nes_irq_callback));
289   nes_state_register(machine);
290}
291
292static void nes_machine_stop( running_machine &machine )
293{
294   nes_state *state = machine.driver_data<nes_state>();
295   device_image_interface *image = dynamic_cast<device_image_interface *>(state->m_cart);
296   /* Write out the battery file if necessary */
297   if (state->m_battery)
298      image->battery_save(state->m_battery_ram, state->m_battery_size);
299
300   if (state->m_mapper_bram_size)
301      image->battery_save(state->m_mapper_bram, state->m_mapper_bram_size);
302}
303
304
305
306READ8_HANDLER( nes_IN0_r )
307{
308   nes_state *state = space->machine().driver_data<nes_state>();
309   int cfg = input_port_read(space->machine(), "CTRLSEL");
310   int ret;
311
312   if ((cfg & 0x000f) >= 0x07)   // for now we treat the FC keyboard separately from other inputs!
313   {
314      // here we should have the tape input
315      ret = 0;
316   }
317   else
318   {
319      /* Some games expect bit 6 to be set because the last entry on the data bus shows up */
320      /* in the unused upper 3 bits, so typically a read from $4016 leaves 0x40 there. */
321      ret = 0x40;
322
323      ret |= ((state->m_in_0.i0 >> state->m_in_0.shift) & 0x01);
324
325      /* zapper */
326      if ((cfg & 0x000f) == 0x0002)
327      {
328         int x = state->m_in_0.i1;   /* read Zapper x-position */
329         int y = state->m_in_0.i2;   /* read Zapper y-position */
330         UINT32 pix, color_base;
331
332         /* get the pixel at the gun position */
333         pix = ppu2c0x_get_pixel(state->m_ppu, x, y);
334
335         /* get the color base from the ppu */
336         color_base = ppu2c0x_get_colorbase(state->m_ppu);
337
338         /* look at the screen and see if the cursor is over a bright pixel */
339         if ((pix == color_base + 0x20) || (pix == color_base + 0x30) ||
340            (pix == color_base + 0x33) || (pix == color_base + 0x34))
341         {
342            ret &= ~0x08; /* sprite hit */
343         }
344         else
345            ret |= 0x08;  /* no sprite hit */
346
347         /* If button 1 is pressed, indicate the light gun trigger is pressed */
348         ret |= ((state->m_in_0.i0 & 0x01) << 4);
349      }
350
351      if (LOG_JOY)
352         logerror("joy 0 read, val: %02x, pc: %04x, bits read: %d, chan0: %08x\n", ret, cpu_get_pc(&space->device()), state->m_in_0.shift, state->m_in_0.i0);
353
354      state->m_in_0.shift++;
355   }
356
357   return ret;
358}
359
360// row of the keyboard matrix are read 4-bits at time, and gets returned as bit1->bit4
361static UINT8 nes_read_fc_keyboard_line( running_machine &machine, UINT8 scan, UINT8 mode )
362{
363   static const char *const fc_keyport_names[] = { "FCKEY0", "FCKEY1", "FCKEY2", "FCKEY3", "FCKEY4", "FCKEY5", "FCKEY6", "FCKEY7", "FCKEY8" };
364   return ((input_port_read(machine, fc_keyport_names[scan]) >> (mode * 4)) & 0x0f) << 1;
365}
366
367static UINT8 nes_read_subor_keyboard_line( running_machine &machine, UINT8 scan, UINT8 mode )
368{
369   static const char *const sub_keyport_names[] = { "SUBKEY0", "SUBKEY1", "SUBKEY2", "SUBKEY3", "SUBKEY4",
370      "SUBKEY5", "SUBKEY6", "SUBKEY7", "SUBKEY8", "SUBKEY9", "SUBKEY10", "SUBKEY11", "SUBKEY12" };
371   return ((input_port_read(machine, sub_keyport_names[scan]) >> (mode * 4)) & 0x0f) << 1;
372}
373
374READ8_HANDLER( nes_IN1_r )
375{
376   nes_state *state = space->machine().driver_data<nes_state>();
377   int cfg = input_port_read(space->machine(), "CTRLSEL");
378   int ret;
379
380   if ((cfg & 0x000f) == 0x07)   // for now we treat the FC keyboard separately from other inputs!
381   {
382      if (state->m_fck_scan < 9)
383         ret = ~nes_read_fc_keyboard_line(space->machine(), state->m_fck_scan, state->m_fck_mode) & 0x1e;
384      else
385         ret = 0x1e;
386   }
387   else if ((cfg & 0x000f) == 0x08)   // for now we treat the Subor keyboard separately from other inputs!
388   {
389      if (state->m_fck_scan < 12)
390         ret = ~nes_read_subor_keyboard_line(space->machine(), state->m_fck_scan, state->m_fck_mode) & 0x1e;
391      else
392         ret = 0x1e;
393   }
394   else
395   {
396      /* Some games expect bit 6 to be set because the last entry on the data bus shows up */
397      /* in the unused upper 3 bits, so typically a read from $4017 leaves 0x40 there. */
398      ret = 0x40;
399
400      /* Handle data line 0's serial output */
401      ret |= ((state->m_in_1.i0 >> state->m_in_1.shift) & 0x01);
402
403      /* zapper */
404      if ((cfg & 0x00f0) == 0x0030)
405      {
406         int x = state->m_in_1.i1;   /* read Zapper x-position */
407         int y = state->m_in_1.i2;   /* read Zapper y-position */
408         UINT32 pix, color_base;
409
410         /* get the pixel at the gun position */
411         pix = ppu2c0x_get_pixel(state->m_ppu, x, y);
412
413         /* get the color base from the ppu */
414         color_base = ppu2c0x_get_colorbase(state->m_ppu);
415
416         /* look at the screen and see if the cursor is over a bright pixel */
417         if ((pix == color_base + 0x20) || (pix == color_base + 0x30) ||
418            (pix == color_base + 0x33) || (pix == color_base + 0x34))
419         {
420            ret &= ~0x08; /* sprite hit */
421         }
422         else
423            ret |= 0x08;  /* no sprite hit */
424
425         /* If button 1 is pressed, indicate the light gun trigger is pressed */
426         ret |= ((state->m_in_1.i0 & 0x01) << 4);
427      }
428
429      /* arkanoid dial */
430      else if ((cfg & 0x00f0) == 0x0040)
431      {
432         /* Handle data line 2's serial output */
433         ret |= ((state->m_in_1.i2 >> state->m_in_1.shift) & 0x01) << 3;
434
435         /* Handle data line 3's serial output - bits are reversed */
436         /* NPW 27-Nov-2007 - there is no third subscript! commenting out */
437         /* ret |= ((state->m_in_1[3] >> state->m_in_1.shift) & 0x01) << 4; */
438         /* ret |= ((state->m_in_1[3] << state->m_in_1.shift) & 0x80) >> 3; */
439      }
440
441      if (LOG_JOY)
442         logerror("joy 1 read, val: %02x, pc: %04x, bits read: %d, chan0: %08x\n", ret, cpu_get_pc(&space->device()), state->m_in_1.shift, state->m_in_1.i0);
443
444      state->m_in_1.shift++;
445   }
446
447   return ret;
448}
449
450
451// FIXME: this is getting messier and messier (no pun intended). inputs reading should be simplified and port_categories cleaned up
452// to also emulate the fact that nothing should be in Port 2 if there is a Crazy Climber pad, etc.
453static void nes_read_input_device( running_machine &machine, int cfg, nes_input *vals, int pad_port, int supports_zapper )
454{
455   nes_state *state = machine.driver_data<nes_state>();
456   static const char *const padnames[] = { "PAD1", "PAD2", "PAD3", "PAD4", "CC_LEFT", "CC_RIGHT" };
457
458   vals->i0 = 0;
459   vals->i1 = 0;
460   vals->i2 = 0;
461
462   switch (cfg & 0x0f)
463   {
464      case 0x01:   /* gamepad */
465         if (pad_port >= 0)
466            vals->i0 = input_port_read(machine, padnames[pad_port]);
467         break;
468
469      case 0x02:   /* zapper 1 */
470         if (supports_zapper)
471         {
472            vals->i0 = input_port_read(machine, "ZAPPER1_T");
473            vals->i1 = input_port_read(machine, "ZAPPER1_X");
474            vals->i2 = input_port_read(machine, "ZAPPER1_Y");
475         }
476         break;
477
478      case 0x03:   /* zapper 2 */
479         if (supports_zapper)
480         {
481            vals->i0 = input_port_read(machine, "ZAPPER2_T");
482            vals->i1 = input_port_read(machine, "ZAPPER2_X");
483            vals->i2 = input_port_read(machine, "ZAPPER2_Y");
484         }
485         break;
486
487      case 0x04:   /* arkanoid paddle */
488         if (pad_port == 1)
489            vals->i0 = (UINT8) ((UINT8) input_port_read(machine, "PADDLE") + (UINT8)0x52) ^ 0xff;
490         break;
491
492      case 0x05:   /* crazy climber controller */
493         if (pad_port == 0)
494         {
495            state->m_in_0.i0 = input_port_read(machine, padnames[4]);
496            state->m_in_1.i0 = input_port_read(machine, padnames[5]);
497         }
498         break;
499   }
500}
501
502
503static TIMER_CALLBACK( lightgun_tick )
504{
505   if ((input_port_read(machine, "CTRLSEL") & 0x000f) == 0x0002)
506   {
507      /* enable lightpen crosshair */
508      crosshair_set_screen(machine, 0, CROSSHAIR_SCREEN_ALL);
509   }
510   else
511   {
512      /* disable lightpen crosshair */
513      crosshair_set_screen(machine, 0, CROSSHAIR_SCREEN_NONE);
514   }
515
516   if ((input_port_read(machine, "CTRLSEL") & 0x00f0) == 0x0030)
517   {
518      /* enable lightpen crosshair */
519      crosshair_set_screen(machine, 1, CROSSHAIR_SCREEN_ALL);
520   }
521   else
522   {
523      /* disable lightpen crosshair */
524      crosshair_set_screen(machine, 1, CROSSHAIR_SCREEN_NONE);
525   }
526}
527
528WRITE8_HANDLER( nes_IN0_w )
529{
530   nes_state *state = space->machine().driver_data<nes_state>();
531   int cfg = input_port_read(space->machine(), "CTRLSEL");
532
533   /* Check if lightgun has been chosen as input: if so, enable crosshair */
534   space->machine().scheduler().timer_set(attotime::zero, FUNC(lightgun_tick));
535
536   if ((cfg & 0x000f) >= 0x07)   // for now we treat the FC keyboard separately from other inputs!
537   {
538      // here we should also have the tape output
539
540      if (BIT(data, 2))   // keyboard active
541      {
542         int lines = ((cfg & 0x000f) == 0x04) ? 9 : 12;
543         UINT8 out = BIT(data, 1);   // scan
544
545         if (state->m_fck_mode && !out && ++state->m_fck_scan > lines)
546            state->m_fck_scan = 0;
547
548         state->m_fck_mode = out;   // access lower or upper 4 bits
549
550         if (BIT(data, 0))   // reset
551            state->m_fck_scan = 0;
552      }
553   }
554   else
555   {
556      if (data & 0x01)
557         return;
558
559      if (LOG_JOY)
560         logerror("joy 0 bits read: %d\n", state->m_in_0.shift);
561
562      /* Toggling bit 0 high then low resets both controllers */
563      state->m_in_0.shift = 0;
564      state->m_in_1.shift = 0;
565
566      /* Read the input devices */
567      if ((cfg & 0x000f) != 0x06)
568      {
569         nes_read_input_device(space->machine(), cfg >>  0, &state->m_in_0, 0,  TRUE);
570         nes_read_input_device(space->machine(), cfg >>  4, &state->m_in_1, 1,  TRUE);
571         nes_read_input_device(space->machine(), cfg >>  8, &state->m_in_2, 2, FALSE);
572         nes_read_input_device(space->machine(), cfg >> 12, &state->m_in_3, 3, FALSE);
573      }
574      else // crazy climber pad
575      {
576         nes_read_input_device(space->machine(), 0, &state->m_in_1, 1,  TRUE);
577         nes_read_input_device(space->machine(), 0, &state->m_in_2, 2, FALSE);
578         nes_read_input_device(space->machine(), 0, &state->m_in_3, 3, FALSE);
579         nes_read_input_device(space->machine(), cfg >>  0, &state->m_in_0, 0,  TRUE);
580      }
581
582      if (cfg & 0x0f00)
583         state->m_in_0.i0 |= (state->m_in_2.i0 << 8) | (0x08 << 16);
584
585      if (cfg & 0xf000)
586         state->m_in_1.i0 |= (state->m_in_3.i0 << 8) | (0x04 << 16);
587   }
588}
589
590
591WRITE8_HANDLER( nes_IN1_w )
592{
593}
594
595struct nes_cart_lines
596{
597   const char *tag;
598   int line;
599};
600
601static const struct nes_cart_lines nes_cart_lines_table[] =
602{
603   { "PRG A0",    0 },
604   { "PRG A1",    1 },
605   { "PRG A2",    2 },
606   { "PRG A3",    3 },
607   { "PRG A4",    4 },
608   { "PRG A5",    5 },
609   { "PRG A6",    6 },
610   { "PRG A7",    7 },
611   { "CHR A10",  10 },
612   { "CHR A11",  11 },
613   { "CHR A12",  12 },
614   { "CHR A13",  13 },
615   { "CHR A14",  14 },
616   { "CHR A15",  15 },
617   { "CHR A16",  16 },
618   { "CHR A17",  17 },
619   { "NC",      127 },
620   { 0 }
621};
622
623static int nes_cart_get_line( const char *feature )
624{
625   const struct nes_cart_lines *nes_line = &nes_cart_lines_table[0];
626
627   if (feature == NULL)
628      return 128;
629
630   while (nes_line->tag)
631   {
632      if (strcmp(nes_line->tag, feature) == 0)
633         break;
634
635      nes_line++;
636   }
637
638   return nes_line->line;
639}
640
641DEVICE_IMAGE_LOAD( nes_cart )
642{
643   nes_state *state = image.device().machine().driver_data<nes_state>();
644   state->m_pcb_id = NO_BOARD;   // initialization
645
646   if (image.software_entry() == NULL)
647   {
648      const char *mapinfo = NULL;
649      int mapint1 = 0, mapint2 = 0, mapint3 = 0, mapint4 = 0, goodcrcinfo = 0;
650      char magic[4], extend[5];
651      int local_options = 0;
652      char m;
653
654      /* Check first 4 bytes of the image to decide if it is UNIF or iNES */
655      /* Unfortunately, many .unf files have been released as .nes, so we cannot rely on extensions only */
656      memset(magic, '\0', sizeof(magic));
657      image.fread(magic, 4);
658
659      if ((magic[0] == 'N') && (magic[1] == 'E') && (magic[2] == 'S'))   /* If header starts with 'NES' it is iNES */
660      {
661         UINT32 prg_size;
662         state->m_ines20 = 0;
663         state->m_battery_size = NES_BATTERY_SIZE; // with iNES we can only support 8K WRAM battery (iNES 2.0 might fix this)
664         state->m_prg_ram = 1;   // always map state->m_wram in bank5 (eventually, this should be enabled only for some mappers)
665
666         // check if the image is recognized by nes.hsi
667         mapinfo = hashfile_extrainfo(image);
668
669         // image_extrainfo() resets the file position back to start.
670         // Let's skip past the magic header once again.
671         image.fseek(4, SEEK_SET);
672
673         image.fread(&state->m_prg_chunks, 1);
674         image.fread(&state->m_chr_chunks, 1);
675         /* Read the first ROM option byte (offset 6) */
676         image.fread(&m, 1);
677
678         /* Interpret the iNES header flags */
679         state->m_mapper = (m & 0xf0) >> 4;
680         local_options = m & 0x0f;
681
682         /* Read the second ROM option byte (offset 7) */
683         image.fread(&m, 1);
684
685         switch (m & 0xc)
686         {
687            case 0x4:
688            case 0xc:
689               // probably the header got corrupted: don't trust upper bits for mapper
690               break;
691
692            case 0x8:   // it's iNES 2.0 format
693               state->m_ines20 = 1;
694            case 0x0:
695            default:
696               state->m_mapper = state->m_mapper | (m & 0xf0);
697               break;
698         }
699
700         if (mapinfo /* && !state->m_ines20 */)
701         {
702            if (4 == sscanf(mapinfo,"%d %d %d %d", &mapint1, &mapint2, &mapint3, &mapint4))
703            {
704               /* image is present in nes.hsi: overwrite the header settings with these */
705               state->m_mapper = mapint1;
706               local_options = mapint2 & 0x0f;
707               state->m_crc_hack = (mapint2 & 0xf0) >> 4;   // this is used to differentiate among variants of the same Mapper (see below)
708               state->m_prg_chunks = mapint3;
709               state->m_chr_chunks = mapint4;
710               logerror("NES.HSI info: %d %d %d %d\n", mapint1, mapint2, mapint3, mapint4);
711//                  mame_printf_error("NES.HSI info: %d %d %d %d\n", mapint1, mapint2, mapint3, mapint4);
712               goodcrcinfo = 1;
713               state->m_ines20 = 0;
714            }
715            else
716            {
717               logerror("NES: [%s], Invalid mapinfo found\n", mapinfo);
718            }
719         }
720         else
721         {
722            logerror("NES: No extrainfo found\n");
723         }
724
725         state->m_hard_mirroring = (local_options & 0x01) ? PPU_MIRROR_VERT : PPU_MIRROR_HORZ;
726//          mame_printf_error("%s\n", state->m_hard_mirroring & 0x01 ? "Vertical" : "Horizontal");
727         state->m_battery = local_options & 0x02;
728         state->m_trainer = local_options & 0x04;
729         state->m_four_screen_vram = local_options & 0x08;
730
731         if (state->m_battery)
732            logerror("-- Battery found\n");
733
734         if (state->m_trainer)
735            logerror("-- Trainer found\n");
736
737         if (state->m_four_screen_vram)
738            logerror("-- 4-screen VRAM\n");
739
740         if (state->m_ines20)
741         {
742            logerror("Extended iNES format:\n");
743            image.fread(&extend, 5);
744            state->m_mapper |= (extend[0] & 0x0f) << 8;
745            logerror("-- mapper: %d\n", state->m_mapper);
746            logerror("-- submapper: %d\n", (extend[0] & 0xf0) >> 4);
747            state->m_prg_chunks |= ((extend[1] & 0x0f) << 8);
748            state->m_chr_chunks |= ((extend[1] & 0xf0) << 4);
749            logerror("-- PRG chunks: %d\n", state->m_prg_chunks);
750            logerror("-- CHR chunks: %d\n", state->m_chr_chunks);
751            logerror("-- PRG NVWRAM: %d\n", extend[2] & 0x0f);
752            logerror("-- PRG WRAM: %d\n", (extend[2] & 0xf0) >> 4);
753            logerror("-- CHR NVWRAM: %d\n", extend[3] & 0x0f);
754            logerror("-- CHR WRAM: %d\n", (extend[3] & 0xf0) >> 4);
755            logerror("-- TV System: %d\n", extend[4] & 3);
756         }
757
758         /* Free the regions that were allocated by the ROM loader */
759         image.device().machine().region_free("maincpu");
760         image.device().machine().region_free("gfx1");
761
762         /* Allocate them again with the proper size */
763         prg_size = (state->m_prg_chunks == 1) ? 2 * 0x4000 : state->m_prg_chunks * 0x4000;
764         image.device().machine().region_alloc("maincpu", 0x10000 + prg_size, 1, ENDIANNESS_LITTLE);
765         if (state->m_chr_chunks)
766            image.device().machine().region_alloc("gfx1", state->m_chr_chunks * 0x2000, 1, ENDIANNESS_LITTLE);
767
768         state->m_rom = image.device().machine().region("maincpu")->base();
769         state->m_vrom = image.device().machine().region("gfx1")->base();
770
771         state->m_vram_chunks = image.device().machine().region("gfx2")->bytes() / 0x2000;
772         state->m_vram = image.device().machine().region("gfx2")->base();
773         // FIXME: this should only be allocated if there is actual wram in the cart (i.e. if state->m_prg_ram = 1)!
774         // or if there is a trainer, I think
775         state->m_wram_size = 0x10000;
776         state->m_wram = auto_alloc_array(image.device().machine(), UINT8, state->m_wram_size);
777
778         /* Setup PCB type (needed to add proper handlers later) */
779         state->m_pcb_id = nes_get_mmc_id(image.device().machine(), state->m_mapper);
780
781         // a few mappers correspond to multiple PCBs, so we need a few additional checks
782         switch (state->m_pcb_id)
783         {
784            case STD_CNROM:
785               if (state->m_mapper == 185)
786               {
787                  switch (state->m_crc_hack)
788                  {
789                     case 0x0: // pin26: CE, pin27: CE (B-Wings, Bird Week)
790                        state->m_ce_mask = 0x03;
791                        state->m_ce_state = 0x03;
792                        break;
793                     case 0x4: // pin26: CE, pin27: /CE (Mighty Bomb Jack, Spy Vs. Spy)
794                        state->m_ce_mask = 0x03;
795                        state->m_ce_state = 0x01;
796                        break;
797                     case 0x8: // pin26: /CE, pin27: CE (Sansu 1, 2, 3 Nen)
798                        state->m_ce_mask = 0x03;
799                        state->m_ce_state = 0x02;
800                        break;
801                     case 0xc: // pin26: /CE, pin27: /CE (Seicross v2.0)
802                        state->m_ce_mask = 0x03;
803                        state->m_ce_state = 0x00;
804                        break;
805                  }
806               }
807               break;
808            case KONAMI_VRC2:
809               if (state->m_mapper == 22)
810               {
811                  state->m_vrc_ls_prg_a = 0;
812                  state->m_vrc_ls_prg_b = 1;
813                  state->m_vrc_ls_chr = 1;
814               }
815               if (state->m_mapper == 23 && !state->m_crc_hack)
816               {
817                  state->m_vrc_ls_prg_a = 1;
818                  state->m_vrc_ls_prg_b = 0;
819                  state->m_vrc_ls_chr = 0;
820               }
821               if (state->m_mapper == 23 && state->m_crc_hack)
822               {
823                  // here there are also Akumajou Special, Crisis Force, Parodius da!, Tiny Toons which are VRC-4
824                  state->m_vrc_ls_prg_a = 3;
825                  state->m_vrc_ls_prg_b = 2;
826                  state->m_pcb_id = KONAMI_VRC4; // this allows for konami_irq to be installed at reset
827               }
828               break;
829            case KONAMI_VRC4:
830               if (state->m_mapper == 21)
831               {
832                  // Wai Wai World 2 & Ganbare Goemon Gaiden 2 (the latter with crc_hack)
833                  state->m_vrc_ls_prg_a = state->m_crc_hack ? 7 : 2;
834                  state->m_vrc_ls_prg_b = state->m_crc_hack ? 6 : 1;
835               }
836               if (state->m_mapper == 25)   // here there is also Ganbare Goemon Gaiden which is VRC-2
837               {
838                  state->m_vrc_ls_prg_a = state->m_crc_hack ? 2 : 0;
839                  state->m_vrc_ls_prg_b = state->m_crc_hack ? 3 : 1;
840               }
841               break;
842            case KONAMI_VRC6:
843               if (state->m_mapper == 24)
844               {
845                  state->m_vrc_ls_prg_a = 1;
846                  state->m_vrc_ls_prg_b = 0;
847               }
848               if (state->m_mapper == 26)
849               {
850                  state->m_vrc_ls_prg_a = 0;
851                  state->m_vrc_ls_prg_b = 1;
852               }
853               break;
854            case IREM_G101:
855               if (state->m_crc_hack)
856                  state->m_hard_mirroring = PPU_MIRROR_HIGH;   // Major League has hardwired mirroring
857               break;
858            case DIS_74X161X161X32:
859               if (state->m_mapper == 70)
860                  state->m_hard_mirroring = PPU_MIRROR_VERT;   // only hardwired mirroring makes different mappers 70 & 152
861               break;
862            case SUNSOFT_2:
863               if (state->m_mapper == 93)
864                  state->m_hard_mirroring = PPU_MIRROR_VERT;   // only hardwired mirroring makes different mappers 89 & 93
865               break;
866            case STD_BXROM:
867               if (state->m_crc_hack)
868                  state->m_pcb_id = AVE_NINA01;   // Mapper 34 is used for 2 diff boards
869               break;
870            case BANDAI_LZ93:
871               if (state->m_crc_hack)
872                  state->m_pcb_id = BANDAI_JUMP2;   // Mapper 153 is used for 2 diff boards
873               break;
874            case IREM_HOLYDIV:
875               if (state->m_crc_hack)
876                  state->m_pcb_id = JALECO_JF16;   // Mapper 78 is used for 2 diff boards
877               break;
878            case CAMERICA_BF9093:
879               if (state->m_crc_hack)
880                  state->m_pcb_id = CAMERICA_BF9097;   // Mapper 71 is used for 2 diff boards
881               break;
882            case HES_BOARD:
883               if (state->m_crc_hack)
884                  state->m_pcb_id = HES6IN1_BOARD;   // Mapper 113 is used for 2 diff boards
885               break;
886            case WAIXING_ZS:
887               if (state->m_crc_hack)
888                  state->m_pcb_id = WAIXING_DQ8;   // Mapper 242 is used for 2 diff boards
889               break;
890            //FIXME: we also have to fix Action 52 PRG loading somewhere...
891         }
892
893         /* Allocate internal Mapper RAM for boards which require it */
894         if (state->m_pcb_id == STD_EXROM)
895            state->m_mapper_ram = auto_alloc_array(image.device().machine(), UINT8, 0x400);
896
897         if (state->m_pcb_id == TAITO_X1_005 || state->m_pcb_id == TAITO_X1_005_A)
898            state->m_mapper_bram = auto_alloc_array(image.device().machine(), UINT8, 0x80);
899
900         if (state->m_pcb_id == TAITO_X1_017)
901            state->m_mapper_bram = auto_alloc_array(image.device().machine(), UINT8, 0x1400);
902
903         if (state->m_pcb_id == NAMCOT_163)
904            state->m_mapper_ram = auto_alloc_array(image.device().machine(), UINT8, 0x2000);
905
906         if (state->m_pcb_id == FUKUTAKE_BOARD)
907            state->m_mapper_ram = auto_alloc_array(image.device().machine(), UINT8, 2816);
908
909         /* Position past the header */
910         image.fseek(16, SEEK_SET);
911
912         /* Load the 0x200 byte trainer at 0x7000 if it exists */
913         if (state->m_trainer)
914            image.fread(&state->m_wram[0x1000], 0x200);
915
916         /* Read in the program chunks */
917         image.fread(&state->m_rom[0x10000], 0x4000 * state->m_prg_chunks);
918         if (state->m_prg_chunks == 1)
919            memcpy(&state->m_rom[0x14000], &state->m_rom[0x10000], 0x4000);
920
921#if SPLIT_PRG
922         {
923            FILE *prgout;
924            char outname[255];
925
926            sprintf(outname, "%s.prg", image.filename());
927            prgout = fopen(outname, "wb");
928            if (prgout)
929            {
930               fwrite(&state->m_rom[0x10000], 1, 0x4000 * state->m_prg_chunks, prgout);
931               mame_printf_error("Created PRG chunk\n");
932            }
933
934            fclose(prgout);
935         }
936#endif
937
938         logerror("**\n");
939         logerror("Mapper: %d\n", state->m_mapper);
940         logerror("PRG chunks: %02x, size: %06x\n", state->m_prg_chunks, 0x4000 * state->m_prg_chunks);
941         // mame_printf_error("Mapper: %d\n", state->m_mapper);
942         // mame_printf_error("PRG chunks: %02x, size: %06x\n", state->m_prg_chunks, 0x4000 * state->m_prg_chunks);
943
944         /* Read in any chr chunks */
945         if (state->m_chr_chunks > 0)
946         {
947            image.fread(state->m_vrom, state->m_chr_chunks * 0x2000);
948            if (state->m_mapper == 2)
949               logerror("Warning: VROM has been found in VRAM-based mapper. Either the mapper is set wrong or the ROM image is incorrect.\n");
950         }
951
952#if SPLIT_CHR
953         if (state->m_chr_chunks > 0)
954         {
955            FILE *chrout;
956            char outname[255];
957
958            sprintf(outname, "%s.chr", image.filename());
959            chrout= fopen(outname, "wb");
960            if (chrout)
961            {
962               fwrite(state->m_vrom, 1, 0x2000 * state->m_chr_chunks, chrout);
963               mame_printf_error("Created CHR chunk\n");
964            }
965            fclose(chrout);
966         }
967#endif
968
969         logerror("CHR chunks: %02x, size: %06x\n", state->m_chr_chunks, 0x2000 * state->m_chr_chunks);
970         logerror("**\n");
971         // mame_printf_error("CHR chunks: %02x, size: %06x\n", state->m_chr_chunks, 0x2000 * state->m_chr_chunks);
972         // mame_printf_error("**\n");
973      }
974      else if ((magic[0] == 'U') && (magic[1] == 'N') && (magic[2] == 'I') && (magic[3] == 'F')) /* If header starts with 'UNIF' it is UNIF */
975      {
976         UINT32 unif_ver = 0;
977         char magic2[4];
978         UINT8 buffer[4];
979         UINT32 chunk_length = 0, read_length = 0x20;
980         UINT32 prg_start = 0, chr_start = 0, prg_size;
981         char unif_mapr[32];   // here we should store MAPR chunks
982         UINT32 size = image.length();
983         int mapr_chunk_found = 0;
984         // allocate space to temporarily store PRG & CHR banks
985         UINT8 *temp_prg = auto_alloc_array(image.device().machine(), UINT8, 256 * 0x4000);
986         UINT8 *temp_chr = auto_alloc_array(image.device().machine(), UINT8, 256 * 0x2000);
987         UINT8 temp_byte = 0;
988
989         /* init prg/chr chunks to 0: the exact number of chunks will be determined while reading the file */
990         state->m_prg_chunks = 0;
991         state->m_chr_chunks = 0;
992
993         image.fread(&buffer, 4);
994         unif_ver = buffer[0] | (buffer[1] << 8) | (buffer[2] << 16) | (buffer[3] << 24);
995         logerror("UNIF file found, version %d\n", unif_ver);
996
997         if (size <= 0x20)
998         {
999            logerror("%s only contains the UNIF header and no data.\n", image.filename());
1000            return IMAGE_INIT_FAIL;
1001         }
1002
1003         do
1004         {
1005            image.fseek(read_length, SEEK_SET);
1006
1007            memset(magic2, '\0', sizeof(magic2));
1008            image.fread(&magic2, 4);
1009
1010            /* We first run through the whole image to find a [MAPR] chunk. This is needed
1011                 because, unfortunately, the MAPR chunk is not always the first chunk (see
1012                 Super 24-in-1). When such a chunk is found, we set mapr_chunk_found=1 and
1013                 we go back to load other chunks! */
1014            if (!mapr_chunk_found)
1015            {
1016               if ((magic2[0] == 'M') && (magic2[1] == 'A') && (magic2[2] == 'P') && (magic2[3] == 'R'))
1017               {
1018                  mapr_chunk_found = 1;
1019                  logerror("[MAPR] chunk found: ");
1020                  image.fread(&buffer, 4);
1021                  chunk_length = buffer[0] | (buffer[1] << 8) | (buffer[2] << 16) | (buffer[3] << 24);
1022
1023                  if (chunk_length <= 0x20)
1024                     image.fread(&unif_mapr, chunk_length);
1025
1026                  // find out prg/chr size, battery, wram, etc.
1027                  unif_mapr_setup(image.device().machine(), unif_mapr);
1028
1029                  /* now that we found the MAPR chunk, we can go back to load other chunks */
1030                  image.fseek(0x20, SEEK_SET);
1031                  read_length = 0x20;
1032               }
1033               else
1034               {
1035                  logerror("Skip this chunk. We need a [MAPR] chunk before anything else.\n");
1036                  image.fread(&buffer, 4);
1037                  chunk_length = buffer[0] | (buffer[1] << 8) | (buffer[2] << 16) | (buffer[3] << 24);
1038
1039                  read_length += (chunk_length + 8);
1040               }
1041            }
1042            else
1043            {
1044               /* What kind of chunk do we have here? */
1045               if ((magic2[0] == 'M') && (magic2[1] == 'A') && (magic2[2] == 'P') && (magic2[3] == 'R'))
1046               {
1047                  /* The [MAPR] chunk has already been read, so we skip it */
1048                  /* TO DO: it would be nice to check if more than one MAPR chunk is present */
1049                  logerror("[MAPR] chunk found (in the 2nd run). Already loaded.\n");
1050                  image.fread(&buffer, 4);
1051                  chunk_length = buffer[0] | (buffer[1] << 8) | (buffer[2] << 16) | (buffer[3] << 24);
1052
1053                  read_length += (chunk_length + 8);
1054               }
1055               else if ((magic2[0] == 'R') && (magic2[1] == 'E') && (magic2[2] == 'A') && (magic2[3] == 'D'))
1056               {
1057                  logerror("[READ] chunk found. No support yet.\n");
1058                  image.fread(&buffer, 4);
1059                  chunk_length = buffer[0] | (buffer[1] << 8) | (buffer[2] << 16) | (buffer[3] << 24);
1060
1061                  read_length += (chunk_length + 8);
1062               }
1063               else if ((magic2[0] == 'N') && (magic2[1] == 'A') && (magic2[2] == 'M') && (magic2[3] == 'E'))
1064               {
1065                  logerror("[NAME] chunk found. No support yet.\n");
1066                  image.fread(&buffer, 4);
1067                  chunk_length = buffer[0] | (buffer[1] << 8) | (buffer[2] << 16) | (buffer[3] << 24);
1068
1069                  read_length += (chunk_length + 8);
1070               }
1071               else if ((magic2[0] == 'W') && (magic2[1] == 'R') && (magic2[2] == 'T') && (magic2[3] == 'R'))
1072               {
1073                  logerror("[WRTR] chunk found. No support yet.\n");
1074                  image.fread(&buffer, 4);
1075                  chunk_length = buffer[0] | (buffer[1] << 8) | (buffer[2] << 16) | (buffer[3] << 24);
1076
1077                  read_length += (chunk_length + 8);
1078               }
1079               else if ((magic2[0] == 'T') && (magic2[1] == 'V') && (magic2[2] == 'C') && (magic2[3] == 'I'))
1080               {
1081                  logerror("[TVCI] chunk found.\n");
1082                  image.fread(&buffer, 4);
1083                  chunk_length = buffer[0] | (buffer[1] << 8) | (buffer[2] << 16) | (buffer[3] << 24);
1084
1085                  image.fread(&temp_byte, 1);
1086                  logerror("Television Standard : %s\n", (temp_byte == 0) ? "NTSC" : (temp_byte == 1) ? "PAL" : "Does not matter");
1087
1088                  read_length += (chunk_length + 8);
1089               }
1090               else if ((magic2[0] == 'T') && (magic2[1] == 'V') && (magic2[2] == 'S') && (magic2[3] == 'C')) // is this the same as TVCI??
1091               {
1092                  logerror("[TVSC] chunk found. No support yet.\n");
1093                  image.fread(&buffer, 4);
1094                  chunk_length = buffer[0] | (buffer[1] << 8) | (buffer[2] << 16) | (buffer[3] << 24);
1095
1096                  read_length += (chunk_length + 8);
1097               }
1098               else if ((magic2[0] == 'D') && (magic2[1] == 'I') && (magic2[2] == 'N') && (magic2[3] == 'F'))
1099               {
1100                  logerror("[DINF] chunk found. No support yet.\n");
1101                  image.fread(&buffer, 4);
1102                  chunk_length = buffer[0] | (buffer[1] << 8) | (buffer[2] << 16) | (buffer[3] << 24);
1103
1104                  read_length += (chunk_length + 8);
1105               }
1106               else if ((magic2[0] == 'C') && (magic2[1] == 'T') && (magic2[2] == 'R') && (magic2[3] == 'L'))
1107               {
1108                  logerror("[CTRL] chunk found. No support yet.\n");
1109                  image.fread(&buffer, 4);
1110                  chunk_length = buffer[0] | (buffer[1] << 8) | (buffer[2] << 16) | (buffer[3] << 24);
1111
1112                  read_length += (chunk_length + 8);
1113               }
1114               else if ((magic2[0] == 'B') && (magic2[1] == 'A') && (magic2[2] == 'T') && (magic2[3] == 'R'))
1115               {
1116                  logerror("[BATR] chunk found. No support yet.\n");
1117                  image.fread(&buffer, 4);
1118                  chunk_length = buffer[0] | (buffer[1] << 8) | (buffer[2] << 16) | (buffer[3] << 24);
1119
1120                  read_length += (chunk_length + 8);
1121               }
1122               else if ((magic2[0] == 'V') && (magic2[1] == 'R') && (magic2[2] == 'O') && (magic2[3] == 'R'))
1123               {
1124                  logerror("[VROR] chunk found. No support yet.\n");
1125                  image.fread(&buffer, 4);
1126                  chunk_length = buffer[0] | (buffer[1] << 8) | (buffer[2] << 16) | (buffer[3] << 24);
1127
1128                  read_length += (chunk_length + 8);
1129               }
1130               else if ((magic2[0] == 'M') && (magic2[1] == 'I') && (magic2[2] == 'R') && (magic2[3] == 'R'))
1131               {
1132                  logerror("[MIRR] chunk found.\n");
1133                  image.fread(&buffer, 4);
1134                  chunk_length = buffer[0] | (buffer[1] << 8) | (buffer[2] << 16) | (buffer[3] << 24);
1135
1136                  image.fread(&temp_byte, 1);
1137                  switch (temp_byte)
1138                  {
1139                     case 0:   // Horizontal Mirroring (Hard Wired)
1140                        state->m_hard_mirroring = PPU_MIRROR_HORZ;
1141                        break;
1142                     case 1:   // Vertical Mirroring (Hard Wired)
1143                        state->m_hard_mirroring = PPU_MIRROR_VERT;
1144                        break;
1145                     case 2:   // Mirror All Pages From $2000 (Hard Wired)
1146                        state->m_hard_mirroring = PPU_MIRROR_LOW;
1147                        break;
1148                     case 3:   // Mirror All Pages From $2400 (Hard Wired)
1149                        state->m_hard_mirroring = PPU_MIRROR_HIGH;
1150                        break;
1151                     case 4:   // Four Screens of VRAM (Hard Wired)
1152                        state->m_four_screen_vram = 1;
1153                        break;
1154                     case 5:   // Mirroring Controlled By Mapper Hardware
1155                        logerror("Mirroring handled by the board hardware.\n");
1156                        // default to horizontal at start
1157                        state->m_hard_mirroring = PPU_MIRROR_HORZ;
1158                        break;
1159                     default:
1160                        logerror("Undocumented mirroring value.\n");
1161                        // default to horizontal
1162                        state->m_hard_mirroring = PPU_MIRROR_HORZ;
1163                        break;
1164                  }
1165
1166                  read_length += (chunk_length + 8);
1167               }
1168               else if ((magic2[0] == 'P') && (magic2[1] == 'C') && (magic2[2] == 'K'))
1169               {
1170                  logerror("[PCK%c] chunk found. No support yet.\n", magic2[3]);
1171                  image.fread(&buffer, 4);
1172                  chunk_length = buffer[0] | (buffer[1] << 8) | (buffer[2] << 16) | (buffer[3] << 24);
1173
1174                  read_length += (chunk_length + 8);
1175               }
1176               else if ((magic2[0] == 'C') && (magic2[1] == 'C') && (magic2[2] == 'K'))
1177               {
1178                  logerror("[CCK%c] chunk found. No support yet.\n", magic2[3]);
1179                  image.fread(&buffer, 4);
1180                  chunk_length = buffer[0] | (buffer[1] << 8) | (buffer[2] << 16) | (buffer[3] << 24);
1181
1182                  read_length += (chunk_length + 8);
1183               }
1184               else if ((magic2[0] == 'P') && (magic2[1] == 'R') && (magic2[2] == 'G'))
1185               {
1186                  logerror("[PRG%c] chunk found. ", magic2[3]);
1187                  image.fread(&buffer, 4);
1188                  chunk_length = buffer[0] | (buffer[1] << 8) | (buffer[2] << 16) | (buffer[3] << 24);
1189
1190                  // FIXME: we currently don't support PRG chunks smaller than 16K!
1191                  state->m_prg_chunks += (chunk_length / 0x4000);
1192
1193                  if (chunk_length / 0x4000)
1194                     logerror("It consists of %d 16K-blocks.\n", chunk_length / 0x4000);
1195                  else
1196                     logerror("This chunk is smaller than 16K: the emulation might have issues. Please report this file to the MESS forums.\n");
1197
1198                  /* Read in the program chunks */
1199                  image.fread(&temp_prg[prg_start], chunk_length);
1200
1201                  prg_start += chunk_length;
1202                  read_length += (chunk_length + 8);
1203               }
1204               else if ((magic2[0] == 'C') && (magic2[1] == 'H') && (magic2[2] == 'R'))
1205               {
1206                  logerror("[CHR%c] chunk found. ", magic2[3]);
1207                  image.fread(&buffer, 4);
1208                  chunk_length = buffer[0] | (buffer[1] << 8) | (buffer[2] << 16) | (buffer[3] << 24);
1209
1210                  state->m_chr_chunks += (chunk_length / 0x2000);
1211
1212                  logerror("It consists of %d 8K-blocks.\n", chunk_length / 0x2000);
1213
1214                  /* Read in the vrom chunks */
1215                  image.fread(&temp_chr[chr_start], chunk_length);
1216
1217                  chr_start += chunk_length;
1218                  read_length += (chunk_length + 8);
1219               }
1220               else
1221               {
1222                  logerror("Unsupported UNIF chunk or corrupted header. Please report the problem at MESS Board.\n");
1223                  read_length = size;
1224               }
1225            }
1226         } while (size > read_length);
1227
1228         if (!mapr_chunk_found)
1229         {
1230            auto_free(image.device().machine(), temp_prg);
1231            auto_free(image.device().machine(), temp_chr);
1232            fatalerror("UNIF should have a [MAPR] chunk to work. Check if your image has been corrupted");
1233         }
1234
1235         if (!prg_start)
1236         {
1237            auto_free(image.device().machine(), temp_prg);
1238            auto_free(image.device().machine(), temp_chr);
1239            fatalerror("Unsupported UNIF chunk or corrupted header. Please report the problem at MESS Board.\n");
1240         }
1241
1242         /* Free the regions that were allocated by the ROM loader */
1243         image.device().machine().region_free("maincpu");
1244         image.device().machine().region_free("gfx1");
1245         image.device().machine().region_free("gfx2");
1246
1247         /* Allocate them again, and copy PRG/CHR from temp buffers */
1248         /* Take care of PRG */
1249         prg_size = (state->m_prg_chunks == 1) ? 2 * 0x4000 : state->m_prg_chunks * 0x4000;
1250         image.device().machine().region_alloc("maincpu", 0x10000 + prg_size, 1, ENDIANNESS_LITTLE);
1251         state->m_rom = image.device().machine().region("maincpu")->base();
1252         memcpy(&state->m_rom[0x10000], &temp_prg[0x00000], state->m_prg_chunks * 0x4000);
1253         /* If only a single 16K PRG chunk is present, mirror it! */
1254         if (state->m_prg_chunks == 1)
1255            memcpy(&state->m_rom[0x14000], &state->m_rom[0x10000], 0x4000);
1256
1257         /* Take care of CHR ROM */
1258         if (state->m_chr_chunks)
1259         {
1260            image.device().machine().region_alloc("gfx1", state->m_chr_chunks * 0x2000, 1, ENDIANNESS_LITTLE);
1261            state->m_vrom = image.device().machine().region("gfx1")->base();
1262            memcpy(&state->m_vrom[0x00000], &temp_chr[0x00000], state->m_chr_chunks * 0x2000);
1263         }
1264
1265         /* Take care of CHR RAM */
1266         if (state->m_vram_chunks)
1267         {
1268            image.device().machine().region_alloc("gfx2", state->m_vram_chunks * 0x2000, 1, ENDIANNESS_LITTLE);
1269            state->m_vram = image.device().machine().region("gfx2")->base();
1270         }
1271
1272         // FIXME: this should only be allocated if there is actual wram in the cart (i.e. if state->m_prg_ram = 1)!
1273         state->m_wram_size = 0x10000;
1274         state->m_wram = auto_alloc_array(image.device().machine(), UINT8, state->m_wram_size);
1275
1276#if SPLIT_PRG
1277         {
1278            FILE *prgout;
1279            char outname[255];
1280
1281            sprintf(outname, "%s.prg", image.filename());
1282            prgout = fopen(outname, "wb");
1283            if (prgout)
1284            {
1285               fwrite(&state->m_rom[0x10000], 1, 0x4000 * state->m_prg_chunks, prgout);
1286               mame_printf_error("Created PRG chunk\n");
1287            }
1288
1289            fclose(prgout);
1290         }
1291#endif
1292
1293#if SPLIT_CHR
1294         if (state->m_chr_chunks > 0)
1295         {
1296            FILE *chrout;
1297            char outname[255];
1298
1299            sprintf(outname, "%s.chr", image.filename());
1300            chrout= fopen(outname, "wb");
1301            if (chrout)
1302            {
1303               fwrite(state->m_vrom, 1, 0x2000 * state->m_chr_chunks, chrout);
1304               mame_printf_error("Created CHR chunk\n");
1305            }
1306            fclose(chrout);
1307         }
1308#endif
1309         // free the temporary copy of PRG/CHR
1310         auto_free(image.device().machine(), temp_prg);
1311         auto_free(image.device().machine(), temp_chr);
1312         logerror("UNIF support is only very preliminary.\n");
1313      }
1314      else
1315      {
1316         logerror("%s is NOT a file in either iNES or UNIF format.\n", image.filename());
1317         return IMAGE_INIT_FAIL;
1318      }
1319   }
1320   else
1321   {
1322      UINT32 prg_size = image.get_software_region_length("prg");
1323      UINT32 chr_size = image.get_software_region_length("chr");
1324      UINT32 vram_size = image.get_software_region_length("vram");
1325      vram_size += image.get_software_region_length("vram2");
1326
1327      /* Free the regions that were allocated by the ROM loader */
1328      image.device().machine().region_free("maincpu");
1329      image.device().machine().region_free("gfx1");
1330      image.device().machine().region_free("gfx2");
1331
1332      /* Allocate them again with the proper size */
1333      image.device().machine().region_alloc("maincpu", 0x10000 + prg_size, 1, ENDIANNESS_LITTLE);
1334
1335      // validate the xml fields
1336      if (!prg_size)
1337         fatalerror("No PRG entry for this software! Please check if the xml list got corrupted");
1338      if (prg_size < 0x8000)
1339         fatalerror("PRG entry is too small! Please check if the xml list got corrupted");
1340
1341      if (chr_size)
1342         image.device().machine().region_alloc("gfx1", chr_size, 1, ENDIANNESS_LITTLE);
1343
1344      if (vram_size)
1345         image.device().machine().region_alloc("gfx2", vram_size, 1, ENDIANNESS_LITTLE);
1346
1347      state->m_rom = image.device().machine().region("maincpu")->base();
1348      state->m_vrom = image.device().machine().region("gfx1")->base();
1349      state->m_vram = image.device().machine().region("gfx2")->base();
1350
1351      memcpy(state->m_rom + 0x10000, image.get_software_region("prg"), prg_size);
1352
1353      if (chr_size)
1354         memcpy(state->m_vrom, image.get_software_region("chr"), chr_size);
1355
1356      state->m_prg_chunks = prg_size / 0x4000;
1357      state->m_chr_chunks = chr_size / 0x2000;
1358      state->m_vram_chunks = vram_size / 0x2000;
1359
1360      state->m_pcb_id = nes_get_pcb_id(image.device().machine(), image.get_feature("pcb"));
1361
1362      if (state->m_pcb_id == STD_TVROM || state->m_pcb_id == STD_DRROM || state->m_pcb_id == IREM_LROG017)
1363         state->m_four_screen_vram = 1;
1364      else
1365         state->m_four_screen_vram = 0;
1366
1367      state->m_battery = (image.get_software_region("bwram") != NULL) ? 1 : 0;
1368      state->m_battery_size = image.get_software_region_length("bwram");
1369
1370      if (state->m_pcb_id == BANDAI_LZ93EX)
1371      {
1372         // allocate the 24C01 or 24C02 EEPROM
1373         state->m_battery = 1;
1374         state->m_battery_size += 0x2000;
1375      }
1376
1377      if (state->m_pcb_id == BANDAI_DATACH)
1378      {
1379         // allocate the 24C01 and 24C02 EEPROM
1380         state->m_battery = 1;
1381         state->m_battery_size += 0x4000;
1382      }
1383
1384      state->m_prg_ram = (image.get_software_region("wram") != NULL) ? 1 : 0;
1385      state->m_wram_size = image.get_software_region_length("wram");
1386      state->m_mapper_ram_size = image.get_software_region_length("mapper_ram");
1387      state->m_mapper_bram_size = image.get_software_region_length("mapper_bram");
1388
1389      if (state->m_prg_ram)
1390         state->m_wram = auto_alloc_array(image.device().machine(), UINT8, state->m_wram_size);
1391      if (state->m_mapper_ram_size)
1392         state->m_mapper_ram = auto_alloc_array(image.device().machine(), UINT8, state->m_mapper_ram_size);
1393      if (state->m_mapper_bram_size)
1394         state->m_mapper_bram = auto_alloc_array(image.device().machine(), UINT8, state->m_mapper_bram_size);
1395
1396      /* Check for mirroring */
1397      if (image.get_feature("mirroring") != NULL)
1398      {
1399         const char *mirroring = image.get_feature("mirroring");
1400         if (!strcmp(mirroring, "horizontal"))
1401            state->m_hard_mirroring = PPU_MIRROR_HORZ;
1402         if (!strcmp(mirroring, "vertical"))
1403            state->m_hard_mirroring = PPU_MIRROR_VERT;
1404         if (!strcmp(mirroring, "high"))
1405            state->m_hard_mirroring = PPU_MIRROR_HIGH;
1406         if (!strcmp(mirroring, "low"))
1407            state->m_hard_mirroring = PPU_MIRROR_LOW;
1408      }
1409
1410      state->m_chr_open_bus = 0;
1411      state->m_ce_mask = 0;
1412      state->m_ce_state = 0;
1413      state->m_vrc_ls_prg_a = 0;
1414      state->m_vrc_ls_prg_b = 0;
1415      state->m_vrc_ls_chr = 0;
1416
1417      /* Check for pins in specific boards which require them */
1418      if (state->m_pcb_id == STD_CNROM)
1419      {
1420         if (image.get_feature("chr-pin26") != NULL)
1421         {
1422            state->m_ce_mask |= 0x01;
1423            state->m_ce_state |= !strcmp(image.get_feature("chr-pin26"), "CE") ? 0x01 : 0;
1424         }
1425         if (image.get_feature("chr-pin27") != NULL)
1426         {
1427            state->m_ce_mask |= 0x02;
1428            state->m_ce_state |= !strcmp(image.get_feature("chr-pin27"), "CE") ? 0x02 : 0;
1429         }
1430      }
1431
1432      if (state->m_pcb_id == TAITO_X1_005 && image.get_feature("x1-pin17") != NULL && image.get_feature("x1-pin31") != NULL)
1433      {
1434         if (!strcmp(image.get_feature("x1-pin17"), "CIRAM A10") && !strcmp(image.get_feature("x1-pin31"), "NC"))
1435            state->m_pcb_id = TAITO_X1_005_A;
1436      }
1437
1438      if (state->m_pcb_id == KONAMI_VRC2)
1439      {
1440         state->m_vrc_ls_prg_a = nes_cart_get_line(image.get_feature("vrc2-pin3"));
1441         state->m_vrc_ls_prg_b = nes_cart_get_line(image.get_feature("vrc2-pin4"));
1442         state->m_vrc_ls_chr = (nes_cart_get_line(image.get_feature("vrc2-pin21")) != 10) ? 1 : 0;
1443//          mame_printf_error("VRC-2, pin3: A%d, pin4: A%d, pin21: %s\n", state->m_vrc_ls_prg_a, state->m_vrc_ls_prg_b, state->m_vrc_ls_chr ? "NC" : "A10");
1444      }
1445
1446      if (state->m_pcb_id == KONAMI_VRC4)
1447      {
1448         state->m_vrc_ls_prg_a = nes_cart_get_line(image.get_feature("vrc4-pin3"));
1449         state->m_vrc_ls_prg_b = nes_cart_get_line(image.get_feature("vrc4-pin4"));
1450//          mame_printf_error("VRC-4, pin3: A%d, pin4: A%d\n", state->m_vrc_ls_prg_a, state->m_vrc_ls_prg_b);
1451      }
1452
1453      if (state->m_pcb_id == KONAMI_VRC6)
1454      {
1455         state->m_vrc_ls_prg_a = nes_cart_get_line(image.get_feature("vrc6-pin9"));
1456         state->m_vrc_ls_prg_b = nes_cart_get_line(image.get_feature("vrc6-pin10"));
1457//          mame_printf_error("VRC-6, pin9: A%d, pin10: A%d\n", state->m_vrc_ls_prg_a, state->m_vrc_ls_prg_b);
1458      }
1459
1460      /* Check for other misc board variants */
1461      if (state->m_pcb_id == STD_SOROM)
1462      {
1463         if (image.get_feature("mmc1_type") != NULL && !strcmp(image.get_feature("mmc1_type"), "MMC1A"))
1464            state->m_pcb_id = STD_SOROM_A;   // in MMC1-A PRG RAM is always enabled
1465      }
1466
1467      if (state->m_pcb_id == STD_SXROM)
1468      {
1469         if (image.get_feature("mmc1_type") != NULL && !strcmp(image.get_feature("mmc1_type"), "MMC1A"))
1470            state->m_pcb_id = STD_SXROM_A;   // in MMC1-A PRG RAM is always enabled
1471      }
1472
1473      if (state->m_pcb_id == STD_NXROM || state->m_pcb_id == SUNSOFT_DCS)
1474      {
1475         if (image.get_software_region("minicart") != NULL)   // check for dual minicart
1476         {
1477            state->m_pcb_id = SUNSOFT_DCS;
1478            // we shall load somewhere the minicart, but we still do not support this
1479         }
1480      }
1481
1482#if 0
1483      if (state->m_pcb_id == UNSUPPORTED_BOARD)
1484         mame_printf_error("This board (%s) is currently not supported by MESS\n", image.get_feature("pcb"));
1485      mame_printf_error("PCB Feature: %s\n", image.get_feature("pcb"));
1486      mame_printf_error("PRG chunks: %d\n", state->m_prg_chunks);
1487      mame_printf_error("CHR chunks: %d\n", state->m_chr_chunks);
1488      mame_printf_error("VRAM: Present %s, size: %d\n", state->m_vram_chunks ? "Yes" : "No", vram_size);
1489      mame_printf_error("NVWRAM: Present %s, size: %d\n", state->m_battery ? "Yes" : "No", state->m_battery_size);
1490      mame_printf_error("WRAM:   Present %s, size: %d\n", state->m_prg_ram ? "Yes" : "No", state->m_wram_size);
1491#endif
1492   }
1493
1494   // Attempt to load a battery file for this ROM
1495   // A few boards have internal RAM with a battery (MMC6, Taito X1-005 & X1-017, etc.)
1496   if (state->m_battery || state->m_mapper_bram_size)
1497   {
1498      UINT8 *temp_nvram = auto_alloc_array(image.device().machine(), UINT8, state->m_battery_size + state->m_mapper_bram_size);
1499      image.battery_load(temp_nvram, state->m_battery_size + state->m_mapper_bram_size, 0x00);
1500      if (state->m_battery)
1501      {
1502         state->m_battery_ram = auto_alloc_array(image.device().machine(), UINT8, state->m_battery_size);
1503         memcpy(state->m_battery_ram, temp_nvram, state->m_battery_size);
1504      }
1505      if (state->m_mapper_bram_size)
1506         memcpy(state->m_mapper_bram, temp_nvram + state->m_battery_size, state->m_mapper_bram_size);
1507
1508      auto_free(image.device().machine(), temp_nvram);
1509   }
1510
1511   return IMAGE_INIT_PASS;
1512}
1513
1514
1515
1516void nes_partialhash(hash_collection &dest, const unsigned char *data,
1517   unsigned long length, const char *functions)
1518{
1519   if (length <= 16)
1520      return;
1521   dest.compute(&data[16], length - 16, functions);
1522}
1523
1524/**************************
1525
1526 Disk System emulation
1527
1528**************************/
1529
1530static void fds_irq( device_t *device, int scanline, int vblank, int blanked )
1531{
1532   nes_state *state = device->machine().driver_data<nes_state>();
1533
1534   if (state->m_IRQ_enable_latch)
1535      device_set_input_line(state->m_maincpu, M6502_IRQ_LINE, HOLD_LINE);
1536
1537   if (state->m_IRQ_enable)
1538   {
1539      if (state->m_IRQ_count <= 114)
1540      {
1541         device_set_input_line(state->m_maincpu, M6502_IRQ_LINE, HOLD_LINE);
1542         state->m_IRQ_enable = 0;
1543         state->m_fds_status0 |= 0x01;
1544      }
1545      else
1546         state->m_IRQ_count -= 114;
1547   }
1548}
1549
1550static READ8_HANDLER( nes_fds_r )
1551{
1552   nes_state *state = space->machine().driver_data<nes_state>();
1553   UINT8 ret = 0x00;
1554
1555   switch (offset)
1556   {
1557      case 0x00: /* $4030 - disk status 0 */
1558         ret = state->m_fds_status0;
1559         /* clear the disk IRQ detect flag */
1560         state->m_fds_status0 &= ~0x01;
1561         break;
1562      case 0x01: /* $4031 - data latch */
1563         /* don't read data if disk is unloaded */
1564         if (state->m_fds_data == NULL)
1565            ret = 0;
1566         else if (state->m_fds_current_side)
1567            ret = state->m_fds_data[(state->m_fds_current_side - 1) * 65500 + state->m_fds_head_position++];
1568         else
1569            ret = 0;
1570         break;
1571      case 0x02: /* $4032 - disk status 1 */
1572         /* return "no disk" status if disk is unloaded */
1573         if (state->m_fds_data == NULL)
1574            ret = 1;
1575         else if (state->m_fds_last_side != state->m_fds_current_side)
1576         {
1577            /* If we've switched disks, report "no disk" for a few reads */
1578            ret = 1;
1579            state->m_fds_count++;
1580            if (state->m_fds_count == 50)
1581            {
1582               state->m_fds_last_side = state->m_fds_current_side;
1583               state->m_fds_count = 0;
1584            }
1585         }
1586         else
1587            ret = (state->m_fds_current_side == 0); /* 0 if a disk is inserted */
1588         break;
1589      case 0x03: /* $4033 */
1590         ret = 0x80;
1591         break;
1592      default:
1593         ret = 0x00;
1594         break;
1595   }
1596
1597   return ret;
1598}
1599
1600static WRITE8_HANDLER( nes_fds_w )
1601{
1602   nes_state *state = space->machine().driver_data<nes_state>();
1603
1604   switch (offset)
1605   {
1606      case 0x00:
1607         state->m_IRQ_count_latch = (state->m_IRQ_count_latch & 0xff00) | data;
1608         break;
1609      case 0x01:
1610         state->m_IRQ_count_latch = (state->m_IRQ_count_latch & 0x00ff) | (data << 8);
1611         break;
1612      case 0x02:
1613         state->m_IRQ_count = state->m_IRQ_count_latch;
1614         state->m_IRQ_enable = data;
1615         break;
1616      case 0x03:
1617         // d0 = sound io (1 = enable)
1618         // d1 = disk io (1 = enable)
1619         break;
1620      case 0x04:
1621         /* write data out to disk */
1622         break;
1623      case 0x05:
1624         state->m_fds_motor_on = BIT(data, 0);
1625
1626         if (BIT(data, 1))
1627            state->m_fds_head_position = 0;
1628
1629         state->m_fds_read_mode = BIT(data, 2);
1630         set_nt_mirroring(space->machine(), BIT(data, 3) ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT);
1631
1632         if ((!(data & 0x40)) && (state->m_fds_write_reg & 0x40))
1633            state->m_fds_head_position -= 2; // ???
1634
1635         state->m_IRQ_enable_latch = BIT(data, 7);
1636         state->m_fds_write_reg = data;
1637         break;
1638   }
1639}
1640
1641static void nes_load_proc( device_image_interface &image )
1642{
1643   nes_state *state = image.device().machine().driver_data<nes_state>();
1644   int header = 0;
1645   state->m_fds_sides = 0;
1646
1647   if (image.length() % 65500)
1648      header = 0x10;
1649
1650   state->m_fds_sides = (image.length() - header) / 65500;
1651
1652   if (state->m_fds_data == NULL)
1653      state->m_fds_data = (UINT8*)image.image_malloc(state->m_fds_sides * 65500);   // I don't think we can arrive here ever, probably it can be removed...
1654
1655   /* if there is an header, skip it */
1656   image.fseek(header, SEEK_SET);
1657
1658   image.fread(state->m_fds_data, 65500 * state->m_fds_sides);
1659   return;
1660}
1661
1662static void nes_unload_proc( device_image_interface &image )
1663{
1664   nes_state *state = image.device().machine().driver_data<nes_state>();
1665
1666   /* TODO: should write out changes here as well */
1667   state->m_fds_sides =  0;
1668}
1669
1670DRIVER_INIT( famicom )
1671{
1672   nes_state *state = machine.driver_data<nes_state>();
1673   int i;
1674
1675   /* clear some of the variables we don't use */
1676   state->m_trainer = 0;
1677   state->m_battery = 0;
1678   state->m_prg_ram = 0;
1679   state->m_four_screen_vram = 0;
1680   state->m_hard_mirroring = 0;
1681   state->m_prg_chunks = state->m_chr_chunks = 0;
1682
1683   /* initialize the disk system */
1684   state->m_disk_expansion = 1;
1685   state->m_pcb_id = NO_BOARD;
1686
1687   state->m_fds_sides = 0;
1688   state->m_fds_last_side = 0;
1689   state->m_fds_count = 0;
1690   state->m_fds_motor_on = 0;
1691   state->m_fds_door_closed = 0;
1692   state->m_fds_current_side = 1;
1693   state->m_fds_head_position = 0;
1694   state->m_fds_status0 = 0;
1695   state->m_fds_read_mode = state->m_fds_write_reg = 0;
1696
1697   state->m_fds_data = auto_alloc_array_clear(machine, UINT8, 65500 * 2);
1698   state->m_fds_ram = auto_alloc_array_clear(machine, UINT8, 0x8000);
1699   state->save_pointer(NAME(state->m_fds_ram), 0x8000);
1700
1701   // setup CHR accesses to 8k VRAM
1702   state->m_vram = machine.region("gfx2")->base();
1703   for (i = 0; i < 8; i++)
1704   {
1705      state->m_chr_map[i].source = CHRRAM;
1706      state->m_chr_map[i].origin = i * 0x400; // for save state uses!
1707      state->m_chr_map[i].access = &state->m_vram[state->m_chr_map[i].origin];
1708   }
1709
1710   floppy_install_load_proc(floppy_get_device(machine, 0), nes_load_proc);
1711   floppy_install_unload_proc(floppy_get_device(machine, 0), nes_unload_proc);
1712}
src/mame/machine/amigacd.h
r11531r11532
1#ifndef __AMIGACD_H__
2#define __AMIGACD_H__
3
4
5MACHINE_START( amigacd );
6MACHINE_RESET( amigacd );
7
8/* 6525tpi */
9READ8_DEVICE_HANDLER( amigacd_tpi6525_portc_r );
10WRITE8_DEVICE_HANDLER( amigacd_tpi6525_portb_w );
11WRITE_LINE_DEVICE_HANDLER( amigacd_tpi6525_irq );
12
13
14#endif /* __AMIGACD_H__ */
src/mame/machine/nes_unif.c
r11531r11532
1/*****************************************************************************************
2
3    NES MMC Emulation - UNIF boards
4
5    Very preliminary support for UNIF boards
6
7    TODO:
8    - properly support WRAM, etc.
9
10****************************************************************************************/
11
12typedef struct __unif
13{
14   const char *board; /* UNIF board */
15
16   int nvwram;
17   int wram;
18   int chrram;
19   int board_idx;
20} unif;
21
22
23/*************************************************************
24
25    Constants
26
27*************************************************************/
28
29/* CHRRAM sizes */
30enum
31{
32   CHRRAM_0 = 0,
33   CHRRAM_1,
34   CHRRAM_2,
35   CHRRAM_4,
36   CHRRAM_6,
37   CHRRAM_8,
38   CHRRAM_16,
39   CHRRAM_32
40};
41
42/*************************************************************
43
44    unif_list
45
46    Supported UNIF boards and corresponding handlers
47
48*************************************************************/
49
50static const unif unif_list[] =
51{
52/*       UNIF                       NVW  WRAM  CRAM     IDX*/
53   { "DREAMTECH01",                0,    0, CHRRAM_8,  DREAMTECH_BOARD},      //UNIF only!
54   { "NES-ANROM",                  0,    0, CHRRAM_8,  STD_AXROM},
55   { "NES-AOROM",                  0,    0, CHRRAM_8,  STD_AXROM},
56   { "NES-CNROM",                  0,    0, CHRRAM_0,  STD_CNROM},
57   { "NES-NROM",                   0,    0, CHRRAM_0,  STD_NROM},
58   { "NES-NROM-128",               0,    0, CHRRAM_0,  STD_NROM},
59   { "NES-NROM-256",               0,    0, CHRRAM_0,  STD_NROM},
60   { "NES-NTBROM",                 8,    0, CHRRAM_0,  STD_NXROM},
61   { "NES-SLROM",                  0,    0, CHRRAM_0,  STD_SXROM},
62   { "NES-TBROM",                  0,    0, CHRRAM_0,  STD_TXROM},
63   { "NES-TFROM",                  0,    0, CHRRAM_0,  STD_TXROM},
64   { "NES-TKROM",                  8,    0, CHRRAM_0,  STD_TXROM},
65   { "NES-TLROM",                  0,    0, CHRRAM_0,  STD_TXROM},
66   { "NES-UOROM",                  0,    0, CHRRAM_8,  STD_UXROM},
67   { "UNL-22211",                  0,    0, CHRRAM_0,  TXC_22211A},
68   // mapper 172 & 173 are variant of this one... no UNIF?
69   { "UNL-KOF97",                  0,    0, CHRRAM_0,  UNL_KOF97},
70   { "UNL-SA-NROM",                0,    0, CHRRAM_0,  SACHEN_TCA01},
71   { "UNL-VRC7",                   0,    0, CHRRAM_0,  KONAMI_VRC7},
72   { "UNL-T-230",                  0,    0, CHRRAM_8,  UNL_T230},
73   { "UNL-CC-21",                  0,    0, CHRRAM_0,  UNL_CC21},
74   { "UNL-AX5705",                 0,    0, CHRRAM_0,  UNL_AX5705},
75   { "UNL-SMB2J",                  8,    8, CHRRAM_0,  UNL_SMB2J},
76   { "UNL-8237",                   0,    0, CHRRAM_0,  UNL_8237},
77   { "UNL-SL1632",                 0,    0, CHRRAM_0,  REXSOFT_SL1632},
78   { "UNL-SACHEN-74LS374N",        0,    0, CHRRAM_0,  SACHEN_74LS374},
79   // mapper 243 variant exists! how to distinguish?!?  mapper243_l_w, NULL, NULL, NULL, NULL, NULL, NULL (also uses NT_VERT!)
80   { "UNL-TC-U01-1.5M",            0,    0, CHRRAM_0,  SACHEN_TCU01},
81   { "UNL-SACHEN-8259C",           0,    0, CHRRAM_0,  SACHEN_8259C},
82   { "UNL-SA-016-1M",              0,    0, CHRRAM_0,  AVE_NINA06},   // actually this is Mapper 146, but works like 79!
83   { "UNL-SACHEN-8259D",           0,    0, CHRRAM_0,  SACHEN_8259D},
84   { "UNL-SA-72007",               0,    0, CHRRAM_0,  SACHEN_SA72007},
85   { "UNL-SA-72008",               0,    0, CHRRAM_0,  SACHEN_SA72008},
86   { "UNL-SA-0037",                0,    0, CHRRAM_0,  SACHEN_SA0037},
87   { "UNL-SA-0036",                0,    0, CHRRAM_0,  SACHEN_SA0036},
88   { "UNL-SACHEN-8259A",           0,    0, CHRRAM_0,  SACHEN_8259A},
89   { "UNL-SACHEN-8259B",           0,    0, CHRRAM_0,  SACHEN_8259B},
90   { "BMC-190IN1",                 0,    0, CHRRAM_0,  BMC_190IN1},
91   { "BMC-64IN1NOREPEAT",          0,    0, CHRRAM_0,  BMC_64IN1NR},      //UNIF only!
92   { "BMC-A65AS",                  0,    0, CHRRAM_8,  BMC_A65AS},      //UNIF only!
93   { "BMC-GS-2004",                0,    0, CHRRAM_8,  BMC_GS2004},      //UNIF only!
94   { "BMC-GS-2013",                0,    0, CHRRAM_8,  BMC_GS2013},      //UNIF only!
95   { "BMC-NOVELDIAMOND9999999IN1", 0,    0, CHRRAM_0,  BMC_NOVELDIAMOND},
96   { "BMC-SUPER24IN1SC03",         8,    0, CHRRAM_8,  BMC_S24IN1SC03},
97   { "BMC-SUPERHIK8IN1",           8,    0, CHRRAM_0,  BMC_HIK8IN1},
98   { "BMC-T-262",                  0,    0, CHRRAM_8,  BMC_T262},      //UNIF only!
99   { "BMC-WS",                     0,    0, CHRRAM_0,  BMC_WS},      //UNIF only!
100   { "BMC-N625092",                0,    0, CHRRAM_0,  UNL_N625092},
101   // below are boards which are not yet supported, but are used by some UNIF files. they are here as a reminder to what is missing to be added
102   { "UNL-TEK90",                  0,    0, CHRRAM_0,  UNSUPPORTED_BOARD},   // related to JY Company? (i.e. mappers 90, 209, 211?)
103   { "UNL-KS7017",                 0,    0, CHRRAM_0,  UNSUPPORTED_BOARD},
104   { "UNL-KS7032",                 0,    0, CHRRAM_0,  KAISER_KS7032}, //  mapper 142
105   { "UNL-DANCE",                  0,    0, CHRRAM_0,  UNSUPPORTED_BOARD},
106   { "UNL-603-5052",               0,    0, CHRRAM_0,  UNL_603_5052}, // mapper 238?
107   { "UNL-EDU2000",               32,    0, CHRRAM_8,  UNL_EDU2K},
108   { "UNL-H2288",                  0,    0, CHRRAM_0,  UNL_H2288},   // mapper 123
109   { "UNL-SHERO",                  0,    0, CHRRAM_8,  UNSUPPORTED_BOARD /*SACHEN_SHERO*/},
110   { "UNL-TF1201",                 0,    0, CHRRAM_0,  UNSUPPORTED_BOARD /*UNL_TF1201*/},
111   { "UNL-DRIPGAME",               0,    0, CHRRAM_0,  UNSUPPORTED_BOARD}, // [by Quietust - we need more info]}
112   { "UNL-OneBus",                 0,    0, CHRRAM_0,  UNSUPPORTED_BOARD},
113   { "BTL-MARIO1-MALEE2",          0,    0, CHRRAM_0,  UNSUPPORTED_BOARD},   // mapper 55?
114   { "BMC-FK23C",                  0,    0, CHRRAM_0,  BMC_FK23C},
115   { "BMC-FK23CA",                 0,    0, CHRRAM_0,  BMC_FK23CA},
116   { "BMC-GHOSTBUSTERS63IN1",      0,    0, CHRRAM_8,  BMC_G63IN1 },
117   { "BMC-BS-5",                   0,    0, CHRRAM_0,  BMC_BENSHENG_BS5},
118   { "BMC-810544-C-A1",            0,    0, CHRRAM_0,  BMC_810544},
119   { "BMC-411120-C",               0,    0, CHRRAM_0,  UNSUPPORTED_BOARD},
120   { "BMC-8157",                   0,    0, CHRRAM_8,  UNSUPPORTED_BOARD /*BMC_8157*/},
121   { "BMC-42IN1RESETSWITCH",       0,    0, CHRRAM_0,  UNSUPPORTED_BOARD},   // mapper 60?
122   { "BMC-830118C",                0,    0, CHRRAM_0,  UNSUPPORTED_BOARD},
123   { "BMC-D1038",                  0,    0, CHRRAM_0,  BMC_VT5201}, // mapper 60?
124   { "BMC-12-IN-1",                0,    0, CHRRAM_0,  UNSUPPORTED_BOARD},
125   { "BMC-70IN1",                  0,    0, CHRRAM_0,  UNSUPPORTED_BOARD},   // mapper 236?
126   { "BMC-70IN1B",                 0,    0, CHRRAM_0,  UNSUPPORTED_BOARD},   // mapper 236?
127   { "BMC-SUPERVISION16IN1",       0,    0, CHRRAM_0,  UNSUPPORTED_BOARD},   // mapper 53
128   { "BMC-NTD-03",                 0,    0, CHRRAM_0,  BMC_NTD_03}
129};
130
131const unif *nes_unif_lookup( const char *board )
132{
133   int i;
134   for (i = 0; i < ARRAY_LENGTH(unif_list); i++)
135   {
136      if (!mame_stricmp(unif_list[i].board, board))
137         return &unif_list[i];
138   }
139   return NULL;
140}
141
142/*************************************************************
143
144 unif_mapr_setup
145
146 setup the board specific variables (wram, nvwram, pcb_id etc.)
147 for a given board (after reading the MAPR chunk of the UNIF file)
148
149 *************************************************************/
150
151void unif_mapr_setup( running_machine &machine, const char *board )
152{
153   nes_state *state = machine.driver_data<nes_state>();
154   const unif *unif_board = nes_unif_lookup(board);
155
156   logerror("%s\n", board);
157
158   if (unif_board == NULL)
159      fatalerror("Unknown UNIF board %s.", board);
160
161   state->m_pcb_id = unif_board->board_idx;
162   state->m_battery = unif_board->nvwram;   // we should implement battery banks based on the size of this...
163   state->m_battery_size = NES_BATTERY_SIZE; // FIXME: we should allow for smaller battery!
164   state->m_prg_ram = unif_board->wram;   // we should implement WRAM banks based on the size of this...
165
166   if (unif_board->chrram <= CHRRAM_8)
167      state->m_vram_chunks = 1;
168   else if (unif_board->chrram == CHRRAM_16)
169      state->m_vram_chunks = 2;
170   else if (unif_board->chrram == CHRRAM_32)
171      state->m_vram_chunks = 4;
172}
src/mame/machine/nes_mmc.c
r11531r11532
1/*****************************************************************************************
2
3    NES MMC Emulation
4
5
6    MESS source file to handle various Multi-Memory Controllers (aka Mappers) used by NES carts.
7
8    Many information about the mappers below come from the wonderful doc written by Disch.
9    Current info (when used) are based on v0.6.1 of his docs.
10    You can find the latest version of the doc at http://www.romhacking.net/docs/362/
11
12
13    Missing components:
14    * Currently, we are not emulating 4-screen mirroring (only 3 games use it)
15    * We need a better way to implement CPU cycle based IRQ. Currently we update their counter once every scanline
16      but, with this approach, every time 114 clocks have passed and for certain games it is too much!
17    * We need to emulate additional sound hardware in mappers 019, 024, 026, 069, 085 (and possibly other ones)
18    * We need to emulate EEPROM in mapper 016 and 159
19    * Barcode World (mapper 069) and Datach games (mapper 157) need Barcode Reader emulation
20      Notice that for mapper 157, the barcode reader enters in the irq, so glitches may be related to this!
21    * Karaoke Studio (mapper 188) misses input devices
22
23    Known issues on specific mappers:
24
25    * 000 F1 Race requires more precise PPU timing. It currently has plenty of 1-line glitches.
26    * 001 Yoshi flashes in-game. Back to the Future have heavily corrupted graphics (since forever).
27    * 001 SOROM boards do not properly handle the two WRAM/Battery banks
28    * 002, 003, 094, 097, 152 Bus conflict?
29    * 003 Firehouse Rescue has flashing graphics
30    * 004 Mendel Palace has never worked properly
31    * 004 Ninja Gaiden 2 has flashing bg graphics in the second level
32    * 005 has issues (see e.g. Just Breed or Metal Slader Glory), RAM banking needs hardware flags to determine size
33    * 007 Marble Madness has small graphics corruptions
34    * 014 in-game graphics is glitched
35    * 015 Shanghai Tycoon has corrupted graphics
36    * 033 has still some graphics problem (e.g. missing text in Akira)
37    * 034 Impossible Mission II does not show graphics
38    * 038 seems to miss inputs. separate reads?
39    * 042 Ai Senshi Nicol has broken graphics (our Mapper 42 implementation does not handle CHR banks)
40    * 048 Don Doko Don 2 freezes when you reach the first boss
41    * 051 only half of the games work
42    * 064 has many IRQ problems (due to the way we implement CPU based IRQ) - see Skull & Crossbones.
43          Klax has problems as well (even if it uses scanline based IRQ, according to Disch's docs).
44    * 067 some 1-line glitches that cannot be solved without a better implementation for cycle-based IRQs
45    * 071 Fire Hawk is flashing all the times.
46    * 072, 086, 092 lack samples support (maybe others as well)
47    * 073 16 bit IRQ mode is not implemented
48    * 077 Requires 4-screen mirroring. Currently, it is very glitchy
49    * 083 has serious glitches
50    * 088 Quinty has never worked properly
51    * 096 is preliminary (no correct chr switch in connection to PPU)
52    * 104 Not all the games work
53    * 107 Are the scrolling glitches (check status bar) correct? NEStopia behaves similarly
54    * 112 Master Shooter is not working and misses some graphics
55    * 117 In-game glitches
56    * 119 Pin Bot has glitches when the ball is in the upper half of the screen
57    * 133 Qi Wang starts with corrupted graphics (ingame seems better)
58    * 143 are Dancing Block borders (in the intro) correct?
59    * 158 In addition to IRQ problems (same as 64), mirroring was just a guess (wrong?). info needed!
60    * 164 preliminary - no sprites?
61    * 176 has some graphics problem
62    * 178 Fan Kong Jin Ying is not working (but not even in NEStopia)
63    * 180 Crazy Climber controller?
64    * 187, 198, 208, 215 have some PRG banking issues - preliminary!
65    * 188 needs mic input (reads from 0x6000-0x7fff)
66    * 197 Super Fighter 3 has some glitch in-game (maybe mirroring?)
67    * 222 is only preliminar (wrong IRQ, mirroring or CHR banking?)
68    * 225 115-in-1 has glitches in the menu (games seem fine)
69    * 229 is preliminary
70    * 230 not working yet (needs a value to flip at reset)
71    * 232 has graphics glitches
72    * 241 Commandos is not working (but not even in NEStopia)
73    * 242 In Dragon Quest VIII graphics of the main character is not drawn (it seems similar to Shanghai Tycoon [map15]
74          because in place of the missing graphics we get glitches in the left border)
75    * 249 only half of the games work (and Du Bao Ying Hao seems to suffer the same problem as DQ8 and Shanghai Tycoon)
76    * 255 does not really select game (same in NEStopia apparently)
77
78    A few Mappers suffer of hardware conflict: original dumpers have used the same mapper number for more than
79    a kind of boards. In these cases (and only in these cases) we exploit nes.hsi to set up accordingly
80    emulation. Games which requires this hack are the following:
81    * 032 - Major League needs hardwired mirroring (missing windows and glitched field in top view, otherwise)
82    * 034 - Impossible Mission II is not like BxROM games (it writes to 0x7ffd-0x7fff, instead of 0x8000). It is still
83          unplayable though (see above)
84    * 071 - Fire Hawk is different from other Camerica games (no hardwired mirroring). Without crc_hack no helicopter graphics
85    * 078 - Cosmo Carrier needs a different mirroring than Holy Diver
86    * 113 - HES 6-in-1 requires mirroring (check Bookyman playfield), while other games break with this (check AV Soccer)
87    * 153 - Famicom Jump II uses a different board (or the same in a very different way)
88    * 242 - DQ8 has no mirroring (missing graphics is due to other reasons though)
89
90    crc_hacks have been added also to handle a few wiring settings which would require submappers:
91    * CHR protection pins for mapper 185
92    * VRC-2, VRC-4 and VRC-6 line wiring
93
94    Known issues on specific UNIF boards:
95    * BMC-GS2004 is not working
96    * BMC-GS2013 is not working
97    * BMC-WS some games have corrupted graphics (e.g. Galaxian)
98    * UNL-8237 is not working
99    * UNL-KOF97 is not working
100
101    Details to investigate:
102    * 034 writes to 0x8000-0xffff should not be used for NINA-001 and BNROM, only unlicensed BxROM...
103    * 144 we ignore writes to 0x8000 while NEStopia does not. is it a problem?
104    * 240 we do not map writes to 0x4020-0x40ff. is this a problem?
105    * some other emus uses mapper 210 for mapper 019 games without additional sound hardware and mirroring capabilities
106      (in 210 mirroring is hardwired). However, simply initializing mirroring to Vertical in 019 seems to fix all glitches
107      in 210 games, so there seems to be no reason to have this duplicate mapper
108
109    Some mappers copy PRG rom in SRAM region. Below is a list of those which does it (in MESS) to further
110    investigate if we are supporting them in the right way (e.g. do any of the following have conflicts with SRAM?):
111    * 065 (Gimmick! breaks badly without it)
112    * 040, 042, 050
113
114    Remember that the MMC # does not equal the mapper #. In particular, Mapper 4 is
115    in fact MMC3, Mapper 9 is MMC2 and Mapper 10 is MMC4. Makes perfect sense, right?
116
117    TODO:
118    - add more info
119    - add missing mappers
120
121****************************************************************************************/
122
123#include "emu.h"
124#include "cpu/m6502/m6502.h"
125#include "video/ppu2c0x.h"
126#include "includes/nes.h"
127#include "nes_mmc.h"
128#include "sound/nes_apu.h"
129
130#ifdef MAME_DEBUG
131#define VERBOSE 1
132#else
133#define VERBOSE 0
134#endif
135
136#define LOG_MMC(x) do { if (VERBOSE) logerror x; } while (0)
137#define LOG_FDS(x) do { if (VERBOSE) logerror x; } while (0)
138
139static void ffe_irq( device_t *device, int scanline, int vblank, int blanked );
140static WRITE8_HANDLER( mapper6_l_w );
141static WRITE8_HANDLER( mapper6_w );
142static WRITE8_HANDLER( mapper8_w );
143static WRITE8_HANDLER( mapper17_l_w );
144
145/*************************************************************
146
147    Base emulation (see drivers/nes.c):
148    memory 0x0000-0x1fff RAM
149           0x2000-0x3fff PPU
150           0x4000-0x4017 APU
151           0x4018-0x5fff Expansion Area
152           0x6000-0x7fff PRG RAM
153           0x8000-0xffff PRG ROM
154
155    nes_chr_r/w take care of RAM, nes_nt_r/w take care of PPU.
156    for mapper specific emulation, we generically setup the
157    following handlers:
158    - nes_low_mapper_r/w take care of accesses to 0x4100-0x5fff
159      (calling state->m_mmc_write_low/state->m_mmc_read_low)
160    - state->m_mmc_write/read_mid take care of 0x6000-0x7fff
161    - state->m_mmc_write/read take care of access to 0x8000-0xffff
162      (most mappers only writes in this area)
163    some mappers may access 0x4018-0x4100: this must be taken
164    care separately in init_nes_core
165
166*************************************************************/
167
168WRITE8_HANDLER( nes_chr_w )
169{
170   nes_state *state = space->machine().driver_data<nes_state>();
171   int bank = offset >> 10;
172
173   if (state->m_chr_map[bank].source == CHRRAM)
174   {
175      state->m_chr_map[bank].access[offset & 0x3ff] = data;
176   }
177}
178
179READ8_HANDLER( nes_chr_r )
180{
181   nes_state *state = space->machine().driver_data<nes_state>();
182   int bank = offset >> 10;
183
184   // a few CNROM boards contained copy protection schemes through
185   // suitably configured diodes, so that subsequent CHR reads can
186   // give actual VROM content or open bus values.
187   // For most boards, chr_open_bus remains always zero.
188   if (state->m_chr_open_bus)
189      return 0xff;
190
191   return state->m_chr_map[bank].access[offset & 0x3ff];
192}
193
194WRITE8_HANDLER( nes_nt_w )
195{
196   nes_state *state = space->machine().driver_data<nes_state>();
197   int page = ((offset & 0xc00) >> 10);
198
199   if (state->m_nt_page[page].writable == 0)
200      return;
201
202   state->m_nt_page[page].access[offset & 0x3ff] = data;
203}
204
205READ8_HANDLER( nes_nt_r )
206{
207   nes_state *state = space->machine().driver_data<nes_state>();
208   int page = ((offset & 0xc00) >> 10);
209
210   if (state->m_nt_page[page].source == MMC5FILL)
211   {
212      if ((offset & 0x3ff) >= 0x3c0)
213         return state->m_MMC5_floodattr;
214
215      return state->m_MMC5_floodtile;
216   }
217   return state->m_nt_page[page].access[offset & 0x3ff];
218}
219
220WRITE8_HANDLER( nes_low_mapper_w )
221{
222   nes_state *state = space->machine().driver_data<nes_state>();
223
224   if (state->m_mmc_write_low)
225      (*state->m_mmc_write_low)(space, offset, data);
226   else
227      logerror("Unimplemented LOW mapper write, offset: %04x, data: %02x\n", offset + 0x4100, data);
228}
229
230READ8_HANDLER( nes_low_mapper_r )
231{
232   nes_state *state = space->machine().driver_data<nes_state>();
233
234   if (state->m_mmc_read_low)
235      return (*state->m_mmc_read_low)(space, offset);
236   else
237      logerror("Unimplemented LOW mapper read, offset: %04x\n", offset + 0x4100);
238
239   return 0;
240}
241
242/*************************************************************
243
244    Helpers to handle MMC
245
246*************************************************************/
247
248static void wram_bank( running_machine &machine, int bank, int source )
249{
250   nes_state *state = machine.driver_data<nes_state>();
251
252   assert(state->m_battery || state->m_prg_ram);
253   if (source == NES_BATTERY)
254   {
255      bank &= (state->m_battery_size / 0x2000) - 1;
256      state->m_prg_bank[4] = state->m_battery_bank5_start + bank;
257   }
258   else
259   {
260      bank &= (state->m_wram_size / 0x2000) - 1;
261      state->m_prg_bank[4] = state->m_prgram_bank5_start + bank;
262   }
263   memory_set_bank(machine, "bank5", state->m_prg_bank[4]);
264}
265
266INLINE void prg_bank_refresh( running_machine &machine )
267{
268   nes_state *state = machine.driver_data<nes_state>();
269   memory_set_bank(machine, "bank1", state->m_prg_bank[0]);
270   memory_set_bank(machine, "bank2", state->m_prg_bank[1]);
271   memory_set_bank(machine, "bank3", state->m_prg_bank[2]);
272   memory_set_bank(machine, "bank4", state->m_prg_bank[3]);
273}
274
275/* PRG ROM in 8K, 16K or 32K blocks */
276
277static void prg32( running_machine &machine, int bank )
278{
279   nes_state *state = machine.driver_data<nes_state>();
280
281   /* if there is only 16k PRG, return */
282   if (!(state->m_prg_chunks >> 1))
283      return;
284
285   /* assumes that bank references a 32k chunk */
286   bank &= ((state->m_prg_chunks >> 1) - 1);
287
288   state->m_prg_bank[0] = bank * 4 + 0;
289   state->m_prg_bank[1] = bank * 4 + 1;
290   state->m_prg_bank[2] = bank * 4 + 2;
291   state->m_prg_bank[3] = bank * 4 + 3;
292   prg_bank_refresh(machine);
293}
294
295static void prg16_89ab( running_machine &machine, int bank )
296{
297   nes_state *state = machine.driver_data<nes_state>();
298
299   /* assumes that bank references a 16k chunk */
300   bank &= (state->m_prg_chunks - 1);
301
302   state->m_prg_bank[0] = bank * 2 + 0;
303   state->m_prg_bank[1] = bank * 2 + 1;
304   prg_bank_refresh(machine);
305}
306
307static void prg16_cdef( running_machine &machine, int bank )
308{
309   nes_state *state = machine.driver_data<nes_state>();
310
311   /* assumes that bank references a 16k chunk */
312   bank &= (state->m_prg_chunks - 1);
313
314   state->m_prg_bank[2] = bank * 2 + 0;
315   state->m_prg_bank[3] = bank * 2 + 1;
316   prg_bank_refresh(machine);
317}
318
319static void prg8_89( running_machine &machine, int bank )
320{
321   nes_state *state = machine.driver_data<nes_state>();
322
323   /* assumes that bank references an 8k chunk */
324   bank &= ((state->m_prg_chunks << 1) - 1);
325
326   state->m_prg_bank[0] = bank;
327   prg_bank_refresh(machine);
328}
329
330static void prg8_ab( running_machine &machine, int bank )
331{
332   nes_state *state = machine.driver_data<nes_state>();
333
334   /* assumes that bank references an 8k chunk */
335   bank &= ((state->m_prg_chunks << 1) - 1);
336
337   state->m_prg_bank[1] = bank;
338   prg_bank_refresh(machine);
339}
340
341static void prg8_cd( running_machine &machine, int bank )
342{
343   nes_state *state = machine.driver_data<nes_state>();
344
345   /* assumes that bank references an 8k chunk */
346   bank &= ((state->m_prg_chunks << 1) - 1);
347
348   state->m_prg_bank[2] = bank;
349   prg_bank_refresh(machine);
350}
351
352static void prg8_ef( running_machine &machine, int bank )
353{
354   nes_state *state = machine.driver_data<nes_state>();
355
356   /* assumes that bank references an 8k chunk */
357   bank &= ((state->m_prg_chunks << 1) - 1);
358
359   state->m_prg_bank[3] = bank;
360   prg_bank_refresh(machine);
361}
362
363/* We define an additional helper to map PRG-ROM to 0x6000-0x7000 */
364// TODO: are we implementing this correctly in the mappers which uses it? check!
365
366static void prg8_67( running_machine &machine, int bank )
367{
368   nes_state *state = machine.driver_data<nes_state>();
369
370   /* assumes that bank references an 8k chunk */
371   bank &= ((state->m_prg_chunks << 1) - 1);
372
373   state->m_prg_bank[4] = bank;
374   memory_set_bank(machine, "bank5", state->m_prg_bank[4]);
375}
376
377/* We also define an additional helper to map 8k PRG-ROM to one of the banks (passed as parameter) */
378static void prg8_x( running_machine &machine, int start, int bank )
379{
380   nes_state *state = machine.driver_data<nes_state>();
381
382   assert(start < 4);
383
384   /* assumes that bank references an 8k chunk */
385   bank &= ((state->m_prg_chunks << 1) - 1);
386
387   state->m_prg_bank[start] = bank;
388   prg_bank_refresh(machine);
389}
390
391/* CHR ROM in 1K, 2K, 4K or 8K blocks */
392
393// this can be probably removed later, but it is useful while testing xml and unf handling with VRAM & VROM
394INLINE void chr_sanity_check( running_machine &machine, int source )
395{
396   nes_state *state = machine.driver_data<nes_state>();
397
398   if (source == CHRRAM && state->m_vram == NULL)
399      fatalerror("CHRRAM bankswitch with no VRAM");
400
401   if (source == CHRROM && state->m_vrom == NULL)
402      fatalerror("CHRROM bankswitch with no VROM");
403}
404
405static void chr8( running_machine &machine, int bank, int source )
406{
407   nes_state *state = machine.driver_data<nes_state>();
408   int i;
409
410   chr_sanity_check(machine, source);
411
412   if (source == CHRRAM)
413   {
414      bank &= (state->m_vram_chunks - 1);
415      for (i = 0; i < 8; i++)
416      {
417         state->m_chr_map[i].source = source;
418         state->m_chr_map[i].origin = (bank * 0x2000) + (i * 0x400); // for save state uses!
419         state->m_chr_map[i].access = &state->m_vram[state->m_chr_map[i].origin];
420      }
421   }
422   else
423   {
424      bank &= (state->m_chr_chunks - 1);
425      for (i = 0; i < 8; i++)
426      {
427         state->m_chr_map[i].source = source;
428         state->m_chr_map[i].origin = (bank * 0x2000) + (i * 0x400); // for save state uses!
429         state->m_chr_map[i].access = &state->m_vrom[state->m_chr_map[i].origin];
430      }
431   }
432}
433
434static void chr4_x( running_machine &machine, int start, int bank, int source )
435{
436   nes_state *state = machine.driver_data<nes_state>();
437   int i;
438
439   chr_sanity_check(machine, source);
440
441   if (source == CHRRAM)
442   {
443      bank &= ((state->m_vram_chunks << 1) - 1);
444      for (i = 0; i < 4; i++)
445      {
446         state->m_chr_map[i + start].source = source;
447         state->m_chr_map[i + start].origin = (bank * 0x1000) + (i * 0x400); // for save state uses!
448         state->m_chr_map[i + start].access = &state->m_vram[state->m_chr_map[i + start].origin];
449      }
450   }
451   else
452   {
453      bank &= ((state->m_chr_chunks << 1) - 1);
454      for (i = 0; i < 4; i++)
455      {
456         state->m_chr_map[i + start].source = source;
457         state->m_chr_map[i + start].origin = (bank * 0x1000) + (i * 0x400); // for save state uses!
458         state->m_chr_map[i + start].access = &state->m_vrom[state->m_chr_map[i + start].origin];
459      }
460   }
461}
462
463static void chr4_0( running_machine &machine, int bank, int source )
464{
465   chr4_x(machine, 0, bank, source);
466}
467
468static void chr4_4( running_machine &machine, int bank, int source )
469{
470   chr4_x(machine, 4, bank, source);
471}
472
473static void chr2_x( running_machine &machine, int start, int bank, int source )
474{
475   nes_state *state = machine.driver_data<nes_state>();
476   int i;
477
478   chr_sanity_check(machine, source);
479
480   if (source == CHRRAM)
481   {
482      bank &= ((state->m_vram_chunks << 2) - 1);
483      for (i = 0; i < 2; i++)
484      {
485         state->m_chr_map[i + start].source = source;
486         state->m_chr_map[i + start].origin = (bank * 0x800) + (i * 0x400); // for save state uses!
487         state->m_chr_map[i + start].access = &state->m_vram[state->m_chr_map[i + start].origin];
488      }
489   }
490   else
491   {
492      bank &= ((state->m_chr_chunks << 2) - 1);
493      for (i = 0; i < 2; i++)
494      {
495         state->m_chr_map[i + start].source = source;
496         state->m_chr_map[i + start].origin = (bank * 0x800) + (i * 0x400); // for save state uses!
497         state->m_chr_map[i + start].access = &state->m_vrom[state->m_chr_map[i + start].origin];
498      }
499   }
500}
501
502static void chr2_0( running_machine &machine, int bank, int source )
503{
504   chr2_x(machine, 0, bank, source);
505}
506
507static void chr2_2( running_machine &machine, int bank, int source )
508{
509   chr2_x(machine, 2, bank, source);
510}
511
512static void chr2_4( running_machine &machine, int bank, int source )
513{
514   chr2_x(machine, 4, bank, source);
515}
516
517static void chr2_6( running_machine &machine, int bank, int source )
518{
519   chr2_x(machine, 6, bank, source);
520}
521
522static void chr1_x( running_machine &machine, int start, int bank, int source )
523{
524   nes_state *state = machine.driver_data<nes_state>();
525
526   chr_sanity_check(machine, source);
527
528   if (source == CHRRAM)
529   {
530      bank &= ((state->m_vram_chunks << 3) - 1);
531      state->m_chr_map[start].source = source;
532      state->m_chr_map[start].origin = (bank * 0x400); // for save state uses!
533      state->m_chr_map[start].access = &state->m_vram[state->m_chr_map[start].origin];
534   }
535   else
536   {
537      bank &= ((state->m_chr_chunks << 3) - 1);
538      state->m_chr_map[start].source = source;
539      state->m_chr_map[start].origin = (bank * 0x400); // for save state uses!
540      state->m_chr_map[start].access = &state->m_vrom[state->m_chr_map[start].origin];
541   }
542}
543
544static void chr1_0 (running_machine &machine, int bank, int source)
545{
546   chr1_x(machine, 0, bank, source);
547}
548
549static void chr1_1( running_machine &machine, int bank, int source )
550{
551   chr1_x(machine, 1, bank, source);
552}
553
554static void chr1_2( running_machine &machine, int bank, int source )
555{
556   chr1_x(machine, 2, bank, source);
557}
558
559static void chr1_3( running_machine &machine, int bank, int source )
560{
561   chr1_x(machine, 3, bank, source);
562}
563
564static void chr1_4( running_machine &machine, int bank, int source )
565{
566   chr1_x(machine, 4, bank, source);
567}
568
569static void chr1_5( running_machine &machine, int bank, int source )
570{
571   chr1_x(machine, 5, bank, source);
572}
573
574static void chr1_6( running_machine &machine, int bank, int source )
575{
576   chr1_x(machine, 6, bank, source);
577}
578
579static void chr1_7( running_machine &machine, int bank, int source )
580{
581   chr1_x(machine, 7, bank, source);
582}
583
584
585/* NameTable paging and mirroring */
586
587static void set_nt_page( running_machine &machine, int page, int source, int bank, int writable )
588{
589   nes_state *state = machine.driver_data<nes_state>();
590   UINT8* base_ptr;
591
592   switch (source)
593   {
594      case CART_NTRAM:
595         base_ptr = state->m_extended_ntram;
596         break;
597      case MMC5FILL:
598         base_ptr = NULL;
599         break;
600      case ROM:
601         base_ptr = state->m_vrom;
602         break;
603      case EXRAM:
604         base_ptr = state->m_mapper_ram;
605         break;
606      case CIRAM:
607      default:
608         base_ptr = state->m_ciram;
609         break;
610   }
611
612   page &= 3; /* mask down to the 4 logical pages */
613   state->m_nt_page[page].source = source;
614
615   if (base_ptr != NULL)
616   {
617      state->m_nt_page[page].origin = bank * 0x400;
618      state->m_nt_page[page].access = base_ptr + state->m_nt_page[page].origin;
619   }
620
621   state->m_nt_page[page].writable = writable;
622}
623
624void set_nt_mirroring( running_machine &machine, int mirroring )
625{
626   /* setup our videomem handlers based on mirroring */
627   switch (mirroring)
628   {
629      case PPU_MIRROR_VERT:
630         set_nt_page(machine, 0, CIRAM, 0, 1);
631         set_nt_page(machine, 1, CIRAM, 1, 1);
632         set_nt_page(machine, 2, CIRAM, 0, 1);
633         set_nt_page(machine, 3, CIRAM, 1, 1);
634         break;
635
636      case PPU_MIRROR_HORZ:
637         set_nt_page(machine, 0, CIRAM, 0, 1);
638         set_nt_page(machine, 1, CIRAM, 0, 1);
639         set_nt_page(machine, 2, CIRAM, 1, 1);
640         set_nt_page(machine, 3, CIRAM, 1, 1);
641         break;
642
643      case PPU_MIRROR_HIGH:
644         set_nt_page(machine, 0, CIRAM, 1, 1);
645         set_nt_page(machine, 1, CIRAM, 1, 1);
646         set_nt_page(machine, 2, CIRAM, 1, 1);
647         set_nt_page(machine, 3, CIRAM, 1, 1);
648         break;
649
650      case PPU_MIRROR_LOW:
651         set_nt_page(machine, 0, CIRAM, 0, 1);
652         set_nt_page(machine, 1, CIRAM, 0, 1);
653         set_nt_page(machine, 2, CIRAM, 0, 1);
654         set_nt_page(machine, 3, CIRAM, 0, 1);
655         break;
656
657      case PPU_MIRROR_NONE:
658      case PPU_MIRROR_4SCREEN:
659      default:
660         /* external RAM needs to be used somehow. */
661         /* but as a default, we'll arbitrarily set vertical so as not to crash*/
662         /* mappers should use set_nt_page and assign which pages are which */
663
664         logerror("Mapper set 4-screen mirroring without supplying external nametable memory!\n");
665
666         set_nt_page(machine, 0, CIRAM, 0, 1);
667         set_nt_page(machine, 1, CIRAM, 0, 1);
668         set_nt_page(machine, 2, CIRAM, 1, 1);
669         set_nt_page(machine, 3, CIRAM, 1, 1);
670         break;
671   }
672}
673
674/*  Other custom mirroring helpers are defined below: Waixing games use waixing_set_mirror (which swaps
675    MIRROR_HIGH and MIRROR_LOW compared to the above) and Sachen games use sachen_set_mirror (which has
676    a slightly different MIRROR_HIGH, with page 0 set to 0) */
677
678
679/*************************************************************
680
681 Support for xml list
682
683 *************************************************************/
684
685/* Include emulation of NES PCBs for softlist */
686#include "machine/nes_pcb.c"
687
688
689/*************************************************************
690
691    Support for .unf Files
692
693*************************************************************/
694
695/* Include emulation of UNIF Boards for .unf files */
696#include "machine/nes_unif.c"
697
698
699/*************************************************************
700
701 Support for .nes Files
702
703 *************************************************************/
704
705/* Include emulation of iNES Mappers for .nes files */
706#include "machine/nes_ines.c"
707
src/mame/machine/nes_mmc.h
r11531r11532
1#ifndef __MMC_H
2#define __MMC_H
3
4/* Boards */
5enum
6{
7   STD_NROM = 0,
8   STD_AXROM, STD_BXROM, STD_CNROM, STD_CPROM,
9   STD_DXROM, STD_EXROM, STD_FXROM, STD_GXROM,
10   STD_HKROM, STD_JXROM, STD_MXROM, STD_NXROM,
11   STD_PXROM, STD_SXROM, STD_TXROM, STD_TXSROM,
12   STD_TKROM, STD_TQROM, STD_TVROM,
13   STD_UN1ROM, STD_UXROM,
14   HVC_FAMBASIC, NES_QJ, PAL_ZZ, UXROM_CC,
15   STD_DRROM, STD_SXROM_A, STD_SOROM, STD_SOROM_A,
16   /* Discrete components boards (by various manufacturer) */
17   DIS_74X161X138, DIS_74X139X74,
18   DIS_74X377, DIS_74X161X161X32,
19   /* Active Enterprises */
20   ACTENT_ACT52,
21   /* AGCI */
22   AGCI_50282,
23   /* AVE */
24   AVE_NINA01, AVE_NINA06,
25   /* Bandai */
26   BANDAI_JUMP2, BANDAI_PT554,
27   BANDAI_DATACH, BANDAI_KARAOKE, BANDAI_OEKAKIDS,
28   BANDAI_FCG, BANDAI_LZ93, BANDAI_LZ93EX,
29   /* Caltron */
30   CALTRON_6IN1,
31   /* Camerica */
32   CAMERICA_BF9093, CAMERICA_BF9097, CAMERICA_BF9096,
33   CAMERICA_GOLDENFIVE, GG_NROM,
34   /* Dreamtech */
35   DREAMTECH_BOARD,
36   /* Irem */
37   IREM_G101, IREM_H3001, IREM_LROG017,
38   IREM_TAM_S1, IREM_HOLYDIV,
39   /* Jaleco */
40   JALECO_SS88006, JALECO_JF11, JALECO_JF13,
41   JALECO_JF16, JALECO_JF17, JALECO_JF19,
42   /* Konami */
43   KONAMI_VRC1, KONAMI_VRC2, KONAMI_VRC3,
44   KONAMI_VRC4, KONAMI_VRC6, KONAMI_VRC7,
45   /* Namcot */
46   NAMCOT_163, NAMCOT_3453,
47   NAMCOT_3425, NAMCOT_34X3, NAMCOT_3446,
48   /* NTDEC */
49   NTDEC_ASDER, NTDEC_FIGHTINGHERO,
50   /* Rex Soft */
51   REXSOFT_SL1632, REXSOFT_DBZ5,
52   /* Sachen */
53   SACHEN_8259A, SACHEN_8259B, SACHEN_8259C, SACHEN_8259D,
54   SACHEN_SA009, SACHEN_SA0036, SACHEN_SA0037,
55   SACHEN_SA72007, SACHEN_SA72008, SACHEN_TCA01,
56   SACHEN_TCU01, SACHEN_TCU02,
57   SACHEN_74LS374, SACHEN_74LS374_A,
58   /* Sunsoft */
59   SUNSOFT_1, SUNSOFT_2, SUNSOFT_3, SUNSOFT_4,
60   SUNSOFT_DCS, SUNSOFT_5B, SUNSOFT_FME7,
61   /* Taito */
62   TAITO_TC0190FMC, TAITO_TC0190FMCP,
63   TAITO_X1_005, TAITO_X1_005_A, TAITO_X1_017,
64   /* Tengen */
65   TENGEN_800008, TENGEN_800032, TENGEN_800037,
66   /* TXC */
67   TXC_22211A, TXC_22211B, TXC_22211C,
68   TXC_MXMDHTWO, TXC_TW, TXC_STRIKEWOLF,
69   /* Multigame Carts */
70   BMC_64IN1NR, BMC_190IN1, BMC_A65AS, BMC_GS2004, BMC_GS2013,
71   BMC_HIK8IN1, BMC_NOVELDIAMOND, BMC_S24IN1SC03, BMC_T262,
72   BMC_WS, BMC_SUPERBIG_7IN1, BMC_SUPERHIK_4IN1, BMC_BALLGAMES_11IN1,
73   BMC_MARIOPARTY_7IN1, BMC_SUPER_700IN1, BMC_FAMILY_4646B,
74   BMC_36IN1, BMC_21IN1, BMC_150IN1, BMC_35IN1, BMC_64IN1,
75   BMC_15IN1, BMC_SUPERHIK_300IN1, BMC_9999999IN1, BMC_SUPERGUN_20IN1,
76   BMC_GOLDENCARD_6IN1, BMC_72IN1, BMC_SUPER_42IN1, BMC_76IN1,
77   BMC_1200IN1, BMC_31IN1, BMC_22GAMES, BMC_20IN1, BMC_110IN1,
78   BMC_GKA, BMC_GKB, BMC_VT5201, BMC_BENSHENG_BS5, BMC_810544,
79   BMC_NTD_03, BMC_G63IN1, BMC_FK23C, BMC_FK23CA, BMC_PJOY84,
80   /* Unlicensed */
81   UNL_8237, UNL_CC21, UNL_AX5705, UNL_KOF97,
82   UNL_N625092, UNL_SC127, UNL_SMB2J, UNL_T230,
83   UNL_UXROM, UNL_MK2, UNL_XZY, UNL_KOF96,
84   UNL_SUPERFIGHTER3, UNL_RACERMATE, UNL_EDU2K,
85   UNL_SHJY3, UNL_STUDYNGAME, UNL_603_5052, UNL_H2288,
86   /* Bootleg boards */
87   BTL_SMB2A, BTL_MARIOBABY, BTL_AISENSHINICOL, BTL_TOBIDASE,
88   BTL_SMB2B, BTL_SMB3, BTL_SUPERBROS11, BTL_DRAGONNINJA,
89   BTL_PIKACHUY2K,
90   /* Misc: these are needed to convert mappers to boards, I will sort them later */
91   OPENCORP_DAOU306, HES_BOARD, HES6IN1_BOARD, RUMBLESTATION_BOARD,
92   MAGICSERIES_MD, KASING_BOARD, FUTUREMEDIA_BOARD, FUKUTAKE_BOARD, SOMERI_SL12,
93   HENGEDIANZI_BOARD, HENGEDIANZI_XJZB, SUBOR_TYPE0, SUBOR_TYPE1,
94   KAISER_KS7058, KAISER_KS7032, KAISER_KS7022, KAISER_KS7017, KAISER_KS202, CONY_BOARD,
95   CNE_DECATHLON, CNE_FSB, CNE_SHLZ, RCM_GS2015, RCM_TETRISFAMILY,
96   WAIXING_TYPE_A, WAIXING_TYPE_A_1, WAIXING_TYPE_B, WAIXING_TYPE_C, WAIXING_TYPE_D,
97   WAIXING_TYPE_E, WAIXING_TYPE_F, WAIXING_TYPE_G, WAIXING_TYPE_H,
98   WAIXING_TYPE_I, WAIXING_TYPE_J,
99   WAIXING_SGZLZ, WAIXING_SGZ, WAIXING_ZS, WAIXING_SECURITY, WAIXING_SH2,
100   WAIXING_DQ8, WAIXING_FFV, WAIXING_PS2, SUPERGAME_LIONKING, SUPERGAME_BOOGERMAN,
101   KAY_PANDAPRINCE, HOSENKAN_BOARD, NITRA_TDA, GOUDER_37017, NANJING_BOARD,
102   WHIRLWIND_2706,
103   /* FFE boards, for mappers 6, 8, 17 */
104   FFE_MAPPER6, FFE_MAPPER8, FFE_MAPPER17,
105   /* Unsupported (for place-holder boards, with no working emulation) & no-board (at init) */
106   UNSUPPORTED_BOARD, UNKNOWN_BOARD, NO_BOARD
107};
108
109// these are used to setup the proper PCB ID, for each supported type of files
110int nes_get_pcb_id(running_machine &machine, const char *feature);   // for softlist
111void unif_mapr_setup(running_machine &machine, const char *board);   // for UNIF files
112int nes_get_mmc_id(running_machine &machine, int mapper);   // for iNES files
113
114// these are used to setup handlers and callbacks necessary to the emulation (resp. at start and reset)
115void pcb_handlers_setup(running_machine &machine);
116int nes_pcb_reset(running_machine &machine);
117
118
119WRITE8_HANDLER( nes_low_mapper_w );
120READ8_HANDLER( nes_low_mapper_r );
121WRITE8_HANDLER( nes_chr_w );
122READ8_HANDLER( nes_chr_r );
123WRITE8_HANDLER( nes_nt_w );
124READ8_HANDLER( nes_nt_r );
125
126WRITE8_HANDLER( smb2jb_extra_w );
127WRITE8_HANDLER( ks7017_extra_w );
128READ8_HANDLER( ks7017_extra_r );
129WRITE8_HANDLER( unl_6035052_extra_w );
130READ8_HANDLER( unl_6035052_extra_r );
131READ8_HANDLER( waixing_sh2_chr_r );
132
133//TEMPORARY PPU STUFF
134
135/* mirroring types */
136#define PPU_MIRROR_NONE      0
137#define PPU_MIRROR_VERT      1
138#define PPU_MIRROR_HORZ      2
139#define PPU_MIRROR_HIGH      3
140#define PPU_MIRROR_LOW      4
141#define PPU_MIRROR_4SCREEN   5   // Same effect as NONE, but signals that we should never mirror
142
143void set_nt_mirroring(running_machine &machine, int mirroring);
144
145
146#endif
src/mame/machine/nes_ines.c
r11531r11532
1/*****************************************************************************************
2
3    NES MMC Emulation
4
5    Support for iNES Mappers
6
7****************************************************************************************/
8
9typedef struct _nes_mmc  nes_mmc;
10struct _nes_mmc
11{
12   int    iNesMapper; /* iNES Mapper # */
13   int    pcb_id;
14};
15
16/*************************************************************
17
18    Mapper 6
19
20    Known Boards: FFE4 Copier Board
21    Games: Hacked versions of games
22
23    In MESS: Supported? Not sure if we could also have ExRAM or not...
24       However, priority is pretty low for this mapper.
25
26*************************************************************/
27
28/* Here, IRQ counter decrements every CPU cycle. Since we update it every scanline,
29we need to decrement it by 114 (Each scanline consists of 341 dots and, on NTSC,
30there are 3 dots to every 1 CPU cycle, hence 114 is the number of cycles per scanline ) */
31static void ffe_irq( device_t *device, int scanline, int vblank, int blanked )
32{
33   nes_state *state = device->machine().driver_data<nes_state>();
34
35   /* 114 is the number of cycles per scanline */
36   /* TODO: change to reflect the actual number of cycles spent */
37   if (state->m_IRQ_enable)
38   {
39      if ((0xffff - state->m_IRQ_count) < 114)
40      {
41         device_set_input_line(state->m_maincpu, M6502_IRQ_LINE, HOLD_LINE);
42         state->m_IRQ_count = 0xffff;
43         state->m_IRQ_enable = 0;
44      }
45      state->m_IRQ_count -= 114;
46   }
47}
48
49static WRITE8_HANDLER( mapper6_l_w )
50{
51   nes_state *state = space->machine().driver_data<nes_state>();
52   LOG_MMC(("mapper6_l_w, offset: %04x, data: %02x\n", offset, data));
53
54   switch (offset)
55   {
56      case 0x1fe:
57         state->m_mmc_latch1 = data & 0x80;
58         set_nt_mirroring(space->machine(), BIT(data, 4) ? PPU_MIRROR_HIGH : PPU_MIRROR_LOW);
59         break;
60      case 0x1ff:
61         set_nt_mirroring(space->machine(), BIT(data, 4) ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT);
62         break;
63
64      case 0x401:
65         state->m_IRQ_enable = data & 0x01;
66         break;
67      case 0x402:
68         state->m_IRQ_count = (state->m_IRQ_count & 0xff00) | data;
69         break;
70      case 0x403:
71         state->m_IRQ_enable = 1;
72         state->m_IRQ_count = (state->m_IRQ_count & 0x00ff) | (data << 8);
73         break;
74   }
75}
76
77static WRITE8_HANDLER( mapper6_w )
78{
79   nes_state *state = space->machine().driver_data<nes_state>();
80   LOG_MMC(("mapper6_w, offset: %04x, data: %02x\n", offset, data));
81
82   if (!state->m_mmc_latch1)   // when in "FFE mode" we are forced to use CHRRAM/EXRAM bank?
83   {
84      prg16_89ab(space->machine(), data >> 2);
85      // chr8(space->machine(), data & 0x03, ???);
86      // due to lack of info on the exact behavior, we simply act as if mmc_latch1=1
87      if (state->m_mmc_chr_source == CHRROM)
88         chr8(space->machine(), data & 0x03, CHRROM);
89   }
90   else if (state->m_mmc_chr_source == CHRROM)         // otherwise, we can use CHRROM (when present)
91      chr8(space->machine(), data, CHRROM);
92}
93
94/*************************************************************
95
96    Mapper 8
97
98    Known Boards: FFE3 Copier Board
99    Games: Hacked versions of games
100
101    In MESS: Supported? (I have no games to test this)
102
103*************************************************************/
104
105static WRITE8_HANDLER( mapper8_w )
106{
107   LOG_MMC(("mapper8_w, offset: %04x, data: %02x\n", offset, data));
108
109   chr8(space->machine(), data & 0x07, CHRROM);
110   prg16_89ab(space->machine(), data >> 3);
111}
112
113/*************************************************************
114
115    Mapper 17
116
117    Known Boards: FFE8 Copier Board
118    Games: Hacked versions of games
119
120    In MESS: Supported?. IRQ support is just a guess (used to
121      use MMC3 IRQ but it was wrong and it never enabled it)
122
123*************************************************************/
124
125static WRITE8_HANDLER( mapper17_l_w )
126{
127   nes_state *state = space->machine().driver_data<nes_state>();
128   LOG_MMC(("mapper17_l_w, offset: %04x, data: %02x\n", offset, data));
129
130   switch (offset)
131   {
132      case 0x1fe:
133         set_nt_mirroring(space->machine(), BIT(data, 4) ? PPU_MIRROR_HIGH : PPU_MIRROR_LOW);
134         break;
135      case 0x1ff:
136         set_nt_mirroring(space->machine(), BIT(data, 4) ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT);
137         break;
138
139      case 0x401:
140         state->m_IRQ_enable = data & 0x01;
141         break;
142      case 0x402:
143         state->m_IRQ_count = (state->m_IRQ_count & 0xff00) | data;
144         break;
145      case 0x403:
146         state->m_IRQ_enable = 1;
147         state->m_IRQ_count = (state->m_IRQ_count & 0x00ff) | (data << 8);
148         break;
149
150      case 0x404:
151         prg8_89(space->machine(), data);
152         break;
153      case 0x405:
154         prg8_ab(space->machine(), data);
155         break;
156      case 0x406:
157         prg8_cd(space->machine(), data);
158         break;
159      case 0x407:
160         prg8_ef(space->machine(), data);
161         break;
162
163      case 0x410:
164      case 0x411:
165      case 0x412:
166      case 0x413:
167      case 0x414:
168      case 0x415:
169      case 0x416:
170      case 0x417:
171         chr1_x(space->machine(), offset & 7, data, CHRROM);
172         break;
173   }
174}
175
176/*************************************************************
177
178    mmc_list
179
180    Supported mappers and corresponding pcb id
181
182*************************************************************/
183
184static const nes_mmc mmc_list[] =
185{
186/*  INES   DESC                          LOW_W, LOW_R, MED_W, HIGH_W, PPU_latch, scanline CB, hblank CB */
187   {  0, STD_NROM },
188   {  1, STD_SXROM },
189   {  2, STD_UXROM },
190   {  3, STD_CNROM },
191   {  4, STD_TXROM },
192   {  5, STD_EXROM },
193   {  6, FFE_MAPPER6 },
194   {  7, STD_AXROM },
195   {  8, FFE_MAPPER8 },
196   {  9, STD_PXROM },
197   { 10, STD_FXROM },
198   { 11, DIS_74X377 },
199   { 12, REXSOFT_DBZ5 },
200   { 13, STD_CPROM },
201   { 14, REXSOFT_SL1632 },
202   { 15, WAIXING_PS2 },
203   { 16, BANDAI_LZ93EX },   // with 24c02
204   { 17, FFE_MAPPER17 },
205   { 18, JALECO_SS88006 },
206   { 19, NAMCOT_163 },
207   { 21, KONAMI_VRC4 },
208   { 22, KONAMI_VRC2 },
209   { 23, KONAMI_VRC2 },
210   { 24, KONAMI_VRC6 },
211   { 25, KONAMI_VRC4 },
212   { 26, KONAMI_VRC6 },
213   // 27 World Hero board - Unsupported
214   // 28 Unused
215   // 29 Unused
216   // 30 Unused
217   // 31 Unused
218   { 32, IREM_G101 },
219   { 33, TAITO_TC0190FMC },
220   { 34, STD_BXROM },
221   { 35, UNL_SC127 },
222   { 36, TXC_STRIKEWOLF },
223   { 37, PAL_ZZ },
224   { 38, DIS_74X161X138 },
225   { 39, UNL_STUDYNGAME },
226   { 40, BTL_SMB2A },
227   { 41, CALTRON_6IN1 },
228   { 42, BTL_MARIOBABY },   // ai senshi nicol?
229   { 43, UNL_SMB2J },
230   { 44, BMC_SUPERBIG_7IN1 },
231   { 45, BMC_HIK8IN1 },
232   { 46, RUMBLESTATION_BOARD },
233   { 47, NES_QJ },
234   { 48, TAITO_TC0190FMCP },
235   { 49, BMC_SUPERHIK_4IN1 },
236   { 50, BTL_SMB2B },
237   { 51, BMC_BALLGAMES_11IN1 },
238   { 52, BMC_MARIOPARTY_7IN1 },
239   // 53 Supervision 16-in-1 - Unsupported
240   { 54, BMC_NOVELDIAMOND },
241   // 55 Genius SMB - No info (nor images) available
242   { 56, KAISER_KS202 },
243   { 57, BMC_GKA },
244   { 58, BMC_GKB },
245   // 59 Unused
246   // 60 4-in-1, 35-in-1 Reset based
247   { 61, RCM_TETRISFAMILY },
248   { 62, BMC_SUPER_700IN1 },
249   // 63 CH001 X-in-1 - No info (nor images) available
250   { 64, TENGEN_800032 },
251   { 65, IREM_H3001 },
252   { 66, STD_GXROM },
253   { 67, SUNSOFT_3 },
254   { 68, STD_NXROM },
255   { 69, STD_JXROM },
256   { 70, DIS_74X161X161X32 },
257   { 71, CAMERICA_BF9093 },
258   { 72, JALECO_JF17 },
259   { 73, KONAMI_VRC3 },
260   { 74, WAIXING_TYPE_A },
261   { 75, KONAMI_VRC1 },
262   { 76, NAMCOT_3446 },
263   { 77, IREM_LROG017 },
264   { 78, IREM_HOLYDIV },
265   { 79, AVE_NINA06 },
266   { 80, TAITO_X1_005 },
267   // 81 Unused
268   { 82, TAITO_X1_017 },
269   { 83, CONY_BOARD },
270   // 84 Pasofami hacked images?
271   { 85, KONAMI_VRC7 },
272   { 86, JALECO_JF13 },
273   { 87, DIS_74X139X74 },
274   { 88, NAMCOT_34X3 },
275   { 89, SUNSOFT_2 },
276   // 90 JY Company Type A (Aladdin, Final Fight 3, Super Mario World, Tekken 2) - Unsupported
277   { 91, UNL_MK2 },
278   { 92, JALECO_JF19 },
279   { 93, SUNSOFT_2 },
280   { 94, STD_UN1ROM },
281   { 95, NAMCOT_3425 },
282   { 96, BANDAI_OEKAKIDS },
283   { 97, IREM_TAM_S1 },
284   // 98 Unused
285   // 99 VS. system - Not going to be implemented (use MAME instead)
286   // 100 images hacked to work with nesticle?
287   // 101 Unused (Urusei Yatsura had been assigned to this mapper, but it's Mapper 87)
288   // 102 Unused
289   // 103 Bootleg cart 2708 (Doki Doki Panic - FDS Conversion) - Unsupported
290   { 104, CAMERICA_GOLDENFIVE },
291   // 105 Nintendo World Championship - Unsupported
292   { 106, BTL_SMB3 },
293   { 107, MAGICSERIES_MD },
294   { 108, WHIRLWIND_2706 },
295   // 109 Unused
296   // 110 Unused
297   // 111 Ninja Ryuukenden Chinese? - Unsupported
298   { 112, NTDEC_ASDER },
299   { 113, HES_BOARD },
300   { 114, SUPERGAME_LIONKING },
301   { 115, KASING_BOARD },
302   { 116, SOMERI_SL12 },
303   { 117, FUTUREMEDIA_BOARD },
304   { 118, STD_TXSROM },
305   { 119, STD_TQROM },
306   { 120, BTL_TOBIDASE },
307   { 121, KAY_PANDAPRINCE },
308   // 122 Unused
309   { 123, UNL_H2288 },
310   // 124 Unused
311   // 125 Unused
312   { 126, BMC_PJOY84 },
313   // 127 Unused
314   // 128 Unused
315   // 129 Unused
316   // 130 Unused
317   // 131 Unused
318   { 132, TXC_22211B },
319   { 133, SACHEN_SA72008 },
320   { 134, BMC_FAMILY_4646B },
321   // 135 Unused
322   { 136, SACHEN_TCU02 },
323   { 137, SACHEN_8259D },
324   { 138, SACHEN_8259B },
325   { 139, SACHEN_8259C },
326   { 140, JALECO_JF11 },
327   { 141, SACHEN_8259A },
328   { 142, KAISER_KS7032},
329   { 143, SACHEN_TCA01 },
330   { 144, AGCI_50282 },
331   { 145, SACHEN_SA72007 },
332   { 146, AVE_NINA06 }, // basically same as Mapper 79 (Nina006)
333   { 147, SACHEN_TCU01 },
334   { 148, SACHEN_SA0037 },
335   { 149, SACHEN_SA0036 },
336   { 150, SACHEN_74LS374 },
337   // 151 VS. system by Konami - Not going to be implemented (use MAME instead)
338   { 152, DIS_74X161X161X32 },
339   { 153, BANDAI_LZ93 },
340   { 154, NAMCOT_3453 },
341   { 155, STD_SXROM_A }, // diff compared to MMC1 concern WRAM
342   { 156, OPENCORP_DAOU306 },
343   { 157, BANDAI_DATACH },   // no Datach Reader -> we fall back to mapper 16
344   { 158, TENGEN_800037 },
345   { 159, BANDAI_LZ93EX },   // with 24c01
346   { 160, SACHEN_SA009 },
347   // 161 Unused
348   // 162 Unused
349   { 163, NANJING_BOARD},
350   { 164, WAIXING_FFV },
351   { 165, WAIXING_SH2 },
352   { 166, SUBOR_TYPE1 },
353   { 167, SUBOR_TYPE0 },
354   { 168, UNL_RACERMATE },
355   // 169 Unused
356   // 170 Fujiya
357   { 171, KAISER_KS7058 },
358   { 172, TXC_22211B },
359   { 173, TXC_22211C },
360   // 174 Unused
361   { 175, KAISER_KS7022},
362   { 176, UNL_XZY },
363   { 177, HENGEDIANZI_BOARD },
364   { 178, WAIXING_SGZLZ },
365   { 179, HENGEDIANZI_XJZB },
366   { 180, UXROM_CC },
367   // 181 Unused
368   { 182, HOSENKAN_BOARD },
369   // 183 FDS bootleg (Shui Guan Pipe) - Unsupported
370   { 184, SUNSOFT_1 },
371   { 185, STD_CNROM },
372   { 186, FUKUTAKE_BOARD },
373   { 187, UNL_KOF96 },
374   { 188, BANDAI_KARAOKE },
375   { 189, TXC_TW },
376   // 190 Unused
377   { 191, WAIXING_TYPE_B },
378   { 192, WAIXING_TYPE_C },
379   { 193, NTDEC_FIGHTINGHERO },
380   { 194, WAIXING_TYPE_D },
381   { 195, WAIXING_TYPE_E },
382   { 196, BTL_SUPERBROS11 },
383   { 197, UNL_SUPERFIGHTER3 },
384   { 198, WAIXING_TYPE_F },
385   { 199, WAIXING_TYPE_G },
386   { 200, BMC_36IN1 },
387   { 201, BMC_21IN1 },
388   { 202, BMC_150IN1 },
389   { 203, BMC_35IN1 },
390   { 204, BMC_64IN1 },
391   { 205, BMC_15IN1 },
392   { 206, STD_DXROM },
393   { 207, TAITO_X1_005_A },
394   { 208, GOUDER_37017 },
395   // 209 JY Company Type B (Power Rangers 3 & 4, Shin Samurai Spirits 2) - Unsupported
396   // 210 Some emu uses this as Mapper 19 without some features
397   // 211 JY Company Type C (Tiny Toon Adventures 6, Donkey Kong Country 4) - Unsupported
398   { 212, BMC_SUPERHIK_300IN1 },
399   { 213, BMC_9999999IN1 },
400   { 214, BMC_SUPERGUN_20IN1 },
401   { 215, SUPERGAME_BOOGERMAN },
402   { 216, RCM_GS2015 },
403   { 217, BMC_GOLDENCARD_6IN1 },
404   // 218 Unused
405   // 219 Bootleg A9746 - Unsupported
406   // 220 Unused
407   { 221, UNL_N625092 },
408   { 222, BTL_DRAGONNINJA },
409   { 223, WAIXING_TYPE_I },   // (according to NEStopia source, it's MMC3 with more WRAM)
410   { 224, WAIXING_TYPE_J },   // (according to NEStopia source, it's MMC3 with more WRAM)
411   { 225, BMC_72IN1 },
412   { 226, BMC_76IN1 },
413   { 227, BMC_1200IN1 },
414   { 228, ACTENT_ACT52 },
415   { 229, BMC_31IN1 },
416   { 230, BMC_22GAMES },
417   { 231, BMC_20IN1 },
418   { 232, CAMERICA_BF9096 },
419   // 233 Super 22 Games - Unsupported
420   // 234 AVE Maxi 15 - Unsupported
421   // 235 Golden Game x-in-1 - Unsupported
422   // 236 Game 800-in-1 - Unsupported
423   // 237 Unused
424   { 238, UNL_603_5052 },
425   // 239 Unused
426   { 240, CNE_SHLZ },
427   { 241, TXC_MXMDHTWO },
428   { 242, WAIXING_ZS },
429   { 243, SACHEN_74LS374_A },
430   { 244, CNE_DECATHLON },
431   { 245, WAIXING_TYPE_H },
432   { 246, CNE_FSB },
433   // 247 Unused
434   // 248 Unused
435   { 249, WAIXING_SECURITY },
436   { 250, NITRA_TDA },
437   // 251 Shen Hua Jian Yun III?? - Unsupported
438   { 252, WAIXING_SGZ },
439   // 253 Super 8-in-1 99 King Fighter?? - Unsupported
440   { 254, BTL_PIKACHUY2K },
441   { 255, BMC_110IN1 },
442};
443
444const nes_mmc *nes_mapper_lookup( int mapper )
445{
446   int i;
447
448   for (i = 0; i < ARRAY_LENGTH(mmc_list); i++)
449   {
450      if (mmc_list[i].iNesMapper == mapper)
451         return &mmc_list[i];
452   }
453
454   return NULL;
455}
456
457int nes_get_mmc_id( running_machine &machine, int mapper )
458{
459   const nes_mmc *mmc = nes_mapper_lookup(mapper);
460
461   if (mmc == NULL)
462      fatalerror("Unimplemented Mapper %d", mapper);
463
464   return mmc->pcb_id;
465}
src/mame/machine/snescart.c
r11531r11532
1/***************************************************************************
2
3  snescart.c
4
5  Machine file to handle cart loading in the Nintendo Super NES emulation.
6
7***************************************************************************/
8
9#include "emu.h"
10#include "includes/snes.h"
11#include "imagedev/cartslot.h"
12#include "snescart.h"
13
14#define SNES_CART_DEBUG 0
15
16/****** Strings for Cart Header Logging ******/
17
18#define UNK "Unknown"
19
20/* Some known type of cart */
21static const char *const types[] =
22{
23   "ROM",
24   "ROM, DSP-1",
25   "ROM, DSP-2",
26   "ROM, DSP-3",
27   "ROM, DSP-4",
28   "ROM, Super FX / FX2",
29   "ROM, SA-1",
30   "ROM, S-DD1",
31   "ROM, OBC-1",
32   "ROM, S-RTC",
33   "ROM, Z80GB (Super Game Boy)",
34   "ROM, C4",
35   "ROM, Seta ST-010",
36   "ROM, Seta ST-011",
37   "ROM, Seta ST-018",
38   "ROM, SPC7110",
39   "ROM, SPC7110, RTC",
40   UNK,                     // to add: Satellaview BS-X detection
41};
42
43/* Some known countries */
44static const char *const countries[] =
45{
46/* 0*/   "Japan (NTSC)", "USA & Canada (NTSC)", "Europe, Oceania & Asia (PAL)", "Sweden (PAL)",
47/* 4*/   "Finland (PAL)", "Denmark (PAL)", "France (PAL)", "Holland (PAL)",
48/* 8*/   "Spain (PAL)", "Germany, Austria & Switzerland (PAL)", "Italy (PAL)", "Hong Kong & China (PAL)",
49/* c*/   "Indonesia (PAL)", "South Korea (NTSC)", UNK, UNK,
50};
51
52/* Some known companies (integrations to the list from Snes9x) */
53static const char *const companies[] =
54{
55/* 0*/   "Invalid", "Nintendo", "Ajinomoto", "Imagineer-Zoom", "Chris Gray Enterprises Inc.", "Zamuse", "Falcom", UNK,
56/* 8*/   "Capcom", "HOT-B", "Jaleco", "Coconuts", "Rage Software", "Micronet", "Technos", "Mebio Software",
57/*10*/   "SHOUEi System", "Starfish", "Gremlin Graphics", "Electronic Arts", "NCS / Masaya", "COBRA Team", "Human/Field", "KOEI",
58/*18*/   "Hudson Soft", "Game Village", "Yanoman", UNK, "Tecmo", UNK, "Open System", "Virgin Games",
59/*20*/   "KSS", "Sunsoft", "POW", "Micro World", UNK, UNK, "Enix", "Loriciel/Electro Brain",
60/*28*/   "Kemco", "Seta Co.,Ltd.", "Culture Brain", "Irem Japan", "Pal Soft", "Visit Co.,Ltd.", "INTEC Inc.", "System Sacom Corp.",
61/*30*/   "Viacom New Media", "Carrozzeria", "Dynamic", "Nintendo", "Magifact", "Hect", UNK, UNK,
62/*38*/   "Capcom Europe", "Accolade Europe", UNK, "Arcade Zone", "Empire Software", "Loriciel", "Gremlin Graphics", UNK,
63/*40*/   "Seika Corp.", "UBI Soft", UNK, UNK, "LifeFitness Exertainment", UNK, "System 3", "Spectrum Holobyte",
64/*48*/   UNK, "Irem", UNK, "Raya Systems/Sculptured Software", "Renovation Products", "Malibu Games/Black Pearl", UNK, "U.S. Gold",
65/*50*/   "Absolute Entertainment", "Acclaim", "Activision", "American Sammy", "GameTek", "Hi Tech Expressions", "LJN Toys", UNK,
66/*58*/   UNK, UNK, "Mindscape", "Romstar, Inc.", UNK, "Tradewest", UNK, "American Softworks Corp.",
67/*60*/   "Titus", "Virgin Interactive Entertainment", "Maxis", "Origin/FCI/Pony Canyon", UNK, UNK, UNK, "Ocean",
68/*68*/   UNK, "Electronic Arts", UNK, "Laser Beam", UNK, UNK, "Elite", "Electro Brain",
69/*70*/   "Infogrames", "Interplay", "LucasArts", "Parker Brothers", "Konami", "STORM", UNK, UNK,
70/*78*/   "THQ Software", "Accolade Inc.", "Triffix Entertainment", UNK, "Microprose", UNK, UNK, "Kemco",
71/*80*/   "Misawa", "Teichio", "Namco Ltd.", "Lozc", "Koei", UNK, "Tokuma Shoten Intermedia", "Tsukuda Original",
72/*88*/   "DATAM-Polystar", UNK, UNK, "Bullet-Proof Software", "Vic Tokai", UNK, "Character Soft", "I\'\'Max",
73/*90*/   "Takara", "CHUN Soft", "Video System Co., Ltd.", "BEC", UNK, "Varie", "Yonezawa / S'Pal Corp.", "Kaneco",
74/*98*/   UNK, "Pack in Video", "Nichibutsu", "TECMO", "Imagineer Co.", UNK, UNK, UNK,
75/*a0*/   "Telenet", "Hori", UNK, UNK, "Konami", "K.Amusement Leasing Co.", UNK, "Takara",
76/*a8*/   UNK, "Technos Jap.", "JVC", UNK, "Toei Animation", "Toho", UNK, "Namco Ltd.",
77/*b0*/   "Media Rings Corp.", "ASCII Co. Activison", "Bandai", UNK, "Enix America", UNK, "Halken", UNK,
78/*b8*/   UNK, UNK, "Culture Brain", "Sunsoft", "Toshiba EMI", "Sony Imagesoft", UNK, "Sammy",
79/*c0*/   "Taito", UNK, "Kemco", "Square", "Tokuma Soft", "Data East", "Tonkin House", UNK,
80/*c8*/   "KOEI", UNK, "Konami USA", "NTVIC", UNK, "Meldac", "Pony Canyon", "Sotsu Agency/Sunrise",
81/*d0*/   "Disco/Taito", "Sofel", "Quest Corp.", "Sigma", "Ask Kodansha Co., Ltd.", UNK, "Naxat", UNK,
82/*d8*/   "Capcom Co., Ltd.", "Banpresto", "Tomy", "Acclaim", UNK, "NCS", "Human Entertainment", "Altron",
83/*e0*/   "Jaleco", UNK, "Yutaka", UNK, "T&ESoft", "EPOCH Co.,Ltd.", UNK, "Athena",
84/*e8*/   "Asmik", "Natsume", "King Records", "Atlus", "Sony Music Entertainment", UNK, "IGS", UNK,
85/*f0*/   UNK, "Motown Software", "Left Field Entertainment", "Beam Software", "Tec Magik", UNK, UNK, UNK,
86/*f8*/   UNK, "Cybersoft", UNK, "Psygnosis", UNK, UNK, "Davidson", UNK,
87};
88
89
90/* We use this to convert the company_id in the header to int value to be passed in companies[] */
91static int char_to_int_conv( char id )
92{
93   int value;
94
95   if (id == '1') value = 0x01;
96   else if (id == '2') value = 0x02;
97   else if (id == '3') value = 0x03;
98   else if (id == '4') value = 0x04;
99   else if (id == '5') value = 0x05;
100   else if (id == '6') value = 0x06;
101   else if (id == '7') value = 0x07;
102   else if (id == '8') value = 0x08;
103   else if (id == '9') value = 0x09;
104   else if (id == 'A') value = 0x0a;
105   else if (id == 'B') value = 0x0b;
106   else if (id == 'C') value = 0x0c;
107   else if (id == 'D') value = 0x0d;
108   else if (id == 'E') value = 0x0e;
109   else if (id == 'F') value = 0x0f;
110   else value = 0x00;
111
112   return value;
113}
114
115
116/***************************************************************************
117
118  SRAM handling
119
120***************************************************************************/
121
122/* Loads the battery backed RAM into the appropriate memory area */
123static void snes_load_sram(running_machine &machine)
124{
125   snes_state *state = machine.driver_data<snes_state>();
126   UINT8 ii;
127   UINT8 *battery_ram, *ptr;
128
129   battery_ram = (UINT8*)malloc(state->m_cart[0].sram_max);
130   ptr = battery_ram;
131   device_image_interface *image = dynamic_cast<device_image_interface *>(machine.device("cart"));
132   image->battery_load(battery_ram, state->m_cart[0].sram_max, 0xff);
133
134   if (state->m_cart[0].mode == SNES_MODE_20)
135   {
136      UINT32 size = state->m_cart[0].small_sram ? 0x8000 : 0x10000;
137
138      /* There could be some larger image needing banks 0x70 to 0x7f at address 0x8000 for ROM
139         * mirroring. These should be treated separately or data would be overwritten by SRAM */
140      for (ii = 0; ii < 16; ii++)
141      {
142         /* loading */
143         memmove(&snes_ram[0x700000 + (ii * 0x010000)], ptr, size);
144         /* mirroring */
145         memcpy(&snes_ram[0xf00000 + (ii * 0x010000)], &snes_ram[0x700000 + (ii * 0x010000)], size);
146         ptr += size;
147      }
148   }
149   else if (state->m_cart[0].mode == SNES_MODE_21)
150   {
151      for (ii = 0; ii < 16; ii++)
152      {
153         /* loading */
154         memmove(&snes_ram[0x306000 + (ii * 0x010000)], ptr, 0x2000);
155         /* mirroring */
156         memcpy(&snes_ram[0xb06000 + (ii * 0x010000)], &snes_ram[0x306000 + (ii * 0x010000)], 0x2000);
157         ptr += 0x2000;
158      }
159   }
160   else if (state->m_cart[0].mode == SNES_MODE_25)
161   {
162      for (ii = 0; ii < 16; ii++)
163      {
164         memmove(&snes_ram[0xb06000 + (ii * 0x010000)], ptr, 0x2000);
165         ptr += 0x2000;
166      }
167   }
168
169   free(battery_ram);
170}
171
172/* Saves the battery backed RAM from the appropriate memory area */
173static void snes_save_sram(running_machine &machine)
174{
175   snes_state *state = machine.driver_data<snes_state>();
176   UINT8 ii;
177   UINT8 *battery_ram, *ptr;
178
179   battery_ram = (UINT8*)malloc(state->m_cart[0].sram_max);
180   ptr = battery_ram;
181
182   if (state->m_cart[0].mode == SNES_MODE_20)
183   {
184      UINT32 size = state->m_cart[0].small_sram ? 0x8000 : 0x10000;
185
186      for (ii = 0; ii < 16; ii++)
187      {
188         memmove(ptr, &snes_ram[0x700000 + (ii * 0x010000)], size);
189         ptr += size;
190      }
191   }
192   else if (state->m_cart[0].mode == SNES_MODE_21)
193   {
194      for (ii = 0; ii < 16; ii++)
195      {
196         memmove(ptr, &snes_ram[0x306000 + (ii * 0x010000)], 0x2000);
197         ptr += 0x2000;
198      }
199   }
200   else if (state->m_cart[0].mode == SNES_MODE_25)
201   {
202      for (ii = 0; ii < 16; ii++)
203      {
204         memmove(ptr, &snes_ram[0xb06000 + (ii * 0x010000)], 0x2000);
205         ptr += 0x2000;
206      }
207   }
208   device_image_interface *image = dynamic_cast<device_image_interface *>(machine.device("cart"));
209   image->battery_save(battery_ram, state->m_cart[0].sram_max);
210
211   free(battery_ram);
212}
213
214static void snes_machine_stop(running_machine &machine)
215{
216   snes_state *state = machine.driver_data<snes_state>();
217
218   /* Save SRAM */
219   if (state->m_cart[0].sram > 0)
220      snes_save_sram(machine);
221}
222
223MACHINE_START( snes_mess )
224{
225   machine.add_notifier(MACHINE_NOTIFY_EXIT, machine_notify_delegate(FUNC(snes_machine_stop),&machine));
226   MACHINE_START_CALL(snes);
227}
228
229
230static void sufami_load_sram(running_machine &machine, const char *cart_tag)
231{
232   UINT8 ii;
233   UINT8 *battery_ram, *ptr;
234   int st_sram_offset = 0;
235
236   battery_ram = (UINT8*)malloc(0x20000);
237   ptr = battery_ram;
238   device_image_interface *image = dynamic_cast<device_image_interface *>(machine.device(cart_tag));
239   image->battery_load(battery_ram, 0x20000, 0);
240
241   if (strcmp(cart_tag, "slot_a") == 0)
242      st_sram_offset = 0x608000;
243
244   if (strcmp(cart_tag, "slot_b") == 0)
245      st_sram_offset = 0x708000;
246
247   /* Cart RAM is at 0x60-0x63:0x8000-0xffff (+0x10 for slot2) */
248   for (ii = 0; ii < 4; ii++)
249   {
250      /* loading */
251      memcpy(&snes_ram[st_sram_offset + (ii * 0x010000)], ptr + (ii * 0x8000), 0x8000);
252      /* mirroring */
253      memcpy(&snes_ram[0x800000 + st_sram_offset + (ii * 0x010000)], &snes_ram[st_sram_offset + (ii * 0x010000)], 0x8000);
254   }
255
256   free(battery_ram);
257}
258
259static void sufami_machine_stop(running_machine &machine)
260{
261   snes_state *state = machine.driver_data<snes_state>();
262   UINT8 ii;
263   UINT8 *battery_ram, *ptr;
264
265   battery_ram = (UINT8*)malloc(0x20000);
266   ptr = battery_ram;
267
268   if (state->m_cart[0].slot_in_use)
269   {
270      for (ii = 0; ii < 4; ii++)
271      {
272         memmove(ptr + ii * 0x8000, &snes_ram[0x608000 + (ii * 0x010000)], 0x8000);
273      }
274      device_image_interface *image = dynamic_cast<device_image_interface *>(machine.device("slot_a"));
275      image->battery_save(battery_ram, 0x20000);
276   }
277
278   if (state->m_cart[1].slot_in_use)
279   {
280      for (ii = 0; ii < 4; ii++)
281      {
282         memmove(ptr + ii * 0x8000, &snes_ram[0x708000 + (ii * 0x010000)], 0x8000);
283      }
284      device_image_interface *image = dynamic_cast<device_image_interface *>(machine.device("slot_b"));
285      image->battery_save(battery_ram, 0x20000);
286   }
287
288   free(battery_ram);
289}
290
291MACHINE_START( snesst )
292{
293   machine.add_notifier(MACHINE_NOTIFY_EXIT, machine_notify_delegate(FUNC(sufami_machine_stop),&machine));
294   MACHINE_START_CALL(snes);
295}
296
297
298/***************************************************************************
299
300  Cart handling
301
302***************************************************************************/
303
304/* This function assign a 'score' to data immediately after 'offset' to measure how valid they are
305as information block (to decide if the image is HiRom, LoRom, ExLoRom or ExHiRom) */
306/* Code from bsnes, courtesy of byuu - http://byuu.cinnamonpirate.com/ */
307static int snes_validate_infoblock( UINT8 *infoblock, UINT32 offset )
308{
309   int score = 0;
310   UINT16 reset_vector = infoblock[offset + 0x3c] | (infoblock[offset + 0x3d] << 8);
311   UINT16 checksum     = infoblock[offset + 0x1e] | (infoblock[offset + 0x1f] << 8);
312   UINT16 ichecksum    = infoblock[offset + 0x1c] | (infoblock[offset + 0x1d] << 8);
313   UINT8 reset_opcode  = infoblock[(offset & ~0x7fff) | (reset_vector & 0x7fff)];   //first opcode executed upon reset
314   UINT8 mapper        = infoblock[offset + 0x15] & ~0x10;                     //mask off irrelevent FastROM-capable bit
315
316   /* $00:[000-7fff] contains uninitialized RAM and MMIO.
317    reset vector must point to ROM at $00:[8000-ffff] to be considered valid. */
318   if (reset_vector < 0x8000)
319      return 0;
320
321   /* some images duplicate the header in multiple locations, and others have completely
322    invalid header information that cannot be relied upon. The code below will analyze
323    the first opcode executed at the specified reset vector to determine the probability
324    that this is the correct header. Score is assigned accordingly. */
325
326   /* most likely opcodes */
327   if (reset_opcode == 0x78      //sei
328      || reset_opcode == 0x18      //clc (clc; xce)
329      || reset_opcode == 0x38      //sec (sec; xce)
330      || reset_opcode == 0x9c      //stz $nnnn (stz $4200)
331      || reset_opcode == 0x4c      //jmp $nnnn
332      || reset_opcode == 0x5c      //jml $nnnnnn
333   )
334      score += 8;
335
336   /* plausible opcodes */
337   if (reset_opcode == 0xc2      //rep #$nn
338      || reset_opcode == 0xe2      //sep #$nn
339      || reset_opcode == 0xad      //lda $nnnn
340      || reset_opcode == 0xae      //ldx $nnnn
341      || reset_opcode == 0xac      //ldy $nnnn
342      || reset_opcode == 0xaf      //lda $nnnnnn
343      || reset_opcode == 0xa9      //lda #$nn
344      || reset_opcode == 0xa2      //ldx #$nn
345      || reset_opcode == 0xa0      //ldy #$nn
346      || reset_opcode == 0x20      //jsr $nnnn
347      || reset_opcode == 0x22      //jsl $nnnnnn
348   )
349      score += 4;
350
351   /* implausible opcodes */
352   if (reset_opcode == 0x40      //rti
353      || reset_opcode == 0x60      //rts
354      || reset_opcode == 0x6b      //rtl
355      || reset_opcode == 0xcd      //cmp $nnnn
356      || reset_opcode == 0xec      //cpx $nnnn
357      || reset_opcode == 0xcc      //cpy $nnnn
358   )
359      score -= 4;
360
361   /* least likely opcodes */
362   if (reset_opcode == 0x00      //brk #$nn
363      || reset_opcode == 0x02      //cop #$nn
364      || reset_opcode == 0xdb      //stp
365      || reset_opcode == 0x42      //wdm
366      || reset_opcode == 0xff      //sbc $nnnnnn,x
367   )
368      score -= 8;
369
370   /* Sometimes, both the header and reset vector's first opcode will match ...
371    fallback and rely on info validity in these cases to determine more likely header. */
372
373   /* a valid checksum is the biggest indicator of a valid header. */
374   if ((checksum + ichecksum) == 0xffff && (checksum != 0) && (ichecksum != 0))
375      score += 4;
376
377   /* then there are the expected mapper values */
378   if (offset == 0x007fc0 && mapper == 0x20)   // 0x20 is usually LoROM
379      score += 2;
380
381   if (offset == 0x00ffc0 && mapper == 0x21)   // 0x21 is usually HiROM
382      score += 2;
383
384   if (offset == 0x007fc0 && mapper == 0x22)   // 0x22 is usually ExLoROM
385      score += 2;
386
387   if (offset == 0x40ffc0 && mapper == 0x25)   // 0x25 is usually ExHiROM
388      score += 2;
389
390   /* finally, there are valid values in the Company, Region etc. fields */
391   if (infoblock[offset + 0x1a] == 0x33)         // Company field: 0x33 indicates extended header
392      score += 2;
393
394   if (infoblock[offset + 0x16] < 0x08)         // ROM Type field
395      score++;
396
397   if (infoblock[offset + 0x17] < 0x10)         // ROM Size field
398      score++;
399
400   if (infoblock[offset + 0x18] < 0x08)         // SRAM Size field
401      score++;
402
403   if (infoblock[offset + 0x19] < 14)            // Region field
404      score++;
405
406   /* do we still have a positive score? */
407   if (score < 0)
408      score = 0;
409
410   return score;
411}
412
413/* Here we add a couple of cart utilities, to avoid duplicating the code in each DEVICE_IMAGE_LOAD */
414static UINT32 snes_skip_header( device_image_interface &image, UINT32 snes_rom_size )
415{
416   UINT8 header[512];
417   UINT32 offset = 512;
418
419   /* Check for a header (512 bytes) */
420   if (image.software_entry() == NULL)
421      image.fread( header, 512);
422   else
423      memcpy(header, image.get_software_region("rom"), 512);
424
425   if ((header[8] == 0xaa) && (header[9] == 0xbb) && (header[10] == 0x04))
426   {
427      /* Found an SWC identifier */
428      logerror("Found header (SWC) - Skipped\n");
429   }
430   else if ((header[0] | (header[1] << 8)) == (((snes_rom_size - 512) / 1024) / 8))
431   {
432      /* Some headers have the rom size at the start, if this matches with the actual rom size, we probably have a header */
433      logerror("Found header (size) - Skipped\n");
434   }
435   else if ((snes_rom_size % 0x8000) == 512)
436   {
437      /* As a last check we'll see if there's exactly 512 bytes extra to this image. */
438      logerror("Found header (extra) - Skipped\n");
439   }
440   else
441   {
442      /* No header found so go back to the start of the file */
443      logerror("No header found.\n");
444      offset = 0;
445   }
446
447   return offset;
448}
449
450
451/* This determines if a cart is in Mode 20, 21, 22 or 25; sets state->m_cart[0].mode and
452 state->m_cart[0].sram accordingly; and returns the offset of the internal header (needed to
453 detect BSX and ST carts) */
454static UINT32 snes_find_hilo_mode( device_image_interface &image, UINT8 *buffer, UINT32 offset, int cartid )
455{
456   snes_state *state = image.device().machine().driver_data<snes_state>();
457   UINT8 valid_mode20, valid_mode21, valid_mode25;
458   UINT32 retvalue;
459
460   /* Now to determine if this is a lo-ROM, a hi-ROM or an extended lo/hi-ROM */
461   valid_mode20 = snes_validate_infoblock(buffer, 0x007fc0);
462   valid_mode21 = snes_validate_infoblock(buffer, 0x00ffc0);
463   valid_mode25 = snes_validate_infoblock(buffer, 0x40ffc0);
464
465   /* Images larger than 32mbits are likely ExHiRom */
466   if (valid_mode25)
467      valid_mode25 += 4;
468
469   if ((valid_mode20 >= valid_mode21) && (valid_mode20 >= valid_mode25))
470   {
471      if ((buffer[0x007fd5] == 0x32) || ((state->m_cart_size - offset) > 0x401000))
472         state->m_cart[cartid].mode = SNES_MODE_22;   // ExLoRom
473      else
474         state->m_cart[cartid].mode = SNES_MODE_20;   // LoRom
475
476      retvalue = 0x007fc0;
477
478      /* a few games require 512k, however we store twice as much to be sure to cover the various mirrors */
479      state->m_cart[cartid].sram_max = 0x100000;
480   }
481   else if (valid_mode21 >= valid_mode25)
482   {
483      state->m_cart[cartid].mode = SNES_MODE_21;   // HiRom
484      retvalue = 0x00ffc0;
485      state->m_cart[cartid].sram_max = 0x20000;
486   }
487   else
488   {
489      state->m_cart[cartid].mode = SNES_MODE_25;   // ExHiRom
490      retvalue = 0x40ffc0;
491      state->m_cart[cartid].sram_max = 0x20000;
492   }
493
494   logerror( "\t HiROM/LoROM id: %s (LoROM: %d , HiROM: %d, ExHiROM: %d)\n",
495          (state->m_cart[cartid].mode == SNES_MODE_20) ? "LoROM" :
496          (state->m_cart[cartid].mode == SNES_MODE_21) ? "HiROM" :
497          (state->m_cart[cartid].mode == SNES_MODE_22) ? "ExLoROM" :
498          (state->m_cart[cartid].mode == SNES_MODE_25) ? "ExHiROM" : "Other (BSX or ST)",
499          valid_mode20, valid_mode21, valid_mode25);
500
501   return retvalue;
502}
503
504static int snes_find_addon_chip( running_machine &machine )
505{
506   snes_state *state = machine.driver_data<snes_state>();
507   address_space *space = machine.device("maincpu")->memory().space(AS_PROGRAM);
508   int supported_type = 1;
509   int dsp_prg_offset = 0;
510
511   /* Info mostly taken from http://snesemu.black-ship.net/misc/-from%20nsrt.edgeemu.com-chipinfo.htm */
512   switch (snes_r_bank1(space, 0x00ffd6))
513   {
514      case 0x00:
515      case 0x01:
516      case 0x02:
517         state->m_has_addon_chip = HAS_NONE;
518         break;
519
520      case 0x03:
521         if (snes_r_bank1(space, 0x00ffd5) == 0x30)
522         {
523            state->m_has_addon_chip = HAS_DSP4;
524            dsp_prg_offset = SNES_DSP4_OFFSET;
525         }
526         else
527         {
528            state->m_has_addon_chip = HAS_DSP1;
529            dsp_prg_offset = SNES_DSP1B_OFFSET;
530         }
531         break;
532
533      case 0x04:
534         state->m_has_addon_chip = HAS_DSP1;
535         dsp_prg_offset = SNES_DSP1B_OFFSET;
536         break;
537
538      case 0x05:
539         if (snes_r_bank1(space, 0x00ffd5) == 0x20)
540         {
541            state->m_has_addon_chip = HAS_DSP2;
542            dsp_prg_offset = SNES_DSP2_OFFSET;
543         }
544         /* DSP-3 is hard to detect. We exploit the fact that the only game has been manufactured by Bandai */
545         else if ((snes_r_bank1(space, 0x00ffd5) == 0x30) && (snes_r_bank1(space, 0x00ffda) == 0xb2))
546         {
547            state->m_has_addon_chip = HAS_DSP3;
548            dsp_prg_offset = SNES_DSP3_OFFSET;
549         }
550         else
551         {
552            state->m_has_addon_chip = HAS_DSP1;
553            dsp_prg_offset = SNES_DSP1B_OFFSET;
554         }
555         break;
556
557      case 0x13:   // Mario Chip 1
558      case 0x14:   // GSU-x
559      case 0x15:   // GSU-x
560      case 0x1a:   // GSU-1 (21 MHz at start)
561         if (snes_r_bank1(space, 0x00ffd5) == 0x20)
562            state->m_has_addon_chip = HAS_SUPERFX;
563         break;
564
565      case 0x25:
566         state->m_has_addon_chip = HAS_OBC1;
567         break;
568
569      case 0x32:   // needed by a Sample game (according to ZSNES)
570      case 0x34:
571      case 0x35:
572         if (snes_r_bank1(space, 0x00ffd5) == 0x23)
573         {
574            state->m_has_addon_chip = HAS_SA1;
575            supported_type = 0;
576            mame_printf_error("This is a SA-1 type game, currently unsupported by the driver\n");
577         }
578         break;
579
580      case 0x43:
581      case 0x45:
582         if (snes_r_bank1(space, 0x00ffd5) == 0x32)
583         {
584            state->m_has_addon_chip = HAS_SDD1;
585         }
586         break;
587
588      case 0x55:
589         if (snes_r_bank1(space, 0x00ffd5) == 0x35)
590         {
591            state->m_has_addon_chip = HAS_RTC;
592         }
593         break;
594
595      case 0xe3:
596         state->m_has_addon_chip = HAS_Z80GB;
597         supported_type = 0;
598         break;
599
600      case 0xf3:
601         state->m_has_addon_chip = HAS_CX4;
602         break;
603
604      case 0xf5:
605         if (snes_r_bank1(space, 0x00ffd5) == 0x30)
606         {
607            state->m_has_addon_chip = HAS_ST018;
608            supported_type = 0;
609         }
610         else if (snes_r_bank1(space, 0x00ffd5) == 0x3a)
611         {
612            state->m_has_addon_chip = HAS_SPC7110;
613         }
614         break;
615
616      case 0xf6:
617         /* These Seta ST-01X chips have both 0x30 at 0x00ffd5,
618             they only differ for the 'size' at 0x00ffd7 */
619         if (snes_r_bank1(space, 0x00ffd7) < 0x0a)
620            state->m_has_addon_chip = HAS_ST011;
621         else
622            state->m_has_addon_chip = HAS_ST010;
623
624         // if we are loading the game in a driver without the ST01X DSP, revert to HAS_NONE to avoid crash
625         if (!state->m_upd96050)
626            state->m_has_addon_chip = HAS_NONE;
627         break;
628
629      case 0xf9:
630         if (snes_r_bank1(space, 0x00ffd5) == 0x3a)
631         {
632            state->m_has_addon_chip = HAS_SPC7110_RTC;
633            supported_type = 0;
634         }
635         break;
636
637      default:
638         state->m_has_addon_chip = HAS_UNK;
639         supported_type = 0;
640         break;
641   }
642
643   if ((state->m_has_addon_chip >= HAS_DSP1) && (state->m_has_addon_chip <= HAS_DSP4))
644   {
645      UINT8 *dspsrc = (UINT8 *)machine.region("addons")->base();
646      UINT32 *dspprg = (UINT32 *)machine.region("dspprg")->base();
647      UINT16 *dspdata = (UINT16 *)machine.region("dspdata")->base();
648
649      // copy DSP program
650      for (int i = 0; i < 0x2000; i+= 4)
651      {
652         *dspprg = dspsrc[dsp_prg_offset+0+i]<<24 | dspsrc[dsp_prg_offset+1+i]<<16 | dspsrc[dsp_prg_offset+2+i]<<8;
653         dspprg++;
654      }
655
656      // copy DSP data
657      for (int i = 0; i < 0x800; i+= 2)
658      {
659         *dspdata++ = dspsrc[dsp_prg_offset+0x2000+i]<<8 | dspsrc[dsp_prg_offset+0x2001+i];
660      }
661   }
662
663   if ((state->m_has_addon_chip == HAS_ST010) || (state->m_has_addon_chip == HAS_ST011))
664   {
665      UINT8 *dspsrc = (UINT8 *)machine.region("addons")->base();
666      UINT32 *dspprg = (UINT32 *)machine.region("dspprg")->base();
667      UINT16 *dspdata = (UINT16 *)machine.region("dspdata")->base();
668
669      // copy DSP program
670      for (int i = 0; i < 0x10000; i+= 4)
671      {
672         *dspprg = dspsrc[0+i]<<24 | dspsrc[1+i]<<16 | dspsrc[2+i]<<8;
673         dspprg++;
674      }
675
676      // copy DSP data
677      for (int i = 0; i < 0x1000; i+= 2)
678      {
679         *dspdata++ = dspsrc[0x10000+i]<<8 | dspsrc[0x10001+i];
680      }
681   }
682
683   return supported_type;
684}
685
686static void snes_cart_log_info( running_machine &machine, int total_blocks, int supported )
687{
688   snes_state *state = machine.driver_data<snes_state>();
689   address_space *space = machine.device("maincpu")->memory().space(AS_PROGRAM);
690   char title[21], rom_id[4], company_id[2];
691   int i, company, has_ram = 0, has_sram = 0;
692
693   /* Company */
694   for (i = 0; i < 2; i++)
695      company_id[i] = snes_r_bank1(space, 0x00ffb0 + i);
696   company = (char_to_int_conv(company_id[0]) << 4) + char_to_int_conv(company_id[1]);
697   if (company == 0)
698      company = snes_r_bank1(space, 0x00ffda);
699
700   /* ROM ID */
701   for( i = 0; i < 4; i++ )
702      rom_id[i] = snes_r_bank1(space, 0x00ffb2 + i);
703
704   /* Title */
705   for( i = 0; i < 21; i++ )
706      title[i] = snes_r_bank1(space, 0x00ffc0 + i);
707
708   /* RAM */
709   if (((snes_r_bank1(space, 0x00ffd6) & 0xf) == 1) ||
710      ((snes_r_bank1(space, 0x00ffd6) & 0xf) == 2) ||
711      ((snes_r_bank1(space, 0x00ffd6) & 0xf) == 4) ||
712      ((snes_r_bank1(space, 0x00ffd6) & 0xf) == 5))
713      has_ram = 1;
714
715   /* SRAM */
716   if (((snes_r_bank1(space, 0x00ffd6) & 0xf) == 2) ||
717      ((snes_r_bank1(space, 0x00ffd6) & 0xf) == 5) ||
718      ((snes_r_bank1(space, 0x00ffd6) & 0xf) == 6))
719      has_sram = 1;
720
721   logerror( "ROM DETAILS\n" );
722   logerror( "===========\n\n" );
723   logerror( "\tTotal blocks:  %d (%dmb)\n", total_blocks, total_blocks / (state->m_cart[0].mode & 5 ? 32 : 16) );
724   logerror( "\tROM bank size: %s \n",
725          (state->m_cart[0].mode == SNES_MODE_20) ? "LoROM" :
726          (state->m_cart[0].mode == SNES_MODE_21) ? "HiROM" :
727          (state->m_cart[0].mode == SNES_MODE_22) ? "ExLoROM" :
728          (state->m_cart[0].mode == SNES_MODE_25) ? "ExHiROM" : "Other (BSX or ST)" );
729   logerror( "\tCompany:       %s [%.2s]\n", companies[company], company_id );
730   logerror( "\tROM ID:        %.4s\n\n", rom_id );
731
732   logerror( "HEADER DETAILS\n" );
733   logerror( "==============\n\n" );
734   logerror( "\tName:          %.21s\n", title );
735   logerror( "\tSpeed:         %s [%d]\n", ((snes_r_bank1(space, 0x00ffd5) & 0xf0)) ? "FastROM" : "SlowROM", (snes_r_bank1(space, 0x00ffd5) & 0xf0) >> 4 );
736   logerror( "\tBank size:     %s [%d]\n", (snes_r_bank1(space, 0x00ffd5) & 0xf) ? "HiROM" : "LoROM", snes_r_bank1(space, 0x00ffd5) & 0xf );
737
738   logerror( "\tType:          %s", types[state->m_has_addon_chip]);
739   if (has_ram)
740      logerror( ", RAM");
741   if (has_sram)
742      logerror( ", SRAM");
743   logerror( " [%d]\n", snes_r_bank1(space, 0x00ffd6) );
744
745   logerror( "\tSize:          %d megabits [%d]\n", 1 << (snes_r_bank1(space, 0x00ffd7) - 7), snes_r_bank1(space, 0x00ffd7) );
746   logerror( "\tSRAM:          %d kilobits [%d]\n", state->m_cart[0].sram * 8, snes_ram[0xffd8] );
747   logerror( "\tCountry:       %s [%d]\n", countries[snes_r_bank1(space, 0x00ffd9)], snes_r_bank1(space, 0x00ffd9) );
748   logerror( "\tLicense:       %s [%X]\n", companies[snes_r_bank1(space, 0x00ffda)], snes_r_bank1(space, 0x00ffda) );
749   logerror( "\tVersion:       1.%d\n", snes_r_bank1(space, 0x00ffdb) );
750   logerror( "\tInv Checksum:  %X %X\n", snes_r_bank1(space, 0x00ffdd), snes_r_bank1(space, 0x00ffdc) );
751   logerror( "\tChecksum:      %X %X\n", snes_r_bank1(space, 0x00ffdf), snes_r_bank1(space, 0x00ffde) );
752   logerror( "\tNMI Address:   %2X%2Xh\n", snes_r_bank1(space, 0x00fffb), snes_r_bank1(space, 0x00fffa) );
753   logerror( "\tStart Address: %2X%2Xh\n\n", snes_r_bank1(space, 0x00fffd), snes_r_bank1(space, 0x00fffc) );
754
755   logerror( "\tMode: %d\n", state->m_cart[0].mode);
756
757   if (!supported)
758      logerror("WARNING: This cart type \"%s\" is not supported yet!\n", types[state->m_has_addon_chip]);
759}
760
761static DEVICE_IMAGE_LOAD( snes_cart )
762{
763   int supported_type = 1, i, j;
764   running_machine &machine = image.device().machine();
765   snes_state *state = machine.driver_data<snes_state>();
766   address_space *space = machine.device( "maincpu")->memory().space( AS_PROGRAM );
767   int total_blocks, read_blocks, has_bsx_slot = 0, st_bios = 0;
768   UINT32 offset, int_header_offs;
769   UINT8 *ROM = image.device().machine().region("cart")->base();
770
771   if (image.software_entry() == NULL)
772      state->m_cart_size = image.length();
773   else
774      state->m_cart_size = image.get_software_region_length("rom");
775
776   /* Check for a header (512 bytes), and skip it if found */
777   offset = snes_skip_header(image, state->m_cart_size);
778
779   if (image.software_entry() == NULL)
780   {
781      image.fseek(offset, SEEK_SET);
782      image.fread( ROM, state->m_cart_size - offset);
783   }
784   else
785      memcpy(ROM, image.get_software_region("rom") + offset, state->m_cart_size - offset);
786
787   if (SNES_CART_DEBUG) mame_printf_error("size %08X\n", state->m_cart_size - offset);
788
789   /* First, look if the cart is HiROM or LoROM (and set snes_cart accordingly) */
790   int_header_offs = snes_find_hilo_mode(image, ROM, offset, 0);
791
792   /* Then, detect BS-X carts */
793   // Detect presence of BS-X Flash Cart
794   if ((ROM[int_header_offs + 0x13] == 0x00 || ROM[int_header_offs + 0x13] == 0xff) &&
795         ROM[int_header_offs + 0x14] == 0x00)
796   {
797      UINT8 n15 = ROM[int_header_offs + 0x15];
798      if (n15 == 0x00 || n15 == 0x80 || n15 == 0x84 || n15 == 0x9c || n15 == 0xbc || n15 == 0xfc)
799      {
800         if (ROM[int_header_offs + 0x1a] == 0x33 || ROM[int_header_offs + 0x1a] == 0xff)
801         {
802            // BS-X Flash Cart
803            state->m_cart[0].mode = SNES_MODE_BSX;
804         }
805      }
806   }
807
808   // Detect presence of BS-X flash cartridge connector
809   if ((ROM[int_header_offs - 14] == 'Z') && (ROM[int_header_offs - 11] == 'J'))
810   {
811      UINT8 n13 = ROM[int_header_offs - 13];
812      if ((n13 >= 'A' && n13 <= 'Z') || (n13 >= '0' && n13 <= '9'))
813      {
814         if (ROM[int_header_offs + 0x1a] == 0x33 ||
815            (ROM[int_header_offs - 10] == 0x00 && ROM[int_header_offs - 4] == 0x00))
816         {
817            has_bsx_slot = 1;
818         }
819      }
820   }
821
822   // If there is a BS-X connector, detect if it is the Base Cart or a compatible slotted cart
823   if (has_bsx_slot)
824   {
825      if (!memcmp(ROM + int_header_offs, "Satellaview BS-X     ", 21))
826      {
827         //BS-X Base Cart
828         state->m_cart[0].mode = SNES_MODE_BSX;
829         // handle RAM
830      }
831      else
832      {
833         state->m_cart[0].mode = (int_header_offs ==0x007fc0) ? SNES_MODE_BSLO : SNES_MODE_BSHI;
834         // handle RAM?
835      }
836   }
837
838   /* Then, detect Sufami Turbo carts */
839   if (!memcmp(ROM, "BANDAI SFC-ADX", 14))
840   {
841      state->m_cart[0].mode = SNES_MODE_ST;
842      if (!memcmp(ROM + 16, "SFC-ADX BACKUP", 14))
843         st_bios = 1;
844   }
845
846   if (SNES_CART_DEBUG) mame_printf_error("mode %d\n", state->m_cart[0].mode);
847
848   /* FIXME: Insert crc check here? */
849
850   /* How many blocks of data are available to be loaded? */
851   total_blocks = ((state->m_cart_size - offset) / (state->m_cart[0].mode & 0xa5 ? 0x8000 : 0x10000));
852   read_blocks = 0;
853
854   if (SNES_CART_DEBUG) mame_printf_error("blocks %d\n", total_blocks);
855
856   /* Loading all the data blocks from cart, we only partially cover banks 0x00 to 0x7f. Therefore, we
857     * have to mirror the blocks until we reach the end. E.g. for a 11Mbits image (44 blocks), we proceed
858     * as follows:
859     * 11 Mbits = 8 Mbits (blocks 1->32) + 2 Mbits (blocks 33->40) + 1 Mbit (blocks 41->44).
860     * Hence, we fill memory up to 16 Mbits (banks 0x00 to 0x3f) mirroring as follows
861     * 8 Mbits (blocks 1->32) + 2 Mbits (blocks 33->40) + 1 Mbit (blocks 41->44) + 1 Mbit (blocks 41->44)
862     *   + 2 Mbits (blocks 33->40) + 1 Mbit (blocks 41->44) + 1 Mbit (blocks 41->44)
863     * and we repeat the same blocks in the second half of the banks (banks 0x40 to 0x7f).
864     * This is likely what happens in the real SNES as well, because the unit cannot be aware of the exact
865     * size of data in the cart (procedure confirmed by byuu)
866     */
867   switch (state->m_cart[0].mode)
868   {
869      case SNES_MODE_21:
870      /* HiROM carts load data in banks 0xc0 to 0xff. Each bank is fully mirrored in banks 0x40 to 0x7f
871         * (actually up to 0x7d, because 0x7e and 0x7f are overwritten by WRAM). The top half (address
872         * range 0x8000 - 0xffff) of each bank is also mirrored in banks 0x00 to 0x3f and 0x80 to 0xbf.
873         */
874         /* SPC7110 games needs this different loading routine */
875         if ((ROM[0x00ffd6] == 0xf9 || ROM[0x00ffd6] == 0xf5) && (ROM[0x00ffd5] == 0x3a))
876         {
877            while (read_blocks < 16 && read_blocks < total_blocks)
878            {
879               /* Loading data */
880               memcpy(&snes_ram[0xc00000 + read_blocks * 0x10000], &ROM[0x000000 + read_blocks * 0x10000], 0x10000);
881               /* Mirroring */
882               memcpy(&snes_ram[0x008000 + read_blocks * 0x10000], &snes_ram[0xc08000 + read_blocks * 0x10000], 0x8000);
883               memcpy(&snes_ram[0x808000 + read_blocks * 0x10000], &snes_ram[0xc08000 + read_blocks * 0x10000], 0x8000);
884               read_blocks++;
885            }
886         }
887         else
888         {
889            while (read_blocks < 64 && read_blocks < total_blocks)
890            {
891               /* Loading data */
892               memcpy(&snes_ram[0xc00000 + read_blocks * 0x10000], &ROM[0x000000 + read_blocks * 0x10000], 0x10000);
893               /* Mirroring */
894               memcpy(&snes_ram[0x008000 + read_blocks * 0x10000], &snes_ram[0xc08000 + read_blocks * 0x10000], 0x8000);
895               memcpy(&snes_ram[0x400000 + read_blocks * 0x10000], &snes_ram[0xc00000 + read_blocks * 0x10000], 0x10000);
896               memcpy(&snes_ram[0x808000 + read_blocks * 0x10000], &snes_ram[0xc08000 + read_blocks * 0x10000], 0x8000);
897               read_blocks++;
898            }
899            /* Filling banks up to 0xff and their mirrors */
900            while (read_blocks % 64)
901            {
902               int j = 0, repeat_blocks;
903               while ((read_blocks % (64 >> j)) && j < 6)
904                  j++;
905               repeat_blocks = read_blocks % (64 >> (j - 1));
906
907               memcpy(&snes_ram[0xc00000 + read_blocks * 0x10000], &snes_ram[0xc00000 + (read_blocks - repeat_blocks) * 0x10000], repeat_blocks * 0x10000);
908               memcpy(&snes_ram[read_blocks * 0x10000], &snes_ram[(read_blocks - repeat_blocks) * 0x10000], repeat_blocks * 0x10000);
909               memcpy(&snes_ram[0x400000 + read_blocks * 0x10000], &snes_ram[0x400000 + (read_blocks - repeat_blocks) * 0x10000], repeat_blocks * 0x10000);
910               memcpy(&snes_ram[0x800000 + read_blocks * 0x10000], &snes_ram[0x800000 + (read_blocks - repeat_blocks) * 0x10000], repeat_blocks * 0x10000);
911               read_blocks += repeat_blocks;
912            }
913         }
914         break;
915
916      case SNES_MODE_25:
917      /* Extendend HiROM carts start to load data in banks 0xc0 to 0xff. However, they exceed the
918         * available space in these banks, and continue loading at banks 0x40 to 0x7f. The top half
919         * (address range 0x8000 - 0xffff) of each bank is also mirrored either to banks 0x00 to 0x3f
920         * (for data in banks 0x40 to 0x7f) or to banks 0x80 to 0xbf (for data in banks 0xc0 to 0xff).
921         * Notice that banks 0x7e and 0x7f are overwritten by WRAM, but they could contain data at
922         * address > 0x8000 because the mirrors at 0x3e and 0x3f are not overwritten.
923         */
924         /* Reading the first 64 blocks */
925         while (read_blocks < 64 && read_blocks < total_blocks)
926         {
927            /* Loading data */
928            memcpy(&snes_ram[0xc00000 + read_blocks * 0x10000], &ROM[0x000000 + read_blocks * 0x10000], 0x10000);
929            /* Mirroring */
930            memcpy( &snes_ram[0x808000 + read_blocks * 0x10000], &snes_ram[0xc08000 + read_blocks * 0x10000], 0x8000);
931            read_blocks++;
932         }
933         /* ExHiROMs are supposed to be larger than 32Mbits! */
934         if (read_blocks < 64)
935         {
936            logerror("This image has been identified as ExHiROM, but it's too small!\n");
937            logerror("Please verify if it's corrupted. If it's not please report this as a bug.\n");
938            return IMAGE_INIT_FAIL;
939         }
940         /* Scaling down the counter */
941         read_blocks -= 64;
942         /* Reading the next blocks */
943         while (read_blocks < 64  && read_blocks < (total_blocks - 64))
944         {
945            /* Loading data */
946            memcpy(&snes_ram[0x400000 + read_blocks * 0x10000], &ROM[0x400000 + read_blocks * 0x10000], 0x10000);
947            /* Mirroring */
948            memcpy(&snes_ram[0x8000 + read_blocks * 0x10000], &snes_ram[0x408000 + read_blocks * 0x10000], 0x8000);
949            read_blocks++;
950         }
951         /* Filling banks up to 0x7f and their mirrors */
952         while (read_blocks % 64)
953         {
954            int j = 0, repeat_blocks;
955            while ((read_blocks % (64 >> j)) && j < 6)
956               j++;
957            repeat_blocks = read_blocks % (64 >> (j - 1));
958
959            memcpy(&snes_ram[0x400000 + read_blocks * 0x10000], &snes_ram[0x400000 + (read_blocks - repeat_blocks) * 0x10000], repeat_blocks * 0x10000);
960            memcpy(&snes_ram[read_blocks * 0x10000], &snes_ram[(read_blocks - repeat_blocks) * 0x10000], repeat_blocks * 0x10000);
961            read_blocks += repeat_blocks;
962         }
963         break;
964
965      case SNES_MODE_22:
966      /* "Extendend LoROM" carts have their data loaded in banks 0x00 to 0x3f at address 0x8000.
967         * These are then mirrored in banks 0x40 to 0x7f, both at address 0x0000 and at address
968         * 0x8000, in banks 0x80 to 0xbf at address 0x8000 and in banks 0xc0 to 0xff, both at address
969         * 0x0000 and at address 0x8000. Notice that SDD-1 games (Star Ocean and Street Fighter Zero 2)
970         * use SNES_MODE_22
971         */
972         while (read_blocks < 64 && read_blocks < total_blocks)
973         {
974            /* Loading and mirroring data */
975            memcpy(&snes_ram[0x008000 + read_blocks * 0x10000], &ROM[0x000000 + read_blocks * 0x8000], 0x8000);
976            memcpy(&snes_ram[0x808000 + read_blocks * 0x10000], &ROM[0x000000 + read_blocks * 0x8000], 0x8000);
977            memcpy(&snes_ram[0x400000 + read_blocks * 0x10000], &ROM[0x000000 + read_blocks * 0x10000], 0x10000);
978            memcpy(&snes_ram[0xc00000 + read_blocks * 0x10000], &ROM[0x000000 + read_blocks * 0x10000], 0x10000);
979            read_blocks++;
980         }
981         /* Filling banks up to 0x3f and their mirrors */
982         while (read_blocks % 64)
983         {
984            int j = 0, repeat_blocks;
985            while ((read_blocks % (64 >> j)) && j < 6)
986               j++;
987            repeat_blocks = read_blocks % (64 >> (j - 1));
988
989            memcpy(&snes_ram[read_blocks * 0x10000], &snes_ram[(read_blocks - repeat_blocks) * 0x10000], repeat_blocks * 0x10000);
990            memcpy(&snes_ram[0x800000 + read_blocks * 0x10000], &snes_ram[0x800000 + (read_blocks - repeat_blocks) * 0x10000], repeat_blocks * 0x10000);
991            memcpy(&snes_ram[0x400000 + read_blocks * 0x10000], &snes_ram[0x400000 + (read_blocks - repeat_blocks) * 0x10000], repeat_blocks * 0x10000);
992            memcpy(&snes_ram[0xc00000 + read_blocks * 0x10000], &snes_ram[0xc00000 + (read_blocks - repeat_blocks) * 0x10000], repeat_blocks * 0x10000);
993            read_blocks += repeat_blocks;
994         }
995         break;
996
997      case SNES_MODE_ST:
998         if (!st_bios)
999         {
1000            mame_printf_error("This is a Sufami Turbo data cart and cannot be loaded for snes/snespal in MESS.\n");
1001            mame_printf_error("Please use snesst driver to load it, instead.\n");
1002            return IMAGE_INIT_FAIL;
1003         }
1004         else
1005         {
1006            // The Base ST cart consists of 8 * 0x8000 block which have to be loaded (and mirrored)
1007            // at 0x00-0x1f:0x8000-0xffff and 0x80-0x9f:0x8000-0xffff
1008            for (i = 0; i < 8; i++)
1009            {
1010               /* Loading data */
1011               memcpy(&snes_ram[0x008000 + i * 0x10000], &ROM[0x000000 + i * 0x8000], 0x8000);
1012               /* Mirroring */
1013               memcpy(&snes_ram[0x808000 + i * 0x10000], &snes_ram[0x8000 + (i * 0x10000)], 0x8000);
1014
1015               /* Additional mirrors (to fill snes_ram up to 0x1fffff) */
1016               for (j = 1; j < 4; j++)
1017               {
1018                  memcpy(&snes_ram[0x008000 + i * 0x10000 + j * 0x80000], &snes_ram[0x8000 + (i * 0x10000)], 0x8000);
1019                  memcpy(&snes_ram[0x808000 + i * 0x10000 + j * 0x80000], &snes_ram[0x8000 + (i * 0x10000)], 0x8000);
1020               }
1021            }
1022         }
1023         break;
1024
1025      case SNES_MODE_BSX:
1026      case SNES_MODE_BSLO:
1027      case SNES_MODE_BSHI:
1028         /* not handled yet */
1029         mame_printf_error("This is a BS-X Satellaview image: MESS does not support these yet, sorry.\n");
1030#if 0
1031         // shall we force incompatibility of flash carts without a base unit?
1032         if (!has_bsx_slot)
1033         {
1034            mame_printf_error("This is a BS-X flash cart and cannot be loaded in snes/snespal.\n");
1035//              mame_printf_error("Please use snesbsx driver to load it, instead.\n");
1036            return IMAGE_INIT_FAIL;
1037         }
1038#endif
1039         break;
1040
1041      default:
1042      case SNES_MODE_20:
1043      /* LoROM carts load data in banks 0x00 to 0x7f at address 0x8000 (actually up to 0x7d, because 0x7e and
1044         * 0x7f are overwritten by WRAM). Each block is also mirrored in banks 0x80 to 0xff (up to 0xff for real)
1045         */
1046         /* SuperFX games needs this different loading routine */
1047         if (((ROM[0x007fd6] >= 0x13 && ROM[0x007fd6] <= 0x15) || ROM[0x007fd6] == 0x1a) && (ROM[0x007fd5] == 0x20))
1048         {
1049            while (read_blocks < 64 && read_blocks < total_blocks)
1050            {
1051               /* Loading data primary: banks 0-3f from 8000-ffff*/
1052               memcpy(&snes_ram[0x008000 + read_blocks * 0x10000], &ROM[0x000000 + read_blocks * 0x8000], 0x8000);
1053               /* Mirroring at banks 80-bf from 8000-ffff */
1054               memcpy(&snes_ram[0x808000 + read_blocks * 0x10000], &snes_ram[0x8000 + (read_blocks * 0x10000)], 0x8000);
1055               /* Mirroring at banks 40-5f and c0-df */
1056               memcpy(&snes_ram[0x400000 + read_blocks * 0x8000], &snes_ram[0x8000 + (read_blocks * 0x10000)], total_blocks * 0x8000);
1057               memcpy(&snes_ram[0xc00000 + read_blocks * 0x8000], &snes_ram[0x8000 + (read_blocks * 0x10000)], total_blocks * 0x8000);
1058
1059               read_blocks++;
1060            }
1061            /* SuperFX games are supposed to contain 64 blocks! */
1062            if (read_blocks < total_blocks)
1063            {
1064               logerror("This image has been identified as a SuperFX game, but it's too large!\n");
1065               logerror("Please verify if it's corrupted. If it's not please report this as a bug.\n");
1066               return IMAGE_INIT_FAIL;
1067            }
1068         }
1069         else
1070         {
1071            while (read_blocks < 128 && read_blocks < total_blocks)
1072            {
1073               /* Loading data */
1074               memcpy(&snes_ram[0x008000 + read_blocks * 0x10000], &ROM[0x000000 + read_blocks * 0x8000], 0x8000);
1075               /* Mirroring */
1076               memcpy(&snes_ram[0x808000 + read_blocks * 0x10000], &snes_ram[0x8000 + (read_blocks * 0x10000)], 0x8000);
1077               read_blocks++;
1078            }
1079            /* Filling banks up to 0x7f and their mirrors */
1080            while (read_blocks % 128)
1081            {
1082               int j = 0, repeat_blocks;
1083               while ((read_blocks % (128 >> j)) && j < 7)
1084                  j++;
1085               repeat_blocks = read_blocks % (128 >> (j - 1));
1086
1087               memcpy( &snes_ram[read_blocks * 0x10000], &snes_ram[(read_blocks - repeat_blocks) * 0x10000], repeat_blocks * 0x10000);
1088               memcpy( &snes_ram[0x800000 + read_blocks * 0x10000], &snes_ram[(read_blocks - repeat_blocks) * 0x10000], repeat_blocks * 0x10000);
1089               read_blocks += repeat_blocks;
1090            }
1091         }
1092         break;
1093   }
1094
1095   /* Detect special chips */
1096   supported_type = snes_find_addon_chip(machine);
1097
1098   /* Find the amount of cart ram (even if we call it sram...) */
1099   if (image.software_entry() == NULL)
1100   {
1101      if ((state->m_has_addon_chip != HAS_SUPERFX))
1102         state->m_cart[0].sram = snes_r_bank1(space, 0x00ffd8);
1103      else
1104         state->m_cart[0].sram = (snes_r_bank1(space, 0x00ffbd) & 0x07);
1105
1106      if (state->m_cart[0].sram > 0)
1107      {
1108         state->m_cart[0].sram = (1024 << state->m_cart[0].sram);
1109         if (state->m_cart[0].sram > state->m_cart[0].sram_max)
1110            state->m_cart[0].sram = state->m_cart[0].sram_max;
1111      }
1112//      printf("size %x\n", state->m_cart[0].sram);
1113   }
1114   else
1115   {
1116      // if we are loading from softlist, take sram from the xml
1117      state->m_cart[0].sram = image.get_software_region("sram") ? image.get_software_region_length("sram") : 0;
1118
1119      if (state->m_cart[0].sram > 0)
1120      {
1121         if (state->m_cart[0].sram > state->m_cart[0].sram_max)
1122            fatalerror("Found more SRAM than max allowed (found: %x, max: %x), check xml file!\n", state->m_cart[0].sram, state->m_cart[0].sram_max);
1123      }
1124      // TODO: Eventually sram handlers should point to the allocated cart:sram region!
1125      // For now, we only use the region as a placeholder to carry size info...
1126//      printf("size %x\n", state->m_cart[0].sram);
1127   }
1128
1129   /* adjust size for very large carts */
1130   if (state->m_cart[0].mode == SNES_MODE_20 && ((state->m_cart_size - offset) > 0x200000 || state->m_cart[0].sram > (32 * 1024)))
1131      state->m_cart[0].small_sram = 1;
1132   else
1133      state->m_cart[0].small_sram = 0;
1134
1135   /* Log snes_cart information */
1136   snes_cart_log_info(machine, total_blocks, supported_type);
1137
1138   /* Load SRAM */
1139   snes_load_sram(machine);
1140
1141   /* All done */
1142   return IMAGE_INIT_PASS;
1143}
1144
1145static DEVICE_IMAGE_LOAD( sufami_cart )
1146{
1147   running_machine &machine = image.device().machine();
1148   snes_state *state = machine.driver_data<snes_state>();
1149   int total_blocks, read_blocks;
1150   int st_bios = 0, slot_id = 0;
1151   UINT32 offset, st_data_offset = 0;
1152   UINT8 *ROM = image.device().machine().region(image.device().tag())->base();
1153
1154   snes_ram = machine.region("maincpu")->base();
1155
1156   if (strcmp(image.device().tag(), "slot_a") == 0)
1157   {
1158      st_data_offset = 0x200000;
1159      slot_id = 0;
1160   }
1161
1162   if (strcmp(image.device().tag(), "slot_b") == 0)
1163   {
1164      st_data_offset = 0x400000;
1165      slot_id = 1;
1166   }
1167
1168   if (image.software_entry() == NULL)
1169      state->m_cart_size = image.length();
1170   else
1171      state->m_cart_size = image.get_software_region_length("rom");
1172
1173   /* Check for a header (512 bytes), and skip it if found */
1174   offset = snes_skip_header(image, state->m_cart_size);
1175
1176   if (image.software_entry() == NULL)
1177   {
1178      image.fseek(offset, SEEK_SET);
1179      image.fread( ROM, state->m_cart_size - offset);
1180   }
1181   else
1182      memcpy(ROM, image.get_software_region("rom") + offset, state->m_cart_size - offset);
1183
1184   if (SNES_CART_DEBUG) mame_printf_error("size %08X\n", state->m_cart_size - offset);
1185
1186   /* Detect Sufami Turbo carts */
1187   if (!memcmp(ROM, "BANDAI SFC-ADX", 14))
1188   {
1189      state->m_cart[slot_id].mode = SNES_MODE_ST;
1190      if (!memcmp(ROM + 16, "SFC-ADX BACKUP", 14))
1191         st_bios = 1;
1192   }
1193   else
1194   {
1195      mame_printf_error("This is not a Sufami Turbo data pack.\n");
1196      mame_printf_error("This image cannot be loaded in snesst (Use snes or snespal drivers, instead).\n");
1197      return IMAGE_INIT_FAIL;
1198   }
1199
1200   if (st_bios == 1)
1201   {
1202      mame_printf_error("This is the Sufami Turbo BIOS and not a Sufami Turbo data pack.\n");
1203      mame_printf_error("This image cannot be loaded in snesst.\n");
1204      return IMAGE_INIT_FAIL;
1205   }
1206
1207   /* FIXME: Insert crc check here? */
1208
1209   /* How many blocks of data are available to be loaded? */
1210   total_blocks = (state->m_cart_size - offset) / 0x8000;
1211   read_blocks = 0;
1212
1213   if (SNES_CART_DEBUG)
1214      mame_printf_error("blocks %d\n", total_blocks);
1215
1216   // actually load the cart
1217   while (read_blocks < 32 && read_blocks < total_blocks)
1218   {
1219      /* Loading data */
1220      // CART (either A or B)
1221      memcpy(&snes_ram[0x008000 + st_data_offset + read_blocks * 0x10000], &ROM[0x000000 + read_blocks * 0x8000], 0x8000);
1222      /* Mirroring */
1223      memcpy(&snes_ram[0x808000 + st_data_offset + read_blocks * 0x10000], &snes_ram[0x8000 + st_data_offset + (read_blocks * 0x10000)], 0x8000);
1224
1225      read_blocks++;
1226   }
1227
1228   /* Filling banks up to 0x1f and their mirrors */
1229   while (read_blocks % 32)
1230   {
1231      int j = 0, repeat_blocks;
1232      while ((read_blocks % (32 >> j)) && j < 5)
1233         j++;
1234      repeat_blocks = read_blocks % (32 >> (j - 1));
1235
1236      memcpy(&snes_ram[st_data_offset + read_blocks * 0x10000], &snes_ram[st_data_offset + (read_blocks - repeat_blocks) * 0x10000], repeat_blocks * 0x10000);
1237      memcpy(&snes_ram[0x800000 + st_data_offset + read_blocks * 0x10000], &snes_ram[st_data_offset + (read_blocks - repeat_blocks) * 0x10000], repeat_blocks * 0x10000);
1238      read_blocks += repeat_blocks;
1239   }
1240
1241   sufami_load_sram(machine, image.device().tag());
1242
1243   state->m_cart[slot_id].slot_in_use = 1;   // aknowledge the cart in this slot, for saving sram at exit
1244
1245   auto_free(image.device().machine(), ROM);
1246
1247   return IMAGE_INIT_PASS;
1248}
1249
1250static DEVICE_IMAGE_LOAD( bsx_cart )
1251{
1252   running_machine &machine = image.device().machine();
1253   snes_state *state = machine.driver_data<snes_state>();
1254   int total_blocks, read_blocks;
1255   int has_bsx_slot = 0;
1256   UINT32 offset, int_header_offs;
1257   UINT8 *ROM = image.device().machine().region("cart")->base();
1258
1259   if (image.software_entry() == NULL)
1260      state->m_cart_size = image.length();
1261   else
1262      state->m_cart_size = image.get_software_region_length("rom");
1263
1264   /* Check for a header (512 bytes), and skip it if found */
1265   offset = snes_skip_header(image, state->m_cart_size);
1266
1267   if (image.software_entry() == NULL)
1268   {
1269      image.fseek(offset, SEEK_SET);
1270      image.fread( ROM, state->m_cart_size - offset);
1271   }
1272   else
1273      memcpy(ROM, image.get_software_region("rom") + offset, state->m_cart_size - offset);
1274
1275   if (SNES_CART_DEBUG) mame_printf_error("size %08X\n", state->m_cart_size - offset);
1276
1277   /* First, look if the cart is HiROM or LoROM (and set snes_cart accordingly) */
1278   int_header_offs = snes_find_hilo_mode(image, ROM, offset, 0);
1279
1280   // Detect presence of BS-X flash cartridge connector
1281   if ((ROM[int_header_offs - 14] == 'Z') && (ROM[int_header_offs - 11] == 'J'))
1282   {
1283      UINT8 n13 = ROM[int_header_offs - 13];
1284      if ((n13 >= 'A' && n13 <= 'Z') || (n13 >= '0' && n13 <= '9'))
1285      {
1286         if (ROM[int_header_offs + 0x1a] == 0x33 ||
1287            (ROM[int_header_offs - 10] == 0x00 && ROM[int_header_offs - 4] == 0x00))
1288         {
1289            has_bsx_slot = 1;
1290         }
1291      }
1292   }
1293
1294   // If there is a BS-X connector, detect if it is the Base Cart or a compatible slotted cart
1295   if (has_bsx_slot)
1296   {
1297      if (!memcmp(ROM + int_header_offs, "Satellaview BS-X     ", 21))
1298      {
1299         //BS-X Base Cart
1300         state->m_cart[0].mode = SNES_MODE_BSX;
1301         // handle RAM
1302      }
1303      else
1304      {
1305         state->m_cart[0].mode = (int_header_offs ==0x007fc0) ? SNES_MODE_BSLO : SNES_MODE_BSHI;
1306         // handle RAM?
1307      }
1308   }
1309   else
1310   {
1311      mame_printf_error("This is not a BS-X compatible cart.\n");
1312      mame_printf_error("This image cannot be loaded in the first cartslot of snesbsx.\n");
1313      return IMAGE_INIT_FAIL;
1314   }
1315
1316
1317   /* FIXME: Insert crc check here? */
1318
1319   /* How many blocks of data are available to be loaded? */
1320   total_blocks = (state->m_cart_size - offset) / 0x8000;
1321   read_blocks = 0;
1322
1323   if (SNES_CART_DEBUG) mame_printf_error("blocks %d\n", total_blocks);
1324
1325   // actually load the cart
1326   while (read_blocks < 64 && read_blocks < total_blocks)
1327   {
1328      /* Loading data */
1329      memcpy(&snes_ram[0x008000 + read_blocks * 0x10000], &ROM[0x000000 + read_blocks * 0x8000], 0x8000);
1330      /* Mirroring */
1331      memcpy(&snes_ram[0x808000 + read_blocks * 0x10000], &snes_ram[0x8000 + (read_blocks * 0x10000)], 0x8000);
1332
1333      read_blocks++;
1334   }
1335
1336   /* Filling banks up to 0x3f and their mirrors */
1337   while (read_blocks % 64)
1338   {
1339      int j = 0, repeat_blocks;
1340      while ((read_blocks % (64 >> j)) && j < 6)
1341         j++;
1342      repeat_blocks = read_blocks % (64 >> (j - 1));
1343
1344      memcpy(&snes_ram[read_blocks * 0x10000], &snes_ram[(read_blocks - repeat_blocks) * 0x10000], repeat_blocks * 0x10000);
1345      memcpy(&snes_ram[0x800000 + read_blocks * 0x10000], &snes_ram[(read_blocks - repeat_blocks) * 0x10000], repeat_blocks * 0x10000);
1346      read_blocks += repeat_blocks;
1347   }
1348
1349   return IMAGE_INIT_PASS;
1350}
1351
1352static DEVICE_IMAGE_LOAD( bsx2slot_cart )
1353{
1354   running_machine &machine = image.device().machine();
1355   snes_state *state = machine.driver_data<snes_state>();
1356   UINT32 offset, int_header_offs;
1357   UINT8 *ROM = image.device().machine().region("flash")->base();
1358
1359   if (image.software_entry() == NULL)
1360      state->m_cart_size = image.length();
1361   else
1362      state->m_cart_size = image.get_software_region_length("rom");
1363
1364   /* Check for a header (512 bytes), and skip it if found */
1365   offset = snes_skip_header(image, state->m_cart_size);
1366
1367   if (image.software_entry() == NULL)
1368   {
1369      image.fseek(offset, SEEK_SET);
1370      image.fread( ROM, state->m_cart_size - offset);
1371   }
1372   else
1373      memcpy(ROM, image.get_software_region("rom") + offset, state->m_cart_size - offset);
1374
1375   if (SNES_CART_DEBUG) mame_printf_error("size %08X\n", state->m_cart_size - offset);
1376
1377   /* First, look if the cart is HiROM or LoROM (and set snes_cart accordingly) */
1378   int_header_offs = snes_find_hilo_mode(image, ROM, offset, 1);
1379
1380   // Detect presence of BS-X Flash Cart
1381   if ((ROM[int_header_offs + 0x13] == 0x00 || ROM[int_header_offs + 0x13] == 0xff) &&
1382      ROM[int_header_offs + 0x14] == 0x00)
1383   {
1384      UINT8 n15 = ROM[int_header_offs + 0x15];
1385      if (n15 == 0x00 || n15 == 0x80 || n15 == 0x84 || n15 == 0x9c || n15 == 0xbc || n15 == 0xfc)
1386      {
1387         if (ROM[int_header_offs + 0x1a] == 0x33 || ROM[int_header_offs + 0x1a] == 0xff)
1388         {
1389            // BS-X Flash Cart
1390            state->m_cart[1].mode = SNES_MODE_BSX;
1391         }
1392      }
1393   }
1394
1395   if (state->m_cart[1].mode != SNES_MODE_BSX)
1396   {
1397      mame_printf_error("This is not a BS-X flash cart.\n");
1398      mame_printf_error("This image cannot be loaded in the second cartslot of snesbsx.\n");
1399      return IMAGE_INIT_FAIL;
1400   }
1401
1402   // actually load the cart
1403   return IMAGE_INIT_PASS;
1404}
1405
1406MACHINE_CONFIG_FRAGMENT( snes_cartslot )
1407   MCFG_CARTSLOT_ADD("cart")
1408   MCFG_CARTSLOT_EXTENSION_LIST("sfc,smc,fig,swc,bin")
1409   MCFG_CARTSLOT_NOT_MANDATORY
1410   MCFG_CARTSLOT_INTERFACE("snes_cart")
1411   MCFG_CARTSLOT_LOAD(snes_cart)
1412   MCFG_SOFTWARE_LIST_ADD("cart_list","snes")
1413MACHINE_CONFIG_END
1414
1415// This (hackily) emulates a SNES unit with a Sufami Turbo Unit cart inserted:
1416// hence, the user can mount two data cart in the two slots available on the ST Unit
1417MACHINE_CONFIG_FRAGMENT( sufami_cartslot )
1418   MCFG_CARTSLOT_ADD("slot_a")
1419   MCFG_CARTSLOT_EXTENSION_LIST("st,sfc")
1420   MCFG_CARTSLOT_NOT_MANDATORY
1421   MCFG_CARTSLOT_INTERFACE("sufami_cart")
1422   MCFG_CARTSLOT_LOAD(sufami_cart)
1423
1424   MCFG_CARTSLOT_ADD("slot_b")
1425   MCFG_CARTSLOT_EXTENSION_LIST("st,sfc")
1426   MCFG_CARTSLOT_NOT_MANDATORY
1427   MCFG_CARTSLOT_INTERFACE("sufami_cart")
1428   MCFG_CARTSLOT_LOAD(sufami_cart)
1429
1430//  MCFG_SOFTWARE_LIST_ADD("cart_list","snes")
1431MACHINE_CONFIG_END
1432
1433// This (hackily) emulates a SNES unit where you want to load a BS-X compatible cart:
1434// hence, the user can mount a SNES cart in the first slot (either a BS-X BIOS cart, or a
1435// BS-X compatible one, e.g. Same Game), and there is a second slot for the 8M data pack
1436// (in a real SNES this would have been inserted in the smaller slot on the cart itself)
1437MACHINE_CONFIG_FRAGMENT( bsx_cartslot )
1438   MCFG_CARTSLOT_ADD("cart")
1439   MCFG_CARTSLOT_EXTENSION_LIST("sfc,smc,fig,swc,bin")
1440   MCFG_CARTSLOT_NOT_MANDATORY
1441   MCFG_CARTSLOT_INTERFACE("snes_cart")
1442   MCFG_CARTSLOT_LOAD(bsx_cart)
1443
1444   MCFG_CARTSLOT_ADD("slot2")
1445   MCFG_CARTSLOT_EXTENSION_LIST("bs,sfc")
1446   MCFG_CARTSLOT_NOT_MANDATORY
1447   MCFG_CARTSLOT_INTERFACE("bsx_cart")
1448   MCFG_CARTSLOT_LOAD(bsx2slot_cart)
1449
1450//  MCFG_SOFTWARE_LIST_ADD("cart_list","snes")
1451MACHINE_CONFIG_END
1452
1453DRIVER_INIT( snes_mess )
1454{
1455   snes_ram = machine.region("maincpu")->base();
1456   memset(snes_ram, 0, 0x1000000);
1457}
1458
1459DRIVER_INIT( snesst )
1460{
1461   snes_state *state = machine.driver_data<snes_state>();
1462   UINT8 *STBIOS = machine.region("sufami")->base();
1463   int i, j;
1464
1465   state->m_cart[0].slot_in_use = 0;
1466   state->m_cart[1].slot_in_use = 0;
1467
1468   DRIVER_INIT_CALL(snes_mess);
1469
1470   // the Base ST cart consists of 8 * 0x8000 block which have to be loaded (and mirrored)
1471   // at 0x00-0x1f:0x8000-0xffff and 0x80-0x9f:0x8000-0xffff
1472   for (i = 0; i < 8; i++)
1473   {
1474      /* Loading data */
1475      memcpy(&snes_ram[0x008000 + i * 0x10000], &STBIOS[0x000000 + i * 0x8000], 0x8000);
1476      /* Mirroring */
1477      memcpy(&snes_ram[0x808000 + i * 0x10000], &snes_ram[0x8000 + (i * 0x10000)], 0x8000);
1478
1479      /* Additional mirrors (to fill snes_ram up to 0x1fffff) */
1480      for (j = 1; j < 4; j++)
1481      {
1482         memcpy(&snes_ram[0x008000 + i * 0x10000 + j * 0x80000], &snes_ram[0x8000 + (i * 0x10000)], 0x8000);
1483         memcpy(&snes_ram[0x808000 + i * 0x10000 + j * 0x80000], &snes_ram[0x8000 + (i * 0x10000)], 0x8000);
1484      }
1485   }
1486
1487}
src/mame/machine/snescart.h
r11531r11532
1/*
2    snescart.h
3
4*/
5
6#ifndef _SNESCART_H
7#define _SNESCART_H
8
9#include "imagedev/cartslot.h"
10
11MACHINE_START( snes_mess );
12MACHINE_START( snesst );
13
14DRIVER_INIT( snes_mess );
15DRIVER_INIT( snesst );
16
17MACHINE_CONFIG_EXTERN( snes_cartslot );
18MACHINE_CONFIG_EXTERN( sufami_cartslot );
19MACHINE_CONFIG_EXTERN( bsx_cartslot );
20
21#endif /* _SNESCART_H */
22
src/mame/machine/pce.c
r11531r11532
1/************************************************************
2
3PC Engine CD HW notes:
4
5CD Interface Register 0x00 - CDC status
6x--- ---- busy signal
7-x-- ---- request signal
8---x ---- cd signal
9---- x--- i/o signal
10
11CD Interface Register 0x03 - BRAM lock / CD status
12-x-- ---- acknowledge signal
13--x- ---- done signal
14---x ---- bram signal
15---- x--- ADPCM 2
16---- -x-- ADPCM 1
17---- --x- CDDA left/right speaker select
18
19CD Interface Register 0x05 - CD-DA Volume low 8-bit port
20
21CD Interface Register 0x06 - CD-DA Volume high 8-bit port
22
23CD Interface Register 0x07 - BRAM unlock / CD status
24x--- ---- Enables BRAM
25
26CD Interface Register 0x0c - ADPCM status
27x--- ---- ADPCM is reading data
28---- x--- ADPCM playback (0) stopped (1) currently playing
29---- -x-- pending ADPCM data write
30---- ---x ADPCM playback (1) stopped (0) currently playing
31
32CD Interface Register 0x0d - ADPCM address control
33x--- ---- ADPCM reset
34-x-- ---- ADPCM play
35--x- ---- ADPCM repeat
36---x ---- ADPCM set length
37---- x--- ADPCM set read address
38---- --xx ADPCM set write address
39(note: some games reads bit 5 and wants it to be low otherwise they hangs, surely NOT an ADPCM repeat flag read because it doesn't make sense)
40
41CD Interface Register 0x0e - ADPCM playback rate
42
43CD Interface Register 0x0f - ADPCM fade in/out register
44---- xxxx command setting:
450x00 ADPCM/CD-DA Fade-in
460x01 CD-DA fade-in
470x08 CD-DA fade-out (short) ADPCM fade-in
480x09 CD-DA fade-out (long)
490x0a ADPCM fade-out (long)
500x0c CD-DA fade-out (short) ADPCM fade-in
510x0d CD-DA fade-out (short)
520x0e ADPCM fade-out (short)
53
54*************************************************************/
55
56#include "emu.h"
57#include "coreutil.h"
58#include "cpu/h6280/h6280.h"
59#include "includes/pce.h"
60#include "imagedev/chd_cd.h"
61#include "sound/msm5205.h"
62#include "sound/cdda.h"
63#include "hashfile.h"
64
65
66#define PCE_BRAM_SIZE            0x800
67#define PCE_ADPCM_RAM_SIZE         0x10000
68#define PCE_ACARD_RAM_SIZE         0x200000
69#define PCE_CD_COMMAND_BUFFER_SIZE   0x100
70
71#define PCE_CD_IRQ_TRANSFER_READY      0x40
72#define PCE_CD_IRQ_TRANSFER_DONE      0x20
73#define PCE_CD_IRQ_SAMPLE_FULL_PLAY      0x08
74#define PCE_CD_IRQ_SAMPLE_HALF_PLAY      0x04
75
76#define PCE_CD_ADPCM_PLAY_FLAG      0x08
77#define PCE_CD_ADPCM_STOP_FLAG      0x01
78
79#define PCE_CD_DATA_FRAMES_PER_SECOND   75
80
81enum {
82   PCE_CD_CDDA_OFF=0,
83   PCE_CD_CDDA_PLAYING,
84   PCE_CD_CDDA_PAUSED
85};
86
87
88/* CD Unit RAM */
89
90/* MSM5205 ADPCM decoder definition */
91static void pce_cd_msm5205_int(device_t *device);
92const msm5205_interface pce_cd_msm5205_interface = {
93   pce_cd_msm5205_int,   /* interrupt function */
94   MSM5205_S48_4B      /* 1/48 prescaler, 4bit data */
95};
96
97
98/* joystick related data*/
99
100#define JOY_CLOCK   0x01
101#define JOY_RESET   0x02
102
103
104/* prototypes */
105static void pce_cd_init( running_machine &machine );
106static void pce_cd_set_irq_line( running_machine &machine, int num, int state );
107static TIMER_CALLBACK( pce_cd_adpcm_dma_timer_callback );
108static TIMER_CALLBACK( pce_cd_cdda_fadeout_callback );
109static TIMER_CALLBACK( pce_cd_cdda_fadein_callback );
110static TIMER_CALLBACK( pce_cd_adpcm_fadeout_callback );
111static TIMER_CALLBACK( pce_cd_adpcm_fadein_callback );
112
113static WRITE8_HANDLER( pce_sf2_banking_w )
114{
115   memory_set_bankptr( space->machine(), "bank2", space->machine().region("user1")->base() + offset * 0x080000 + 0x080000 );
116   memory_set_bankptr( space->machine(), "bank3", space->machine().region("user1")->base() + offset * 0x080000 + 0x088000 );
117   memory_set_bankptr( space->machine(), "bank4", space->machine().region("user1")->base() + offset * 0x080000 + 0x0D0000 );
118}
119
120static WRITE8_HANDLER( pce_cartridge_ram_w )
121{
122   pce_state *state = space->machine().driver_data<pce_state>();
123   state->m_cartridge_ram[offset] = data;
124}
125
126DEVICE_IMAGE_LOAD(pce_cart)
127{
128   pce_state *state = image.device().machine().driver_data<pce_state>();
129   UINT32 size;
130   int split_rom = 0, offset = 0;
131   const char *extrainfo = NULL;
132   unsigned char *ROM;
133   logerror("*** DEVICE_IMAGE_LOAD(pce_cart) : %s\n", image.filename());
134
135   /* open file to get size */
136   ROM = image.device().machine().region("user1")->base();
137
138   if (image.software_entry() == NULL)
139      size = image.length();
140   else
141      size = image.get_software_region_length("rom");
142
143   /* handle header accordingly */
144   if ((size / 512) & 1)
145   {
146      logerror("*** DEVICE_IMAGE_LOAD(pce_cart) : Header present\n");
147      size -= 512;
148      offset = 512;
149   }
150
151   if (size > PCE_ROM_MAXSIZE)
152      size = PCE_ROM_MAXSIZE;
153
154   if (image.software_entry() == NULL)
155   {
156      image.fseek(offset, SEEK_SET);
157      image.fread( ROM, size);
158      extrainfo = hashfile_extrainfo(image);
159   }
160   else
161      memcpy(ROM, image.get_software_region("rom") + offset, size);
162
163   if (extrainfo)
164   {
165      logerror("extrainfo: %s\n", extrainfo);
166      if (strstr(extrainfo, "ROM_SPLIT"))
167         split_rom = 1;
168   }
169
170   if (ROM[0x1fff] < 0xe0)
171   {
172      int i;
173      UINT8 decrypted[256];
174
175      logerror( "*** DEVICE_IMAGE_LOAD(pce_cart) : ROM image seems encrypted, decrypting...\n" );
176
177      /* Initialize decryption table */
178      for (i = 0; i < 256; i++)
179         decrypted[i] = ((i & 0x01) << 7) | ((i & 0x02) << 5) | ((i & 0x04) << 3) | ((i & 0x08) << 1) | ((i & 0x10) >> 1) | ((i & 0x20 ) >> 3) | ((i & 0x40) >> 5) | ((i & 0x80) >> 7);
180
181      /* Decrypt ROM image */
182      for (i = 0; i < size; i++)
183         ROM[i] = decrypted[ROM[i]];
184   }
185
186   /* check if we're dealing with a split rom image */
187   if (size == 384 * 1024)
188   {
189      split_rom = 1;
190      /* Mirror the upper 128KB part of the image */
191      memcpy(ROM + 0x060000, ROM + 0x040000, 0x020000);   /* Set up 060000 - 07FFFF mirror */
192   }
193
194   /* set up the memory for a split rom image */
195   if (split_rom)
196   {
197      logerror("Split rom detected, setting up memory accordingly\n");
198      /* Set up ROM address space as follows:          */
199      /* 000000 - 03FFFF : ROM data 000000 - 03FFFF    */
200      /* 040000 - 07FFFF : ROM data 000000 - 03FFFF    */
201      /* 080000 - 0BFFFF : ROM data 040000 - 07FFFF    */
202      /* 0C0000 - 0FFFFF : ROM data 040000 - 07FFFF    */
203      memcpy(ROM + 0x080000, ROM + 0x040000, 0x040000);   /* Set up 080000 - 0BFFFF region */
204      memcpy(ROM + 0x0C0000, ROM + 0x040000, 0x040000);   /* Set up 0C0000 - 0FFFFF region */
205      memcpy(ROM + 0x040000, ROM, 0x040000);      /* Set up 040000 - 07FFFF region */
206   }
207   else
208   {
209      /* mirror 256KB rom data */
210      if (size <= 0x040000)
211         memcpy(ROM + 0x040000, ROM, 0x040000);
212
213      /* mirror 512KB rom data */
214      if (size <= 0x080000)
215         memcpy(ROM + 0x080000, ROM, 0x080000);
216   }
217
218   memory_set_bankptr(image.device().machine(), "bank1", ROM);
219   memory_set_bankptr(image.device().machine(), "bank2", ROM + 0x080000);
220   memory_set_bankptr(image.device().machine(), "bank3", ROM + 0x088000);
221   memory_set_bankptr(image.device().machine(), "bank4", ROM + 0x0d0000);
222
223   /* Check for Street fighter 2 */
224   if (size == PCE_ROM_MAXSIZE)
225   {
226      image.device().machine().device("maincpu")->memory().space(AS_PROGRAM)->install_legacy_write_handler(0x01ff0, 0x01ff3, FUNC(pce_sf2_banking_w));
227   }
228
229   /* Check for Populous */
230   if (!memcmp(ROM + 0x1F26, "POPULOUS", 8))
231   {
232      state->m_cartridge_ram = auto_alloc_array(image.device().machine(), UINT8, 0x8000);
233      memory_set_bankptr(image.device().machine(), "bank2", state->m_cartridge_ram);
234      image.device().machine().device("maincpu")->memory().space(AS_PROGRAM)->install_legacy_write_handler(0x080000, 0x087FFF, FUNC(pce_cartridge_ram_w));
235   }
236
237   /* Check for CD system card */
238   state->m_sys3_card = 0;
239   if (!memcmp(ROM + 0x3FFB6, "PC Engine CD-ROM SYSTEM", 23))
240   {
241      /* Check if 192KB additional system card ram should be used */
242      if(!memcmp(ROM + 0x29D1, "VER. 3.", 7))       { state->m_sys3_card = 1; } // JP version
243      else if(!memcmp(ROM + 0x29C4, "VER. 3.", 7 ))   { state->m_sys3_card = 3; } // US version
244
245      if(state->m_sys3_card)
246      {
247         state->m_cartridge_ram = auto_alloc_array(image.device().machine(), UINT8, 0x30000);
248         memory_set_bankptr(image.device().machine(), "bank4", state->m_cartridge_ram);
249         image.device().machine().device("maincpu")->memory().space(AS_PROGRAM)->install_legacy_write_handler(0x0D0000, 0x0FFFFF, FUNC(pce_cartridge_ram_w));
250         image.device().machine().device("maincpu")->memory().space(AS_PROGRAM)->install_legacy_readwrite_handler(0x080000, 0x087FFF, FUNC(pce_cd_acard_wram_r),FUNC(pce_cd_acard_wram_w));
251      }
252   }
253   return 0;
254}
255
256#ifdef MESS
257DRIVER_INIT( pce )
258{
259   pce_state *state = machine.driver_data<pce_state>();
260   state->m_io_port_options = PCE_JOY_SIG | CONST_SIG;
261}
262#endif
263
264DRIVER_INIT( tg16 )
265{
266   pce_state *state = machine.driver_data<pce_state>();
267   state->m_io_port_options = TG_16_JOY_SIG | CONST_SIG;
268}
269
270DRIVER_INIT( sgx )
271{
272   pce_state *state = machine.driver_data<pce_state>();
273   state->m_io_port_options = PCE_JOY_SIG | CONST_SIG;
274}
275
276MACHINE_START( pce )
277{
278   pce_cd_init( machine );
279}
280
281#ifdef MESS
282MACHINE_RESET( pce )
283{
284   pce_state *state = machine.driver_data<pce_state>();
285   pce_cd_t &pce_cd = state->m_cd;
286   int joy_i;
287
288   for (joy_i = 0; joy_i < 5; joy_i++)
289      state->m_joy_6b_packet[joy_i] = 0;
290
291   pce_cd.adpcm_read_buf = 0;
292   pce_cd.adpcm_write_buf = 0;
293
294   // TODO: add CD-DA stop command here
295
296   pce_cd.regs[0x0c] |= PCE_CD_ADPCM_STOP_FLAG;
297   pce_cd.regs[0x0c] &= ~PCE_CD_ADPCM_PLAY_FLAG;
298   //pce_cd.regs[0x03] = (pce_cd.regs[0x03] & ~0x0c) | (PCE_CD_SAMPLE_STOP_PLAY);
299
300   /* Note: Arcade Card BIOS contents are the same as System 3, only internal HW differs.
301       We use a category to select between modes (some games can be run in either S-CD or A-CD modes) */
302   state->m_acard = input_port_read(machine, "A_CARD") & 1;
303}
304
305/* todo: how many input ports does the PCE have? */
306WRITE8_HANDLER ( pce_joystick_w )
307{
308   pce_state *state = space->machine().driver_data<pce_state>();
309   int joy_i;
310   UINT8 joy_type = input_port_read(space->machine(),"JOY_TYPE");
311
312   h6280io_set_buffer(&space->device(), data);
313
314    /* bump counter on a low-to-high transition of bit 1 */
315    if ((!state->m_joystick_data_select) && (data & JOY_CLOCK))
316    {
317        state->m_joystick_port_select = (state->m_joystick_port_select + 1) & 0x07;
318    }
319
320    /* do we want buttons or direction? */
321    state->m_joystick_data_select = data & JOY_CLOCK;
322
323    /* clear counter if bit 2 is set */
324    if (data & JOY_RESET)
325    {
326      state->m_joystick_port_select = 0;
327
328      for (joy_i = 0; joy_i < 5; joy_i++)
329      {
330         if (((joy_type >> (joy_i*2)) & 3) == 2)
331              state->m_joy_6b_packet[joy_i] ^= 1;
332      }
333    }
334}
335
336READ8_HANDLER ( pce_joystick_r )
337{
338   pce_state *state = space->machine().driver_data<pce_state>();
339   static const char *const joyname[4][5] = {
340      { "JOY_P1", "JOY_P2", "JOY_P3", "JOY_P4", "JOY_P5" },
341      { },
342      { "JOY6B_P1", "JOY6B_P2", "JOY6B_P3", "JOY6B_P4", "JOY6B_P5" },
343      { }
344   };
345   UINT8 joy_type = input_port_read(space->machine(), "JOY_TYPE");
346   UINT8 ret, data;
347
348   if (state->m_joystick_port_select <= 4)
349   {
350      switch((joy_type >> (state->m_joystick_port_select*2)) & 3)
351      {
352         case 0: //2-buttons pad
353            data = input_port_read(space->machine(), joyname[0][state->m_joystick_port_select]);
354            break;
355         case 2: //6-buttons pad
356            /*
357                Two packets:
358                1st packet: directions + I, II, Run, Select
359                2nd packet: 6 buttons "header" (high 4 bits active low) + III, IV, V, VI
360                Note that six buttons pad just doesn't work with (almost?) every single 2-button-only games, it's really just an after-thought and it is like this
361                on real HW.
362                */
363            data = input_port_read(space->machine(), joyname[2][state->m_joystick_port_select]) >> (state->m_joy_6b_packet[state->m_joystick_port_select]*8);
364            break;
365         default:
366            data = 0xff;
367            break;
368      }
369   }
370   else
371      data = 0xff;
372
373
374   if (state->m_joystick_data_select)
375      data >>= 4;
376
377   ret = (data & 0x0f) | state->m_io_port_options;
378#ifdef UNIFIED_PCE
379   ret &= ~0x40;
380#endif
381
382   return (ret);
383}
384#endif
385NVRAM_HANDLER( pce )
386{
387   pce_state *state = machine.driver_data<pce_state>();
388   pce_cd_t &pce_cd = state->m_cd;
389   if (read_or_write)
390   {
391      file->write(pce_cd.bram, PCE_BRAM_SIZE);
392   }
393   else
394   {
395      /* load battery backed memory from disk */
396      if (file)
397         file->read(pce_cd.bram, PCE_BRAM_SIZE);
398   }
399}
400
401static void pce_set_cd_bram( running_machine &machine )
402{
403   pce_state *state = machine.driver_data<pce_state>();
404   pce_cd_t &pce_cd = state->m_cd;
405   memory_set_bankptr( machine, "bank10", pce_cd.bram + ( pce_cd.bram_locked ? PCE_BRAM_SIZE : 0 ) );
406}
407
408static void adpcm_stop(running_machine &machine)
409{
410   pce_state *state = machine.driver_data<pce_state>();
411   pce_cd_t &pce_cd = state->m_cd;
412   pce_cd.regs[0x0c] |= PCE_CD_ADPCM_STOP_FLAG;
413   pce_cd.regs[0x0c] &= ~PCE_CD_ADPCM_PLAY_FLAG;
414   //pce_cd.regs[0x03] = (pce_cd.regs[0x03] & ~0x0c) | (PCE_CD_SAMPLE_STOP_PLAY);
415   pce_cd_set_irq_line( machine, PCE_CD_IRQ_SAMPLE_FULL_PLAY, ASSERT_LINE );
416   pce_cd.regs[0x0d] &= ~0x60;
417   pce_cd.msm_idle = 1;
418}
419
420static void adpcm_play(running_machine &machine)
421{
422   pce_state *state = machine.driver_data<pce_state>();
423   pce_cd_t &pce_cd = state->m_cd;
424   pce_cd.regs[0x0c] &= ~PCE_CD_ADPCM_STOP_FLAG;
425   pce_cd.regs[0x0c] |= PCE_CD_ADPCM_PLAY_FLAG;
426   pce_cd_set_irq_line( machine, PCE_CD_IRQ_SAMPLE_FULL_PLAY, CLEAR_LINE );
427   pce_cd.regs[0x03] = (pce_cd.regs[0x03] & ~0x0c);
428   pce_cd.msm_idle = 0;
429}
430
431
432/* Callback for new data from the MSM5205.
433  The PCE cd unit actually divides the clock signal supplied to
434  the MSM5205. Currently we can only use static clocks for the
435  MSM5205.
436 */
437static void pce_cd_msm5205_int(device_t *device)
438{
439   pce_state *state = device->machine().driver_data<pce_state>();
440   pce_cd_t &pce_cd = state->m_cd;
441   UINT8 msm_data;
442
443//  popmessage("%08x %08x %08x %02x %02x",pce_cd.msm_start_addr,pce_cd.msm_end_addr,pce_cd.msm_half_addr,pce_cd.regs[0x0c],pce_cd.regs[0x0d]);
444
445   if ( pce_cd.msm_idle )
446      return;
447
448   /* Supply new ADPCM data */
449   msm_data = (pce_cd.msm_nibble) ? (pce_cd.adpcm_ram[pce_cd.msm_start_addr] & 0x0f) : ((pce_cd.adpcm_ram[pce_cd.msm_start_addr] & 0xf0) >> 4);
450
451   msm5205_data_w(device, msm_data);
452   pce_cd.msm_nibble ^= 1;
453
454   if(pce_cd.msm_nibble == 0)
455   {
456      pce_cd.msm_start_addr++;
457
458      if(pce_cd.msm_start_addr == pce_cd.msm_half_addr)
459      {
460         //pce_cd_set_irq_line( device->machine(), PCE_CD_IRQ_SAMPLE_FULL_PLAY, CLEAR_LINE );
461         //pce_cd_set_irq_line( device->machine(), PCE_CD_IRQ_SAMPLE_HALF_PLAY, ASSERT_LINE );
462      }
463
464      if(pce_cd.msm_start_addr > pce_cd.msm_end_addr)
465      {
466         //pce_cd_set_irq_line( device->machine(), PCE_CD_IRQ_SAMPLE_HALF_PLAY, CLEAR_LINE );
467         //pce_cd_set_irq_line( device->machine(), PCE_CD_IRQ_SAMPLE_FULL_PLAY, CLEAR_LINE );
468         adpcm_stop(device->machine());
469         msm5205_reset_w(device, 1);
470      }
471   }
472}
473
474#define   SCSI_STATUS_OK         0x00
475#define SCSI_CHECK_CONDITION   0x02
476
477static void pce_cd_reply_status_byte( pce_state *state, UINT8 status )
478{
479   pce_cd_t &pce_cd = state->m_cd;
480logerror("Setting CD in reply_status_byte\n");
481   pce_cd.scsi_CD = pce_cd.scsi_IO = pce_cd.scsi_REQ = 1;
482   pce_cd.scsi_MSG = 0;
483   pce_cd.message_after_status = 1;
484   pce_cd.status_sent = pce_cd.message_sent = 0;
485
486   if ( status == SCSI_STATUS_OK )
487   {
488      pce_cd.regs[0x01] = 0x00;
489   }
490   else
491   {
492      pce_cd.regs[0x01] = 0x01;
493   }
494}
495
496/* 0x00 - TEST UNIT READY */
497static void pce_cd_test_unit_ready( running_machine &machine )
498{
499   pce_state *state = machine.driver_data<pce_state>();
500   pce_cd_t &pce_cd = state->m_cd;
501   logerror("test unit ready\n");
502   if ( pce_cd.cd )
503   {
504      logerror( "Sending STATUS_OK status\n" );
505      pce_cd_reply_status_byte( state, SCSI_STATUS_OK );
506   }
507   else
508   {
509      logerror( "Sending CHECK_CONDITION status\n" );
510      pce_cd_reply_status_byte( state, SCSI_CHECK_CONDITION );
511   }
512}
513
514/* 0x08 - READ (6) */
515static void pce_cd_read_6( running_machine &machine )
516{
517   pce_state *state = machine.driver_data<pce_state>();
518   pce_cd_t &pce_cd = state->m_cd;
519   UINT32 frame = ( ( pce_cd.command_buffer[1] & 0x1F ) << 16 ) | ( pce_cd.command_buffer[2] << 8 ) | pce_cd.command_buffer[3];
520   UINT32 frame_count = pce_cd.command_buffer[4];
521
522   /* Check for presence of a CD */
523   if ( ! pce_cd.cd )
524   {
525      pce_cd_reply_status_byte( state, SCSI_CHECK_CONDITION );
526      return;
527   }
528
529   if ( pce_cd.cdda_status != PCE_CD_CDDA_OFF )
530   {
531      pce_cd.cdda_status = PCE_CD_CDDA_OFF;
532      cdda_stop_audio( machine.device( "cdda" ) );
533      pce_cd.end_mark = 0;
534   }
535
536   pce_cd.current_frame = frame;
537   pce_cd.end_frame = frame + frame_count;
538
539   if ( frame_count == 0 )
540   {
541      /* Star Breaker uses this */
542      popmessage("Read Sector frame count == 0, contact MESSdev");
543      pce_cd_reply_status_byte( state, SCSI_STATUS_OK );
544   }
545   else
546   {
547      pce_cd.data_timer->adjust(attotime::from_hz( PCE_CD_DATA_FRAMES_PER_SECOND ), 0, attotime::from_hz( PCE_CD_DATA_FRAMES_PER_SECOND ));
548   }
549}
550
551/* 0xD8 - SET AUDIO PLAYBACK START POSITION (NEC) */
552static void pce_cd_nec_set_audio_start_position( running_machine &machine )
553{
554   pce_state *state = machine.driver_data<pce_state>();
555   pce_cd_t &pce_cd = state->m_cd;
556   UINT32   frame = 0;
557
558   if ( ! pce_cd.cd )
559   {
560      /* Throw some error here */
561      pce_cd_reply_status_byte( state, SCSI_CHECK_CONDITION );
562      return;
563   }
564
565   switch( pce_cd.command_buffer[9] & 0xC0 )
566   {
567   case 0x00:
568      popmessage("CD-DA set start mode 0x00, contact MESSdev");
569      frame = ( pce_cd.command_buffer[3] << 16 ) | ( pce_cd.command_buffer[4] << 8 ) | pce_cd.command_buffer[5];
570      break;
571   case 0x40:
572   {
573      UINT8 m,s,f;
574
575      m = bcd_2_dec( pce_cd.command_buffer[2]);
576      s = bcd_2_dec( pce_cd.command_buffer[3]);
577      f = bcd_2_dec( pce_cd.command_buffer[4]);
578
579      frame = f + 75 * (s + m * 60);
580      if(frame >= 525) // TODO: seven seconds gap? O_o
581         frame -= 525;
582      break;
583   }
584   case 0x80:
585      frame = pce_cd.toc->tracks[ bcd_2_dec( pce_cd.command_buffer[2] ) - 1 ].physframeofs;
586      break;
587   default:
588      popmessage("CD-DA set start mode 0xc0, contact MESSdev");
589      //assert( NULL == pce_cd_nec_set_audio_start_position );
590      break;
591   }
592
593   pce_cd.current_frame = frame;
594
595   if ( pce_cd.cdda_status == PCE_CD_CDDA_PAUSED )
596   {
597      pce_cd.cdda_status = PCE_CD_CDDA_OFF;
598      cdda_stop_audio( machine.device( "cdda" ) );
599      pce_cd.end_frame = pce_cd.last_frame;
600      pce_cd.end_mark = 0;
601   }
602   else
603   {
604      if(pce_cd.command_buffer[1] & 0x03)
605      {
606         pce_cd.cdda_status = PCE_CD_CDDA_PLAYING;
607         pce_cd.end_frame = pce_cd.last_frame; //get the end of the CD
608         cdda_start_audio( machine.device( "cdda" ), pce_cd.current_frame, pce_cd.end_frame - pce_cd.current_frame );
609         pce_cd.cdda_play_mode = (pce_cd.command_buffer[1] & 0x02) ? 2 : 3; // mode 2 sets IRQ at end
610         pce_cd.end_mark =  (pce_cd.command_buffer[1] & 0x02) ? 1 : 0;
611      }
612      else
613      {
614         pce_cd.cdda_status = PCE_CD_CDDA_PLAYING;
615         pce_cd.end_frame = pce_cd.toc->tracks[ cdrom_get_track(pce_cd.cd, pce_cd.current_frame) + 1 ].physframeofs; //get the end of THIS track
616         cdda_start_audio( machine.device( "cdda" ), pce_cd.current_frame, pce_cd.end_frame - pce_cd.current_frame );
617         pce_cd.end_mark = 0;
618         pce_cd.cdda_play_mode = 3;
619      }
620   }
621
622   pce_cd_reply_status_byte( state, SCSI_STATUS_OK );
623   pce_cd_set_irq_line( machine, PCE_CD_IRQ_TRANSFER_DONE, ASSERT_LINE );
624}
625
626/* 0xD9 - SET AUDIO PLAYBACK END POSITION (NEC) */
627static void pce_cd_nec_set_audio_stop_position( running_machine &machine )
628{
629   pce_state *state = machine.driver_data<pce_state>();
630   pce_cd_t &pce_cd = state->m_cd;
631   UINT32  frame = 0;
632
633   if ( ! pce_cd.cd )
634   {
635      /* Throw some error here */
636      pce_cd_reply_status_byte( state, SCSI_CHECK_CONDITION );
637      return;
638   }
639
640   switch( pce_cd.command_buffer[9] & 0xC0 )
641   {
642   case 0x00:
643      popmessage("CD-DA set end mode 0x00, contact MESSdev");
644      frame = ( pce_cd.command_buffer[3] << 16 ) | ( pce_cd.command_buffer[4] << 8 ) | pce_cd.command_buffer[5];
645      break;
646   case 0x40:
647   {
648      UINT8 m,s,f;
649
650      m = bcd_2_dec( pce_cd.command_buffer[2]);
651      s = bcd_2_dec( pce_cd.command_buffer[3]);
652      f = bcd_2_dec( pce_cd.command_buffer[4]);
653
654      frame = f + 75 * (s + m * 60);
655      if(frame >= 525) // TODO: seven seconds gap? O_o
656         frame -= 525;
657      break;
658   }
659   case 0x80:
660      frame = pce_cd.toc->tracks[ bcd_2_dec( pce_cd.command_buffer[2] ) - 1 ].physframeofs;
661      break;
662   default:
663      popmessage("CD-DA set end mode 0xc0, contact MESSdev");
664      //assert( NULL == pce_cd_nec_set_audio_start_position );
665      break;
666   }
667
668   pce_cd.end_frame = frame;
669   pce_cd.cdda_play_mode = pce_cd.command_buffer[1] & 0x03;
670
671   if ( pce_cd.cdda_play_mode )
672   {
673      if ( pce_cd.cdda_status == PCE_CD_CDDA_PAUSED )
674      {
675         cdda_pause_audio( machine.device( "cdda" ), 0 );
676      }
677      else
678      {
679         cdda_start_audio( machine.device( "cdda" ), pce_cd.current_frame, pce_cd.end_frame - pce_cd.current_frame );
680         pce_cd.end_mark = 1;
681      }
682      pce_cd.cdda_status = PCE_CD_CDDA_PLAYING;
683   }
684   else
685   {
686      pce_cd.cdda_status = PCE_CD_CDDA_OFF;
687      cdda_stop_audio( machine.device( "cdda" ) );
688      pce_cd.end_frame = pce_cd.last_frame;
689      pce_cd.end_mark = 0;
690//      assert( NULL == pce_cd_nec_set_audio_stop_position );
691   }
692
693   pce_cd_reply_status_byte( state, SCSI_STATUS_OK );
694   pce_cd_set_irq_line( machine, PCE_CD_IRQ_TRANSFER_DONE, ASSERT_LINE );
695}
696
697/* 0xDA - PAUSE (NEC) */
698static void pce_cd_nec_pause( running_machine &machine )
699{
700   pce_state *state = machine.driver_data<pce_state>();
701   pce_cd_t &pce_cd = state->m_cd;
702
703   /* If no cd mounted throw an error */
704   if ( ! pce_cd.cd )
705   {
706      pce_cd_reply_status_byte( state, SCSI_CHECK_CONDITION );
707      return;
708   }
709
710   /* If there was no cdda playing, throw an error */
711   if ( pce_cd.cdda_status == PCE_CD_CDDA_OFF )
712   {
713      pce_cd_reply_status_byte( state, SCSI_CHECK_CONDITION );
714      return;
715   }
716
717   pce_cd.cdda_status = PCE_CD_CDDA_PAUSED;
718   pce_cd.current_frame = cdda_get_audio_lba( machine.device( "cdda" ) );
719   cdda_pause_audio( machine.device( "cdda" ), 1 );
720   pce_cd_reply_status_byte( state, SCSI_STATUS_OK );
721}
722
723/* 0xDD - READ SUBCHANNEL Q (NEC) */
724static void pce_cd_nec_get_subq( running_machine &machine )
725{
726   pce_state *state = machine.driver_data<pce_state>();
727   pce_cd_t &pce_cd = state->m_cd;
728   /* WP - I do not have access to chds with subchannel information yet, so I'm faking something here */
729   UINT32 msf_abs, msf_rel, track, frame;
730
731   if ( ! pce_cd.cd )
732   {
733      /* Throw some error here */
734      pce_cd_reply_status_byte( state, SCSI_CHECK_CONDITION );
735      return;
736   }
737
738   frame = pce_cd.current_frame;
739
740   switch( pce_cd.cdda_status )
741   {
742   case PCE_CD_CDDA_PAUSED:
743      pce_cd.data_buffer[0] = 2;
744      frame = cdda_get_audio_lba( machine.device( "cdda" ) );
745      break;
746   case PCE_CD_CDDA_PLAYING:
747      pce_cd.data_buffer[0] = 0;
748      frame = cdda_get_audio_lba( machine.device( "cdda" ) );
749      break;
750   default:
751      pce_cd.data_buffer[0] = 3;
752      break;
753   }
754
755   msf_abs = lba_to_msf( frame );
756   track = cdrom_get_track( pce_cd.cd, frame );
757   msf_rel = lba_to_msf( frame - cdrom_get_track_start( pce_cd.cd, track ) );
758
759   pce_cd.data_buffer[1] = 0;
760   pce_cd.data_buffer[2] = dec_2_bcd( track+1 );      /* track */
761   pce_cd.data_buffer[3] = 1;                     /* index */
762   pce_cd.data_buffer[4] = ( msf_rel >> 16 ) & 0xFF;   /* M (relative) */
763   pce_cd.data_buffer[5] = ( msf_rel >> 8 ) & 0xFF;   /* S (relative) */
764   pce_cd.data_buffer[6] = msf_rel & 0xFF;            /* F (relative) */
765   pce_cd.data_buffer[7] = ( msf_abs >> 16 ) & 0xFF;   /* M (absolute) */
766   pce_cd.data_buffer[8] = ( msf_abs >> 8 ) & 0xFF;   /* S (absolute) */
767   pce_cd.data_buffer[9] = msf_abs & 0xFF;            /* F (absolute) */
768   pce_cd.data_buffer_size = 10;
769
770   pce_cd.data_buffer_index = 0;
771   pce_cd.data_transferred = 1;
772   pce_cd.scsi_IO = 1;
773   pce_cd.scsi_CD = 0;
774}
775
776/* 0xDE - GET DIR INFO (NEC) */
777static void pce_cd_nec_get_dir_info( running_machine &machine )
778{
779   pce_state *state = machine.driver_data<pce_state>();
780   pce_cd_t &pce_cd = state->m_cd;
781   UINT32 frame, msf, track = 0;
782   const cdrom_toc   *toc;
783   logerror("nec get dir info\n");
784
785   if ( ! pce_cd.cd )
786   {
787      /* Throw some error here */
788      pce_cd_reply_status_byte( state, SCSI_CHECK_CONDITION );
789   }
790
791   toc = cdrom_get_toc( pce_cd.cd );
792
793   switch( pce_cd.command_buffer[1] )
794   {
795   case 0x00:      /* Get first and last track numbers */
796      pce_cd.data_buffer[0] = dec_2_bcd(1);
797      pce_cd.data_buffer[1] = dec_2_bcd(toc->numtrks);
798      pce_cd.data_buffer_size = 2;
799      break;
800   case 0x01:      /* Get total disk size in MSF format */
801      frame = toc->tracks[toc->numtrks-1].physframeofs;
802      frame += toc->tracks[toc->numtrks-1].frames;
803      msf = lba_to_msf( frame + 150 );
804
805      pce_cd.data_buffer[0] = ( msf >> 16 ) & 0xFF;   /* M */
806      pce_cd.data_buffer[1] = ( msf >> 8 ) & 0xFF;   /* S */
807      pce_cd.data_buffer[2] = msf & 0xFF;            /* F */
808      pce_cd.data_buffer_size = 3;
809      break;
810   case 0x02:      /* Get track information */
811      if ( pce_cd.command_buffer[2] == 0xAA )
812      {
813         frame = toc->tracks[toc->numtrks-1].physframeofs;
814         frame += toc->tracks[toc->numtrks-1].frames;
815         pce_cd.data_buffer[3] = 0x04;   /* correct? */
816      } else
817      {
818         track = MAX( bcd_2_dec( pce_cd.command_buffer[2] ), 1 );
819         frame = toc->tracks[track-1].physframeofs;
820         pce_cd.data_buffer[3] = ( toc->tracks[track-1].trktype == CD_TRACK_AUDIO ) ? 0x00 : 0x04;
821      }
822      logerror("track = %d, frame = %d\n", track, frame );
823      msf = lba_to_msf( frame + 150 );
824      pce_cd.data_buffer[0] = ( msf >> 16 ) & 0xFF;   /* M */
825      pce_cd.data_buffer[1] = ( msf >> 8 ) & 0xFF;   /* S */
826      pce_cd.data_buffer[2] = msf & 0xFF;            /* F */
827      pce_cd.data_buffer_size = 4;
828      break;
829   default:
830//      assert( pce_cd_nec_get_dir_info == NULL );  // Not implemented yet
831      break;
832   }
833
834   pce_cd.data_buffer_index = 0;
835   pce_cd.data_transferred = 1;
836   pce_cd.scsi_IO = 1;
837   pce_cd.scsi_CD = 0;
838}
839
840static void pce_cd_end_of_list( running_machine &machine )
841{
842   pce_state *state = machine.driver_data<pce_state>();
843   pce_cd_reply_status_byte( state, SCSI_CHECK_CONDITION );
844}
845
846static void pce_cd_handle_data_output( running_machine &machine )
847{
848   pce_state *state = machine.driver_data<pce_state>();
849   pce_cd_t &pce_cd = state->m_cd;
850   static const struct {
851      UINT8   command_byte;
852      UINT8   command_size;
853      void   (*command_handler)(running_machine &machine);
854   } pce_cd_commands[] = {
855      { 0x00, 6, pce_cd_test_unit_ready },            /* TEST UNIT READY */
856      { 0x08, 6, pce_cd_read_6 },                     /* READ (6) */
857      { 0xD8,10, pce_cd_nec_set_audio_start_position },   /* NEC SET AUDIO PLAYBACK START POSITION */
858      { 0xD9,10, pce_cd_nec_set_audio_stop_position },   /* NEC SET AUDIO PLAYBACK END POSITION */
859      { 0xDA,10, pce_cd_nec_pause },                  /* NEC PAUSE */
860      { 0xDD,10, pce_cd_nec_get_subq },               /* NEC GET SUBCHANNEL Q */
861      { 0xDE,10, pce_cd_nec_get_dir_info },            /* NEC GET DIR INFO */
862      { 0xFF, 1, pce_cd_end_of_list }                  /* end of list marker */
863   };
864
865   if ( pce_cd.scsi_REQ && pce_cd.scsi_ACK )
866   {
867      /* Command byte received */
868      logerror( "Command byte $%02X received\n", pce_cd.regs[0x01] );
869
870      /* Check for buffer overflow */
871      assert( pce_cd.command_buffer_index < PCE_CD_COMMAND_BUFFER_SIZE );
872
873      pce_cd.command_buffer[pce_cd.command_buffer_index] = pce_cd.regs[0x01];
874      pce_cd.command_buffer_index++;
875      pce_cd.scsi_REQ = 0;
876   }
877
878   if ( ! pce_cd.scsi_REQ && ! pce_cd.scsi_ACK && pce_cd.command_buffer_index )
879   {
880      int i = 0;
881
882      logerror( "Check if command done\n" );
883
884      for( i = 0; pce_cd.command_buffer[0] > pce_cd_commands[i].command_byte; i++ );
885
886      /* Check for unknown commands */
887      if ( pce_cd.command_buffer[0] != pce_cd_commands[i].command_byte )
888      {
889         logerror("Unrecognized command: %02X\n", pce_cd.command_buffer[0] );
890         if(pce_cd.command_buffer[0] == 0x03)
891            popmessage("CD command 0x03 issued (Request Sense), contact MESSdev");
892      }
893      assert( pce_cd.command_buffer[0] == pce_cd_commands[i].command_byte );
894
895      if ( pce_cd.command_buffer_index == pce_cd_commands[i].command_size )
896      {
897         (pce_cd_commands[i].command_handler)( machine );
898         pce_cd.command_buffer_index = 0;
899      }
900      else
901      {
902         pce_cd.scsi_REQ = 1;
903      }
904   }
905}
906
907static void pce_cd_handle_data_input( running_machine &machine )
908{
909   pce_state *state = machine.driver_data<pce_state>();
910   pce_cd_t &pce_cd = state->m_cd;
911   if ( pce_cd.scsi_CD )
912   {
913      /* Command / Status byte */
914      if ( pce_cd.scsi_REQ && pce_cd.scsi_ACK )
915      {
916         logerror( "status sent\n" );
917         pce_cd.scsi_REQ = 0;
918         pce_cd.status_sent = 1;
919      }
920
921      if ( ! pce_cd.scsi_REQ && ! pce_cd.scsi_ACK && pce_cd.status_sent )
922      {
923         pce_cd.status_sent = 0;
924         if ( pce_cd.message_after_status )
925         {
926            logerror( "message after status\n" );
927            pce_cd.message_after_status = 0;
928            pce_cd.scsi_MSG = pce_cd.scsi_REQ = 1;
929            pce_cd.regs[0x01] = 0;
930         }
931      }
932   }
933   else
934   {
935      /* Data */
936      if ( pce_cd.scsi_REQ && pce_cd.scsi_ACK )
937      {
938         pce_cd.scsi_REQ = 0;
939      }
940
941      if ( ! pce_cd.scsi_REQ && ! pce_cd.scsi_ACK )
942      {
943         if ( pce_cd.data_buffer_index == pce_cd.data_buffer_size )
944         {
945            pce_cd_set_irq_line( machine, PCE_CD_IRQ_TRANSFER_READY, CLEAR_LINE );
946            if ( pce_cd.data_transferred )
947            {
948               pce_cd.data_transferred = 0;
949               pce_cd_reply_status_byte( state, SCSI_STATUS_OK );
950               pce_cd_set_irq_line( machine, PCE_CD_IRQ_TRANSFER_DONE, ASSERT_LINE );
951            }
952         }
953         else
954         {
955            logerror("Transfer byte from offset %d\n", pce_cd.data_buffer_index);
956            pce_cd.regs[0x01] = pce_cd.data_buffer[pce_cd.data_buffer_index];
957            pce_cd.data_buffer_index++;
958            pce_cd.scsi_REQ = 1;
959         }
960      }
961   }
962}
963
964static void pce_cd_handle_message_output( pce_state *state )
965{
966   pce_cd_t &pce_cd = state->m_cd;
967   if ( pce_cd.scsi_REQ && pce_cd.scsi_ACK )
968   {
969      pce_cd.scsi_REQ = 0;
970   }
971}
972
973static void pce_cd_handle_message_input( pce_state *state )
974{
975   pce_cd_t &pce_cd = state->m_cd;
976   if ( pce_cd.scsi_REQ && pce_cd.scsi_ACK )
977   {
978      pce_cd.scsi_REQ = 0;
979      pce_cd.message_sent = 1;
980   }
981
982   if ( ! pce_cd.scsi_REQ && ! pce_cd.scsi_ACK && pce_cd.message_sent )
983   {
984      pce_cd.message_sent = 0;
985      pce_cd.scsi_BSY = 0;
986   }
987}
988
989/* Update internal CD statuses */
990static void pce_cd_update( running_machine &machine )
991{
992   pce_state *state = machine.driver_data<pce_state>();
993   pce_cd_t &pce_cd = state->m_cd;
994   /* Check for reset of CD unit */
995   if ( pce_cd.scsi_RST != pce_cd.scsi_last_RST )
996   {
997      if ( pce_cd.scsi_RST )
998      {
999         logerror("Performing CD reset\n");
1000         /* Reset internal data */
1001         pce_cd.scsi_BSY = pce_cd.scsi_SEL = pce_cd.scsi_CD = pce_cd.scsi_IO = 0;
1002         pce_cd.scsi_MSG = pce_cd.scsi_REQ = pce_cd.scsi_ATN = 0;
1003         pce_cd.cd_motor_on = 0;
1004         pce_cd.selected = 0;
1005         pce_cd.cdda_status = PCE_CD_CDDA_OFF;
1006         cdda_stop_audio( machine.device( "cdda" ) );
1007         pce_cd.adpcm_dma_timer->adjust(attotime::never); // stop ADPCM DMA here
1008      }
1009      pce_cd.scsi_last_RST = pce_cd.scsi_RST;
1010   }
1011
1012   /* Check if bus can be freed */
1013   if ( ! pce_cd.scsi_SEL && ! pce_cd.scsi_BSY && pce_cd.selected )
1014   {
1015      logerror( "freeing bus\n" );
1016      pce_cd.selected = 0;
1017      pce_cd.scsi_CD = pce_cd.scsi_MSG = pce_cd.scsi_IO = pce_cd.scsi_REQ = 0;
1018      pce_cd_set_irq_line( machine, PCE_CD_IRQ_TRANSFER_DONE, CLEAR_LINE );
1019   }
1020
1021   /* Select the CD device */
1022   if ( pce_cd.scsi_SEL )
1023   {
1024      if ( ! pce_cd.selected )
1025      {
1026         pce_cd.selected = 1;
1027         logerror("Setting CD in device selection\n");
1028         pce_cd.scsi_BSY = pce_cd.scsi_REQ = pce_cd.scsi_CD = 1;
1029         pce_cd.scsi_MSG = pce_cd.scsi_IO = 0;
1030      }
1031   }
1032
1033   if ( pce_cd.scsi_ATN )
1034   {
1035   }
1036   else
1037   {
1038      /* Check for data and pessage phases */
1039      if ( pce_cd.scsi_BSY )
1040      {
1041         if ( pce_cd.scsi_MSG )
1042         {
1043            /* message phase */
1044            if ( pce_cd.scsi_IO )
1045            {
1046               pce_cd_handle_message_input(state);
1047            }
1048            else
1049            {
1050               pce_cd_handle_message_output(state);
1051            }
1052         }
1053         else
1054         {
1055            /* data phase */
1056            if ( pce_cd.scsi_IO )
1057            {
1058               /* Reading data from target */
1059               pce_cd_handle_data_input( machine );
1060            }
1061            else
1062            {
1063               /* Sending data to target */
1064               pce_cd_handle_data_output( machine );
1065            }
1066         }
1067      }
1068   }
1069
1070   /* FIXME: presumably CD-DA needs an irq interface for this */
1071   if(cdda_audio_ended(machine.device("cdda")) && pce_cd.end_mark == 1)
1072   {
1073      switch(pce_cd.cdda_play_mode & 3)
1074      {
1075         case 1: cdda_start_audio( machine.device( "cdda" ), pce_cd.current_frame, pce_cd.end_frame - pce_cd.current_frame ); pce_cd.end_mark = 1; break; //play with repeat
1076         case 2: pce_cd_set_irq_line( machine, PCE_CD_IRQ_TRANSFER_DONE, ASSERT_LINE ); pce_cd.end_mark = 0; break; //irq when finished
1077         case 3: pce_cd.end_mark = 0; break; //play without repeat
1078      }
1079   }
1080}
1081
1082static void pce_cd_set_irq_line( running_machine &machine, int num, int state )
1083{
1084   pce_state *drvstate = machine.driver_data<pce_state>();
1085   pce_cd_t &pce_cd = drvstate->m_cd;
1086   switch( num )
1087   {
1088   case PCE_CD_IRQ_TRANSFER_DONE:
1089      if ( state == ASSERT_LINE )
1090      {
1091         pce_cd.regs[0x03] |= PCE_CD_IRQ_TRANSFER_DONE;
1092      }
1093      else
1094      {
1095         pce_cd.regs[0x03] &= ~ PCE_CD_IRQ_TRANSFER_DONE;
1096      }
1097      break;
1098   case PCE_CD_IRQ_TRANSFER_READY:
1099      if ( state == ASSERT_LINE )
1100      {
1101         pce_cd.regs[0x03] |= PCE_CD_IRQ_TRANSFER_READY;
1102      }
1103      else
1104      {
1105         pce_cd.regs[0x03] &= ~ PCE_CD_IRQ_TRANSFER_READY;
1106      }
1107      break;
1108   case PCE_CD_IRQ_SAMPLE_FULL_PLAY:
1109      if ( state == ASSERT_LINE )
1110      {
1111         pce_cd.regs[0x03] |= PCE_CD_IRQ_SAMPLE_FULL_PLAY;
1112         //printf("x %02x %02x\n",pce_cd.regs[0x02],pce_cd.regs[0x03]);
1113      }
1114      else
1115      {
1116         pce_cd.regs[0x03] &= ~ PCE_CD_IRQ_SAMPLE_FULL_PLAY;
1117      }
1118      break;
1119   case PCE_CD_IRQ_SAMPLE_HALF_PLAY:
1120      if ( state == ASSERT_LINE )
1121      {
1122         pce_cd.regs[0x03] |= PCE_CD_IRQ_SAMPLE_HALF_PLAY;
1123         //printf("y %02x %02x\n",pce_cd.regs[0x02],pce_cd.regs[0x03]);
1124      }
1125      else
1126      {
1127         pce_cd.regs[0x03] &= ~ PCE_CD_IRQ_SAMPLE_HALF_PLAY;
1128      }
1129      break;
1130   default:
1131      break;
1132   }
1133
1134   if ( pce_cd.regs[0x02] & pce_cd.regs[0x03] & ( PCE_CD_IRQ_TRANSFER_DONE | PCE_CD_IRQ_TRANSFER_READY | PCE_CD_IRQ_SAMPLE_HALF_PLAY | PCE_CD_IRQ_SAMPLE_FULL_PLAY) )
1135   {
1136      cputag_set_input_line(machine, "maincpu", 1, ASSERT_LINE );
1137   }
1138   else
1139   {
1140      cputag_set_input_line(machine, "maincpu", 1, CLEAR_LINE );
1141   }
1142}
1143
1144static TIMER_CALLBACK( pce_cd_data_timer_callback )
1145{
1146   pce_state *state = machine.driver_data<pce_state>();
1147   pce_cd_t &pce_cd = state->m_cd;
1148   if ( pce_cd.data_buffer_index == pce_cd.data_buffer_size )
1149   {
1150      /* Read next data sector */
1151      logerror("read sector %d\n", pce_cd.current_frame );
1152      if ( ! cdrom_read_data( pce_cd.cd, pce_cd.current_frame, pce_cd.data_buffer, CD_TRACK_MODE1 ) )
1153      {
1154         logerror("Mode1 CD read failed for frame #%d\n", pce_cd.current_frame );
1155      }
1156      else
1157      {
1158         logerror("Succesfully read mode1 frame #%d\n", pce_cd.current_frame );
1159      }
1160
1161      pce_cd.data_buffer_index = 0;
1162      pce_cd.data_buffer_size = 2048;
1163      pce_cd.current_frame++;
1164
1165      pce_cd.scsi_IO = 1;
1166      pce_cd.scsi_CD = 0;
1167
1168      if ( pce_cd.current_frame == pce_cd.end_frame )
1169      {
1170         /* We are done, disable the timer */
1171         logerror("Last frame read from CD\n");
1172         pce_cd.data_transferred = 1;
1173         pce_cd.data_timer->adjust(attotime::never);
1174      }
1175      else
1176      {
1177         pce_cd.data_transferred = 0;
1178      }
1179   }
1180}
1181
1182static void pce_cd_init( running_machine &machine )
1183{
1184   pce_state *state = machine.driver_data<pce_state>();
1185   pce_cd_t &pce_cd = state->m_cd;
1186   device_t *device;
1187
1188   /* Initialize pce_cd struct */
1189   memset( &pce_cd, 0, sizeof(pce_cd) );
1190
1191   /* Initialize BRAM */
1192   pce_cd.bram = auto_alloc_array(machine, UINT8, PCE_BRAM_SIZE * 2 );
1193   memset( pce_cd.bram, 0, PCE_BRAM_SIZE );
1194   memset( pce_cd.bram + PCE_BRAM_SIZE, 0xFF, PCE_BRAM_SIZE );
1195   pce_cd.bram_locked = 1;
1196   pce_set_cd_bram(machine);
1197
1198   /* set up adpcm related things */
1199   pce_cd.adpcm_ram = auto_alloc_array(machine, UINT8, PCE_ADPCM_RAM_SIZE );
1200   memset( pce_cd.adpcm_ram, 0, PCE_ADPCM_RAM_SIZE );
1201   pce_cd.adpcm_clock_divider = 1;
1202   msm5205_change_clock_w(machine.device("msm5205"), (PCE_CD_CLOCK / 6) / pce_cd.adpcm_clock_divider);
1203
1204   /* Set up cd command buffer */
1205   pce_cd.command_buffer = auto_alloc_array(machine, UINT8, PCE_CD_COMMAND_BUFFER_SIZE );
1206   memset( pce_cd.command_buffer, 0, PCE_CD_COMMAND_BUFFER_SIZE );
1207   pce_cd.command_buffer_index = 0;
1208
1209   /* Set up Arcade Card RAM buffer */
1210   pce_cd.acard_ram = auto_alloc_array(machine, UINT8, PCE_ACARD_RAM_SIZE );
1211   memset( pce_cd.acard_ram, 0, PCE_ACARD_RAM_SIZE );
1212
1213   pce_cd.data_buffer = auto_alloc_array(machine, UINT8, 8192 );
1214   memset( pce_cd.data_buffer, 0, 8192 );
1215   pce_cd.data_buffer_size = 0;
1216   pce_cd.data_buffer_index = 0;
1217
1218   pce_cd.subcode_buffer = auto_alloc_array(machine, UINT8, 96 );
1219
1220   device = machine.device("cdrom");
1221   if ( device )
1222   {
1223      pce_cd.cd = cd_get_cdrom_file(device);
1224      if ( pce_cd.cd )
1225      {
1226         pce_cd.toc = cdrom_get_toc( pce_cd.cd );
1227         cdda_set_cdrom( machine.device("cdda"), pce_cd.cd );
1228         pce_cd.last_frame = cdrom_get_track_start( pce_cd.cd, cdrom_get_last_track( pce_cd.cd ) - 1 );
1229         pce_cd.last_frame += pce_cd.toc->tracks[ cdrom_get_last_track( pce_cd.cd ) - 1 ].frames;
1230         pce_cd.end_frame = pce_cd.last_frame;
1231      }
1232   }
1233
1234   pce_cd.data_timer = machine.scheduler().timer_alloc(FUNC(pce_cd_data_timer_callback));
1235   pce_cd.data_timer->adjust(attotime::never);
1236   pce_cd.adpcm_dma_timer = machine.scheduler().timer_alloc(FUNC(pce_cd_adpcm_dma_timer_callback));
1237   pce_cd.adpcm_dma_timer->adjust(attotime::never);
1238
1239   pce_cd.cdda_fadeout_timer = machine.scheduler().timer_alloc(FUNC(pce_cd_cdda_fadeout_callback));
1240   pce_cd.cdda_fadeout_timer->adjust(attotime::never);
1241   pce_cd.cdda_fadein_timer = machine.scheduler().timer_alloc(FUNC(pce_cd_cdda_fadein_callback));
1242   pce_cd.cdda_fadein_timer->adjust(attotime::never);
1243
1244   pce_cd.adpcm_fadeout_timer = machine.scheduler().timer_alloc(FUNC(pce_cd_adpcm_fadeout_callback));
1245   pce_cd.adpcm_fadeout_timer->adjust(attotime::never);
1246   pce_cd.adpcm_fadein_timer = machine.scheduler().timer_alloc(FUNC(pce_cd_adpcm_fadein_callback));
1247   pce_cd.adpcm_fadein_timer->adjust(attotime::never);
1248}
1249
1250WRITE8_HANDLER( pce_cd_bram_w )
1251{
1252   pce_state *state = space->machine().driver_data<pce_state>();
1253   pce_cd_t &pce_cd = state->m_cd;
1254   if ( ! pce_cd.bram_locked )
1255   {
1256      pce_cd.bram[ offset ] = data;
1257   }
1258}
1259
1260static void pce_cd_set_adpcm_ram_byte(running_machine &machine, UINT8 val)
1261{
1262   pce_state *state = machine.driver_data<pce_state>();
1263   pce_cd_t &pce_cd = state->m_cd;
1264   if(pce_cd.adpcm_write_buf > 0)
1265   {
1266      pce_cd.adpcm_write_buf--;
1267   }
1268   else
1269   {
1270      pce_cd.adpcm_ram[pce_cd.adpcm_write_ptr] = val;
1271      pce_cd.adpcm_write_ptr = ((pce_cd.adpcm_write_ptr + 1) & 0xffff);
1272      //TODO: length + 1
1273   }
1274}
1275
1276static TIMER_CALLBACK( pce_cd_cdda_fadeout_callback )
1277{
1278   pce_state *state = machine.driver_data<pce_state>();
1279   pce_cd_t &pce_cd = state->m_cd;
1280   pce_cd.cdda_volume-= 0.1;
1281
1282   if(pce_cd.cdda_volume <= 0)
1283   {
1284      pce_cd.cdda_volume = 0.0;
1285      cdda_set_volume(machine.device("cdda"), 0.0);
1286      pce_cd.cdda_fadeout_timer->adjust(attotime::never);
1287   }
1288   else
1289   {
1290      cdda_set_volume(machine.device("cdda"), pce_cd.cdda_volume);
1291      pce_cd.cdda_fadeout_timer->adjust(attotime::from_usec(param), param);
1292   }
1293}
1294
1295static TIMER_CALLBACK( pce_cd_cdda_fadein_callback )
1296{
1297   pce_state *state = machine.driver_data<pce_state>();
1298   pce_cd_t &pce_cd = state->m_cd;
1299   pce_cd.cdda_volume+= 0.1;
1300
1301   if(pce_cd.cdda_volume >= 100.0)
1302   {
1303      pce_cd.cdda_volume = 100.0;
1304      cdda_set_volume(machine.device("cdda"), 100.0);
1305      pce_cd.cdda_fadein_timer->adjust(attotime::never);
1306   }
1307   else
1308   {
1309      cdda_set_volume(machine.device("cdda"), pce_cd.cdda_volume);
1310      pce_cd.cdda_fadein_timer->adjust(attotime::from_usec(param), param);
1311   }
1312}
1313
1314static TIMER_CALLBACK( pce_cd_adpcm_fadeout_callback )
1315{
1316   pce_state *state = machine.driver_data<pce_state>();
1317   pce_cd_t &pce_cd = state->m_cd;
1318   pce_cd.adpcm_volume-= 0.1;
1319
1320   if(pce_cd.adpcm_volume <= 0)
1321   {
1322      pce_cd.adpcm_volume = 0.0;
1323      msm5205_set_volume(machine.device("msm5205"), 0.0);
1324      pce_cd.adpcm_fadeout_timer->adjust(attotime::never);
1325   }
1326   else
1327   {
1328      msm5205_set_volume(machine.device("msm5205"), pce_cd.adpcm_volume);
1329      pce_cd.adpcm_fadeout_timer->adjust(attotime::from_usec(param), param);
1330   }
1331}
1332
1333static TIMER_CALLBACK( pce_cd_adpcm_fadein_callback )
1334{
1335   pce_state *state = machine.driver_data<pce_state>();
1336   pce_cd_t &pce_cd = state->m_cd;
1337   pce_cd.adpcm_volume+= 0.1;
1338
1339   if(pce_cd.adpcm_volume >= 100.0)
1340   {
1341      pce_cd.adpcm_volume = 100.0;
1342      msm5205_set_volume(machine.device("msm5205"), 100.0);
1343      pce_cd.adpcm_fadein_timer->adjust(attotime::never);
1344   }
1345   else
1346   {
1347      msm5205_set_volume(machine.device("msm5205"), pce_cd.adpcm_volume);
1348      pce_cd.adpcm_fadein_timer->adjust(attotime::from_usec(param), param);
1349   }
1350}
1351
1352
1353WRITE8_HANDLER( pce_cd_intf_w )
1354{
1355   pce_state *state = space->machine().driver_data<pce_state>();
1356   pce_cd_t &pce_cd = state->m_cd;
1357   pce_cd_update(space->machine());
1358
1359   if(offset & 0x200 && state->m_sys3_card && state->m_acard) // route Arcade Card handling ports
1360      return pce_cd_acard_w(space,offset,data);
1361
1362   logerror("%04X: write to CD interface offset %02X, data %02X\n", cpu_get_pc(&space->device()), offset, data );
1363
1364   switch( offset & 0xf )
1365   {
1366   case 0x00:   /* CDC status */
1367      /* select device (which bits??) */
1368      pce_cd.scsi_SEL = 1;
1369      pce_cd_update(space->machine());
1370      pce_cd.scsi_SEL = 0;
1371      pce_cd.adpcm_dma_timer->adjust(attotime::never); // stop ADPCM DMA here
1372      /* any write here clears CD transfer irqs */
1373      pce_cd.regs[0x03] &= ~0x70;
1374      cputag_set_input_line(space->machine(), "maincpu", 1, CLEAR_LINE );
1375      break;
1376   case 0x01:   /* CDC command / status / data */
1377      break;
1378   case 0x02:   /* ADPCM / CD control / IRQ enable/disable */
1379            /* bit 6 - transfer ready irq */
1380            /* bit 5 - transfer done irq */
1381            /* bit 4 - ?? irq */
1382            /* bit 3 - ?? irq */
1383            /* bit 2 - ?? irq */
1384      pce_cd.scsi_ACK = data & 0x80;
1385      /* Don't set or reset any irq lines, but just verify the current state */
1386      pce_cd_set_irq_line( space->machine(), 0, 0 );
1387      break;
1388   case 0x03:   /* BRAM lock / CD status / IRQ - Read Only register */
1389      break;
1390   case 0x04:   /* CD reset */
1391      pce_cd.scsi_RST = data & 0x02;
1392      break;
1393   case 0x05:   /* Convert PCM data / PCM data */
1394   case 0x06:   /* PCM data */
1395      break;
1396   case 0x07:   /* BRAM unlock / CD status */
1397      if ( data & 0x80 )
1398      {
1399         pce_cd.bram_locked = 0;
1400         pce_set_cd_bram(space->machine());
1401      }
1402      break;
1403   case 0x08:   /* ADPCM address (LSB) / CD data */
1404      break;
1405   case 0x09:   /* ADPCM address (MSB) */
1406      break;
1407   case 0x0A:   /* ADPCM RAM data port */
1408      pce_cd_set_adpcm_ram_byte(space->machine(), data);
1409      break;
1410   case 0x0B:   /* ADPCM DMA control */
1411      if ( data & 0x03 )
1412      {
1413         /* Start CD to ADPCM transfer */
1414         pce_cd.adpcm_dma_timer->adjust(attotime::from_hz( PCE_CD_DATA_FRAMES_PER_SECOND * 2048 ), 0, attotime::from_hz( PCE_CD_DATA_FRAMES_PER_SECOND * 2048 ) );
1415         pce_cd.regs[0x0c] |= 4;
1416      }
1417      break;
1418   case 0x0C:   /* ADPCM status */
1419      break;
1420   case 0x0D:   /* ADPCM address control */
1421      if ( ( pce_cd.regs[0x0D] & 0x80 ) && ! ( data & 0x80 ) ) // ADPCM reset
1422      {
1423         /* Reset ADPCM hardware */
1424         pce_cd.adpcm_read_ptr = 0;
1425         pce_cd.adpcm_write_ptr = 0;
1426         pce_cd.msm_start_addr = 0;
1427         pce_cd.msm_end_addr = 0;
1428         pce_cd.msm_half_addr = 0;
1429         pce_cd.msm_nibble = 0;
1430         adpcm_stop(space->machine());
1431         msm5205_reset_w( space->machine().device( "msm5205"), 1 );
1432      }
1433
1434      if(data & 0x20)
1435         pce_cd.msm_half_addr = (pce_cd.adpcm_read_ptr + (pce_cd.adpcm_length / ((data & 0x40) ? 2 : 1))) & 0xffff;
1436
1437      if ( ( data & 0x40) && ((pce_cd.regs[0x0D] & 0x40) == 0) ) // ADPCM play
1438      {
1439         pce_cd.msm_start_addr = (pce_cd.adpcm_read_ptr);
1440         pce_cd.msm_end_addr = (pce_cd.adpcm_read_ptr + pce_cd.adpcm_length) & 0xffff;
1441         pce_cd.msm_nibble = 0;
1442         adpcm_play(space->machine());
1443         msm5205_reset_w( space->machine().device( "msm5205"), 0 );
1444
1445         //popmessage("%08x %08x",pce_cd.adpcm_read_ptr,pce_cd.adpcm_length);
1446      }
1447      else if ( (data & 0x40) == 0 )
1448      {
1449         /* used by Buster Bros to cancel an in-flight sample */
1450         adpcm_stop(space->machine());
1451         msm5205_reset_w( space->machine().device( "msm5205"), 1 );
1452      }
1453
1454      if ( data & 0x10 ) //ADPCM set length
1455      {
1456         pce_cd.adpcm_length = ( pce_cd.regs[0x09] << 8 ) | pce_cd.regs[0x08];
1457      }
1458      if ( data & 0x08 ) //ADPCM set read address
1459      {
1460         pce_cd.adpcm_read_ptr = ( pce_cd.regs[0x09] << 8 ) | pce_cd.regs[0x08];
1461         pce_cd.adpcm_read_buf = 2;
1462      }
1463      if ( ( data & 0x02 ) == 0x02 ) //ADPCM set write address
1464      {
1465         pce_cd.adpcm_write_ptr = ( pce_cd.regs[0x09] << 8 ) | pce_cd.regs[0x08];
1466         pce_cd.adpcm_write_buf = data & 1;
1467      }
1468      break;
1469   case 0x0E:   /* ADPCM playback rate */
1470      pce_cd.adpcm_clock_divider = 0x10 - ( data & 0x0F );
1471      msm5205_change_clock_w(space->machine().device("msm5205"), (PCE_CD_CLOCK / 6) / pce_cd.adpcm_clock_divider);
1472      break;
1473   case 0x0F:   /* ADPCM and CD audio fade timer */
1474      /* TODO: timers needs HW tests */
1475      if(pce_cd.regs[0xf] != data)
1476      {
1477         switch(data & 0xf)
1478         {
1479            case 0x00: //CD-DA / ADPCM enable (100 msecs)
1480               pce_cd.cdda_volume = 0.0;
1481               pce_cd.cdda_fadein_timer->adjust(attotime::from_usec(100), 100);
1482               pce_cd.adpcm_volume = 0.0;
1483               pce_cd.adpcm_fadein_timer->adjust(attotime::from_usec(100), 100);
1484               pce_cd.cdda_fadeout_timer->adjust(attotime::never);
1485               pce_cd.adpcm_fadeout_timer->adjust(attotime::never);
1486               break;
1487            case 0x01: //CD-DA enable (100 msecs)
1488               pce_cd.cdda_volume = 0.0;
1489               pce_cd.cdda_fadein_timer->adjust(attotime::from_usec(100), 100);
1490               pce_cd.cdda_fadeout_timer->adjust(attotime::never);
1491               break;
1492            case 0x08: //CD-DA short (1500 msecs) fade out / ADPCM enable
1493               pce_cd.cdda_volume = 100.0;
1494               pce_cd.cdda_fadeout_timer->adjust(attotime::from_usec(1500), 1500);
1495               pce_cd.adpcm_volume = 0.0;
1496               pce_cd.adpcm_fadein_timer->adjust(attotime::from_usec(100), 100);
1497               pce_cd.cdda_fadein_timer->adjust(attotime::never);
1498               pce_cd.adpcm_fadeout_timer->adjust(attotime::never);
1499               break;
1500            case 0x09: //CD-DA long (5000 msecs) fade out
1501               pce_cd.cdda_volume = 100.0;
1502               pce_cd.cdda_fadeout_timer->adjust(attotime::from_usec(5000), 5000);
1503               pce_cd.cdda_fadein_timer->adjust(attotime::never);
1504               break;
1505            case 0x0a: //ADPCM long (5000 msecs) fade out
1506               pce_cd.adpcm_volume = 100.0;
1507               pce_cd.adpcm_fadeout_timer->adjust(attotime::from_usec(5000), 5000);
1508               pce_cd.adpcm_fadein_timer->adjust(attotime::never);
1509               break;
1510            case 0x0c: //CD-DA short (1500 msecs) fade out / ADPCM enable
1511               pce_cd.cdda_volume = 100.0;
1512               pce_cd.cdda_fadeout_timer->adjust(attotime::from_usec(1500), 1500);
1513               pce_cd.adpcm_volume = 0.0;
1514               pce_cd.adpcm_fadein_timer->adjust(attotime::from_usec(100), 100);
1515               pce_cd.cdda_fadein_timer->adjust(attotime::never);
1516               pce_cd.adpcm_fadeout_timer->adjust(attotime::never);
1517               break;
1518            case 0x0d: //CD-DA short (1500 msecs) fade out
1519               pce_cd.cdda_volume = 100.0;
1520               pce_cd.cdda_fadeout_timer->adjust(attotime::from_usec(1500), 1500);
1521               pce_cd.cdda_fadein_timer->adjust(attotime::never);
1522               break;
1523            case 0x0e: //ADPCM short (1500 msecs) fade out
1524               pce_cd.adpcm_volume = 100.0;
1525               pce_cd.adpcm_fadeout_timer->adjust(attotime::from_usec(1500), 1500);
1526               pce_cd.adpcm_fadein_timer->adjust(attotime::never);
1527               break;
1528            default:
1529               popmessage("CD-DA / ADPCM Fade effect mode %02x, contact MESSdev",data & 0x0f);
1530               break;
1531         }
1532      }
1533      break;
1534   default:
1535      return;
1536   }
1537   pce_cd.regs[offset & 0xf] = data;
1538   pce_cd_update(space->machine());
1539}
1540
1541static TIMER_CALLBACK( pce_cd_clear_ack )
1542{
1543   pce_state *state = machine.driver_data<pce_state>();
1544   pce_cd_t &pce_cd = state->m_cd;
1545   pce_cd_update(machine);
1546   pce_cd.scsi_ACK = 0;
1547   pce_cd_update(machine);
1548   if ( pce_cd.scsi_CD )
1549   {
1550      pce_cd.regs[0x0B] &= 0xFE;
1551   }
1552}
1553
1554static UINT8 pce_cd_get_cd_data_byte(running_machine &machine)
1555{
1556   pce_state *state = machine.driver_data<pce_state>();
1557   pce_cd_t &pce_cd = state->m_cd;
1558   UINT8 data = pce_cd.regs[0x01];
1559   if ( pce_cd.scsi_REQ && ! pce_cd.scsi_ACK && ! pce_cd.scsi_CD )
1560   {
1561      if ( pce_cd.scsi_IO )
1562      {
1563         pce_cd.scsi_ACK = 1;
1564         machine.scheduler().timer_set(machine.device<cpu_device>("maincpu")->cycles_to_attotime(15), FUNC(pce_cd_clear_ack));
1565      }
1566   }
1567   return data;
1568}
1569
1570
1571static TIMER_CALLBACK( pce_cd_adpcm_dma_timer_callback )
1572{
1573   pce_state *state = machine.driver_data<pce_state>();
1574   pce_cd_t &pce_cd = state->m_cd;
1575   if ( pce_cd.scsi_REQ && ! pce_cd.scsi_ACK && ! pce_cd.scsi_CD && pce_cd.scsi_IO  )
1576   {
1577      pce_cd.adpcm_ram[pce_cd.adpcm_write_ptr] = pce_cd_get_cd_data_byte(machine);
1578      pce_cd.adpcm_write_ptr = ( pce_cd.adpcm_write_ptr + 1 ) & 0xFFFF;
1579
1580      pce_cd.regs[0x0c] &= ~4;
1581   }
1582}
1583
1584static UINT8 pce_cd_get_adpcm_ram_byte(running_machine &machine)
1585{
1586   pce_state *state = machine.driver_data<pce_state>();
1587   pce_cd_t &pce_cd = state->m_cd;
1588   if(pce_cd.adpcm_read_buf > 0)
1589   {
1590      pce_cd.adpcm_read_buf--;
1591      return 0;
1592   }
1593   else
1594   {
1595      UINT8 res;
1596
1597      res = pce_cd.adpcm_ram[pce_cd.adpcm_read_ptr];
1598      pce_cd.adpcm_read_ptr = ((pce_cd.adpcm_read_ptr + 1) & 0xffff);
1599
1600      return res;
1601   }
1602}
1603
1604READ8_HANDLER( pce_cd_intf_r )
1605{
1606   pce_state *state = space->machine().driver_data<pce_state>();
1607   pce_cd_t &pce_cd = state->m_cd;
1608   UINT8 data = pce_cd.regs[offset & 0x0F];
1609
1610   pce_cd_update(space->machine());
1611
1612   if(offset & 0x200 && state->m_sys3_card && state->m_acard) // route Arcade Card handling ports
1613      return pce_cd_acard_r(space,offset);
1614
1615   logerror("%04X: read from CD interface offset %02X\n", cpu_get_pc(&space->device()), offset );
1616
1617   if((offset & 0xc0) == 0xc0 && state->m_sys3_card) //System 3 Card header handling
1618   {
1619      switch(offset & 0xcf)
1620      {
1621         case 0xc1: return 0xaa;
1622         case 0xc2: return 0x55;
1623         case 0xc3: return 0x00;
1624         case 0xc5: return (state->m_sys3_card & 2) ? 0x55 : 0xaa;
1625         case 0xc6: return (state->m_sys3_card & 2) ? 0xaa : 0x55;
1626         case 0xc7: return 0x03;
1627      }
1628   }
1629
1630   switch( offset & 0xf )
1631   {
1632   case 0x00:   /* CDC status */
1633      data &= 0x07;
1634      data |= pce_cd.scsi_BSY ? 0x80 : 0;
1635      data |= pce_cd.scsi_REQ ? 0x40 : 0;
1636      data |= pce_cd.scsi_MSG ? 0x20 : 0;
1637      data |= pce_cd.scsi_CD  ? 0x10 : 0;
1638      data |= pce_cd.scsi_IO  ? 0x08 : 0;
1639      break;
1640   case 0x01:   /* CDC command / status / data */
1641      break;
1642   case 0x02:   /* ADPCM / CD control */
1643      break;
1644   case 0x03:   /* BRAM lock / CD status */
1645      /* bit 4 set when CD motor is on */
1646      /* bit 2 set when less than half of the ADPCM data is remaining ?? */
1647      pce_cd.bram_locked = 1;
1648      pce_set_cd_bram(space->machine());
1649      data = data & 0x6E;
1650      data |= ( pce_cd.cd_motor_on ? 0x10 : 0 );
1651      pce_cd.regs[0x03] ^= 0x02;         /* TODO: get rid of this hack */
1652      break;
1653   case 0x04:   /* CD reset */
1654      break;
1655   case 0x05:   /* Convert PCM data / PCM data */
1656   case 0x06:   /* PCM data */
1657      break;
1658   case 0x07:   /* BRAM unlock / CD status */
1659      data = ( pce_cd.bram_locked ? ( data & 0x7F ) : ( data | 0x80 ) );
1660      break;
1661   case 0x08:   /* ADPCM address (LSB) / CD data */
1662      data = pce_cd_get_cd_data_byte(space->machine());
1663      break;
1664   case 0x0A:   /* ADPCM RAM data port */
1665      data = pce_cd_get_adpcm_ram_byte(space->machine());
1666      break;
1667   case 0x0B:   /* ADPCM DMA control */
1668      break;
1669   case 0x0C:   /* ADPCM status */
1670      break;
1671   case 0x0D:   /* ADPCM address control */
1672      break;
1673   /* These are read-only registers */
1674   case 0x09:   /* ADPCM address (MSB) */
1675   case 0x0E:   /* ADPCM playback rate */
1676   case 0x0F:   /* ADPCM and CD audio fade timer */
1677      return 0;
1678   default:
1679      data = 0xFF;
1680      break;
1681   }
1682
1683   return data;
1684}
1685
1686
1687/*
1688
1689PC Engine Arcade Card emulation
1690
1691*/
1692
1693READ8_HANDLER( pce_cd_acard_r )
1694{
1695   pce_state *state = space->machine().driver_data<pce_state>();
1696   pce_cd_t &pce_cd = state->m_cd;
1697   UINT8 r_num;
1698
1699   if((offset & 0x2e0) == 0x2e0)
1700   {
1701      switch(offset & 0x2ef)
1702      {
1703         case 0x2e0: return (pce_cd.acard_shift >> 0)  & 0xff;
1704         case 0x2e1: return (pce_cd.acard_shift >> 8)  & 0xff;
1705         case 0x2e2: return (pce_cd.acard_shift >> 16) & 0xff;
1706         case 0x2e3: return (pce_cd.acard_shift >> 24) & 0xff;
1707         case 0x2e4: return (pce_cd.acard_shift_reg);
1708         case 0x2e5: return pce_cd.acard_latch;
1709         case 0x2ee: return 0x10;
1710         case 0x2ef: return 0x51;
1711      }
1712
1713      return 0;
1714   }
1715
1716   r_num = (offset & 0x30) >> 4;
1717
1718   switch(offset & 0x0f)
1719   {
1720      case 0x00:
1721      case 0x01:
1722      {
1723         UINT8 res;
1724         if(pce_cd.acard_ctrl[r_num] & 2)
1725            res = pce_cd.acard_ram[(pce_cd.acard_base_addr[r_num] + pce_cd.acard_addr_offset[r_num]) & 0x1fffff];
1726         else
1727            res = pce_cd.acard_ram[pce_cd.acard_base_addr[r_num] & 0x1fffff];
1728
1729         if(pce_cd.acard_ctrl[r_num] & 0x1)
1730         {
1731            if(pce_cd.acard_ctrl[r_num] & 0x10)
1732            {
1733               pce_cd.acard_base_addr[r_num] += pce_cd.acard_addr_inc[r_num];
1734               pce_cd.acard_base_addr[r_num] &= 0xffffff;
1735            }
1736            else
1737            {
1738               pce_cd.acard_addr_offset[r_num] += pce_cd.acard_addr_inc[r_num];
1739            }
1740         }
1741
1742         return res;
1743      }
1744      case 0x02: return (pce_cd.acard_base_addr[r_num] >> 0) & 0xff;
1745      case 0x03: return (pce_cd.acard_base_addr[r_num] >> 8) & 0xff;
1746      case 0x04: return (pce_cd.acard_base_addr[r_num] >> 16) & 0xff;
1747      case 0x05: return (pce_cd.acard_addr_offset[r_num] >> 0) & 0xff;
1748      case 0x06: return (pce_cd.acard_addr_offset[r_num] >> 8) & 0xff;
1749      case 0x07: return (pce_cd.acard_addr_inc[r_num] >> 0) & 0xff;
1750      case 0x08: return (pce_cd.acard_addr_inc[r_num] >> 8) & 0xff;
1751      case 0x09: return pce_cd.acard_ctrl[r_num];
1752      default:   return 0;
1753   }
1754
1755   return 0;
1756}
1757
1758WRITE8_HANDLER( pce_cd_acard_w )
1759{
1760   pce_state *state = space->machine().driver_data<pce_state>();
1761   pce_cd_t &pce_cd = state->m_cd;
1762   UINT8 w_num;
1763
1764   if((offset & 0x2e0) == 0x2e0)
1765   {
1766      switch(offset & 0x0f)
1767      {
1768         case 0: pce_cd.acard_shift = (data & 0xff) | (pce_cd.acard_shift & 0xffffff00); break;
1769         case 1: pce_cd.acard_shift = (data << 8)   | (pce_cd.acard_shift & 0xffff00ff); break;
1770         case 2: pce_cd.acard_shift = (data << 16)  | (pce_cd.acard_shift & 0xff00ffff); break;
1771         case 3: pce_cd.acard_shift = (data << 24)  | (pce_cd.acard_shift & 0x00ffffff); break;
1772         case 4:
1773            {
1774               pce_cd.acard_shift_reg = data & 0x0f;
1775
1776               if(pce_cd.acard_shift_reg != 0)
1777               {
1778                   pce_cd.acard_shift = (pce_cd.acard_shift_reg < 8) ?
1779                                 (pce_cd.acard_shift << pce_cd.acard_shift_reg)
1780                                 : (pce_cd.acard_shift >> (16 - pce_cd.acard_shift_reg));
1781               }
1782            }
1783            break;
1784         case 5: pce_cd.acard_latch = data; break;
1785      }
1786   }
1787   else
1788   {
1789      w_num = (offset & 0x30) >> 4;
1790
1791      switch(offset & 0x0f)
1792      {
1793         case 0x00:
1794         case 0x01:
1795            if(pce_cd.acard_ctrl[w_num] & 2)
1796               pce_cd.acard_ram[(pce_cd.acard_base_addr[w_num] + pce_cd.acard_addr_offset[w_num]) & 0x1fffff] = data;
1797            else
1798               pce_cd.acard_ram[pce_cd.acard_base_addr[w_num] & 0x1FFFFF] = data;
1799
1800            if(pce_cd.acard_ctrl[w_num] & 0x1)
1801            {
1802               if(pce_cd.acard_ctrl[w_num] & 0x10)
1803               {
1804                  pce_cd.acard_base_addr[w_num] += pce_cd.acard_addr_inc[w_num];
1805                  pce_cd.acard_base_addr[w_num] &= 0xffffff;
1806               }
1807               else
1808               {
1809                  pce_cd.acard_addr_offset[w_num] += pce_cd.acard_addr_inc[w_num];
1810               }
1811            }
1812
1813            break;
1814
1815         case 0x02: pce_cd.acard_base_addr[w_num] = (data & 0xff) | (pce_cd.acard_base_addr[w_num] & 0xffff00);   break;
1816         case 0x03: pce_cd.acard_base_addr[w_num] = (data << 8) | (pce_cd.acard_base_addr[w_num] & 0xff00ff);      break;
1817         case 0x04: pce_cd.acard_base_addr[w_num] = (data << 16) | (pce_cd.acard_base_addr[w_num] & 0x00ffff);   break;
1818         case 0x05: pce_cd.acard_addr_offset[w_num] = (data & 0xff) | (pce_cd.acard_addr_offset[w_num] & 0xff00);   break;
1819         case 0x06:
1820            pce_cd.acard_addr_offset[w_num] = (data << 8) | (pce_cd.acard_addr_offset[w_num] & 0x00ff);
1821
1822            if((pce_cd.acard_ctrl[w_num] & 0x60) == 0x40)
1823            {
1824               pce_cd.acard_base_addr[w_num] += pce_cd.acard_addr_offset[w_num] + ((pce_cd.acard_ctrl[w_num] & 0x08) ? 0xff0000 : 0);
1825               pce_cd.acard_base_addr[w_num] &= 0xffffff;
1826            }
1827            break;
1828         case 0x07: pce_cd.acard_addr_inc[w_num] = (data & 0xff) | (pce_cd.acard_addr_inc[w_num] & 0xff00);      break;
1829         case 0x08: pce_cd.acard_addr_inc[w_num] = (data << 8) | (pce_cd.acard_addr_inc[w_num] & 0x00ff);         break;
1830         case 0x09: pce_cd.acard_ctrl[w_num] = data & 0x7f;                                    break;
1831         case 0x0a:
1832            if((pce_cd.acard_ctrl[w_num] & 0x60) == 0x60)
1833            {
1834               pce_cd.acard_base_addr[w_num] += pce_cd.acard_addr_offset[w_num];
1835               pce_cd.acard_base_addr[w_num] &= 0xffffff;
1836            }
1837            break;
1838      }
1839   }
1840}
1841
1842READ8_HANDLER( pce_cd_acard_wram_r )
1843{
1844   return pce_cd_intf_r(space,0x200 | (offset & 0x6000) >> 9);
1845}
1846
1847WRITE8_HANDLER( pce_cd_acard_wram_w )
1848{
1849   pce_cd_intf_w(space,0x200 | (offset & 0x6000) >> 9,data);
1850}
1851
src/mame/machine/atarifdc.c
r11531r11532
1/***************************************************************************
2
3    Atari 400/800
4
5    Floppy Disk Controller code
6
7    Juergen Buchmueller, June 1998
8
9***************************************************************************/
10
11#include <ctype.h>
12
13#include "emu.h"
14#include "cpu/m6502/m6502.h"
15#include "includes/atari.h"
16#include "ataridev.h"
17#include "sound/pokey.h"
18#include "machine/6821pia.h"
19#include "imagedev/flopdrv.h"
20#include "image.h"
21
22#define VERBOSE_SERIAL   0
23#define VERBOSE_CHKSUM   0
24
25typedef struct _atari_drive atari_drive;
26struct _atari_drive
27{
28   UINT8 *image;      /* malloc'd image */
29   int type;         /* type of image (XFD, ATR, DSK) */
30   int mode;         /* 0 read only, != 0 read/write */
31   int density;      /* 0 SD, 1 MD, 2 DD */
32   int header_skip;   /* number of bytes in format header */
33   int tracks;       /* number of tracks (35,40,77,80) */
34   int heads;         /* number of heads (1,2) */
35   int spt;         /* sectors per track (18,26) */
36   int seclen;       /* sector length (128,256) */
37   int bseclen;      /* boot sector length (sectors 1..3) */
38   int sectors;      /* total sectors, ie. tracks x heads x spt */
39};
40
41typedef struct _atari_fdc_t atari_fdc_t;
42struct _atari_fdc_t
43{
44   int  serout_count;
45   int  serout_offs;
46   UINT8 serout_buff[512];
47   UINT8 serout_chksum;
48   int  serout_delay;
49
50   int  serin_count;
51   int  serin_offs;
52   UINT8 serin_buff[512];
53   UINT8 serin_chksum;
54   int  serin_delay;
55
56   atari_drive drv[4];
57};
58
59/*************************************
60 *
61 *  Disk stuff
62 *
63 *************************************/
64
65#define FORMAT_XFD   0
66#define FORMAT_ATR   1
67#define FORMAT_DSK   2
68
69/*****************************************************************************
70    INLINE FUNCTIONS
71*****************************************************************************/
72INLINE atari_fdc_t *get_safe_token(device_t *device)
73{
74   assert(device != NULL);
75   assert(device->type() == ATARI_FDC);
76
77   return (atari_fdc_t *)downcast<legacy_device_base *>(device)->token();
78}
79
80/*****************************************************************************
81 * This is the structure I used in my own Atari 800 emulator some years ago
82 * Though it's a bit overloaded, I used it as it is the maximum of all
83 * supported formats:
84 * XFD no header at all
85 * ATR 16 bytes header
86 * DSK this struct
87 * It is used to determine the format of a XFD image by it's size only
88 *****************************************************************************/
89
90typedef struct _dsk_format dsk_format;
91struct _dsk_format
92{
93   UINT8 density;
94   UINT8 tracks;
95   UINT8 door;
96   UINT8 sta1;
97   UINT8 spt;
98   UINT8 doublesided;
99   UINT8 highdensity;
100   UINT8 seclen_hi;
101   UINT8 seclen_lo;
102   UINT8 status;
103   UINT8 sta2;
104   UINT8 sta3;
105   UINT8 sta4;
106   UINT8 cr;
107   UINT8 info[65+1];
108};
109
110/* combined with the size the image should have */
111typedef struct _xfd_format xfd_format;
112struct _xfd_format
113{
114   int size;
115   dsk_format dsk;
116};
117
118/* here's a table of known xfd formats */
119static const xfd_format xfd_formats[] =
120{
121   {35 * 18 * 1 * 128,             {0,35,1,0,18,0,0,0,128,255,0,0,0,13,"35 SS/SD"}},
122   {35 * 26 * 1 * 128,             {1,35,1,0,26,0,4,0,128,255,0,0,0,13,"35 SS/MD"}},
123   {(35 * 18 * 1 - 3) * 256 + 3 * 128, {2,35,1,0,18,0,4,1,  0,255,0,0,0,13,"35 SS/DD"}},
124   {40 * 18 * 1 * 128,             {0,40,1,0,18,0,0,0,128,255,0,0,0,13,"40 SS/SD"}},
125   {40 * 26 * 1 * 128,             {1,40,1,0,26,0,4,0,128,255,0,0,0,13,"40 SS/MD"}},
126   {(40 * 18 * 1 - 3) * 256 + 3 * 128, {2,40,1,0,18,0,4,1,  0,255,0,0,0,13,"40 SS/DD"}},
127   {40 * 18 * 2 * 128,             {0,40,1,0,18,1,0,0,128,255,0,0,0,13,"40 DS/SD"}},
128   {40 * 26 * 2 * 128,             {1,40,1,0,26,1,4,0,128,255,0,0,0,13,"40 DS/MD"}},
129   {(40 * 18 * 2 - 3) * 256 + 3 * 128, {2,40,1,0,18,1,4,1,  0,255,0,0,0,13,"40 DS/DD"}},
130   {77 * 18 * 1 * 128,             {0,77,1,0,18,0,0,0,128,255,0,0,0,13,"77 SS/SD"}},
131   {77 * 26 * 1 * 128,             {1,77,1,0,26,0,4,0,128,255,0,0,0,13,"77 SS/MD"}},
132   {(77 * 18 * 1 - 3) * 256 + 3 * 128, {2,77,1,0,18,0,4,1,  0,255,0,0,0,13,"77 SS/DD"}},
133   {77 * 18 * 2 * 128,             {0,77,1,0,18,1,0,0,128,255,0,0,0,13,"77 DS/SD"}},
134   {77 * 26 * 2 * 128,             {1,77,1,0,26,1,4,0,128,255,0,0,0,13,"77 DS/MD"}},
135   {(77 * 18 * 2 - 3) * 256 + 3 * 128, {2,77,1,0,18,1,4,1,  0,255,0,0,0,13,"77 DS/DD"}},
136   {80 * 18 * 2 * 128,             {0,80,1,0,18,1,0,0,128,255,0,0,0,13,"80 DS/SD"}},
137   {80 * 26 * 2 * 128,             {1,80,1,0,26,1,4,0,128,255,0,0,0,13,"80 DS/MD"}},
138   {(80 * 18 * 2 - 3) * 256 + 3 * 128, {2,80,1,0,18,1,4,1,  0,255,0,0,0,13,"80 DS/DD"}},
139   {0, {0,}}
140};
141
142/*****************************************************************************
143 *
144 * Open a floppy image for drive 'drive' if it is not yet openend
145 * and a name was given. Determine the image geometry depending on the
146 * type of image and store the results into the global drv[] structure
147 *
148 *****************************************************************************/
149
150#define MAXSIZE 5760 * 256 + 80
151static void atari_load_proc(device_image_interface &image)
152{
153   atari_fdc_t *fdc = get_safe_token(image.device().owner());
154   int id = floppy_get_drive(image);
155   int size, i;
156   const char *ext;
157
158   fdc->drv[id].image = (UINT8*)image.image_malloc(MAXSIZE);
159   if (!fdc->drv[id].image)
160      return;
161
162   /* tell whether the image is writable */
163   fdc->drv[id].mode = !image.is_readonly();
164   /* set up image if it has been created */
165   if (image.has_been_created())
166   {
167      int sector;
168      char buff[256];
169      memset(buff, 0, sizeof(buff));
170      /* default to 720 sectors */
171      for( sector = 0; sector < 720; sector++ )
172         image.fwrite(buff, 256);
173      image.fseek(0, SEEK_SET);
174   }
175
176   size = image.fread(fdc->drv[id].image, MAXSIZE);
177   if( size <= 0 )
178   {
179      fdc->drv[id].image = NULL;
180      return;
181   }
182   /* re allocate the buffer; we don't want to be too lazy ;) */
183    fdc->drv[id].image = (UINT8*)image.image_realloc(fdc->drv[id].image, size);
184
185   ext = image.filetype();
186    /* no extension: assume XFD format (no header) */
187    if (!ext)
188    {
189        fdc->drv[id].type = FORMAT_XFD;
190        fdc->drv[id].header_skip = 0;
191    }
192    else
193    /* XFD extension */
194    if( toupper(ext[0])=='X' && toupper(ext[1])=='F' && toupper(ext[2])=='D' )
195    {
196        fdc->drv[id].type = FORMAT_XFD;
197        fdc->drv[id].header_skip = 0;
198    }
199    else
200    /* ATR extension */
201    if( toupper(ext[0])=='A' && toupper(ext[1])=='T' && toupper(ext[2])=='R' )
202    {
203        fdc->drv[id].type = FORMAT_ATR;
204        fdc->drv[id].header_skip = 16;
205    }
206    else
207    /* DSK extension */
208    if( toupper(ext[0])=='D' && toupper(ext[1])=='S' && toupper(ext[2])=='K' )
209    {
210        fdc->drv[id].type = FORMAT_DSK;
211        fdc->drv[id].header_skip = sizeof(dsk_format);
212    }
213    else
214    {
215      fdc->drv[id].type = FORMAT_XFD;
216        fdc->drv[id].header_skip = 0;
217    }
218
219   if( fdc->drv[id].type == FORMAT_ATR &&
220      (fdc->drv[id].image[0] != 0x96 || fdc->drv[id].image[1] != 0x02) )
221   {
222      fdc->drv[id].type = FORMAT_XFD;
223      fdc->drv[id].header_skip = 0;
224   }
225
226   switch (fdc->drv[id].type)
227   {
228   /* XFD or unknown format: find a matching size from the table */
229   case FORMAT_XFD:
230      for( i = 0; xfd_formats[i].size; i++ )
231      {
232         if( size == xfd_formats[i].size )
233         {
234            fdc->drv[id].density = xfd_formats[i].dsk.density;
235            fdc->drv[id].tracks = xfd_formats[i].dsk.tracks;
236            fdc->drv[id].spt = xfd_formats[i].dsk.spt;
237            fdc->drv[id].heads = (xfd_formats[i].dsk.doublesided) ? 2 : 1;
238            fdc->drv[id].bseclen = 128;
239            fdc->drv[id].seclen = 256 * xfd_formats[i].dsk.seclen_hi + xfd_formats[i].dsk.seclen_lo;
240            fdc->drv[id].sectors = fdc->drv[id].tracks * fdc->drv[id].heads * fdc->drv[id].spt;
241            break;
242         }
243      }
244      break;
245   /* ATR format: find a size including the 16 bytes header */
246   case FORMAT_ATR:
247      {
248         int s;
249
250         fdc->drv[id].bseclen = 128;
251         /* get sectors from ATR header */
252         s = (size - 16) / 128;
253         /* 3 + odd number of sectors ? */
254         if ( fdc->drv[id].image[4] == 128 || (s % 18) == 0 || (s % 26) == 0 || ((s - 3) % 1) != 0 )
255         {
256            fdc->drv[id].sectors = s;
257            fdc->drv[id].seclen = 128;
258            /* sector size 128 or count not evenly dividable by 26 ? */
259            if( fdc->drv[id].seclen == 128 || (s % 26) != 0 )
260            {
261               /* yup! single density */
262               fdc->drv[id].density = 0;
263               fdc->drv[id].spt = 18;
264               fdc->drv[id].heads = 1;
265               fdc->drv[id].tracks = s / 18;
266               if( s % 18 != 0 )
267                  fdc->drv[id].tracks += 1;
268               if( fdc->drv[id].tracks % 2 == 0 && fdc->drv[id].tracks > 80 )
269               {
270                  fdc->drv[id].heads = 2;
271                  fdc->drv[id].tracks /= 2;
272               }
273            }
274            else
275            {
276               /* yes: medium density */
277               fdc->drv[id].density = 0;
278               fdc->drv[id].spt = 26;
279               fdc->drv[id].heads = 1;
280               fdc->drv[id].tracks = s / 26;
281               if( s % 26 != 0 )
282                  fdc->drv[id].tracks += 1;
283               if( fdc->drv[id].tracks % 2 == 0 && fdc->drv[id].tracks > 80 )
284               {
285                  fdc->drv[id].heads = 2;
286                  fdc->drv[id].tracks /= 2;
287               }
288            }
289         }
290         else
291         {
292            /* it's double density */
293            s = (s - 3) / 2 + 3;
294            fdc->drv[id].sectors = s;
295            fdc->drv[id].density = 2;
296            fdc->drv[id].seclen = 256;
297            fdc->drv[id].spt = 18;
298            fdc->drv[id].heads = 1;
299            fdc->drv[id].tracks = s / 18;
300            if( s % 18 != 0 )
301               fdc->drv[id].tracks += 1;
302            if( fdc->drv[id].tracks % 2 == 0 && fdc->drv[id].tracks > 80 )
303            {
304               fdc->drv[id].heads = 2;
305               fdc->drv[id].tracks /= 2;
306            }
307         }
308      }
309      break;
310   /* DSK format: it's all in the header */
311   case FORMAT_DSK:
312      {
313         dsk_format *dsk = (dsk_format *) fdc->drv[id].image;
314
315         fdc->drv[id].tracks = dsk->tracks;
316         fdc->drv[id].spt = dsk->spt;
317         fdc->drv[id].heads = (dsk->doublesided) ? 2 : 1;
318         fdc->drv[id].seclen = 256 * dsk->seclen_hi + dsk->seclen_lo;
319         fdc->drv[id].bseclen = fdc->drv[id].seclen;
320         fdc->drv[id].sectors = fdc->drv[id].tracks * fdc->drv[id].heads * fdc->drv[id].spt;
321      }
322      break;
323   }
324   logerror("atari opened floppy '%s', %d sectors (%d %s%s) %d bytes/sector\n",
325         image.filename(),
326         fdc->drv[id].sectors,
327         fdc->drv[id].tracks,
328         (fdc->drv[id].heads == 1) ? "SS" : "DS",
329         (fdc->drv[id].density == 0) ? "SD" : (fdc->drv[id].density == 1) ? "MD" : "DD",
330         fdc->drv[id].seclen);
331   return;
332}
333
334
335
336/*****************************************************************************
337 *
338 * This is a description of the data flow between Atari (A) and the
339 * Floppy (F) for the supported commands.
340 *
341 * A->F     DEV  CMD  AUX1 AUX2 CKS
342 *          '1'  'S'  00   00                 get status
343 * F->A     ACK  CPL  04   FF   E0   00   CKS
344 *                     ^    ^
345 *                     |    |
346 *                     |    bit 7 : door closed
347 *                     |
348 *                     bit7  : MD 128 bytes/sector, 26 sectors/track
349 *                     bit5  : DD 256 bytes/sector, 18 sectors/track
350 *                     else  : SD 128 bytes/sector, 18 sectors/track
351 *
352 * A->F     DEV  CMD  AUX1 AUX2 CKS
353 *          '1'  'R'  SECL SECH               read sector
354 * F->A     ACK                               command acknowledge
355 *               ***                          now read the sector
356 * F->A              CPL                      complete: sector read
357 * F->A                  128/256 byte CKS
358 *
359 * A->F     DEV  CMD  AUX1 AUX2 CKS
360 *          '1'  'W'  SECL SECH               write with verify
361 * F->A     ACK                               command acknowledge
362 * A->F          128/256 data CKS
363 * F->A                            CPL        complete: CKS okay
364 *          execute writing the sector
365 * F->A                                 CPL   complete: sector written
366 *
367 * A->F     DEV  CMD  AUX1 AUX2 CKS
368 *          '1'  'P'  SECL SECH               put sector
369 * F->A     ACK                               command acknowledge
370 * A->F          128/256 data CKS
371 * F->A                            CPL        complete: CKS okay
372 *          execute writing the sector
373 * F->A                                 CPL   complete: sector written
374 *
375 * A->F     DEV  CMD  AUX1 AUX2 CKS
376 *           '1' '!'  xx   xx                 single density format
377 * F->A     ACK                               command acknowledge
378 *          execute formatting
379 * F->A               CPL                     complete: format
380 * F->A                    128/256 byte CKS   bad sector table
381 *
382 *
383 * A->F     DEV  CMD  AUX1 AUX2 CKS
384 *          '1'  '"'  xx   xx                 double density format
385 * F->A     ACK                               command acknowledge
386 *          execute formatting
387 * F->A               CPL                     complete: format
388 * F->A                    128/256 byte CKS   bad sector table
389 *
390 *****************************************************************************/
391static void make_chksum(UINT8 * chksum, UINT8 data)
392{
393   UINT8 newone;
394   newone= *chksum + data;
395   if (newone < *chksum)
396      newone++;
397
398   if (VERBOSE_CHKSUM)
399      logerror("atari chksum old $%02x + data $%02x -> new $%02x\n", *chksum, data, newone);
400
401   *chksum = newone;
402}
403
404static void clr_serout(device_t *device,int expect_data)
405{
406   atari_fdc_t *fdc = get_safe_token(device);
407
408   fdc->serout_chksum = 0;
409   fdc->serout_offs = 0;
410   fdc->serout_count = expect_data + 1;
411}
412
413static void add_serout(device_t *device,int expect_data)
414{
415   atari_fdc_t *fdc = get_safe_token(device);
416
417   fdc->serout_chksum = 0;
418   fdc->serout_count = expect_data + 1;
419}
420
421static void clr_serin(device_t *device, int ser_delay)
422{
423   atari_fdc_t *fdc = get_safe_token(device);
424   device_t *pokey = device->machine().device("pokey");
425   fdc->serin_chksum = 0;
426   fdc->serin_offs = 0;
427   fdc->serin_count = 0;
428   pokey_serin_ready(pokey, ser_delay * 40);
429}
430
431static void add_serin(device_t *device,UINT8 data, int with_checksum)
432{
433   atari_fdc_t *fdc = get_safe_token(device);
434   fdc->serin_buff[fdc->serin_count++] = data;
435   if (with_checksum)
436      make_chksum(&fdc->serin_chksum, data);
437}
438
439static void ATTR_PRINTF(2,3) atari_set_frame_message(device_t *device,const char *fmt, ...)
440{
441   va_list arg;
442   va_start(arg, fmt);
443
444   vsprintf(atari_frame_message, fmt, arg);
445   atari_frame_counter = 30; /* FIXME */
446
447   va_end(arg);
448}
449
450static void a800_serial_command(device_t *device)
451{
452   int i, drive, sector, offset;
453   atari_fdc_t *fdc = get_safe_token(device);
454
455   if( !fdc->serout_offs )
456   {
457      if (VERBOSE_SERIAL)
458         logerror("atari serout command offset = 0\n");
459      return;
460   }
461   clr_serin(device, 10);
462
463   if (VERBOSE_SERIAL)
464   {
465      logerror("atari serout command %d: %02X %02X %02X %02X %02X : %02X ",
466         fdc->serout_offs,
467         fdc->serout_buff[0], fdc->serout_buff[1], fdc->serout_buff[2],
468         fdc->serout_buff[3], fdc->serout_buff[4], fdc->serout_chksum);
469   }
470
471   if (fdc->serout_chksum == 0)
472   {
473      if (VERBOSE_SERIAL)
474         logerror("OK\n");
475
476      drive = fdc->serout_buff[0] - '1';   /* drive # */
477      /* sector # */
478      if (drive < 0 || drive > 3)          /* ignore unknown drives */
479      {
480         logerror("atari unsupported drive #%d\n", drive+1);
481         atari_set_frame_message(device, "DRIVE #%d not supported", drive+1);
482         return;
483      }
484
485      /* extract sector number from the command buffer */
486      sector = fdc->serout_buff[2] + 256 * fdc->serout_buff[3];
487
488      switch (fdc->serout_buff[1]) /* command ? */
489      {
490         case 'S':   /* status */
491            atari_set_frame_message(device, "DRIVE #%d STATUS", drive+1);
492
493            if (VERBOSE_SERIAL)
494               logerror("atari status\n");
495
496            add_serin(device,'A',0);
497            add_serin(device,'C',0);
498            if (!fdc->drv[drive].mode) /* read only mode ? */
499            {
500               if (fdc->drv[drive].spt == 26)
501                  add_serin(device,0x80,1);   /* MD: 0x80 */
502               else
503               if (fdc->drv[drive].seclen == 128)
504                  add_serin(device,0x00,1);   /* SD: 0x00 */
505               else
506                  add_serin(device,0x20,1);   /* DD: 0x20 */
507            }
508            else
509            {
510               if (fdc->drv[drive].spt == 26)
511                  add_serin(device,0x84,1);   /* MD: 0x84 */
512               else
513               if (fdc->drv[drive].seclen == 128)
514                  add_serin(device,0x04,1);   /* SD: 0x04 */
515               else
516                  add_serin(device,0x24,1);   /* DD: 0x24 */
517            }
518            if (fdc->drv[drive].image)
519               add_serin(device,0xff,1);   /* door closed: 0xff */
520            else
521               add_serin(device,0x7f,1);   /* door open: 0x7f */
522            add_serin(device,0xe0,1);   /* dunno */
523            add_serin(device,0x00,1);   /* dunno */
524            add_serin(device,fdc->serin_chksum,0);
525            break;
526
527         case 'R':   /* read sector */
528            if (VERBOSE_SERIAL)
529               logerror("atari read sector #%d\n", sector);
530
531            if( sector < 1 || sector > fdc->drv[drive].sectors )
532            {
533               atari_set_frame_message(device, "DRIVE #%d READ SECTOR #%3d - ERR", drive+1, sector);
534
535               if (VERBOSE_SERIAL)
536                  logerror("atari bad sector #\n");
537
538               add_serin(device,'E',0);
539               break;
540            }
541            add_serin(device,'A',0);   /* acknowledge */
542            add_serin(device,'C',0);   /* completed */
543            if (sector < 4)    /* sector 1 .. 3 might be different length */
544            {
545               atari_set_frame_message(device, "DRIVE #%d READ SECTOR #%3d - SD", drive+1, sector);
546               offset = (sector - 1) * fdc->drv[drive].bseclen + fdc->drv[drive].header_skip;
547               for (i = 0; i < 128; i++)
548                  add_serin(device,fdc->drv[drive].image[offset++],1);
549            }
550            else
551            {
552               atari_set_frame_message(device, "DRIVE #%d READ SECTOR #%3d - %cD", drive+1, sector, (fdc->drv[drive].seclen == 128) ? 'S' : 'D');
553                    offset = (sector - 1) * fdc->drv[drive].seclen + fdc->drv[drive].header_skip;
554               for (i = 0; i < fdc->drv[drive].seclen; i++)
555                  add_serin(device,fdc->drv[drive].image[offset++],1);
556            }
557            add_serin(device,fdc->serin_chksum,0);
558            break;
559
560         case 'W':   /* write sector with verify */
561            if (VERBOSE_SERIAL)
562               logerror("atari write sector #%d\n", sector);
563
564            add_serin(device,'A',0);
565            if (sector < 4)    /* sector 1 .. 3 might be different length */
566            {
567               add_serout(device,fdc->drv[drive].bseclen);
568               atari_set_frame_message(device, "DRIVE #%d WRITE SECTOR #%3d - SD", drive+1, sector);
569                }
570            else
571            {
572               add_serout(device,fdc->drv[drive].seclen);
573               atari_set_frame_message(device, "DRIVE #%d WRITE SECTOR #%3d - %cD", drive+1, sector, (fdc->drv[drive].seclen == 128) ? 'S' : 'D');
574                }
575            break;
576
577         case 'P':   /* put sector (no verify) */
578            if (VERBOSE_SERIAL)
579               logerror("atari put sector #%d\n", sector);
580
581            add_serin(device,'A',0);
582            if (sector < 4)    /* sector 1 .. 3 might be different length */
583            {
584               add_serout(device,fdc->drv[drive].bseclen);
585               atari_set_frame_message(device, "DRIVE #%d PUT SECTOR #%3d - SD", drive+1, sector);
586                }
587            else
588            {
589               add_serout(device,fdc->drv[drive].seclen);
590               atari_set_frame_message(device, "DRIVE #%d PUT SECTOR #%3d - %cD", drive+1, sector, (fdc->drv[drive].seclen == 128) ? 'S' : 'D');
591                }
592            break;
593
594         case '!':   /* SD format */
595            if (VERBOSE_SERIAL)
596               logerror("atari format SD drive #%d\n", drive+1);
597
598            atari_set_frame_message(device, "DRIVE #%d FORMAT SD", drive+1);
599                add_serin(device,'A',0);   /* acknowledge */
600            add_serin(device,'C',0);   /* completed */
601            for (i = 0; i < 128; i++)
602               add_serin(device,0,1);
603            add_serin(device,fdc->serin_chksum,0);
604            break;
605
606         case '"':   /* DD format */
607            if (VERBOSE_SERIAL)
608               logerror("atari format DD drive #%d\n", drive+1);
609
610            atari_set_frame_message(device, "DRIVE #%d FORMAT DD", drive+1);
611                add_serin(device,'A',0);   /* acknowledge */
612            add_serin(device,'C',0);   /* completed */
613            for (i = 0; i < 256; i++)
614               add_serin(device,0,1);
615            add_serin(device,fdc->serin_chksum,0);
616            break;
617
618         default:
619            if (VERBOSE_SERIAL)
620               logerror("atari unknown command #%c\n", fdc->serout_buff[1]);
621
622            atari_set_frame_message(device, "DRIVE #%d UNKNOWN CMD '%c'", drive+1, fdc->serout_buff[1]);
623                add_serin(device,'N',0);   /* negative acknowledge */
624      }
625   }
626   else
627   {
628      atari_set_frame_message(device, "serial cmd chksum error");
629      if (VERBOSE_SERIAL)
630         logerror("BAD\n");
631
632      add_serin(device,'E',0);
633   }
634   if (VERBOSE_SERIAL)
635      logerror("atari %d bytes to read\n", fdc->serin_count);
636}
637
638static void a800_serial_write(device_t *device)
639{
640   int i, drive, sector, offset;
641   atari_fdc_t *fdc = get_safe_token(device);
642
643   if (VERBOSE_SERIAL)
644   {
645      logerror("atari serout %d bytes written : %02X ",
646         fdc->serout_offs, fdc->serout_chksum);
647   }
648
649   clr_serin(device, 80);
650   if (fdc->serout_chksum == 0)
651   {
652      if (VERBOSE_SERIAL)
653         logerror("OK\n");
654
655      add_serin(device,'C',0);
656      /* write the sector */
657      drive = fdc->serout_buff[0] - '1';   /* drive # */
658      /* not write protected and image available ? */
659      if (fdc->drv[drive].mode && fdc->drv[drive].image)
660      {
661         /* extract sector number from the command buffer */
662         sector = fdc->serout_buff[2] + 256 * fdc->serout_buff[3];
663         if (sector < 4)    /* sector 1 .. 3 might be different length */
664         {
665            offset = (sector - 1) * fdc->drv[drive].bseclen + fdc->drv[drive].header_skip;
666
667            if (VERBOSE_SERIAL)
668               logerror("atari storing 128 byte sector %d at offset 0x%08X", sector, offset );
669
670            for (i = 0; i < 128; i++)
671               fdc->drv[drive].image[offset++] = fdc->serout_buff[5+i];
672            atari_set_frame_message(device, "DRIVE #%d WROTE SECTOR #%3d - SD", drive+1, sector);
673            }
674         else
675         {
676            offset = (sector - 1) * fdc->drv[drive].seclen + fdc->drv[drive].header_skip;
677
678            if (VERBOSE_SERIAL)
679               logerror("atari storing %d byte sector %d at offset 0x%08X", fdc->drv[drive].seclen, sector, offset );
680
681            for (i = 0; i < fdc->drv[drive].seclen; i++)
682               fdc->drv[drive].image[offset++] = fdc->serout_buff[5+i];
683            atari_set_frame_message(device, "DRIVE #%d WROTE SECTOR #%3d - %cD", drive+1, sector, (fdc->drv[drive].seclen == 128) ? 'S' : 'D');
684            }
685         add_serin(device,'C',0);
686      }
687      else
688      {
689         add_serin(device,'E',0);
690      }
691   }
692   else
693   {
694      if (VERBOSE_SERIAL)
695         logerror("BAD\n");
696
697      add_serin(device,'E',0);
698   }
699}
700
701READ8_DEVICE_HANDLER ( atari_serin_r )
702{
703   int data = 0x00;
704   int ser_delay = 0;
705   atari_fdc_t *fdc = get_safe_token(device);
706
707   if (fdc->serin_count)
708   {
709      device_t *pokey = device->machine().device("pokey");
710
711      data = fdc->serin_buff[fdc->serin_offs];
712      ser_delay = 2 * 40;
713      if (fdc->serin_offs < 3)
714      {
715         ser_delay = 4 * 40;
716         if (fdc->serin_offs < 2)
717            ser_delay = 200 * 40;
718      }
719      fdc->serin_offs++;
720      if (--fdc->serin_count == 0)
721         fdc->serin_offs = 0;
722      else
723         pokey_serin_ready(pokey, ser_delay);
724   }
725
726   if (VERBOSE_SERIAL)
727      logerror("atari serin[$%04x] -> $%02x; delay %d\n", fdc->serin_offs, data, ser_delay);
728
729   return data;
730}
731
732WRITE8_DEVICE_HANDLER ( atari_serout_w )
733{
734   pia6821_device *pia = device->machine().device<pia6821_device>( "pia" );
735   atari_fdc_t *fdc = get_safe_token(device);
736
737   /* ignore serial commands if no floppy image is specified */
738   if( !fdc->drv[0].image )
739      return;
740   if (fdc->serout_count)
741   {
742      /* store data */
743      fdc->serout_buff[fdc->serout_offs] = data;
744
745      if (VERBOSE_SERIAL)
746         logerror("atari serout[$%04x] <- $%02x; count %d\n", fdc->serout_offs, data, fdc->serout_count);
747
748      fdc->serout_offs++;
749      if (--fdc->serout_count == 0)
750      {
751         /* exclusive or written checksum with calculated */
752         fdc->serout_chksum ^= data;
753         /* if the attention line is high, this should be data */
754         if (pia->irq_b_state())
755            a800_serial_write(device);
756      }
757      else
758      {
759         make_chksum(&fdc->serout_chksum, data);
760      }
761   }
762}
763
764WRITE_LINE_DEVICE_HANDLER(atarifdc_pia_cb2_w)
765{
766   atari_fdc_t *fdc = get_safe_token(device);
767   if (!state)
768   {
769      clr_serout(device,4); /* expect 4 command bytes + checksum */
770   }
771   else
772   {
773      fdc->serin_delay = 0;
774      a800_serial_command(device);
775   }
776}
777
778static FLOPPY_IDENTIFY( atari_dsk_identify )
779{
780   *vote = 100;
781   return FLOPPY_ERROR_SUCCESS;
782}
783
784
785static FLOPPY_CONSTRUCT( atari_dsk_construct )
786{
787   return FLOPPY_ERROR_SUCCESS;
788}
789
790FLOPPY_OPTIONS_START( atari_only )
791   FLOPPY_OPTION(
792      atari_dsk,
793      "atr,dsk,xfd",
794      "Atari floppy disk image",
795      atari_dsk_identify,
796      atari_dsk_construct,
797      NULL,
798      NULL
799   )
800FLOPPY_OPTIONS_END0
801
802static const floppy_config atari_floppy_config =
803{
804   DEVCB_NULL,
805   DEVCB_NULL,
806   DEVCB_NULL,
807   DEVCB_NULL,
808   DEVCB_NULL,
809   FLOPPY_STANDARD_5_25_DSHD,
810   FLOPPY_OPTIONS_NAME(atari_only),
811   NULL
812};
813
814static MACHINE_CONFIG_FRAGMENT( atari_fdc )
815   MCFG_FLOPPY_4_DRIVES_ADD(atari_floppy_config)
816MACHINE_CONFIG_END
817
818device_t *atari_floppy_get_device_child(device_t *device,int drive)
819{
820   switch(drive) {
821      case 0 : return device->subdevice(FLOPPY_0);
822      case 1 : return device->subdevice(FLOPPY_1);
823      case 2 : return device->subdevice(FLOPPY_2);
824      case 3 : return device->subdevice(FLOPPY_3);
825   }
826   return NULL;
827}
828
829static DEVICE_START(atari_fdc)
830{
831   int id;
832   for(id=0;id<4;id++)
833   {
834      floppy_install_load_proc(atari_floppy_get_device_child(device, id), atari_load_proc);
835   }
836}
837
838static DEVICE_RESET(atari_fdc)
839{
840}
841
842DEVICE_GET_INFO( atari_fdc )
843{
844   switch (state)
845   {
846      /* --- the following bits of info are returned as 64-bit signed integers --- */
847      case DEVINFO_INT_INLINE_CONFIG_BYTES:         info->i = 0;                                    break;
848      case DEVINFO_INT_TOKEN_BYTES:               info->i = sizeof(atari_fdc_t);                        break;
849
850      /* --- the following bits of info are returned as pointers --- */
851      case DEVINFO_PTR_MACHINE_CONFIG:            info->machine_config = MACHINE_CONFIG_NAME(atari_fdc);      break;
852
853      /* --- the following bits of info are returned as pointers to data or functions --- */
854      case DEVINFO_FCT_START:                     info->start = DEVICE_START_NAME(atari_fdc);               break;
855      case DEVINFO_FCT_STOP:                     /* Nothing */                                    break;
856      case DEVINFO_FCT_RESET:                     info->reset = DEVICE_RESET_NAME(atari_fdc);               break;
857
858      /* --- the following bits of info are returned as NULL-terminated strings --- */
859      case DEVINFO_STR_NAME:                     strcpy(info->s, "Atari FDC");                        break;
860      case DEVINFO_STR_FAMILY:                  strcpy(info->s, "Atari FDC");                        break;
861      case DEVINFO_STR_VERSION:                  strcpy(info->s, "1.0");                              break;
862      case DEVINFO_STR_SOURCE_FILE:               strcpy(info->s, __FILE__);                           break;
863      case DEVINFO_STR_CREDITS:                  strcpy(info->s, "Copyright the MESS Team");             break;
864   }
865}
866
867DEFINE_LEGACY_DEVICE(ATARI_FDC, atari_fdc);
src/mame/includes/nes.h
r11531r11532
1/*****************************************************************************
2 *
3 * includes/nes.h
4 *
5 * Nintendo Entertainment System (Famicom)
6 *
7 ****************************************************************************/
8
9#ifndef NES_H_
10#define NES_H_
11
12
13/***************************************************************************
14    CONSTANTS
15***************************************************************************/
16
17#define NTSC_CLOCK           N2A03_DEFAULTCLOCK     /* 1.789772 MHz */
18#define PAL_CLOCK              (26601712.0/16)        /* 1.662607 MHz */
19
20#define NES_BATTERY_SIZE 0x2000
21
22
23/***************************************************************************
24    TYPE DEFINITIONS
25***************************************************************************/
26
27struct nes_input
28{
29   UINT32 shift;
30   UINT32 i0, i1, i2;
31};
32
33/*PPU fast banking constants and structures */
34
35#define CHRROM 0
36#define CHRRAM 1
37
38typedef struct
39{
40   int source;   //defines source of base pointer
41   int origin; //defines offset of 0x400 byte segment at base pointer
42   UINT8* access;   //source translated + origin -> valid pointer!
43} chr_bank;
44
45/*PPU nametable fast banking constants and structures */
46
47#define CIRAM 0
48#define ROM 1
49#define EXRAM 2
50#define MMC5FILL 3
51#define CART_NTRAM 4
52
53#define NES_BATTERY 0
54#define NES_WRAM 1
55
56typedef struct
57{
58   int source;      /* defines source of base pointer */
59   int origin;      /* defines offset of 0x400 byte segment at base pointer */
60   int writable;   /* ExRAM, at least, can be write-protected AND used as nametable */
61   UINT8* access;   /* direct access when possible */
62} name_table;
63
64typedef void (*nes_prg_callback)(running_machine &machine, int start, int bank);
65typedef void (*nes_chr_callback)(running_machine &machine, int start, int bank, int source);
66
67class nes_state : public driver_device
68{
69public:
70   nes_state(const machine_config &mconfig, device_type type, const char *tag)
71      : driver_device(mconfig, type, tag) { }
72
73   /* input_related - this part has to be cleaned up (e.g. in_2 and in_3 are not really necessary here...) */
74   nes_input m_in_0, m_in_1, m_in_2, m_in_3;
75   UINT8 m_fck_scan, m_fck_mode;
76
77   int           m_prg_bank[5];
78   chr_bank      m_chr_map[8];  //quick banking structure, because some of this changes multiple times per scanline!
79   name_table    m_nt_page[4];  //quick banking structure for a maximum of 4K of RAM/ROM/ExRAM
80
81   int m_chr_open_bus;
82   int m_prgram_bank5_start, m_battery_bank5_start, m_empty_bank5_start;
83
84   UINT8 m_ce_mask, m_ce_state;
85   UINT8 m_vrc_ls_prg_a, m_vrc_ls_prg_b, m_vrc_ls_chr;
86
87   int m_MMC5_floodtile;
88   int m_MMC5_floodattr;
89   int m_mmc5_vram_control;
90   UINT8 m_mmc5_high_chr;
91   UINT8 m_mmc5_split_scr;
92   UINT8 *m_extended_ntram;
93
94   UINT8 m_mmc5_last_chr_a;
95   UINT16 m_mmc5_vrom_regA[8];
96   UINT16 m_mmc5_vrom_regB[4];
97   UINT8 m_mmc5_prg_regs[4];
98   UINT8 m_mmc5_bank_security;
99   UINT8 m_mmc5_prg_mode;
100   UINT8 m_mmc5_chr_mode;
101   UINT8 m_mmc5_chr_high;
102   UINT8 m_mmc5_split_ctrl;
103   UINT8 m_mmc5_split_yst;
104   UINT8 m_mmc5_split_bank;
105
106   /* video-related */
107   int m_nes_vram_sprite[8]; /* Used only by mmc5 for now */
108   int m_last_frame_flip;
109
110   /* misc */
111   write8_space_func   m_mmc_write_low;
112   const char        *m_mmc_write_low_name;
113   write8_space_func   m_mmc_write_mid;
114   const char        *m_mmc_write_mid_name;
115   write8_space_func   m_mmc_write;
116   const char        *m_mmc_write_name;
117   read8_space_func    m_mmc_read_low;
118   const char        *m_mmc_read_low_name;
119   read8_space_func    m_mmc_read_mid;
120   const char        *m_mmc_read_mid_name;
121   read8_space_func    m_mmc_read;
122   const char        *m_mmc_read_name;
123   emu_timer           *m_irq_timer;
124
125   nes_prg_callback    m_mmc3_prg_cb;   // these are used to simplify a lot emulation of some MMC3 pirate clones
126   nes_chr_callback    m_mmc3_chr_cb;
127
128   /* devices */
129   device_t      *m_maincpu;
130   device_t      *m_ppu;
131   device_t      *m_sound;
132   device_t      *m_cart;
133
134   /* misc region to be allocated at init */
135   // variables which don't change at run-time
136   UINT8      *m_rom;
137   UINT8      *m_vrom;
138   UINT8      *m_vram;
139   UINT8      *m_wram;
140   UINT8      *m_ciram; //PPU nametable RAM - external to PPU!
141   UINT8      *m_battery_ram;
142   UINT8      *m_mapper_ram;
143   UINT8      *m_mapper_bram;
144
145   /***** Mapper-related variables *****/
146
147   // common ones
148   int        m_IRQ_enable, m_IRQ_enable_latch;
149   UINT16     m_IRQ_count, m_IRQ_count_latch;
150   UINT8      m_IRQ_toggle;
151   UINT8      m_IRQ_reset;
152   UINT8      m_IRQ_status;
153   UINT8      m_IRQ_mode;
154   UINT8      m_IRQ_clear;
155   int        m_mult1, m_mult2;
156
157   UINT8 m_mmc_chr_source;         // This is set at init to CHRROM or CHRRAM. a few mappers can swap between
158                           // the two (this is done in the specific handlers).
159
160   UINT8 m_mmc_cmd1, m_mmc_cmd2;      // These represent registers where the mapper writes important values
161   UINT8 m_mmc_count;            // This is used as counter in mappers like 1 and 45
162
163   int m_mmc_prg_base, m_mmc_prg_mask;   // MMC3 based multigame carts select a block of banks by using these (and then act like normal MMC3),
164   int m_mmc_chr_base, m_mmc_chr_mask;   // while MMC3 and clones (mapper 118 & 119) simply set them as 0 and 0xff resp.
165
166   UINT8 m_mmc_prg_bank[6];            // Many mappers writes only some bits of the selected bank (for both PRG and CHR),
167   UINT8 m_mmc_vrom_bank[16];         // hence these are handy to latch bank values.
168
169   UINT16 m_MMC5_vrom_bank[12];         // MMC5 has 10bit wide VROM regs!
170   UINT8 m_mmc_extra_bank[16];         // some MMC3 clone have 2 series of PRG/CHR banks...
171                              // we collect them all here: first 4 elements PRG banks, then 6/8 CHR banks
172
173   UINT8 m_mmc_latch1, m_mmc_latch2;
174   UINT8 m_mmc_reg[16];
175
176   UINT8 m_mmc_dipsetting;
177
178   // misc mapper related variables which should be merged with the above one, where possible
179   int m_mmc1_reg_write_enable;
180   int m_mmc1_latch;
181   int m_mmc1_count;
182
183   int m_mmc3_latch;
184   int m_mmc3_wram_protect;
185   int m_mmc3_alt_irq;
186
187   int m_MMC5_rom_bank_mode;
188   int m_MMC5_vrom_bank_mode;
189   int m_MMC5_vram_protect;
190   int m_MMC5_scanline;
191   int m_vrom_page_a;
192   int m_vrom_page_b;
193   // int vrom_next[4];
194
195   UINT8 m_mmc6_reg;
196
197   // these might be unified in single mmc_reg[] array, together with state->m_mmc_cmd1 & state->m_mmc_cmd2
198   // but be careful that MMC3 clones often use state->m_mmc_cmd1/state->m_mmc_cmd2 (from base MMC3) AND additional regs below!
199   UINT8 m_mapper83_reg[10];
200   UINT8 m_mapper83_low_reg[4];
201   UINT8 m_txc_reg[4];   // used by mappers 132, 172 & 173
202   UINT8 m_subor_reg[4];   // used by mappers 166 & 167
203   UINT8 m_sachen_reg[8];   // used by mappers 137, 138, 139 & 141
204   UINT8 m_map52_reg_written;
205   UINT8 m_map114_reg, m_map114_reg_enabled;
206
207   /***** NES-cart related *****/
208
209   /* load-time cart variables which remain constant */
210   UINT16 m_prg_chunks;      // iNES 2.0 allows for more chunks (a recently dumped multigame cart has 256 chunks of both PRG & CHR!)
211   UINT16 m_chr_chunks;
212   UINT16 m_vram_chunks;
213   UINT8 m_trainer;
214   UINT8 m_battery;         // if there is PRG RAM with battery backup
215   UINT32 m_battery_size;
216   UINT8 m_prg_ram;         // if there is PRG RAM with no backup
217   UINT32 m_wram_size;
218   UINT32 m_mapper_ram_size;
219   UINT32 m_mapper_bram_size;
220
221   /* system variables which don't change at run-time */
222   UINT16 m_mapper;      // for iNES
223   UINT16 m_pcb_id;      // for UNIF & xml
224   UINT8 m_four_screen_vram;
225   UINT8 m_hard_mirroring;
226   UINT8 m_crc_hack;   // this is needed to detect different boards sharing the same Mappers (shame on .nes format)
227   UINT8 m_ines20;
228
229   /***** FDS-floppy related *****/
230
231   int     m_disk_expansion;
232
233   UINT8   m_fds_sides;
234   UINT8   *m_fds_data;   // here, we store a copy of the disk
235   UINT8   *m_fds_ram;   // here, we emulate the RAM adapter
236
237   /* Variables which can change */
238   UINT8   m_fds_motor_on;
239   UINT8   m_fds_door_closed;
240   UINT8   m_fds_current_side;
241   UINT32  m_fds_head_position;
242   UINT8   m_fds_status0;
243   UINT8   m_fds_read_mode;
244   UINT8   m_fds_write_reg;
245
246   /* these are used in the mapper 20 handlers */
247   int     m_fds_last_side;
248   int     m_fds_count;
249};
250
251
252/*----------- defined in machine/nes.c -----------*/
253
254WRITE8_HANDLER ( nes_IN0_w );
255WRITE8_HANDLER ( nes_IN1_w );
256
257/* protos */
258
259DEVICE_IMAGE_LOAD(nes_cart);
260DEVICE_START(nes_disk);
261DEVICE_IMAGE_LOAD(nes_disk);
262DEVICE_IMAGE_UNLOAD(nes_disk);
263
264MACHINE_START( nes );
265MACHINE_RESET( nes );
266
267DRIVER_INIT( famicom );
268
269READ8_HANDLER( nes_IN0_r );
270READ8_HANDLER( nes_IN1_r );
271
272int nes_ppu_vidaccess( device_t *device, int address, int data );
273
274void nes_partialhash(hash_collection &dest, const unsigned char *data, unsigned long length, const char *functions);
275
276/*----------- defined in video/nes.c -----------*/
277
278PALETTE_INIT( nes );
279VIDEO_START( nes );
280SCREEN_UPDATE( nes );
281
282
283#endif /* NES_H_ */
src/mame/includes/pce.h
r11531r11532
1/*****************************************************************************
2 *
3 * includes/pce.h
4 *
5 * NEC PC Engine/TurboGrafx16
6 *
7 ****************************************************************************/
8
9#ifndef PCE_H_
10#define PCE_H_
11
12#include "cdrom.h"
13#include "sound/msm5205.h"
14
15#define C6280_TAG         "c6280"
16
17#define   MAIN_CLOCK      21477270
18#define PCE_CD_CLOCK   9216000
19
20#define PCE_HEADER_SIZE      512
21
22#define TG_16_JOY_SIG      0x00
23#define PCE_JOY_SIG         0x40
24#define NO_CD_SIG         0x80
25#define CD_SIG            0x00
26/* these might be used to indicate something, but they always seem to return 1 */
27#define CONST_SIG         0x30
28
29/* the largest possible cartridge image (street fighter 2 - 2.5MB) */
30#define PCE_ROM_MAXSIZE      0x280000
31
32typedef struct
33{
34   UINT8   regs[16];
35   UINT8   *bram;
36   UINT8   *adpcm_ram;
37   int      bram_locked;
38   int      adpcm_read_ptr;
39   UINT8   adpcm_read_buf;
40   int      adpcm_write_ptr;
41   UINT8   adpcm_write_buf;
42   int      adpcm_length;
43   int      adpcm_clock_divider;
44   UINT32  msm_start_addr;
45   UINT32   msm_end_addr;
46   UINT32   msm_half_addr;
47   UINT8   msm_nibble;
48   UINT8   msm_idle;
49
50   /* SCSI signals */
51   int      scsi_BSY;   /* Busy. Bus in use */
52   int      scsi_SEL;   /* Select. Initiator has won arbitration and has selected a target */
53   int      scsi_CD;   /* Control/Data. Target is sending control (data) information */
54   int      scsi_IO;   /* Input/Output. Target is sending (receiving) information */
55   int      scsi_MSG;   /* Message. Target is sending or receiving a message */
56   int      scsi_REQ;   /* Request. Target is requesting a data transfer */
57   int      scsi_ACK;   /* Acknowledge. Initiator acknowledges that it is ready for a data transfer */
58   int      scsi_ATN;   /* Attention. Initiator has a message ready for the target */
59   int      scsi_RST;   /* Reset. Initiator forces all targets and any other initiators to do a warm reset */
60   int      scsi_last_RST;   /* To catch setting of RST signal */
61   int      cd_motor_on;
62   int      selected;
63   UINT8   *command_buffer;
64   int      command_buffer_index;
65   int      status_sent;
66   int      message_after_status;
67   int      message_sent;
68   UINT8   *data_buffer;
69   int      data_buffer_size;
70   int      data_buffer_index;
71   int      data_transferred;
72
73   /* Arcade Card specific */
74   UINT8   *acard_ram;
75   UINT8   acard_latch;
76   UINT8   acard_ctrl[4];
77   UINT32   acard_base_addr[4];
78   UINT16   acard_addr_offset[4];
79   UINT16   acard_addr_inc[4];
80   UINT32   acard_shift;
81   UINT8   acard_shift_reg;
82
83   UINT32   current_frame;
84   UINT32   end_frame;
85   UINT32   last_frame;
86   UINT8   cdda_status;
87   UINT8   cdda_play_mode;
88   UINT8   *subcode_buffer;
89   UINT8   end_mark;
90   cdrom_file   *cd;
91   const cdrom_toc*   toc;
92   emu_timer   *data_timer;
93   emu_timer   *adpcm_dma_timer;
94
95   emu_timer   *cdda_fadeout_timer;
96   emu_timer   *cdda_fadein_timer;
97   double   cdda_volume;
98   emu_timer   *adpcm_fadeout_timer;
99   emu_timer   *adpcm_fadein_timer;
100   double   adpcm_volume;
101} pce_cd_t;
102
103
104class pce_state : public driver_device
105{
106public:
107   pce_state(const machine_config &mconfig, device_type type, const char *tag)
108      : driver_device(mconfig, type, tag) { }
109
110   unsigned char *m_user_ram;
111   UINT8 *m_cd_ram;
112   UINT8 m_io_port_options;
113   UINT8 m_sys3_card;
114   UINT8 m_acard;
115   pce_cd_t m_cd;
116   UINT8 *m_cartridge_ram;
117   int m_joystick_port_select;
118   int m_joystick_data_select;
119   UINT8 m_joy_6b_packet[5];
120};
121
122
123/*----------- defined in machine/pce.c -----------*/
124
125DEVICE_IMAGE_LOAD(pce_cart);
126NVRAM_HANDLER( pce );
127WRITE8_HANDLER ( pce_joystick_w );
128 READ8_HANDLER ( pce_joystick_r );
129
130extern const msm5205_interface pce_cd_msm5205_interface;
131WRITE8_HANDLER( pce_cd_bram_w );
132WRITE8_HANDLER( pce_cd_intf_w );
133READ8_HANDLER( pce_cd_intf_r );
134WRITE8_HANDLER( pce_cd_acard_w );
135READ8_HANDLER( pce_cd_acard_r );
136WRITE8_HANDLER( pce_cd_acard_wram_w );
137READ8_HANDLER( pce_cd_acard_wram_r );
138
139DRIVER_INIT( pce );
140DRIVER_INIT( tg16 );
141DRIVER_INIT( sgx );
142MACHINE_START( pce );
143MACHINE_RESET( pce );
144
145
146#endif /* PCE_H_ */
src/mame/video/nes.c
r11531r11532
1/***************************************************************************
2
3  video/nes.c
4
5  Routines to control the unique NES video hardware/PPU.
6
7***************************************************************************/
8
9#include "emu.h"
10#include "video/ppu2c0x.h"
11#include "includes/nes.h"
12#include "machine/nes_mmc.h"
13
14static void nes_vh_reset( running_machine &machine )
15{
16   nes_state *state = machine.driver_data<nes_state>();
17   ppu2c0x_set_vidaccess_callback(machine.device("ppu"), nes_ppu_vidaccess);
18
19   if (state->m_four_screen_vram)
20      set_nt_mirroring(machine, PPU_MIRROR_4SCREEN);
21   else
22   {
23      switch (state->m_hard_mirroring)
24      {
25         case PPU_MIRROR_HORZ:
26         case PPU_MIRROR_VERT:
27         case PPU_MIRROR_HIGH:
28         case PPU_MIRROR_LOW:
29            set_nt_mirroring(machine, state->m_hard_mirroring);
30            break;
31         default:
32            set_nt_mirroring(machine, PPU_MIRROR_NONE);
33            break;
34      }
35   }
36}
37
38VIDEO_START( nes )
39{
40   nes_state *state = machine.driver_data<nes_state>();
41
42   state->m_last_frame_flip =  0;
43
44   machine.add_notifier(MACHINE_NOTIFY_RESET, machine_notify_delegate(FUNC(nes_vh_reset),&machine));
45}
46
47PALETTE_INIT( nes )
48{
49   ppu2c0x_init_palette(machine, 0);
50}
51
52
53/***************************************************************************
54
55  Display refresh
56
57***************************************************************************/
58
59SCREEN_UPDATE( nes )
60{
61   nes_state *state = screen->machine().driver_data<nes_state>();
62
63   /* render the ppu */
64   ppu2c0x_render(state->m_ppu, bitmap, 0, 0, 0, 0);
65
66   /* if this is a disk system game, check for the flip-disk key */
67   if (state->m_disk_expansion && state->m_pcb_id == NO_BOARD)
68   {
69      // latch this input so it doesn't go at warp speed
70      if ((input_port_read(screen->machine(), "FLIPDISK") & 0x01) && (!state->m_last_frame_flip))
71      {
72         state->m_last_frame_flip = 1;
73         state->m_fds_current_side++;
74         if (state->m_fds_current_side > state->m_fds_sides)
75            state->m_fds_current_side = 0;
76
77         if (state->m_fds_current_side == 0)
78            popmessage("No disk inserted.");
79         else
80            popmessage("Disk set to side %d", state->m_fds_current_side);
81      }
82
83      if (!(input_port_read(screen->machine(), "FLIPDISK") & 0x01))
84         state->m_last_frame_flip = 0;
85   }
86   return 0;
87}
src/mame/drivers/ng_aes.c
r11531r11532
1/***************************************************************************
2
3    Neo-Geo AES hardware
4
5    Credits (from MAME neogeo.c, since this is just a minor edit of that driver):
6        * This driver was made possible by the research done by
7          Charles MacDonald.  For a detailed description of the Neo-Geo
8          hardware, please visit his page at:
9          http://cgfm2.emuviews.com/temp/mvstech.txt
10        * Presented to you by the Shin Emu Keikaku team.
11        * The following people have all spent probably far
12          too much time on this:
13          AVDB
14          Bryan McPhail
15          Fuzz
16          Ernesto Corvi
17          Andrew Prime
18          Zsolt Vasvari
19
20    MESS cartridge support by R. Belmont based on work by Michael Zapf
21
22    Current status:
23        - Cartridges run.
24
25    ToDo :
26        - Change input code to allow selection of the mahjong panel in PORT_CATEGORY.
27        - Clean up code, to reduce duplication of MAME source
28
29****************************************************************************/
30
31#include "emu.h"
32#include "cpu/m68000/m68000.h"
33#include "includes/neogeo.h"
34#include "machine/pd4990a.h"
35#include "cpu/z80/z80.h"
36#include "sound/2610intf.h"
37#include "machine/aescart.h"
38#include "imagedev/cartslot.h"
39#ifdef MESS
40#include "neogeo.lh"
41#else
42extern const char layout_neogeo[];
43#endif
44
45
46// CD-ROM / DMA control registers
47typedef struct
48{
49   UINT8 area_sel;
50   UINT8 pcm_bank_sel;
51   UINT8 spr_bank_sel;
52   UINT32 addr_source; // target if in fill mode
53   UINT32 addr_target;
54   UINT16 fill_word;
55   UINT32 word_count;
56   UINT16 dma_mode[10];
57} neocd_ctrl_t;
58
59class ng_aes_state : public neogeo_state
60{
61public:
62   ng_aes_state(const machine_config &mconfig, device_type type, const char *tag)
63      : neogeo_state(mconfig, type, tag) { }
64
65   UINT8 *m_memcard_data;
66   neocd_ctrl_t m_neocd_ctrl;
67};
68
69
70
71#define LOG_VIDEO_SYSTEM      (0)
72#define LOG_CPU_COMM         (0)
73#define LOG_MAIN_CPU_BANKING   (1)
74#define LOG_AUDIO_CPU_BANKING   (1)
75
76#define NEOCD_AREA_SPR    0
77#define NEOCD_AREA_PCM    1
78#define NEOCD_AREA_AUDIO  4
79#define NEOCD_AREA_FIX    5
80
81/*************************************
82 *
83 *  Global variables
84 *
85 *************************************/
86
87//static UINT16 *save_ram;
88
89UINT16* neocd_work_ram;
90
91/*************************************
92 *
93 *  Forward declarations
94 *
95 *************************************/
96
97//static void set_output_latch(running_machine &machine, UINT8 data);
98//static void set_output_data(running_machine &machine, UINT8 data);
99
100
101/*************************************
102 *
103 *  Main CPU interrupt generation
104 *
105 *************************************/
106
107#define IRQ2CTRL_ENABLE            (0x10)
108#define IRQ2CTRL_LOAD_RELATIVE      (0x20)
109#define IRQ2CTRL_AUTOLOAD_VBLANK   (0x40)
110#define IRQ2CTRL_AUTOLOAD_REPEAT   (0x80)
111
112
113static void adjust_display_position_interrupt_timer( running_machine &machine )
114{
115   neogeo_state *state = machine.driver_data<neogeo_state>();
116
117   if ((state->m_display_counter + 1) != 0)
118   {
119      attotime period = (attotime::from_hz(NEOGEO_PIXEL_CLOCK) * (state->m_display_counter + 1));
120      if (LOG_VIDEO_SYSTEM) logerror("adjust_display_position_interrupt_timer  current y: %02x  current x: %02x   target y: %x  target x: %x\n", machine.primary_screen->vpos(), machine.primary_screen->hpos(), (state->m_display_counter + 1) / NEOGEO_HTOTAL, (state->m_display_counter + 1) % NEOGEO_HTOTAL);
121
122      state->m_display_position_interrupt_timer->adjust(period);
123   }
124}
125
126#ifdef MESS
127void neogeo_set_display_position_interrupt_control( running_machine &machine, UINT16 data )
128{
129   neogeo_state *state = machine.driver_data<neogeo_state>();
130   state->m_display_position_interrupt_control = data;
131}
132
133
134void neogeo_set_display_counter_msb( address_space *space, UINT16 data )
135{
136   neogeo_state *state = space->machine().driver_data<neogeo_state>();
137
138   state->m_display_counter = (state->m_display_counter & 0x0000ffff) | ((UINT32)data << 16);
139
140   if (LOG_VIDEO_SYSTEM) logerror("PC %06x: set_display_counter %08x\n", cpu_get_pc(&space->device()), state->m_display_counter);
141}
142
143
144void neogeo_set_display_counter_lsb( address_space *space, UINT16 data )
145{
146   neogeo_state *state = space->machine().driver_data<neogeo_state>();
147
148   state->m_display_counter = (state->m_display_counter & 0xffff0000) | data;
149
150   if (LOG_VIDEO_SYSTEM) logerror("PC %06x: set_display_counter %08x\n", cpu_get_pc(&space->device()), state->m_display_counter);
151
152   if (state->m_display_position_interrupt_control & IRQ2CTRL_LOAD_RELATIVE)
153   {
154      if (LOG_VIDEO_SYSTEM) logerror("AUTOLOAD_RELATIVE ");
155      adjust_display_position_interrupt_timer(space->machine());
156   }
157}
158#endif
159
160static void update_interrupts( running_machine &machine )
161{
162   neogeo_state *state = machine.driver_data<neogeo_state>();
163
164   if(strcmp((char*)machine.system().name,"aes") != 0)
165   {  // raster and vblank IRQs are swapped on the NeoCD.
166      cputag_set_input_line(machine, "maincpu", 2, state->m_vblank_interrupt_pending ? ASSERT_LINE : CLEAR_LINE);
167      cputag_set_input_line(machine, "maincpu", 1, state->m_display_position_interrupt_pending ? ASSERT_LINE : CLEAR_LINE);
168      cputag_set_input_line(machine, "maincpu", 3, state->m_irq3_pending ? ASSERT_LINE : CLEAR_LINE);
169   }
170   else
171   {
172      cputag_set_input_line(machine, "maincpu", 1, state->m_vblank_interrupt_pending ? ASSERT_LINE : CLEAR_LINE);
173      cputag_set_input_line(machine, "maincpu", 2, state->m_display_position_interrupt_pending ? ASSERT_LINE : CLEAR_LINE);
174      cputag_set_input_line(machine, "maincpu", 3, state->m_irq3_pending ? ASSERT_LINE : CLEAR_LINE);
175   }
176}
177
178#ifdef MESS
179void neogeo_acknowledge_interrupt( running_machine &machine, UINT16 data )
180{
181   neogeo_state *state = machine.driver_data<neogeo_state>();
182
183   if (data & 0x01)
184      state->m_irq3_pending = 0;
185   if (data & 0x02)
186      state->m_display_position_interrupt_pending = 0;
187   if (data & 0x04)
188      state->m_vblank_interrupt_pending = 0;
189
190   update_interrupts(machine);
191}
192#endif
193
194static TIMER_CALLBACK( display_position_interrupt_callback )
195{
196   neogeo_state *state = machine.driver_data<neogeo_state>();
197
198   if (LOG_VIDEO_SYSTEM) logerror("--- Scanline @ %d,%d\n", machine.primary_screen->vpos(), machine.primary_screen->hpos());
199
200   if (state->m_display_position_interrupt_control & IRQ2CTRL_ENABLE)
201   {
202      if (LOG_VIDEO_SYSTEM) logerror("*** Scanline interrupt (IRQ2) ***  y: %02x  x: %02x\n", machine.primary_screen->vpos(), machine.primary_screen->hpos());
203      state->m_display_position_interrupt_pending = 1;
204
205      update_interrupts(machine);
206   }
207
208   if (state->m_display_position_interrupt_control & IRQ2CTRL_AUTOLOAD_REPEAT)
209   {
210      if (LOG_VIDEO_SYSTEM) logerror("AUTOLOAD_REPEAT ");
211      adjust_display_position_interrupt_timer(machine);
212   }
213}
214
215
216static TIMER_CALLBACK( display_position_vblank_callback )
217{
218   neogeo_state *state = machine.driver_data<neogeo_state>();
219
220   if (state->m_display_position_interrupt_control & IRQ2CTRL_AUTOLOAD_VBLANK)
221   {
222      if (LOG_VIDEO_SYSTEM) logerror("AUTOLOAD_VBLANK ");
223      adjust_display_position_interrupt_timer(machine);
224   }
225
226   /* set timer for next screen */
227   state->m_display_position_vblank_timer->adjust(machine.primary_screen->time_until_pos(NEOGEO_VBSTART, NEOGEO_VBLANK_RELOAD_HPOS));
228}
229
230
231static TIMER_CALLBACK( vblank_interrupt_callback )
232{
233   neogeo_state *state = machine.driver_data<neogeo_state>();
234
235   if (LOG_VIDEO_SYSTEM) logerror("+++ VBLANK @ %d,%d\n", machine.primary_screen->vpos(), machine.primary_screen->hpos());
236
237   /* add a timer tick to the pd4990a */
238   upd4990a_addretrace(state->m_upd4990a);
239
240   state->m_vblank_interrupt_pending = 1;
241
242   update_interrupts(machine);
243
244   /* set timer for next screen */
245   state->m_vblank_interrupt_timer->adjust(machine.primary_screen->time_until_pos(NEOGEO_VBSTART, 0));
246}
247
248
249static void create_interrupt_timers( running_machine &machine )
250{
251   neogeo_state *state = machine.driver_data<neogeo_state>();
252   state->m_display_position_interrupt_timer = machine.scheduler().timer_alloc(FUNC(display_position_interrupt_callback));
253   state->m_display_position_vblank_timer = machine.scheduler().timer_alloc(FUNC(display_position_vblank_callback));
254   state->m_vblank_interrupt_timer = machine.scheduler().timer_alloc(FUNC(vblank_interrupt_callback));
255}
256
257
258static void start_interrupt_timers( running_machine &machine )
259{
260   neogeo_state *state = machine.driver_data<neogeo_state>();
261   state->m_vblank_interrupt_timer->adjust(machine.primary_screen->time_until_pos(NEOGEO_VBSTART, 0));
262   state->m_display_position_vblank_timer->adjust(machine.primary_screen->time_until_pos(NEOGEO_VBSTART, NEOGEO_VBLANK_RELOAD_HPOS));
263}
264
265
266
267/*************************************
268 *
269 *  Audio CPU interrupt generation
270 *
271 *************************************/
272
273static void audio_cpu_irq(device_t *device, int assert)
274{
275   neogeo_state *state = device->machine().driver_data<neogeo_state>();
276   device_set_input_line(state->m_audiocpu, 0, assert ? ASSERT_LINE : CLEAR_LINE);
277}
278
279
280static void audio_cpu_assert_nmi(running_machine &machine)
281{
282   neogeo_state *state = machine.driver_data<neogeo_state>();
283   device_set_input_line(state->m_audiocpu, INPUT_LINE_NMI, ASSERT_LINE);
284}
285
286
287static WRITE8_HANDLER( audio_cpu_clear_nmi_w )
288{
289   neogeo_state *state = space->machine().driver_data<neogeo_state>();
290   device_set_input_line(state->m_audiocpu, INPUT_LINE_NMI, CLEAR_LINE);
291}
292
293
294
295/*************************************
296 *
297 *  Input ports / Controllers
298 *
299 *************************************/
300
301static void select_controller( running_machine &machine, UINT8 data )
302{
303   neogeo_state *state = machine.driver_data<neogeo_state>();
304   state->m_controller_select = data;
305}
306
307
308#if 0
309static CUSTOM_INPUT( multiplexed_controller_r )
310{
311   int port = (FPTR)param;
312
313   static const char *const cntrl[2][2] =
314      {
315         { "IN0-0", "IN0-1" }, { "IN1-0", "IN1-1" }
316      };
317
318   return input_port_read_safe(field.machine(), cntrl[port][controller_select & 0x01], 0x00);
319}
320
321
322static CUSTOM_INPUT( mahjong_controller_r )
323{
324   UINT32 ret;
325
326/*
327cpu #0 (PC=00C18B9A): unmapped memory word write to 00380000 = 0012 & 00FF
328cpu #0 (PC=00C18BB6): unmapped memory word write to 00380000 = 001B & 00FF
329cpu #0 (PC=00C18D54): unmapped memory word write to 00380000 = 0024 & 00FF
330cpu #0 (PC=00C18D6C): unmapped memory word write to 00380000 = 0009 & 00FF
331cpu #0 (PC=00C18C40): unmapped memory word write to 00380000 = 0000 & 00FF
332*/
333   switch (controller_select)
334   {
335   default:
336   case 0x00: ret = 0x0000; break; /* nothing? */
337   case 0x09: ret = input_port_read(field.machine(), "MAHJONG1"); break;
338   case 0x12: ret = input_port_read(field.machine(), "MAHJONG2"); break;
339   case 0x1b: ret = input_port_read(field.machine(), "MAHJONG3"); break; /* player 1 normal inputs? */
340   case 0x24: ret = input_port_read(field.machine(), "MAHJONG4"); break;
341   }
342
343   return ret;
344}
345
346#endif
347
348static WRITE16_HANDLER( io_control_w )
349{
350   neogeo_state *state = space->machine().driver_data<neogeo_state>();
351   switch (offset)
352   {
353   case 0x00: select_controller(space->machine(), data & 0x00ff); break;
354//  case 0x18: set_output_latch(space->machine(), data & 0x00ff); break;
355//  case 0x20: set_output_data(space->machine(), data & 0x00ff); break;
356   case 0x28: upd4990a_control_16_w(state->m_upd4990a, 0, data, mem_mask); break;
357//  case 0x30: break; // coin counters
358//  case 0x31: break; // coin counters
359//  case 0x32: break; // coin lockout
360//  case 0x33: break; // coui lockout
361
362   default:
363      logerror("PC: %x  Unmapped I/O control write.  Offset: %x  Data: %x\n", cpu_get_pc(&space->device()), offset, data);
364      break;
365   }
366}
367
368
369
370/*************************************
371 *
372 *  Unmapped memory access
373 *
374 *************************************/
375#ifdef MESS
376READ16_HANDLER( neogeo_unmapped_r )
377{
378   neogeo_state *state = space->machine().driver_data<neogeo_state>();
379   UINT16 ret;
380
381   /* unmapped memory returns the last word on the data bus, which is almost always the opcode
382       of the next instruction due to prefetch */
383
384   /* prevent recursion */
385   if (state->m_recurse)
386      ret = 0xffff;
387   else
388   {
389      state->m_recurse = 1;
390      ret = space->read_word(cpu_get_pc(&space->device()));
391      state->m_recurse = 0;
392   }
393
394   return ret;
395}
396#endif
397
398
399
400/*************************************
401 *
402 *  uPD4990A calendar chip
403 *
404 *************************************/
405#if 0
406static void calendar_init(running_machine &machine)
407{
408   /* set the celander IC to 'right now' */
409   system_time systime;
410   system_tm time;
411
412   machine.base_datetime(&systime);
413   time = systime.local_time;
414
415   pd4990a.seconds = ((time.second / 10) << 4) + (time.second % 10);
416   pd4990a.minutes = ((time.minute / 10) << 4) + (time.minute % 10);
417   pd4990a.hours = ((time.hour / 10) <<4 ) + (time.hour % 10);
418   pd4990a.days = ((time.mday / 10) << 4) + (time.mday % 10);
419   pd4990a.month = time.month + 1;
420   pd4990a.year = ((((time.year - 1900) % 100) / 10) << 4) + ((time.year - 1900) % 10);
421   pd4990a.weekday = time.weekday;
422}
423
424
425static void calendar_clock(void)
426{
427//  pd4990a_addretrace();
428}
429#endif
430
431static CUSTOM_INPUT( get_calendar_status )
432{
433   neogeo_state *state = field.machine().driver_data<neogeo_state>();
434   return (upd4990a_databit_r(state->m_upd4990a, 0) << 1) | upd4990a_testbit_r(state->m_upd4990a, 0);
435}
436
437
438
439/*************************************
440 *
441 *  NVRAM (Save RAM)
442 *
443 *************************************/
444#if 0
445static NVRAM_HANDLER( neogeo )
446{
447   if (read_or_write)
448      /* save the SRAM settings */
449      mame_fwrite(file, save_ram, 0x2000);
450   else
451   {
452      /* load the SRAM settings */
453      if (file)
454         mame_fread(file, save_ram, 0x2000);
455      else
456         memset(save_ram, 0, 0x10000);
457   }
458}
459
460
461static void set_save_ram_unlock( running_machine &machine, UINT8 data )
462{
463   neogeo_state *state = machine.driver_data<neogeo_state>();
464   state->m_save_ram_unlocked = data;
465}
466
467
468static WRITE16_HANDLER( save_ram_w )
469{
470   neogeo_state *state = space->machine().driver_data<neogeo_state>();
471
472   if (state->m_save_ram_unlocked)
473      COMBINE_DATA(&save_ram[offset]);
474}
475#endif
476
477
478/*************************************
479 *
480 *  Memory card
481 *
482 *************************************/
483
484#define MEMCARD_SIZE   0x0800
485
486static CUSTOM_INPUT( get_memcard_status )
487{
488   /* D0 and D1 are memcard presence indicators, D2 indicates memcard
489       write protect status (we are always write enabled) */
490   if(strcmp((char*)field.machine().system().name,"aes") != 0)
491      return 0x00;  // On the Neo Geo CD, the memory card is internal and therefore always present.
492   else
493      return (memcard_present(field.machine()) == -1) ? 0x07 : 0x00;
494}
495
496static READ16_HANDLER( memcard_r )
497{
498   ng_aes_state *state = space->machine().driver_data<ng_aes_state>();
499   UINT16 ret;
500
501   if (memcard_present(space->machine()) != -1)
502      ret = state->m_memcard_data[offset] | 0xff00;
503   else
504      ret = 0xffff;
505
506   return ret;
507}
508
509
510static WRITE16_HANDLER( memcard_w )
511{
512   ng_aes_state *state = space->machine().driver_data<ng_aes_state>();
513   if (ACCESSING_BITS_0_7)
514   {
515      if (memcard_present(space->machine()) != -1)
516         state->m_memcard_data[offset] = data;
517   }
518}
519
520/* The NeoCD has an 8kB internal memory card, instead of memcard slots like the MVS and AES */
521static READ16_HANDLER( neocd_memcard_r )
522{
523   ng_aes_state *state = space->machine().driver_data<ng_aes_state>();
524   return state->m_memcard_data[offset] | 0xff00;
525}
526
527
528static WRITE16_HANDLER( neocd_memcard_w )
529{
530   ng_aes_state *state = space->machine().driver_data<ng_aes_state>();
531   if (ACCESSING_BITS_0_7)
532   {
533      state->m_memcard_data[offset] = data;
534   }
535}
536
537static MEMCARD_HANDLER( neogeo )
538{
539   ng_aes_state *state = machine.driver_data<ng_aes_state>();
540   switch (action)
541   {
542   case MEMCARD_CREATE:
543      memset(state->m_memcard_data, 0, MEMCARD_SIZE);
544      file.write(state->m_memcard_data, MEMCARD_SIZE);
545      break;
546
547   case MEMCARD_INSERT:
548      file.read(state->m_memcard_data, MEMCARD_SIZE);
549      break;
550
551   case MEMCARD_EJECT:
552      file.write(state->m_memcard_data, MEMCARD_SIZE);
553      break;
554   }
555}
556
557
558
559/*************************************
560 *
561 *  Inter-CPU communications
562 *
563 *************************************/
564
565static WRITE16_HANDLER( audio_command_w )
566{
567   /* accessing the LSB only is not mapped */
568   if (mem_mask != 0x00ff)
569   {
570      soundlatch_w(space, 0, data >> 8);
571
572      audio_cpu_assert_nmi(space->machine());
573
574      /* boost the interleave to let the audio CPU read the command */
575      space->machine().scheduler().boost_interleave(attotime::zero, attotime::from_usec(50));
576
577      if (LOG_CPU_COMM) logerror("MAIN CPU PC %06x: audio_command_w %04x - %04x\n", cpu_get_pc(&space->device()), data, mem_mask);
578   }
579}
580
581
582static READ8_HANDLER( audio_command_r )
583{
584   UINT8 ret = soundlatch_r(space, 0);
585
586   if (LOG_CPU_COMM) logerror(" AUD CPU PC   %04x: audio_command_r %02x\n", cpu_get_pc(&space->device()), ret);
587
588   /* this is a guess */
589   audio_cpu_clear_nmi_w(space, 0, 0);
590
591   return ret;
592}
593
594
595static WRITE8_HANDLER( audio_result_w )
596{
597   neogeo_state *state = space->machine().driver_data<neogeo_state>();
598
599   if (LOG_CPU_COMM && (state->m_audio_result != data)) logerror(" AUD CPU PC   %04x: audio_result_w %02x\n", cpu_get_pc(&space->device()), data);
600
601   state->m_audio_result = data;
602}
603
604
605static CUSTOM_INPUT( get_audio_result )
606{
607   neogeo_state *state = field.machine().driver_data<neogeo_state>();
608   UINT32 ret = state->m_audio_result;
609
610//  if (LOG_CPU_COMM) logerror("MAIN CPU PC %06x: audio_result_r %02x\n", cpu_get_pc(field.machine().device("maincpu")), ret);
611
612   return ret;
613}
614
615
616
617/*************************************
618 *
619 *  Main CPU banking
620 *
621 *************************************/
622
623static void _set_main_cpu_vector_table_source( running_machine &machine )
624{
625   neogeo_state *state = machine.driver_data<neogeo_state>();
626   memory_set_bank(machine, NEOGEO_BANK_VECTORS, state->m_main_cpu_vector_table_source);
627}
628
629
630static void set_main_cpu_vector_table_source( running_machine &machine, UINT8 data )
631{
632   neogeo_state *state = machine.driver_data<neogeo_state>();
633   state->m_main_cpu_vector_table_source = data;
634
635   _set_main_cpu_vector_table_source(machine);
636}
637
638
639static void _set_main_cpu_bank_address( running_machine &machine )
640{
641   neogeo_state *state = machine.driver_data<neogeo_state>();
642   memory_set_bankptr(machine, NEOGEO_BANK_CARTRIDGE, &machine.region("maincpu")->base()[state->m_main_cpu_bank_address]);
643}
644
645#ifdef MESS
646void neogeo_set_main_cpu_bank_address( address_space *space, UINT32 bank_address )
647{
648   neogeo_state *state = space->machine().driver_data<neogeo_state>();
649
650   if (LOG_MAIN_CPU_BANKING) logerror("MAIN CPU PC %06x: neogeo_set_main_cpu_bank_address %06x\n", cpu_get_pc(&space->device()), bank_address);
651
652   state->m_main_cpu_bank_address = bank_address;
653
654   _set_main_cpu_bank_address(space->machine());
655}
656#endif
657
658static WRITE16_HANDLER( main_cpu_bank_select_w )
659{
660   UINT32 bank_address;
661   UINT32 len = space->machine().region("maincpu")->bytes();
662
663   if ((len <= 0x100000) && (data & 0x07))
664      logerror("PC %06x: warning: bankswitch to %02x but no banks available\n", cpu_get_pc(&space->device()), data);
665   else
666   {
667      bank_address = ((data & 0x07) + 1) * 0x100000;
668
669      if (bank_address >= len)
670      {
671         logerror("PC %06x: warning: bankswitch to empty bank %02x\n", cpu_get_pc(&space->device()), data);
672         bank_address = 0x100000;
673      }
674
675      neogeo_set_main_cpu_bank_address(space, bank_address);
676   }
677}
678
679
680static void main_cpu_banking_init( running_machine &machine )
681{
682   address_space *mainspace = machine.device("maincpu")->memory().space(AS_PROGRAM);
683
684   /* create vector banks */
685   memory_configure_bank(machine, NEOGEO_BANK_VECTORS, 0, 1, machine.region("mainbios")->base(), 0);
686   memory_configure_bank(machine, NEOGEO_BANK_VECTORS, 1, 1, machine.region("maincpu")->base(), 0);
687
688   /* set initial main CPU bank */
689   if (machine.region("maincpu")->bytes() > 0x100000)
690      neogeo_set_main_cpu_bank_address(mainspace, 0x100000);
691   else
692      neogeo_set_main_cpu_bank_address(mainspace, 0x000000);
693}
694
695
696
697/*************************************
698 *
699 *  Audio CPU banking
700 *
701 *************************************/
702
703static void set_audio_cpu_banking( running_machine &machine )
704{
705   neogeo_state *state = machine.driver_data<neogeo_state>();
706   int region;
707
708   for (region = 0; region < 4; region++)
709      memory_set_bank(machine, NEOGEO_BANK_AUDIO_CPU_CART_BANK + region, state->m_audio_cpu_banks[region]);
710}
711
712
713static void audio_cpu_bank_select( address_space *space, int region, UINT8 bank )
714{
715   neogeo_state *state = space->machine().driver_data<neogeo_state>();
716
717   if (LOG_AUDIO_CPU_BANKING) logerror("Audio CPU PC %03x: audio_cpu_bank_select: Region: %d   Bank: %02x\n", cpu_get_pc(&space->device()), region, bank);
718
719   state->m_audio_cpu_banks[region] = bank;
720
721   set_audio_cpu_banking(space->machine());
722}
723
724
725static READ8_HANDLER( audio_cpu_bank_select_f000_f7ff_r )
726{
727   audio_cpu_bank_select(space, 0, offset >> 8);
728
729   return 0;
730}
731
732
733static READ8_HANDLER( audio_cpu_bank_select_e000_efff_r )
734{
735   audio_cpu_bank_select(space, 1, offset >> 8);
736
737   return 0;
738}
739
740
741static READ8_HANDLER( audio_cpu_bank_select_c000_dfff_r )
742{
743   audio_cpu_bank_select(space, 2, offset >> 8);
744
745   return 0;
746}
747
748
749static READ8_HANDLER( audio_cpu_bank_select_8000_bfff_r )
750{
751   audio_cpu_bank_select(space, 3, offset >> 8);
752
753   return 0;
754}
755
756
757static void _set_audio_cpu_rom_source( address_space *space )
758{
759   neogeo_state *state = space->machine().driver_data<neogeo_state>();
760
761/*  if (!machine.region("audiobios")->base())   */
762      state->m_audio_cpu_rom_source = 1;
763
764   memory_set_bank(space->machine(), NEOGEO_BANK_AUDIO_CPU_MAIN_BANK, state->m_audio_cpu_rom_source);
765
766   /* reset CPU if the source changed -- this is a guess */
767   if (state->m_audio_cpu_rom_source != state->m_audio_cpu_rom_source_last)
768   {
769      state->m_audio_cpu_rom_source_last = state->m_audio_cpu_rom_source;
770
771      cputag_set_input_line(space->machine(), "audiocpu", INPUT_LINE_RESET, PULSE_LINE);
772
773      if (LOG_AUDIO_CPU_BANKING) logerror("Audio CPU PC %03x: selectign %s ROM\n", cpu_get_pc(&space->device()), state->m_audio_cpu_rom_source ? "CARTRIDGE" : "BIOS");
774   }
775}
776
777
778static void set_audio_cpu_rom_source( address_space *space, UINT8 data )
779{
780   neogeo_state *state = space->machine().driver_data<neogeo_state>();
781   state->m_audio_cpu_rom_source = data;
782
783   _set_audio_cpu_rom_source(space);
784}
785
786
787static void audio_cpu_banking_init( running_machine &machine )
788{
789   neogeo_state *state = machine.driver_data<neogeo_state>();
790   int region;
791   int bank;
792   UINT8 *rgn;
793   UINT32 address_mask;
794
795   /* audio bios/cartridge selection */
796   if (machine.region("audiobios")->base())
797      memory_configure_bank(machine, NEOGEO_BANK_AUDIO_CPU_MAIN_BANK, 0, 1, machine.region("audiobios")->base(), 0);
798   memory_configure_bank(machine, NEOGEO_BANK_AUDIO_CPU_MAIN_BANK, 1, 1, machine.region("audiocpu")->base(), 0);
799
800   /* audio banking */
801   address_mask = machine.region("audiocpu")->bytes() - 0x10000 - 1;
802
803   rgn = machine.region("audiocpu")->base();
804   for (region = 0; region < 4; region++)
805   {
806      for (bank = 0; bank < 0x100; bank++)
807      {
808         UINT32 bank_address = 0x10000 + (((bank << (11 + region)) & 0x3ffff) & address_mask);
809         memory_configure_bank(machine, NEOGEO_BANK_AUDIO_CPU_CART_BANK + region, bank, 1, &rgn[bank_address], 0);
810      }
811   }
812
813   /* set initial audio banks --
814       how does this really work, or is it even neccessary? */
815   state->m_audio_cpu_banks[0] = 0x1e;
816   state->m_audio_cpu_banks[1] = 0x0e;
817   state->m_audio_cpu_banks[2] = 0x06;
818   state->m_audio_cpu_banks[3] = 0x02;
819
820   set_audio_cpu_banking(machine);
821
822   state->m_audio_cpu_rom_source_last = 0;
823   set_audio_cpu_rom_source(machine.device("maincpu")->memory().space(AS_PROGRAM), 0);
824}
825
826
827
828/*************************************
829 *
830 *  System control register
831 *
832 *************************************/
833
834static WRITE16_HANDLER( system_control_w )
835{
836   if (ACCESSING_BITS_0_7)
837   {
838      UINT8 bit = (offset >> 3) & 0x01;
839
840      switch (offset & 0x07)
841      {
842      default:
843      case 0x00: neogeo_set_screen_dark(space->machine(), bit); break;
844      case 0x01: set_main_cpu_vector_table_source(space->machine(), bit);
845               set_audio_cpu_rom_source(space, bit); /* this is a guess */
846               break;
847      case 0x05: neogeo_set_fixed_layer_source(space->machine(), bit); break;
848//      case 0x06: set_save_ram_unlock(space->machine(), bit); break;
849      case 0x07: neogeo_set_palette_bank(space->machine(), bit); break;
850
851      case 0x02: /* unknown - HC32 middle pin 1 */
852      case 0x03: /* unknown - uPD4990 pin ? */
853      case 0x04: /* unknown - HC32 middle pin 10 */
854         logerror("PC: %x  Unmapped system control write.  Offset: %x  Data: %x\n", cpu_get_pc(&space->device()), offset & 0x07, bit);
855         break;
856      }
857
858      if (LOG_VIDEO_SYSTEM && ((offset & 0x07) != 0x06)) logerror("PC: %x  System control write.  Offset: %x  Data: %x\n", cpu_get_pc(&space->device()), offset & 0x07, bit);
859   }
860}
861
862/*
863 *  CD-ROM / DMA control
864 *
865 *  DMA
866
867    FF0061  Write 0x40 means start DMA transfer
868    FF0064  Source address (in copy mode), Target address (in filll mode)
869    FF0068  Target address (in copy mode)
870    FF006C  Fill word
871    FF0070  Words count
872    FF007E  \
873    ......   | DMA programming words?   NeoGeoCD uses Sanyo Puppet LC8359 chip to
874    FF008E  /                           interface with CD, and do DMA transfers
875
876    Memory access control
877
878    FF011C  DIP SWITCH (Region code)
879    FF0105  Area Selector (5 = FIX, 0 = SPR, 4 = Z80, 1 = PCM)
880    FF01A1  Sprite bank selector
881    FF01A3  PCM bank selector
882    FF0120  Prepare sprite area for transfer
883    FF0122  Prepare PCM area for transfer
884    FF0126  Prepare Z80 area for transfer
885    FF0128  Prepare Fix area for transfer
886    FF0140  Terminate work on Spr Area  (Sprites must be decoded here)
887    FF0142  Terminate work on Pcm Area
888    FF0146  Terminate work on Z80 Area  (Z80 needs to be reset)
889    FF0148  Terminate work on Fix Area
890
891    CD-ROM:
892    0xff0102 == 0xF0 start cd transfer
893    int m=bcd(fast_r8(0x10f6c8));
894    int s=bcd(fast_r8(0x10f6c9));
895    int f=bcd(fast_r8(0x10f6ca));
896    int seccount=fast_r16(0x10f688);
897
898    inisec=((m*60)+s)*75+f;
899    inisec-=150;
900    dstaddr=0x111204; // this must come from somewhere
901
902    the value @ 0x10f688 is decremented each time a sector is read until it's 0.
903
904 *
905 */
906
907static void neocd_do_dma(address_space* space)
908{
909   ng_aes_state *state = space->machine().driver_data<ng_aes_state>();
910   // TODO: Proper DMA timing and control
911   int count;
912//  UINT16 word;
913
914   switch(state->m_neocd_ctrl.dma_mode[0])
915   {
916   case 0xffdd:
917      for(count=0;count<state->m_neocd_ctrl.word_count;count++)
918      {
919         //word = space->read_word(state->m_neocd_ctrl.addr_source);
920         space->write_word(state->m_neocd_ctrl.addr_source+(count*2),state->m_neocd_ctrl.fill_word);
921      }
922      logerror("CTRL: DMA word-fill transfer of %i bytes\n",count*2);
923      break;
924   case 0xfef5:
925      for(count=0;count<state->m_neocd_ctrl.word_count;count++)
926      {
927         //word = space->read_word(state->m_neocd_ctrl.addr_source);
928         space->write_word(state->m_neocd_ctrl.addr_source+(count*4),(state->m_neocd_ctrl.addr_source+(count*4)) >> 16);
929         space->write_word(state->m_neocd_ctrl.addr_source+(count*4)+2,(state->m_neocd_ctrl.addr_source+(count*4)) & 0xffff);
930      }
931      logerror("CTRL: DMA mode 2 transfer of %i bytes\n",count*4);
932      break;
933   case 0xcffd:
934      for(count=0;count<state->m_neocd_ctrl.word_count;count++)
935      {
936         //word = space->read_word(state->m_neocd_ctrl.addr_source);
937         space->write_word(state->m_neocd_ctrl.addr_source+(count*8),((state->m_neocd_ctrl.addr_source+(count*8)) >> 24) | 0xff00);
938         space->write_word(state->m_neocd_ctrl.addr_source+(count*8)+2,((state->m_neocd_ctrl.addr_source+(count*8)) >> 16) | 0xff00);
939         space->write_word(state->m_neocd_ctrl.addr_source+(count*8)+4,((state->m_neocd_ctrl.addr_source+(count*8)) >> 8) | 0xff00);
940         space->write_word(state->m_neocd_ctrl.addr_source+(count*8)+6,(state->m_neocd_ctrl.addr_source+(count*8)) | 0xff00);
941      }
942      logerror("CTRL: DMA mode 3 transfer of %i bytes\n",count*8);
943      break;
944   default:
945      logerror("CTRL: Unknown DMA transfer mode %04x\n",state->m_neocd_ctrl.dma_mode[0]);
946   }
947}
948
949static READ16_HANDLER( neocd_control_r )
950{
951   ng_aes_state *state = space->machine().driver_data<ng_aes_state>();
952
953   switch(offset)
954   {
955   case 0x64/2: // source address, high word
956      return (state->m_neocd_ctrl.addr_source >> 16) & 0xffff;
957   case 0x66/2: // source address, low word
958      return state->m_neocd_ctrl.addr_source & 0xffff;
959   case 0x68/2: // target address, high word
960      return (state->m_neocd_ctrl.addr_target >> 16) & 0xffff;
961   case 0x6a/2: // target address, low word
962      return state->m_neocd_ctrl.addr_target & 0xffff;
963   case 0x6c/2: // fill word
964      return state->m_neocd_ctrl.fill_word;
965   case 0x70/2: // word count
966      return (state->m_neocd_ctrl.word_count >> 16) & 0xffff;
967   case 0x72/2:
968      return state->m_neocd_ctrl.word_count & 0xffff;
969   case 0x7e/2:  // DMA parameters
970   case 0x80/2:
971   case 0x82/2:
972   case 0x84/2:
973   case 0x86/2:
974   case 0x88/2:
975   case 0x8a/2:
976   case 0x8c/2:
977   case 0x8e/2:
978      return state->m_neocd_ctrl.dma_mode[offset-(0x7e/2)];
979      break;
980   case 0x105/2:
981      return state->m_neocd_ctrl.area_sel;
982   case 0x11c/2:
983      logerror("CTRL: Read region code.\n");
984      return 0x0600;  // we'll just force USA region for now
985   case 0x1a0/2:
986      return state->m_neocd_ctrl.spr_bank_sel;
987      break;
988   case 0x1a2/2:
989      return state->m_neocd_ctrl.pcm_bank_sel;
990      break;
991   default:
992      logerror("CTRL: Read offset %04x\n",offset);
993   }
994
995   return 0;
996}
997
998static WRITE16_HANDLER( neocd_control_w )
999{
1000   ng_aes_state *state = space->machine().driver_data<ng_aes_state>();
1001   switch(offset)
1002   {
1003   case 0x60/2: // Start DMA transfer
1004      if((data & 0xff) == 0x40)
1005         neocd_do_dma(space);
1006      break;
1007   case 0x64/2: // source address, high word
1008      state->m_neocd_ctrl.addr_source = (state->m_neocd_ctrl.addr_source & 0x0000ffff) | (data << 16);
1009      logerror("CTRL: Set source address to %08x\n",state->m_neocd_ctrl.addr_source);
1010      break;
1011   case 0x66/2: // source address, low word
1012      state->m_neocd_ctrl.addr_source = (state->m_neocd_ctrl.addr_source & 0xffff0000) | data;
1013      logerror("CTRL: Set source address to %08x\n",state->m_neocd_ctrl.addr_source);
1014      break;
1015   case 0x68/2: // target address, high word
1016      state->m_neocd_ctrl.addr_target = (state->m_neocd_ctrl.addr_target & 0x0000ffff) | (data << 16);
1017      logerror("CTRL: Set target address to %08x\n",state->m_neocd_ctrl.addr_target);
1018      break;
1019   case 0x6a/2: // target address, low word
1020      state->m_neocd_ctrl.addr_target = (state->m_neocd_ctrl.addr_target & 0xffff0000) | data;
1021      logerror("CTRL: Set target address to %08x\n",state->m_neocd_ctrl.addr_target);
1022      break;
1023   case 0x6c/2: // fill word
1024      state->m_neocd_ctrl.fill_word = data;
1025      logerror("CTRL: Set fill word to %04x\n",data);
1026      break;
1027   case 0x70/2: // word count
1028      state->m_neocd_ctrl.word_count = (state->m_neocd_ctrl.word_count & 0x0000ffff) | (data << 16);
1029      logerror("CTRL: Set word count to %i\n",state->m_neocd_ctrl.word_count);
1030      break;
1031   case 0x72/2: // word count (low word)
1032      state->m_neocd_ctrl.word_count = (state->m_neocd_ctrl.word_count & 0xffff0000) | data;
1033      logerror("CTRL: Set word count to %i\n",state->m_neocd_ctrl.word_count);
1034      break;
1035   case 0x7e/2:  // DMA parameters
1036   case 0x80/2:
1037   case 0x82/2:
1038   case 0x84/2:
1039   case 0x86/2:
1040   case 0x88/2:
1041   case 0x8a/2:
1042   case 0x8c/2:
1043   case 0x8e/2:
1044      state->m_neocd_ctrl.dma_mode[offset-(0x7e/2)] = data;
1045      logerror("CTRL: DMA parameter %i set to %04x\n",offset-(0x7e/2),data);
1046      break;
1047   case 0x104/2:
1048      state->m_neocd_ctrl.area_sel = data & 0x00ff;
1049      logerror("CTRL: 0xExxxxx set to area %i\n",data & 0xff);
1050      break;
1051   case 0x140/2:  // end sprite transfer
1052      video_reset_neogeo(space->machine());
1053      break;
1054   case 0x142/2:  // end PCM transfer
1055      break;
1056   case 0x146/2:  // end Z80 transfer
1057      cputag_set_input_line(space->machine(),"audiocpu",INPUT_LINE_RESET,PULSE_LINE);
1058      break;
1059   case 0x148/2:  // end FIX transfer
1060      video_reset_neogeo(space->machine());
1061      break;
1062   case 0x1a0/2:
1063      state->m_neocd_ctrl.spr_bank_sel = data & 0xff;
1064      logerror("CTRL: Sprite area set to bank %i\n",data & 0xff);
1065      break;
1066   case 0x1a2/2:
1067      state->m_neocd_ctrl.pcm_bank_sel = data & 0xff;
1068      logerror("CTRL: PCM area set to bank %i\n",data & 0xff);
1069      break;
1070   default:
1071      logerror("CTRL: Write offset %04x, data %04x\n",offset*2,data);
1072   }
1073}
1074
1075/*
1076 *  Handling NeoCD banked RAM
1077 *  When the Z80 space is banked in to 0xe00000, only the low byte of each word is used
1078 */
1079
1080static READ16_HANDLER(neocd_transfer_r)
1081{
1082   ng_aes_state *state = space->machine().driver_data<ng_aes_state>();
1083   UINT16 ret = 0x0000;
1084   UINT8* Z80 = space->machine().region("audiocpu")->base();
1085   UINT8* PCM = space->machine().region("ymsnd")->base();
1086   UINT8* FIX = space->machine().region("fixed")->base();
1087   UINT16* SPR = (UINT16*)space->machine().region("sprites")->base();
1088
1089   switch(state->m_neocd_ctrl.area_sel)
1090   {
1091   case NEOCD_AREA_AUDIO:
1092      ret = Z80[offset & 0xffff] | 0xff00;
1093      break;
1094   case NEOCD_AREA_PCM:
1095      ret = PCM[offset + (0x100000*state->m_neocd_ctrl.pcm_bank_sel)] | 0xff00;
1096      break;
1097   case NEOCD_AREA_SPR:
1098      ret = SPR[offset + (0x80000*state->m_neocd_ctrl.spr_bank_sel)];
1099      break;
1100   case NEOCD_AREA_FIX:
1101      ret = FIX[offset & 0x1ffff] | 0xff00;
1102      break;
1103   }
1104
1105   return ret;
1106}
1107
1108static WRITE16_HANDLER(neocd_transfer_w)
1109{
1110   ng_aes_state *state = space->machine().driver_data<ng_aes_state>();
1111   UINT8* Z80 = space->machine().region("audiocpu")->base();
1112   UINT8* PCM = space->machine().region("ymsnd")->base();
1113   UINT8* FIX = space->machine().region("fixed")->base();
1114   UINT16* SPR = (UINT16*)space->machine().region("sprites")->base();
1115
1116   switch(state->m_neocd_ctrl.area_sel)
1117   {
1118   case NEOCD_AREA_AUDIO:
1119      Z80[offset & 0xffff] = data & 0xff;
1120      break;
1121   case NEOCD_AREA_PCM:
1122      PCM[offset + (0x100000*state->m_neocd_ctrl.pcm_bank_sel)] = data & 0xff;
1123      break;
1124   case NEOCD_AREA_SPR:
1125      COMBINE_DATA(SPR+(offset + (0x80000*state->m_neocd_ctrl.spr_bank_sel)));
1126      break;
1127   case NEOCD_AREA_FIX:
1128      FIX[offset & 0x1ffff] = data & 0xff;
1129      break;
1130   }
1131
1132}
1133
1134/*
1135 * Handling selectable controller types
1136 */
1137
1138static READ16_HANDLER( aes_in0_r )
1139{
1140   neogeo_state *state = space->machine().driver_data<neogeo_state>();
1141   UINT32 ret = 0xffff;
1142   UINT32 ctrl = input_port_read(space->machine(),"CTRLSEL");
1143
1144   switch(ctrl & 0x0f)
1145   {
1146   case 0x00:
1147      ret = 0xffff;
1148      break;
1149   case 0x01:
1150      ret = input_port_read(space->machine(),"IN0");
1151      break;
1152   case 0x02:
1153      switch (state->m_controller_select)
1154      {
1155         case 0x09: ret = input_port_read(space->machine(), "MJ01_P1"); break;
1156         case 0x12: ret = input_port_read(space->machine(), "MJ02_P1"); break;
1157         case 0x1b: ret = input_port_read(space->machine(), "MJ03_P1"); break; /* player 1 normal inputs? */
1158         case 0x24: ret = input_port_read(space->machine(), "MJ04_P1"); break;
1159         default:
1160            ret = input_port_read(space->machine(),"IN0");
1161            break;
1162      }
1163      break;
1164   }
1165
1166   return ret;
1167}
1168
1169static READ16_HANDLER( aes_in1_r )
1170{
1171   neogeo_state *state = space->machine().driver_data<neogeo_state>();
1172   UINT32 ret = 0xffff;
1173   UINT32 ctrl = input_port_read(space->machine(),"CTRLSEL");
1174
1175   switch(ctrl & 0xf0)
1176   {
1177   case 0x00:
1178      ret = 0xffff;
1179      break;
1180   case 0x10:
1181      ret = input_port_read(space->machine(),"IN1");
1182      break;
1183   case 0x20:
1184      switch (state->m_controller_select)
1185      {
1186         case 0x09: ret = input_port_read(space->machine(), "MJ01_P2"); break;
1187         case 0x12: ret = input_port_read(space->machine(), "MJ02_P2"); break;
1188         case 0x1b: ret = input_port_read(space->machine(), "MJ03_P2"); break; /* player 2 normal inputs? */
1189         case 0x24: ret = input_port_read(space->machine(), "MJ04_P2"); break;
1190         default:
1191            ret = input_port_read(space->machine(),"IN1");
1192            break;
1193      }
1194      break;
1195   }
1196
1197   return ret;
1198}
1199
1200
1201static READ16_HANDLER(aes_in2_r)
1202{
1203   UINT32 in2 = input_port_read(space->machine(),"IN2");
1204   UINT32 ret = in2;
1205   UINT32 sel = input_port_read(space->machine(),"CTRLSEL");
1206   neogeo_state *state = space->machine().driver_data<neogeo_state>();
1207
1208   if((sel & 0x02) && (state->m_controller_select == 0x24))
1209      ret ^= 0x0200;
1210
1211   if((sel & 0x20) && (state->m_controller_select == 0x24))
1212      ret ^= 0x0800;
1213
1214   return ret;
1215}
1216
1217
1218/*************************************
1219 *
1220 *  Machine initialization
1221 *
1222 *************************************/
1223
1224static void aes_postload(neogeo_state *state)
1225{
1226   _set_main_cpu_bank_address(state->machine());
1227   _set_main_cpu_vector_table_source(state->machine());
1228   set_audio_cpu_banking(state->machine());
1229   _set_audio_cpu_rom_source(state->machine().device("maincpu")->memory().space(AS_PROGRAM));
1230}
1231
1232static void common_machine_start(running_machine &machine)
1233{
1234   neogeo_state *state = machine.driver_data<neogeo_state>();
1235
1236   /* set the BIOS bank */
1237   memory_set_bankptr(machine, NEOGEO_BANK_BIOS, machine.region("mainbios")->base());
1238
1239   /* set the initial main CPU bank */
1240   main_cpu_banking_init(machine);
1241
1242   /* set the initial audio CPU ROM banks */
1243   audio_cpu_banking_init(machine);
1244
1245   create_interrupt_timers(machine);
1246
1247   /* start with an IRQ3 - but NOT on a reset */
1248   state->m_irq3_pending = 1;
1249
1250   /* get devices */
1251   state->m_maincpu = machine.device("maincpu");
1252   state->m_audiocpu = machine.device("audiocpu");
1253   state->m_upd4990a = machine.device("upd4990a");
1254
1255   /* register state save */
1256   state->save_item(NAME(state->m_display_position_interrupt_control));
1257   state->save_item(NAME(state->m_display_counter));
1258   state->save_item(NAME(state->m_vblank_interrupt_pending));
1259   state->save_item(NAME(state->m_display_position_interrupt_pending));
1260   state->save_item(NAME(state->m_irq3_pending));
1261   state->save_item(NAME(state->m_audio_result));
1262   state->save_item(NAME(state->m_controller_select));
1263   state->save_item(NAME(state->m_main_cpu_bank_address));
1264   state->save_item(NAME(state->m_main_cpu_vector_table_source));
1265   state->save_item(NAME(state->m_audio_cpu_banks));
1266   state->save_item(NAME(state->m_audio_cpu_rom_source));
1267   state->save_item(NAME(state->m_audio_cpu_rom_source_last));
1268   state->save_item(NAME(state->m_save_ram_unlocked));
1269   state->save_item(NAME(state->m_output_data));
1270   state->save_item(NAME(state->m_output_latch));
1271   state->save_item(NAME(state->m_el_value));
1272   state->save_item(NAME(state->m_led1_value));
1273   state->save_item(NAME(state->m_led2_value));
1274   state->save_item(NAME(state->m_recurse));
1275
1276   machine.save().register_postload(save_prepost_delegate(FUNC(aes_postload), state));
1277}
1278
1279static MACHINE_START( neogeo )
1280{
1281   ng_aes_state *state = machine.driver_data<ng_aes_state>();
1282   common_machine_start(machine);
1283
1284   /* initialize the memcard data structure */
1285   state->m_memcard_data = auto_alloc_array_clear(machine, UINT8, MEMCARD_SIZE);
1286   state->save_pointer(NAME(state->m_memcard_data), 0x0800);
1287}
1288
1289static MACHINE_START(neocd)
1290{
1291   ng_aes_state *state = machine.driver_data<ng_aes_state>();
1292   UINT8* ROM = machine.region("mainbios")->base();
1293   UINT8* RAM = machine.region("maincpu")->base();
1294   UINT8* Z80bios = machine.region("audiobios")->base();
1295   UINT8* FIXbios = machine.region("fixedbios")->base();
1296   int x;
1297
1298   common_machine_start(machine);
1299
1300   /* initialize the memcard data structure */
1301   /* NeoCD doesn't have memcard slots, rather, it has a larger internal memory which works the same */
1302   state->m_memcard_data = auto_alloc_array_clear(machine, UINT8, 0x2000);
1303   state->save_pointer(NAME(state->m_memcard_data), 0x2000);
1304
1305   // copy initial 68k vectors into RAM
1306   memcpy(RAM,ROM,0x80);
1307
1308   // copy Z80 code into Z80 space (from 0x20000)
1309   for(x=0;x<0x10000;x+=2)
1310   {
1311      Z80bios[x] = ROM[x+0x20001];
1312      Z80bios[x+1] = ROM[x+0x20000];
1313   }
1314
1315   // copy fixed tiles into FIX space (from 0x70000)
1316   memcpy(FIXbios,ROM+0x70000,0x10000);
1317}
1318
1319//static DEVICE_IMAGE_LOAD(aes_cart)
1320//{
1321//  else
1322//      return IMAGE_INIT_FAIL;
1323
1324//  return IMAGE_INIT_PASS;
1325//}
1326
1327/*************************************
1328 *
1329 *  Machine reset
1330 *
1331 *************************************/
1332
1333static MACHINE_RESET( neogeo )
1334{
1335   neogeo_state *state = machine.driver_data<neogeo_state>();
1336   offs_t offs;
1337   address_space *space = machine.device("maincpu")->memory().space(AS_PROGRAM);
1338
1339   /* reset system control registers */
1340   for (offs = 0; offs < 8; offs++)
1341      system_control_w(space, offs, 0, 0x00ff);
1342
1343   machine.device("maincpu")->reset();
1344
1345   neogeo_reset_rng(machine);
1346
1347   start_interrupt_timers(machine);
1348
1349   /* trigger the IRQ3 that was set by MACHINE_START */
1350   update_interrupts(machine);
1351
1352   state->m_recurse = 0;
1353
1354   /* AES apparently always uses the cartridge's fixed bank mode */
1355   neogeo_set_fixed_layer_source(machine,1);
1356}
1357
1358
1359
1360/*************************************
1361 *
1362 *  Main CPU memory handlers
1363 *
1364 *************************************/
1365
1366static ADDRESS_MAP_START( main_map, AS_PROGRAM, 16 )
1367   AM_RANGE(0x000000, 0x00007f) AM_ROMBANK(NEOGEO_BANK_VECTORS)
1368   AM_RANGE(0x000080, 0x0fffff) AM_ROM
1369   AM_RANGE(0x100000, 0x10ffff) AM_MIRROR(0x0f0000) AM_RAM
1370   /* some games have protection devices in the 0x200000 region, it appears to map to cart space, not surprising, the ROM is read here too */
1371   AM_RANGE(0x200000, 0x2fffff) AM_ROMBANK(NEOGEO_BANK_CARTRIDGE)
1372   AM_RANGE(0x2ffff0, 0x2fffff) AM_WRITE(main_cpu_bank_select_w)
1373   AM_RANGE(0x300000, 0x300001) AM_MIRROR(0x01ff7e) AM_READ(aes_in0_r)
1374   AM_RANGE(0x300080, 0x300081) AM_MIRROR(0x01ff7e) AM_READ_PORT("IN4")
1375   AM_RANGE(0x300000, 0x300001) AM_MIRROR(0x01ffe0) AM_READ(neogeo_unmapped_r) AM_WRITENOP   // AES has no watchdog
1376   AM_RANGE(0x320000, 0x320001) AM_MIRROR(0x01fffe) AM_READ_PORT("IN3") AM_WRITE(audio_command_w)
1377   AM_RANGE(0x340000, 0x340001) AM_MIRROR(0x01fffe) AM_READ(aes_in1_r)
1378   AM_RANGE(0x360000, 0x37ffff) AM_READ(neogeo_unmapped_r)
1379   AM_RANGE(0x380000, 0x380001) AM_MIRROR(0x01fffe) AM_READ(aes_in2_r)
1380   AM_RANGE(0x380000, 0x38007f) AM_MIRROR(0x01ff80) AM_WRITE(io_control_w)
1381   AM_RANGE(0x3a0000, 0x3a001f) AM_MIRROR(0x01ffe0) AM_READWRITE(neogeo_unmapped_r, system_control_w)
1382   AM_RANGE(0x3c0000, 0x3c0007) AM_MIRROR(0x01fff8) AM_READ(neogeo_video_register_r)
1383   AM_RANGE(0x3c0000, 0x3c000f) AM_MIRROR(0x01fff0) AM_WRITE(neogeo_video_register_w)
1384   AM_RANGE(0x3e0000, 0x3fffff) AM_READ(neogeo_unmapped_r)
1385   AM_RANGE(0x400000, 0x401fff) AM_MIRROR(0x3fe000) AM_READWRITE(neogeo_paletteram_r, neogeo_paletteram_w)
1386   AM_RANGE(0x800000, 0x800fff) AM_READWRITE(memcard_r, memcard_w)
1387   AM_RANGE(0xc00000, 0xc1ffff) AM_MIRROR(0x0e0000) AM_ROMBANK(NEOGEO_BANK_BIOS)
1388   AM_RANGE(0xd00000, 0xd0ffff) AM_MIRROR(0x0f0000) AM_READ(neogeo_unmapped_r) //AM_RAM_WRITE(save_ram_w) AM_BASE(&save_ram)
1389   AM_RANGE(0xe00000, 0xffffff) AM_READ(neogeo_unmapped_r)
1390ADDRESS_MAP_END
1391
1392static ADDRESS_MAP_START( neocd_main_map, AS_PROGRAM, 16 )
1393   AM_RANGE(0x000000, 0x00007f) AM_RAMBANK(NEOGEO_BANK_VECTORS)
1394   AM_RANGE(0x000080, 0x0fffff) AM_RAM
1395   AM_RANGE(0x100000, 0x10ffff) AM_MIRROR(0x0f0000) AM_RAM AM_BASE(&neocd_work_ram)
1396   /* some games have protection devices in the 0x200000 region, it appears to map to cart space, not surprising, the ROM is read here too */
1397   AM_RANGE(0x200000, 0x2fffff) AM_ROMBANK(NEOGEO_BANK_CARTRIDGE)
1398   AM_RANGE(0x2ffff0, 0x2fffff) AM_WRITE(main_cpu_bank_select_w)
1399   AM_RANGE(0x300000, 0x300001) AM_MIRROR(0x01ff7e) AM_READ(aes_in0_r)
1400   AM_RANGE(0x300080, 0x300081) AM_MIRROR(0x01ff7e) AM_READ_PORT("IN4")
1401   AM_RANGE(0x300000, 0x300001) AM_MIRROR(0x01ffe0) AM_READ(neogeo_unmapped_r) AM_WRITENOP   // AES has no watchdog
1402   AM_RANGE(0x320000, 0x320001) AM_MIRROR(0x01fffe) AM_READ_PORT("IN3") AM_WRITE(audio_command_w)
1403   AM_RANGE(0x340000, 0x340001) AM_MIRROR(0x01fffe) AM_READ(aes_in1_r)
1404   AM_RANGE(0x360000, 0x37ffff) AM_READ(neogeo_unmapped_r)
1405   AM_RANGE(0x380000, 0x380001) AM_MIRROR(0x01fffe) AM_READ(aes_in2_r)
1406   AM_RANGE(0x380000, 0x38007f) AM_MIRROR(0x01ff80) AM_WRITE(io_control_w)
1407   AM_RANGE(0x3a0000, 0x3a001f) AM_MIRROR(0x01ffe0) AM_READWRITE(neogeo_unmapped_r, system_control_w)
1408   AM_RANGE(0x3c0000, 0x3c0007) AM_MIRROR(0x01fff8) AM_READ(neogeo_video_register_r)
1409   AM_RANGE(0x3c0000, 0x3c000f) AM_MIRROR(0x01fff0) AM_WRITE(neogeo_video_register_w)
1410   AM_RANGE(0x3e0000, 0x3fffff) AM_READ(neogeo_unmapped_r)
1411   AM_RANGE(0x400000, 0x401fff) AM_MIRROR(0x3fe000) AM_READWRITE(neogeo_paletteram_r, neogeo_paletteram_w)
1412   AM_RANGE(0x800000, 0x803fff) AM_READWRITE(neocd_memcard_r, neocd_memcard_w)
1413   AM_RANGE(0xc00000, 0xcfffff) AM_ROMBANK(NEOGEO_BANK_BIOS)
1414   AM_RANGE(0xd00000, 0xd0ffff) AM_MIRROR(0x0f0000) AM_READ(neogeo_unmapped_r) //AM_RAM_WRITE(save_ram_w) AM_BASE(&save_ram)
1415   AM_RANGE(0xe00000, 0xefffff) AM_READWRITE(neocd_transfer_r,neocd_transfer_w)
1416   AM_RANGE(0xf00000, 0xfeffff) AM_READ(neogeo_unmapped_r)
1417   AM_RANGE(0xff0000, 0xff01ff) AM_READWRITE(neocd_control_r, neocd_control_w) // CDROM / DMA
1418   AM_RANGE(0xff0200, 0xffffff) AM_READ(neogeo_unmapped_r)
1419ADDRESS_MAP_END
1420
1421
1422/*************************************
1423 *
1424 *  Audio CPU memory handlers
1425 *
1426 *************************************/
1427
1428static ADDRESS_MAP_START( audio_map, AS_PROGRAM, 8 )
1429   AM_RANGE(0x0000, 0x7fff) AM_ROMBANK(NEOGEO_BANK_AUDIO_CPU_MAIN_BANK)
1430   AM_RANGE(0x8000, 0xbfff) AM_ROMBANK(NEOGEO_BANK_AUDIO_CPU_CART_BANK + 3)
1431   AM_RANGE(0xc000, 0xdfff) AM_ROMBANK(NEOGEO_BANK_AUDIO_CPU_CART_BANK + 2)
1432   AM_RANGE(0xe000, 0xefff) AM_ROMBANK(NEOGEO_BANK_AUDIO_CPU_CART_BANK + 1)
1433   AM_RANGE(0xf000, 0xf7ff) AM_ROMBANK(NEOGEO_BANK_AUDIO_CPU_CART_BANK + 0)
1434   AM_RANGE(0xf800, 0xffff) AM_RAM
1435ADDRESS_MAP_END
1436
1437
1438
1439/*************************************
1440 *
1441 *  Audio CPU port handlers
1442 *
1443 *************************************/
1444
1445static ADDRESS_MAP_START( audio_io_map, AS_IO, 8 )
1446  /*AM_RANGE(0x00, 0x00) AM_MIRROR(0xff00) AM_READWRITE(audio_command_r, audio_cpu_clear_nmi_w);*/  /* may not and NMI clear */
1447   AM_RANGE(0x00, 0x00) AM_MIRROR(0xff00) AM_READ(audio_command_r)
1448   AM_RANGE(0x04, 0x07) AM_MIRROR(0xff00) AM_DEVREADWRITE("ymsnd", ym2610_r, ym2610_w)
1449   AM_RANGE(0x08, 0x08) AM_MIRROR(0xff00) /* write - NMI enable / acknowledge? (the data written doesn't matter) */
1450   AM_RANGE(0x08, 0x08) AM_MIRROR(0xfff0) AM_MASK(0xfff0) AM_READ(audio_cpu_bank_select_f000_f7ff_r)
1451   AM_RANGE(0x09, 0x09) AM_MIRROR(0xfff0) AM_MASK(0xfff0) AM_READ(audio_cpu_bank_select_e000_efff_r)
1452   AM_RANGE(0x0a, 0x0a) AM_MIRROR(0xfff0) AM_MASK(0xfff0) AM_READ(audio_cpu_bank_select_c000_dfff_r)
1453   AM_RANGE(0x0b, 0x0b) AM_MIRROR(0xfff0) AM_MASK(0xfff0) AM_READ(audio_cpu_bank_select_8000_bfff_r)
1454   AM_RANGE(0x0c, 0x0c) AM_MIRROR(0xff00) AM_WRITE(audio_result_w)
1455   AM_RANGE(0x18, 0x18) AM_MIRROR(0xff00) /* write - NMI disable? (the data written doesn't matter) */
1456ADDRESS_MAP_END
1457
1458
1459
1460/*************************************
1461 *
1462 *  Audio interface
1463 *
1464 *************************************/
1465
1466static const ym2610_interface ym2610_config =
1467{
1468   audio_cpu_irq
1469};
1470
1471
1472
1473/*************************************
1474 *
1475 *  Standard Neo-Geo DIPs and
1476 *  input port definition
1477 *
1478 *************************************/
1479
1480#define STANDARD_DIPS                                                      \
1481   PORT_DIPNAME( 0x0001, 0x0001, "Test Switch" ) PORT_DIPLOCATION("SW:1")               \
1482   PORT_DIPSETTING(     0x0001, DEF_STR( Off ) )                                 \
1483   PORT_DIPSETTING(     0x0000, DEF_STR( On ) )                                 \
1484   PORT_DIPNAME( 0x0002, 0x0002, "Coin Chutes?" ) PORT_DIPLOCATION("SW:2")               \
1485   PORT_DIPSETTING(     0x0000, "1?" )                                       \
1486   PORT_DIPSETTING(     0x0002, "2?" )                                       \
1487   PORT_DIPNAME( 0x0004, 0x0004, "Autofire (in some games)" ) PORT_DIPLOCATION("SW:3")      \
1488   PORT_DIPSETTING(     0x0004, DEF_STR( Off ) )                                 \
1489   PORT_DIPSETTING(     0x0000, DEF_STR( On ) )                                 \
1490   PORT_DIPNAME( 0x0018, 0x0018, "COMM Setting (Cabinet No.)" ) PORT_DIPLOCATION("SW:4,5")   \
1491   PORT_DIPSETTING(     0x0018, "1" )                                          \
1492   PORT_DIPSETTING(     0x0008, "2" )                                          \
1493   PORT_DIPSETTING(     0x0010, "3" )                                          \
1494   PORT_DIPSETTING(     0x0000, "4" )                                          \
1495   PORT_DIPNAME( 0x0020, 0x0020, "COMM Setting (Link Enable)" ) PORT_DIPLOCATION("SW:6")   \
1496   PORT_DIPSETTING(     0x0020, DEF_STR( Off ) )                                 \
1497   PORT_DIPSETTING(     0x0000, DEF_STR( On ) )                                 \
1498   PORT_DIPNAME( 0x0040, 0x0040, DEF_STR( Free_Play ) ) PORT_DIPLOCATION("SW:7")         \
1499   PORT_DIPSETTING(     0x0040, DEF_STR( Off ) )                                 \
1500   PORT_DIPSETTING(     0x0000, DEF_STR( On ) )                                 \
1501   PORT_DIPNAME( 0x0080, 0x0080, "Freeze" ) PORT_DIPLOCATION("SW:8")                  \
1502   PORT_DIPSETTING(     0x0080, DEF_STR( Off ) )                                 \
1503   PORT_DIPSETTING(     0x0000, DEF_STR( On ) )
1504
1505#define STANDARD_IN2                                                            \
1506   PORT_START("IN2")                                                            \
1507   PORT_BIT( 0x00ff, IP_ACTIVE_LOW, IPT_UNUSED )                                       \
1508   PORT_BIT( 0x0100, IP_ACTIVE_LOW, IPT_START1 )                           \
1509   PORT_BIT( 0x0200, IP_ACTIVE_LOW, IPT_BUTTON5) PORT_NAME("1P Select") PORT_CODE(KEYCODE_5) PORT_PLAYER(1)   \
1510   PORT_BIT( 0x0400, IP_ACTIVE_LOW, IPT_START2 )                           \
1511   PORT_BIT( 0x0800, IP_ACTIVE_LOW, IPT_BUTTON5) PORT_NAME("2P Select") PORT_CODE(KEYCODE_6) PORT_PLAYER(2)   \
1512   PORT_BIT( 0x7000, IP_ACTIVE_HIGH, IPT_SPECIAL ) PORT_CUSTOM(get_memcard_status, NULL)         \
1513   PORT_BIT( 0x8000, IP_ACTIVE_HIGH, IPT_UNKNOWN )  /* Matrimelee expects this bit to be active high when on an AES */
1514
1515#define STANDARD_IN3                                                            \
1516   PORT_START("IN3")                                                            \
1517   PORT_BIT( 0x0001, IP_ACTIVE_LOW, IPT_UNUSED )  /* Coin 1 - AES has no coin slots, it's a console */   \
1518   PORT_BIT( 0x0002, IP_ACTIVE_LOW, IPT_UNUSED )  /* Coin 2 - AES has no coin slots, it's a console */   \
1519   PORT_BIT( 0x0004, IP_ACTIVE_LOW, IPT_UNUSED )  /* Service Coin - not used, AES is a console */   \
1520   PORT_BIT( 0x0008, IP_ACTIVE_HIGH, IPT_UNKNOWN ) /* having this ACTIVE_HIGH causes you to start with 2 credits using USA bios roms */   \
1521   PORT_BIT( 0x0010, IP_ACTIVE_HIGH, IPT_UNKNOWN ) /* having this ACTIVE_HIGH causes you to start with 2 credits using USA bios roms */   \
1522   PORT_BIT( 0x0020, IP_ACTIVE_LOW, IPT_SPECIAL ) /* what is this? */                        \
1523   PORT_BIT( 0x00c0, IP_ACTIVE_HIGH, IPT_SPECIAL ) PORT_CUSTOM(get_calendar_status, NULL)         \
1524   PORT_BIT( 0xff00, IP_ACTIVE_HIGH, IPT_SPECIAL ) PORT_CUSTOM(get_audio_result, NULL)
1525
1526
1527#define STANDARD_IN4                                                         \
1528   PORT_START("IN4")                                                         \
1529   PORT_BIT( 0x0001, IP_ACTIVE_HIGH, IPT_UNKNOWN )                                    \
1530   PORT_BIT( 0x0002, IP_ACTIVE_HIGH, IPT_UNKNOWN )                                    \
1531   PORT_BIT( 0x0004, IP_ACTIVE_HIGH, IPT_UNKNOWN )                                    \
1532   PORT_BIT( 0x0008, IP_ACTIVE_HIGH, IPT_UNKNOWN )                                    \
1533   PORT_BIT( 0x0010, IP_ACTIVE_HIGH, IPT_UNKNOWN )                                    \
1534   PORT_BIT( 0x0020, IP_ACTIVE_HIGH, IPT_UNKNOWN )                                    \
1535   PORT_BIT( 0x0040, IP_ACTIVE_HIGH, IPT_SPECIAL ) /* what is this? - is 0 for 1 or 2 slot MVS (and AES?)*/                     \
1536   PORT_BIT( 0x0080, IP_ACTIVE_LOW, IPT_OTHER ) PORT_NAME("Enter BIOS") PORT_CODE(KEYCODE_F2)   \
1537   PORT_BIT( 0xff00, IP_ACTIVE_LOW, IPT_UNUSED )
1538
1539static INPUT_PORTS_START( controller )
1540   PORT_START("IN0")
1541   PORT_BIT( 0x00ff, IP_ACTIVE_LOW, IPT_UNUSED )
1542   PORT_BIT( 0x0100, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) PORT_PLAYER(1) PORT_CATEGORY (1)
1543   PORT_BIT( 0x0200, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) PORT_PLAYER(1) PORT_CATEGORY (1)
1544   PORT_BIT( 0x0400, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) PORT_PLAYER(1) PORT_CATEGORY (1)
1545   PORT_BIT( 0x0800, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) PORT_PLAYER(1) PORT_CATEGORY (1)
1546   PORT_BIT( 0x1000, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_PLAYER(1) PORT_CATEGORY (1)
1547   PORT_BIT( 0x2000, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_PLAYER(1) PORT_CATEGORY (1)
1548   PORT_BIT( 0x4000, IP_ACTIVE_LOW, IPT_BUTTON3 ) PORT_PLAYER(1) PORT_CATEGORY (1)
1549   PORT_BIT( 0x8000, IP_ACTIVE_LOW, IPT_BUTTON4 ) PORT_PLAYER(1) PORT_CATEGORY (1)
1550
1551
1552   PORT_START("IN1")
1553   PORT_BIT( 0x00ff, IP_ACTIVE_LOW, IPT_UNUSED )
1554   PORT_BIT( 0x0100, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) PORT_PLAYER(2) PORT_CATEGORY (2)
1555   PORT_BIT( 0x0200, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) PORT_PLAYER(2) PORT_CATEGORY (2)
1556   PORT_BIT( 0x0400, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) PORT_PLAYER(2) PORT_CATEGORY (2)
1557   PORT_BIT( 0x0800, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) PORT_PLAYER(2) PORT_CATEGORY (2)
1558   PORT_BIT( 0x1000, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_PLAYER(2) PORT_CATEGORY (2)
1559   PORT_BIT( 0x2000, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_PLAYER(2) PORT_CATEGORY (2)
1560   PORT_BIT( 0x4000, IP_ACTIVE_LOW, IPT_BUTTON3 ) PORT_PLAYER(2) PORT_CATEGORY (2)
1561   PORT_BIT( 0x8000, IP_ACTIVE_LOW, IPT_BUTTON4 ) PORT_PLAYER(2) PORT_CATEGORY (2)
1562INPUT_PORTS_END
1563
1564static INPUT_PORTS_START( mjpanel )
1565   PORT_START("MJ01_P1")
1566   PORT_BIT( 0x00ff, IP_ACTIVE_HIGH, IPT_UNUSED )
1567   PORT_BIT( 0x0100, IP_ACTIVE_LOW, IPT_MAHJONG_A ) PORT_PLAYER(1) PORT_CATEGORY (3)
1568   PORT_BIT( 0x0200, IP_ACTIVE_LOW, IPT_MAHJONG_B ) PORT_PLAYER(1) PORT_CATEGORY (3)
1569   PORT_BIT( 0x0400, IP_ACTIVE_LOW, IPT_MAHJONG_C ) PORT_PLAYER(1) PORT_CATEGORY (3)
1570   PORT_BIT( 0x0800, IP_ACTIVE_LOW, IPT_MAHJONG_D ) PORT_PLAYER(1) PORT_CATEGORY (3)
1571   PORT_BIT( 0x1000, IP_ACTIVE_LOW, IPT_MAHJONG_E ) PORT_PLAYER(1) PORT_CATEGORY (3)
1572   PORT_BIT( 0x2000, IP_ACTIVE_LOW, IPT_MAHJONG_F ) PORT_PLAYER(1) PORT_CATEGORY (3)
1573   PORT_BIT( 0x4000, IP_ACTIVE_LOW, IPT_MAHJONG_G ) PORT_PLAYER(1) PORT_CATEGORY (3)
1574   PORT_BIT( 0x8000, IP_ACTIVE_LOW, IPT_UNKNOWN )
1575
1576   PORT_START("MJ02_P1")
1577   PORT_BIT( 0x00ff, IP_ACTIVE_HIGH, IPT_UNUSED )
1578   PORT_BIT( 0x0100, IP_ACTIVE_LOW, IPT_MAHJONG_H ) PORT_PLAYER(1) PORT_CATEGORY (3)
1579   PORT_BIT( 0x0200, IP_ACTIVE_LOW, IPT_MAHJONG_I ) PORT_PLAYER(1) PORT_CATEGORY (3)
1580   PORT_BIT( 0x0400, IP_ACTIVE_LOW, IPT_MAHJONG_J ) PORT_PLAYER(1) PORT_CATEGORY (3)
1581   PORT_BIT( 0x0800, IP_ACTIVE_LOW, IPT_MAHJONG_K ) PORT_PLAYER(1) PORT_CATEGORY (3)
1582   PORT_BIT( 0x1000, IP_ACTIVE_LOW, IPT_MAHJONG_L ) PORT_PLAYER(1) PORT_CATEGORY (3)
1583   PORT_BIT( 0x2000, IP_ACTIVE_LOW, IPT_MAHJONG_M ) PORT_PLAYER(1) PORT_CATEGORY (3)
1584   PORT_BIT( 0x4000, IP_ACTIVE_LOW, IPT_MAHJONG_N ) PORT_PLAYER(1) PORT_CATEGORY (3)
1585   PORT_BIT( 0x8000, IP_ACTIVE_LOW, IPT_BUTTON6 ) PORT_PLAYER(1) PORT_CATEGORY (3)
1586
1587   PORT_START("MJ03_P1")
1588   PORT_BIT( 0x00ff, IP_ACTIVE_HIGH, IPT_UNUSED )
1589   PORT_BIT( 0x0100, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) PORT_PLAYER(1) PORT_CATEGORY (3)
1590   PORT_BIT( 0x0200, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) PORT_PLAYER(1) PORT_CATEGORY (3)
1591   PORT_BIT( 0x0400, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) PORT_PLAYER(1) PORT_CATEGORY (3)
1592   PORT_BIT( 0x0800, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) PORT_PLAYER(1) PORT_CATEGORY (3)
1593   PORT_BIT( 0x1000, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_PLAYER(1) PORT_CATEGORY (3)
1594   PORT_BIT( 0x2000, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_PLAYER(1) PORT_CATEGORY (3)
1595   PORT_BIT( 0x4000, IP_ACTIVE_LOW, IPT_BUTTON3 ) PORT_PLAYER(1) PORT_CATEGORY (3)
1596   PORT_BIT( 0x8000, IP_ACTIVE_LOW, IPT_BUTTON4 ) PORT_PLAYER(1) PORT_CATEGORY (3)
1597
1598   PORT_START("MJ04_P1")
1599   PORT_BIT( 0x00ff, IP_ACTIVE_HIGH, IPT_UNUSED )
1600   PORT_BIT( 0x0100, IP_ACTIVE_LOW, IPT_MAHJONG_PON ) PORT_PLAYER(1) PORT_CATEGORY (3)
1601   PORT_BIT( 0x0200, IP_ACTIVE_LOW, IPT_MAHJONG_CHI ) PORT_PLAYER(1) PORT_CATEGORY (3)
1602   PORT_BIT( 0x0400, IP_ACTIVE_LOW, IPT_MAHJONG_KAN ) PORT_PLAYER(1) PORT_CATEGORY (3)
1603   PORT_BIT( 0x0800, IP_ACTIVE_LOW, IPT_MAHJONG_RON ) PORT_PLAYER(1) PORT_CATEGORY (3)
1604   PORT_BIT( 0x1000, IP_ACTIVE_LOW, IPT_MAHJONG_REACH ) PORT_PLAYER(1) PORT_CATEGORY (3)
1605   PORT_BIT( 0x2000, IP_ACTIVE_LOW, IPT_UNKNOWN )
1606   PORT_BIT( 0x4000, IP_ACTIVE_LOW, IPT_UNKNOWN )
1607   PORT_BIT( 0x8000, IP_ACTIVE_LOW, IPT_UNKNOWN )
1608
1609   PORT_START("MJ01_P2")
1610   PORT_BIT( 0x00ff, IP_ACTIVE_HIGH, IPT_UNUSED )
1611   PORT_BIT( 0x0100, IP_ACTIVE_LOW, IPT_MAHJONG_A ) PORT_PLAYER(2) PORT_CATEGORY (4)
1612   PORT_BIT( 0x0200, IP_ACTIVE_LOW, IPT_MAHJONG_B ) PORT_PLAYER(2) PORT_CATEGORY (4)
1613   PORT_BIT( 0x0400, IP_ACTIVE_LOW, IPT_MAHJONG_C ) PORT_PLAYER(2) PORT_CATEGORY (4)
1614   PORT_BIT( 0x0800, IP_ACTIVE_LOW, IPT_MAHJONG_D ) PORT_PLAYER(2) PORT_CATEGORY (4)
1615   PORT_BIT( 0x1000, IP_ACTIVE_LOW, IPT_MAHJONG_E ) PORT_PLAYER(2) PORT_CATEGORY (4)
1616   PORT_BIT( 0x2000, IP_ACTIVE_LOW, IPT_MAHJONG_F ) PORT_PLAYER(2) PORT_CATEGORY (4)
1617   PORT_BIT( 0x4000, IP_ACTIVE_LOW, IPT_MAHJONG_G ) PORT_PLAYER(2) PORT_CATEGORY (4)
1618   PORT_BIT( 0x8000, IP_ACTIVE_LOW, IPT_UNKNOWN )
1619
1620   PORT_START("MJ02_P2")
1621   PORT_BIT( 0x00ff, IP_ACTIVE_HIGH, IPT_UNUSED )
1622   PORT_BIT( 0x0100, IP_ACTIVE_LOW, IPT_MAHJONG_H ) PORT_PLAYER(2) PORT_CATEGORY (4)
1623   PORT_BIT( 0x0200, IP_ACTIVE_LOW, IPT_MAHJONG_I ) PORT_PLAYER(2) PORT_CATEGORY (4)
1624   PORT_BIT( 0x0400, IP_ACTIVE_LOW, IPT_MAHJONG_J ) PORT_PLAYER(2) PORT_CATEGORY (4)
1625   PORT_BIT( 0x0800, IP_ACTIVE_LOW, IPT_MAHJONG_K ) PORT_PLAYER(2) PORT_CATEGORY (4)
1626   PORT_BIT( 0x1000, IP_ACTIVE_LOW, IPT_MAHJONG_L ) PORT_PLAYER(2) PORT_CATEGORY (4)
1627   PORT_BIT( 0x2000, IP_ACTIVE_LOW, IPT_MAHJONG_M ) PORT_PLAYER(2) PORT_CATEGORY (4)
1628   PORT_BIT( 0x4000, IP_ACTIVE_LOW, IPT_MAHJONG_N ) PORT_PLAYER(2) PORT_CATEGORY (4)
1629   PORT_BIT( 0x8000, IP_ACTIVE_LOW, IPT_UNKNOWN )
1630
1631   PORT_START("MJ03_P2")
1632   PORT_BIT( 0x00ff, IP_ACTIVE_HIGH, IPT_UNUSED )
1633   PORT_BIT( 0x0100, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) PORT_PLAYER(2) PORT_CATEGORY (4)
1634   PORT_BIT( 0x0200, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) PORT_PLAYER(2) PORT_CATEGORY (4)
1635   PORT_BIT( 0x0400, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) PORT_PLAYER(2) PORT_CATEGORY (4)
1636   PORT_BIT( 0x0800, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) PORT_PLAYER(2) PORT_CATEGORY (4)
1637   PORT_BIT( 0x1000, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_PLAYER(2) PORT_CATEGORY (4)
1638   PORT_BIT( 0x2000, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_PLAYER(2) PORT_CATEGORY (4)
1639   PORT_BIT( 0x4000, IP_ACTIVE_LOW, IPT_BUTTON3 ) PORT_PLAYER(2) PORT_CATEGORY (4)
1640   PORT_BIT( 0x8000, IP_ACTIVE_LOW, IPT_BUTTON4 ) PORT_PLAYER(2) PORT_CATEGORY (4)
1641
1642   PORT_START("MJ04_P2")
1643   PORT_BIT( 0x00ff, IP_ACTIVE_HIGH, IPT_UNUSED )
1644   PORT_BIT( 0x0100, IP_ACTIVE_LOW, IPT_MAHJONG_PON ) PORT_PLAYER(2) PORT_CATEGORY (4)
1645   PORT_BIT( 0x0200, IP_ACTIVE_LOW, IPT_MAHJONG_CHI ) PORT_PLAYER(2) PORT_CATEGORY (4)
1646   PORT_BIT( 0x0400, IP_ACTIVE_LOW, IPT_MAHJONG_KAN ) PORT_PLAYER(2) PORT_CATEGORY (4)
1647   PORT_BIT( 0x0800, IP_ACTIVE_LOW, IPT_MAHJONG_RON ) PORT_PLAYER(2) PORT_CATEGORY (4)
1648   PORT_BIT( 0x1000, IP_ACTIVE_LOW, IPT_MAHJONG_REACH ) PORT_PLAYER(2) PORT_CATEGORY (4)
1649   PORT_BIT( 0x2000, IP_ACTIVE_LOW, IPT_UNKNOWN )
1650   PORT_BIT( 0x4000, IP_ACTIVE_LOW, IPT_UNKNOWN )
1651   PORT_BIT( 0x8000, IP_ACTIVE_LOW, IPT_UNKNOWN )
1652
1653INPUT_PORTS_END
1654
1655static INPUT_PORTS_START( aes )
1656// was there anyting in place of dipswitch in the home console?
1657/*  PORT_START("IN0")
1658    PORT_BIT( 0x00ff, IP_ACTIVE_LOW, IPT_UNUSED )
1659//  PORT_DIPNAME( 0x0001, 0x0001, "Test Switch" ) PORT_DIPLOCATION("SW:1")
1660//  PORT_DIPSETTING(      0x0001, DEF_STR( Off ) )
1661//  PORT_DIPSETTING(      0x0000, DEF_STR( On ) )
1662//  PORT_DIPNAME( 0x0002, 0x0002, "Coin Chutes?" ) PORT_DIPLOCATION("SW:2")
1663//  PORT_DIPSETTING(      0x0000, "1?" )
1664//  PORT_DIPSETTING(      0x0002, "2?" )
1665//  PORT_DIPNAME( 0x0004, 0x0000, "Mahjong Control Panel (or Auto Fire)" ) PORT_DIPLOCATION("SW:3")
1666//  PORT_DIPSETTING(      0x0004, DEF_STR( Off ) )
1667//  PORT_DIPSETTING(      0x0000, DEF_STR( On ) )
1668//  PORT_DIPNAME( 0x0018, 0x0018, "COMM Setting (Cabinet No.)" ) PORT_DIPLOCATION("SW:4,5")
1669//  PORT_DIPSETTING(      0x0018, "1" )
1670//  PORT_DIPSETTING(      0x0008, "2" )
1671//  PORT_DIPSETTING(      0x0010, "3" )
1672//  PORT_DIPSETTING(      0x0000, "4" )
1673//  PORT_DIPNAME( 0x0020, 0x0020, "COMM Setting (Link Enable)" ) PORT_DIPLOCATION("SW:6")
1674//  PORT_DIPSETTING(      0x0020, DEF_STR( Off ) )
1675//  PORT_DIPSETTING(      0x0000, DEF_STR( On ) )
1676//  PORT_DIPNAME( 0x0040, 0x0040, DEF_STR( Free_Play ) ) PORT_DIPLOCATION("SW:7")
1677//  PORT_DIPSETTING(      0x0040, DEF_STR( Off ) )
1678//  PORT_DIPSETTING(      0x0000, DEF_STR( On ) )
1679//  PORT_DIPNAME( 0x0080, 0x0080, "Freeze" ) PORT_DIPLOCATION("SW:8")
1680//  PORT_DIPSETTING(      0x0080, DEF_STR( Off ) )
1681//  PORT_DIPSETTING(      0x0000, DEF_STR( On ) )
1682    PORT_BIT( 0xff00, IP_ACTIVE_HIGH, IPT_SPECIAL ) PORT_CUSTOM(aes_controller_r, NULL) */
1683
1684   PORT_START("CTRLSEL")  /* Select Controller Type */
1685   PORT_CATEGORY_CLASS( 0x0f, 0x01, "P1 Controller")
1686   PORT_CATEGORY_ITEM(  0x00, "Unconnected",         0 )
1687   PORT_CATEGORY_ITEM(  0x01, "NeoGeo Controller",      1 )
1688   PORT_CATEGORY_ITEM(  0x02, "NeoGeo Mahjong Panel",   3 )
1689   PORT_CATEGORY_CLASS( 0xf0, 0x10, "P2 Controller")
1690   PORT_CATEGORY_ITEM(  0x00, "Unconnected",      0 )
1691   PORT_CATEGORY_ITEM(  0x10, "NeoGeo Controller",      2 )
1692   PORT_CATEGORY_ITEM(  0x20, "NeoGeo Mahjong Panel",   4 )
1693
1694   PORT_INCLUDE( controller )
1695
1696   PORT_INCLUDE( mjpanel )
1697
1698// were some of these present in the AES?!?
1699   STANDARD_IN2
1700
1701   STANDARD_IN3
1702
1703   STANDARD_IN4
1704INPUT_PORTS_END
1705
1706
1707
1708/*************************************
1709 *
1710 *  Machine driver
1711 *
1712 *************************************/
1713
1714static MACHINE_CONFIG_START( neogeo, ng_aes_state )
1715
1716   /* basic machine hardware */
1717   MCFG_CPU_ADD("maincpu", M68000, NEOGEO_MAIN_CPU_CLOCK)
1718   MCFG_CPU_PROGRAM_MAP(main_map)
1719
1720   MCFG_CPU_ADD("audiocpu", Z80, NEOGEO_AUDIO_CPU_CLOCK)
1721   MCFG_CPU_PROGRAM_MAP(audio_map)
1722   MCFG_CPU_IO_MAP(audio_io_map)
1723
1724   MCFG_MACHINE_START(neogeo)
1725   MCFG_MACHINE_RESET(neogeo)
1726
1727   /* video hardware */
1728   MCFG_VIDEO_START(neogeo)
1729   MCFG_VIDEO_RESET(neogeo)
1730   MCFG_DEFAULT_LAYOUT(layout_neogeo)
1731
1732   MCFG_SCREEN_ADD("screen", RASTER)
1733   MCFG_SCREEN_FORMAT(BITMAP_FORMAT_RGB32)
1734   MCFG_SCREEN_RAW_PARAMS(NEOGEO_PIXEL_CLOCK, NEOGEO_HTOTAL, NEOGEO_HBEND, NEOGEO_HBSTART, NEOGEO_VTOTAL, NEOGEO_VBEND, NEOGEO_VBSTART)
1735   MCFG_SCREEN_UPDATE(neogeo)
1736
1737   /* audio hardware */
1738   MCFG_SPEAKER_STANDARD_STEREO("lspeaker", "rspeaker")
1739
1740   MCFG_SOUND_ADD("ymsnd", YM2610, NEOGEO_YM2610_CLOCK)
1741   MCFG_SOUND_CONFIG(ym2610_config)
1742   MCFG_SOUND_ROUTE(0, "lspeaker",  0.60)
1743   MCFG_SOUND_ROUTE(0, "rspeaker", 0.60)
1744   MCFG_SOUND_ROUTE(1, "lspeaker",  1.0)
1745   MCFG_SOUND_ROUTE(2, "rspeaker", 1.0)
1746
1747   /* NEC uPD4990A RTC */
1748   MCFG_UPD4990A_ADD("upd4990a")
1749MACHINE_CONFIG_END
1750
1751static MACHINE_CONFIG_DERIVED( aes, neogeo )
1752
1753   MCFG_MEMCARD_HANDLER(neogeo)
1754
1755   MCFG_AES_CARTRIDGE_ADD("aes_multicart")
1756//  MCFG_CARTSLOT_ADD("cart")
1757//  MCFG_CARTSLOT_MANDATORY
1758
1759//  MCFG_CARTSLOT_LOAD(aes_cart)
1760
1761   MCFG_SOFTWARE_LIST_ADD("cart_list","aes")
1762MACHINE_CONFIG_END
1763
1764static MACHINE_CONFIG_DERIVED( neocd, neogeo )
1765
1766   MCFG_CPU_MODIFY("maincpu")
1767   MCFG_CPU_PROGRAM_MAP(neocd_main_map)
1768
1769   MCFG_MACHINE_START(neocd)
1770MACHINE_CONFIG_END
1771
1772/*************************************
1773 *
1774 *  Driver initalization
1775 *
1776 *************************************/
1777
1778static DRIVER_INIT( neogeo )
1779{
1780}
1781
1782
1783ROM_START( aes )
1784   ROM_REGION16_BE( 0x80000, "mainbios", 0 )
1785   ROM_SYSTEM_BIOS( 0, "jap-aes",   "Japan AES" )
1786   ROMX_LOAD("neo-po.bin",  0x00000, 0x020000, CRC(16d0c132) SHA1(4e4a440cae46f3889d20234aebd7f8d5f522e22c), ROM_GROUPWORD | ROM_REVERSE | ROM_BIOS(1))   /* AES Console (Japan) Bios */
1787   ROM_SYSTEM_BIOS( 1, "asia-aes",   "Asia AES" )
1788   ROMX_LOAD("neo-epo.bin", 0x00000, 0x020000, CRC(d27a71f1) SHA1(1b3b22092f30c4d1b2c15f04d1670eb1e9fbea07), ROM_GROUPWORD | ROM_REVERSE | ROM_BIOS(2))   /* AES Console (Asia?) Bios */
1789//  ROM_SYSTEM_BIOS( 2, "uni-bios_2_3","Universe Bios (Hack, Ver. 2.3)" )
1790//  ROMX_LOAD( "uni-bios_2_3.rom",  0x00000, 0x020000, CRC(27664eb5) SHA1(5b02900a3ccf3df168bdcfc98458136fd2b92ac0), ROM_GROUPWORD | ROM_REVERSE | ROM_BIOS(3) ) /* Universe Bios v2.3 (hack) */
1791
1792   ROM_REGION( 0x200000, "maincpu", ROMREGION_ERASEFF )
1793
1794   ROM_REGION( 0x20000, "audiobios", 0 )
1795   ROM_LOAD( "sm1.sm1", 0x00000, 0x20000, CRC(94416d67) SHA1(42f9d7ddd6c0931fd64226a60dc73602b2819dcf) )
1796
1797   ROM_REGION( 0x90000, "audiocpu", ROMREGION_ERASEFF )
1798
1799   ROM_REGION( 0x20000, "zoomy", 0 )
1800   ROM_LOAD( "000-lo.lo", 0x00000, 0x20000, CRC(5a86cff2) SHA1(5992277debadeb64d1c1c64b0a92d9293eaf7e4a) )
1801
1802   ROM_REGION( 0x20000, "fixedbios", 0 )
1803   ROM_LOAD( "sfix.sfix", 0x000000, 0x20000, CRC(c2ea0cfd) SHA1(fd4a618cdcdbf849374f0a50dd8efe9dbab706c3) )
1804
1805   ROM_REGION( 0x20000, "fixed", ROMREGION_ERASEFF )
1806
1807   ROM_REGION( 0x1000000, "ymsnd", ROMREGION_ERASEFF )
1808
1809   ROM_REGION( 0x1000000, "ymsnd.deltat", ROMREGION_ERASEFF )
1810
1811   ROM_REGION( 0x900000, "sprites", ROMREGION_ERASEFF )
1812ROM_END
1813
1814ROM_START( neocd )
1815   ROM_REGION16_BE( 0x100000, "mainbios", 0 )
1816   ROM_LOAD16_WORD_SWAP( "top-sp1.bin",    0x00000, 0x80000, CRC(19f0ad1a) SHA1(b3e2f8467e9a642c122428d075024a9bd1fe0679) )
1817
1818   ROM_REGION( 0x200000, "maincpu", ROMREGION_ERASEFF )
1819
1820   ROM_REGION( 0x100000, "audiobios", ROMREGION_ERASEFF )
1821
1822   ROM_REGION( 0x10000, "audiocpu", ROMREGION_ERASEFF )
1823
1824   ROM_REGION( 0x20000, "zoomy", 0 )
1825   ROM_LOAD( "000-lo.lo", 0x00000, 0x20000, CRC(5a86cff2) SHA1(5992277debadeb64d1c1c64b0a92d9293eaf7e4a) )
1826
1827   ROM_REGION( 0x20000, "fixedbios", ROMREGION_ERASEFF )
1828
1829   ROM_REGION( 0x20000, "fixed", ROMREGION_ERASEFF )
1830
1831   ROM_REGION( 0x400000, "ymsnd", ROMREGION_ERASEFF )
1832
1833//    NO_DELTAT_REGION
1834
1835   ROM_REGION( 0x400000, "sprites", ROMREGION_ERASEFF )
1836ROM_END
1837
1838ROM_START( neocdz )
1839   ROM_REGION16_BE( 0x100000, "mainbios", 0 )
1840   ROM_LOAD16_WORD_SWAP( "neocd.bin",    0x00000, 0x80000, CRC(df9de490) SHA1(7bb26d1e5d1e930515219cb18bcde5b7b23e2eda) )
1841
1842   ROM_REGION( 0x200000, "maincpu", ROMREGION_ERASEFF )
1843
1844   ROM_REGION( 0x20000, "audiobios", ROMREGION_ERASEFF )
1845
1846   ROM_REGION( 0x10000, "audiocpu", ROMREGION_ERASEFF )
1847
1848   ROM_REGION( 0x20000, "zoomy", 0 )
1849   ROM_LOAD( "000-lo.lo", 0x00000, 0x20000, CRC(5a86cff2) SHA1(5992277debadeb64d1c1c64b0a92d9293eaf7e4a) )
1850
1851   ROM_REGION( 0x20000, "fixedbios", ROMREGION_ERASEFF )
1852
1853   ROM_REGION( 0x20000, "fixed", ROMREGION_ERASEFF )
1854
1855   ROM_REGION( 0x400000, "ymsnd", ROMREGION_ERASEFF )
1856
1857//    NO_DELTAT_REGION
1858
1859   ROM_REGION( 0x400000, "sprites", ROMREGION_ERASEFF )
1860ROM_END
1861
1862/*    YEAR  NAME  PARENT COMPAT MACHINE INPUT  INIT     COMPANY      FULLNAME            FLAGS */
1863CONS( 1990, aes,    0,   0,   aes,      aes,   neogeo,  "SNK", "Neo-Geo AES", 0)
1864CONS( 1994, neocd,  aes, 0,   neocd,    aes,   neogeo,  "SNK", "Neo-Geo CD", GAME_NOT_WORKING )
1865CONS( 1996, neocdz, aes, 0,   neocd,    aes,   neogeo,  "SNK", "Neo-Geo CDZ", GAME_NOT_WORKING )
src/mame/drivers/nes.c
r11531r11532
1/***************************************************************************
2
3  nes.c
4
5  Driver file to handle emulation of the Nintendo Entertainment System (Famicom).
6
7  MESS driver by Brad Oliver (bradman@pobox.com), NES sound code by Matt Conte.
8  Based in part on the old xNes code, by Nicolas Hamel, Chuck Mason, Brad Oliver,
9  Richard Bannister and Jeff Mitchell.
10
11***************************************************************************/
12
13#include "emu.h"
14#include "video/ppu2c0x.h"
15#include "machine/nes_mmc.h"
16#include "includes/nes.h"
17#include "cpu/m6502/m6502.h"
18#include "imagedev/cartslot.h"
19#include "sound/nes_apu.h"
20#include "imagedev/flopdrv.h"
21#include "formats/nes_dsk.h"
22
23
24static READ8_DEVICE_HANDLER( psg_4015_r )
25{
26   return nes_psg_r(device, 0x15);
27}
28
29static WRITE8_DEVICE_HANDLER( psg_4015_w )
30{
31   nes_psg_w(device, 0x15, data);
32}
33
34static WRITE8_DEVICE_HANDLER( psg_4017_w )
35{
36   nes_psg_w(device, 0x17, data);
37}
38
39static WRITE8_HANDLER(nes_vh_sprite_dma_w)
40{
41   nes_state *state = space->machine().driver_data<nes_state>();
42   ppu2c0x_spriteram_dma(space, state->m_ppu, data);
43}
44
45static ADDRESS_MAP_START( nes_map, AS_PROGRAM, 8 )
46   AM_RANGE(0x0000, 0x07ff) AM_RAM AM_MIRROR(0x1800)               /* RAM */
47   AM_RANGE(0x2000, 0x3fff) AM_DEVREADWRITE("ppu", ppu2c0x_r, ppu2c0x_w)      /* PPU registers */
48   AM_RANGE(0x4000, 0x4013) AM_DEVREADWRITE("nessound", nes_psg_r, nes_psg_w)      /* PSG primary registers */
49   AM_RANGE(0x4014, 0x4014) AM_WRITE(nes_vh_sprite_dma_w)            /* stupid address space hole */
50   AM_RANGE(0x4015, 0x4015) AM_DEVREADWRITE("nessound", psg_4015_r, psg_4015_w)      /* PSG status / first control register */
51   AM_RANGE(0x4016, 0x4016) AM_READWRITE(nes_IN0_r, nes_IN0_w)         /* IN0 - input port 1 */
52   AM_RANGE(0x4017, 0x4017) AM_READ(nes_IN1_r)                     /* IN1 - input port 2 */
53   AM_RANGE(0x4017, 0x4017) AM_DEVWRITE("nessound", psg_4017_w)      /* PSG second control register */
54   AM_RANGE(0x4100, 0x5fff) AM_READWRITE(nes_low_mapper_r, nes_low_mapper_w)   /* Perform unholy acts on the machine */
55ADDRESS_MAP_END
56
57
58static INPUT_PORTS_START( nes_controllers )
59   PORT_START("CTRLSEL")  /* Select Controller Type */
60   PORT_CATEGORY_CLASS( 0x000f, 0x0001, "P1 Controller")
61   PORT_CATEGORY_ITEM(  0x0000, "Unconnected",      0 )
62   PORT_CATEGORY_ITEM(  0x0001, "Gamepad",         1 )
63   PORT_CATEGORY_ITEM(  0x0002, "Zapper",         5 )
64   PORT_CATEGORY_ITEM(  0x0006, "Crazy Climber pad", 10 )
65   PORT_CATEGORY_CLASS( 0x00f0, 0x0010, "P2 Controller")
66   PORT_CATEGORY_ITEM(  0x0000, "Unconnected",      0 )
67   PORT_CATEGORY_ITEM(  0x0010, "Gamepad",         2 )
68   PORT_CATEGORY_ITEM(  0x0030, "Zapper",         6 )
69   PORT_CATEGORY_ITEM(  0x0040, "Arkanoid paddle",   7 )
70//  PORT_CATEGORY_ITEM(  0x0050, "Family Trainer",  11 )
71   PORT_CATEGORY_CLASS( 0x0f00, 0x0000, "P3 Controller")
72   PORT_CATEGORY_ITEM(  0x0000, "Unconnected",      0 )
73   PORT_CATEGORY_ITEM(  0x0100, "Gamepad",         3 )
74   PORT_CATEGORY_CLASS( 0xf000, 0x0000, "P4 Controller")
75   PORT_CATEGORY_ITEM(  0x0000, "Unconnected",      0 )
76   PORT_CATEGORY_ITEM(  0x1000, "Gamepad",         4 )
77
78   PORT_START("PAD1")   /* Joypad 1 */
79   PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_BUTTON1 ) PORT_NAME("P1 A") PORT_CATEGORY(1) PORT_PLAYER(1)
80   PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_BUTTON2 ) PORT_NAME("P1 B") PORT_CATEGORY(1) PORT_PLAYER(1)
81   PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_SELECT ) PORT_CATEGORY(1) PORT_PLAYER(1)
82   PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_START ) PORT_CATEGORY(1) PORT_PLAYER(1)
83   PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_JOYSTICK_UP ) PORT_CATEGORY(1) PORT_PLAYER(1)
84   PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_JOYSTICK_DOWN ) PORT_CATEGORY(1) PORT_PLAYER(1)
85   PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_JOYSTICK_LEFT ) PORT_CATEGORY(1) PORT_PLAYER(1)
86   PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_JOYSTICK_RIGHT ) PORT_CATEGORY(1) PORT_PLAYER(1)
87
88   PORT_START("PAD2")   /* Joypad 2 */
89   PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_BUTTON1 ) PORT_NAME("P2 A") PORT_CATEGORY(2) PORT_PLAYER(2)
90   PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_BUTTON2 ) PORT_NAME("P2 B") PORT_CATEGORY(2) PORT_PLAYER(2)
91   PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_SELECT ) PORT_CATEGORY(2) PORT_PLAYER(2)
92   PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_START ) PORT_CATEGORY(2) PORT_PLAYER(2)
93   PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_JOYSTICK_UP ) PORT_CATEGORY(2) PORT_PLAYER(2)
94   PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_JOYSTICK_DOWN ) PORT_CATEGORY(2) PORT_PLAYER(2)
95   PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_JOYSTICK_LEFT ) PORT_CATEGORY(2) PORT_PLAYER(2)
96   PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_JOYSTICK_RIGHT ) PORT_CATEGORY(2) PORT_PLAYER(2)
97
98   PORT_START("PAD3")   /* Joypad 3 */
99   PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_BUTTON1 ) PORT_NAME("P3 A") PORT_CATEGORY(3) PORT_PLAYER(3)
100   PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_BUTTON2 ) PORT_NAME("P3 B") PORT_CATEGORY(3) PORT_PLAYER(3)
101   PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_SELECT ) PORT_CATEGORY(3) PORT_PLAYER(3)
102   PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_START ) PORT_CATEGORY(3) PORT_PLAYER(3)
103   PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_JOYSTICK_UP ) PORT_CATEGORY(3) PORT_PLAYER(3)
104   PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_JOYSTICK_DOWN ) PORT_CATEGORY(3) PORT_PLAYER(3)
105   PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_JOYSTICK_LEFT ) PORT_CATEGORY(3) PORT_PLAYER(3)
106   PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_JOYSTICK_RIGHT ) PORT_CATEGORY(3) PORT_PLAYER(3)
107
108   PORT_START("PAD4")   /* Joypad 4 */
109   PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_BUTTON1 ) PORT_NAME("P4 A") PORT_CATEGORY(4) PORT_PLAYER(4)
110   PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_BUTTON2 ) PORT_NAME("P4 B") PORT_CATEGORY(4) PORT_PLAYER(4)
111   PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_SELECT ) PORT_CATEGORY(4) PORT_PLAYER(4)
112   PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_START ) PORT_CATEGORY(4) PORT_PLAYER(4)
113   PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_JOYSTICK_UP ) PORT_CATEGORY(4) PORT_PLAYER(4)
114   PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_JOYSTICK_DOWN ) PORT_CATEGORY(4) PORT_PLAYER(4)
115   PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_JOYSTICK_LEFT ) PORT_CATEGORY(4) PORT_PLAYER(4)
116   PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_JOYSTICK_RIGHT ) PORT_CATEGORY(4) PORT_PLAYER(4)
117
118   PORT_START("ZAPPER1_X")  /* P1 zapper */
119   PORT_BIT( 0xff, 0x80, IPT_LIGHTGUN_X) PORT_CROSSHAIR(X, 1.0, 0.0, 0) PORT_SENSITIVITY(70) PORT_KEYDELTA(30) PORT_MINMAX(0,255)                                          PORT_CATEGORY(5) PORT_PLAYER(1)
120   PORT_START("ZAPPER1_Y")  /* P1 zapper */
121   PORT_BIT( 0xff, 0x80, IPT_LIGHTGUN_Y) PORT_CROSSHAIR(Y, 1.0, 0.0, 0) PORT_SENSITIVITY(50) PORT_KEYDELTA(30) PORT_MINMAX(0,255)                                          PORT_CATEGORY(5) PORT_PLAYER(1)
122   PORT_START("ZAPPER1_T")  /* P1 zapper trigger */
123   PORT_BIT( 0x03, IP_ACTIVE_HIGH, IPT_BUTTON1) PORT_NAME("P1 Lightgun Trigger") PORT_CATEGORY(5) PORT_PLAYER(1)
124
125   PORT_START("ZAPPER2_X")  /* P2 zapper */
126   PORT_BIT( 0xff, 0x80, IPT_LIGHTGUN_X) PORT_CROSSHAIR(X, 1.0, 0.0, 0) PORT_SENSITIVITY(70) PORT_KEYDELTA(30) PORT_MINMAX(0,255 )                                          PORT_CATEGORY(6) PORT_PLAYER(2)
127   PORT_START("ZAPPER2_Y")  /* P2 zapper */
128   PORT_BIT( 0xff, 0x80, IPT_LIGHTGUN_Y) PORT_CROSSHAIR(Y, 1.0, 0.0, 0) PORT_SENSITIVITY(50) PORT_KEYDELTA(30) PORT_MINMAX(0,255 )                                          PORT_CATEGORY(6) PORT_PLAYER(2)
129   PORT_START("ZAPPER2_T")  /* P2 zapper trigger */
130   PORT_BIT( 0x03, IP_ACTIVE_HIGH, IPT_BUTTON1) PORT_NAME("P2 Lightgun Trigger") PORT_CATEGORY(6) PORT_PLAYER(2)
131
132   PORT_START("PADDLE")  /* Arkanoid paddle */
133   PORT_BIT( 0xff, 0x7f, IPT_PADDLE) PORT_SENSITIVITY(25) PORT_KEYDELTA(3) PORT_MINMAX(0x62,0xf2)                                                   PORT_CATEGORY(7)
134
135   PORT_START("CC_LEFT")
136   PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_UNUSED ) PORT_CATEGORY(10) PORT_PLAYER(1)
137   PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_UNUSED ) PORT_CATEGORY(10) PORT_PLAYER(1)
138   PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_SELECT ) PORT_CATEGORY(10) PORT_PLAYER(1)
139   PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_START ) PORT_CATEGORY(10) PORT_PLAYER(1)
140   PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_JOYSTICKLEFT_UP ) PORT_CATEGORY(10) PORT_PLAYER(1)
141   PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_JOYSTICKLEFT_DOWN ) PORT_CATEGORY(10) PORT_PLAYER(1)
142   PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_JOYSTICKLEFT_LEFT ) PORT_CATEGORY(10) PORT_PLAYER(1)
143   PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_JOYSTICKLEFT_RIGHT ) PORT_CATEGORY(10) PORT_PLAYER(1)
144
145   PORT_START("CC_RIGHT")
146   PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_UNUSED ) PORT_CATEGORY(10) PORT_PLAYER(1)
147   PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_UNUSED ) PORT_CATEGORY(10) PORT_PLAYER(1)
148   PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_UNUSED ) PORT_CATEGORY(10) PORT_PLAYER(1)
149   PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_UNUSED ) PORT_CATEGORY(10) PORT_PLAYER(1)
150   PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_JOYSTICKRIGHT_UP ) PORT_CATEGORY(10) PORT_PLAYER(1)
151   PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_JOYSTICKRIGHT_DOWN ) PORT_CATEGORY(10) PORT_PLAYER(1)
152   PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_JOYSTICKRIGHT_LEFT ) PORT_CATEGORY(10) PORT_PLAYER(1)
153   PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_JOYSTICKRIGHT_RIGHT ) PORT_CATEGORY(10) PORT_PLAYER(1)
154
155INPUT_PORTS_END
156
157static INPUT_PORTS_START( nes )
158   PORT_INCLUDE( nes_controllers )
159
160   PORT_START("CONFIG")  /* configuration */
161   PORT_CONFNAME( 0x01, 0x00, "Draw Top/Bottom 8 Lines")
162   PORT_CONFSETTING(    0x01, DEF_STR(No) )
163   PORT_CONFSETTING(    0x00, DEF_STR(Yes) )
164   PORT_CONFNAME( 0x02, 0x00, "Enforce 8 Sprites/line")
165   PORT_CONFSETTING(    0x02, DEF_STR(No) )
166   PORT_CONFSETTING(    0x00, DEF_STR(Yes) )
167INPUT_PORTS_END
168
169static INPUT_PORTS_START( famicom )
170   PORT_INCLUDE( nes_controllers )
171
172   PORT_START("FLIPDISK") /* fake keys */
173   PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_BUTTON3) PORT_NAME("Change Disk Side")
174INPUT_PORTS_END
175
176static INPUT_PORTS_START( fc_keyboard )
177   PORT_START("FCKEY0")
178   PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(8) PORT_CODE(KEYCODE_F8) PORT_CHAR(UCHAR_MAMEKEY(F8))
179   PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(8) PORT_CODE(KEYCODE_ENTER) PORT_CHAR(13)
180   PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(8) PORT_CODE(KEYCODE_CLOSEBRACE)   PORT_CHAR('[')
181   PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(8) PORT_CODE(KEYCODE_BACKSLASH)   PORT_CHAR(']')
182   PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(8) PORT_NAME("Kana")
183   PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(8) PORT_CODE(KEYCODE_RSHIFT)
184   PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(8) PORT_CODE(KEYCODE_BACKSLASH2)   PORT_CHAR('\\')
185   PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(8) PORT_NAME("Stop") PORT_CODE(KEYCODE_BACKSPACE)
186
187   PORT_START("FCKEY1")
188   PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(8) PORT_CODE(KEYCODE_F7) PORT_CHAR(UCHAR_MAMEKEY(F7))
189   PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(8) PORT_CODE(KEYCODE_OPENBRACE)   PORT_CHAR('@')
190   PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(8) PORT_CODE(KEYCODE_COLON)   PORT_CHAR(':')
191   PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(8) PORT_CODE(KEYCODE_QUOTE)   PORT_CHAR(';')
192   PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(8) PORT_CHAR('_')
193   PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(8) PORT_CHAR('/')
194   PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(8) PORT_CODE(KEYCODE_MINUS)   PORT_CHAR('-')
195   PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(8) PORT_CODE(KEYCODE_EQUALS)   PORT_CHAR('^')
196
197   PORT_START("FCKEY2")
198   PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(8) PORT_CODE(KEYCODE_F6) PORT_CHAR(UCHAR_MAMEKEY(F6))
199   PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(8) PORT_CODE(KEYCODE_O)   PORT_CHAR('O')
200   PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(8) PORT_CODE(KEYCODE_L)   PORT_CHAR('L')
201   PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(8) PORT_CODE(KEYCODE_K)   PORT_CHAR('K')
202   PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(8) PORT_CODE(KEYCODE_STOP)   PORT_CHAR('.')
203   PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(8) PORT_CODE(KEYCODE_COMMA)   PORT_CHAR(',')
204   PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(8) PORT_CODE(KEYCODE_P)   PORT_CHAR('P')
205   PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(8) PORT_CODE(KEYCODE_0)   PORT_CHAR('0')
206
207   PORT_START("FCKEY3")
208   PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(8) PORT_CODE(KEYCODE_F5) PORT_CHAR(UCHAR_MAMEKEY(F5))
209   PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(8) PORT_CODE(KEYCODE_I)   PORT_CHAR('I')
210   PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(8) PORT_CODE(KEYCODE_U)   PORT_CHAR('U')
211   PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(8) PORT_CODE(KEYCODE_J)   PORT_CHAR('J')
212   PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(8) PORT_CODE(KEYCODE_M)   PORT_CHAR('M')
213   PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(8) PORT_CODE(KEYCODE_N)   PORT_CHAR('N')
214   PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(8) PORT_CODE(KEYCODE_9)   PORT_CHAR('9')
215   PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(8) PORT_CODE(KEYCODE_8)   PORT_CHAR('8')
216
217   PORT_START("FCKEY4")
218   PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(8) PORT_CODE(KEYCODE_F4) PORT_CHAR(UCHAR_MAMEKEY(F4))
219   PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(8) PORT_CODE(KEYCODE_Y)   PORT_CHAR('Y')
220   PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(8) PORT_CODE(KEYCODE_G)   PORT_CHAR('G')
221   PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(8) PORT_CODE(KEYCODE_H)   PORT_CHAR('H')
222   PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(8) PORT_CODE(KEYCODE_B)   PORT_CHAR('B')
223   PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(8) PORT_CODE(KEYCODE_V)   PORT_CHAR('V')
224   PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(8) PORT_CODE(KEYCODE_7)   PORT_CHAR('7')
225   PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(8) PORT_CODE(KEYCODE_6)   PORT_CHAR('6')
226
227   PORT_START("FCKEY5")
228   PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(8) PORT_CODE(KEYCODE_F3) PORT_CHAR(UCHAR_MAMEKEY(F3))
229   PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(8) PORT_CODE(KEYCODE_T)   PORT_CHAR('T')
230   PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(8) PORT_CODE(KEYCODE_R)   PORT_CHAR('R')
231   PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(8) PORT_CODE(KEYCODE_D)   PORT_CHAR('D')
232   PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(8) PORT_CODE(KEYCODE_F)   PORT_CHAR('F')
233   PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(8) PORT_CODE(KEYCODE_C)   PORT_CHAR('C')
234   PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(8) PORT_CODE(KEYCODE_5)   PORT_CHAR('5')
235   PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(8) PORT_CODE(KEYCODE_4)   PORT_CHAR('4')
236
237   PORT_START("FCKEY6")
238   PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(8) PORT_CODE(KEYCODE_F2) PORT_CHAR(UCHAR_MAMEKEY(F2))
239   PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(8) PORT_CODE(KEYCODE_W)   PORT_CHAR('W')
240   PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(8) PORT_CODE(KEYCODE_S)   PORT_CHAR('S')
241   PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(8) PORT_CODE(KEYCODE_A)   PORT_CHAR('A')
242   PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(8) PORT_CODE(KEYCODE_X)   PORT_CHAR('X')
243   PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(8) PORT_CODE(KEYCODE_Z)   PORT_CHAR('Z')
244   PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(8) PORT_CODE(KEYCODE_E)   PORT_CHAR('E')
245   PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(8) PORT_CODE(KEYCODE_3)   PORT_CHAR('3')
246
247   PORT_START("FCKEY7")
248   PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(8) PORT_CODE(KEYCODE_F1) PORT_CHAR(UCHAR_MAMEKEY(F1))
249   PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(8) PORT_CODE(KEYCODE_TAB) PORT_CHAR(UCHAR_MAMEKEY(ESC))
250   PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(8) PORT_CODE(KEYCODE_Q)   PORT_CHAR('Q')
251   PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(8) PORT_CODE(KEYCODE_LCONTROL)      PORT_CHAR(UCHAR_SHIFT_2)
252   PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(8) PORT_CODE(KEYCODE_LSHIFT)      PORT_CHAR(UCHAR_SHIFT_1)
253   PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(8) PORT_NAME("Grph") PORT_CODE(KEYCODE_LALT)
254   PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(8) PORT_CODE(KEYCODE_1)   PORT_CHAR('1')
255   PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(8) PORT_CODE(KEYCODE_2)   PORT_CHAR('2')
256
257   PORT_START("FCKEY8")
258   PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(8) PORT_NAME("Clr")
259   PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(8) PORT_CODE(KEYCODE_UP)   PORT_CHAR(UCHAR_MAMEKEY(UP))
260   PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(8) PORT_CODE(KEYCODE_RIGHT) PORT_CHAR(UCHAR_MAMEKEY(RIGHT))
261   PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(8) PORT_CODE(KEYCODE_LEFT) PORT_CHAR(UCHAR_MAMEKEY(LEFT))
262   PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(8) PORT_CODE(KEYCODE_DOWN) PORT_CHAR(UCHAR_MAMEKEY(DOWN))
263   PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(8) PORT_CODE(KEYCODE_SPACE)      PORT_CHAR(' ')
264   PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(8) PORT_NAME("Del") PORT_CODE(KEYCODE_DEL)
265   PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(8) PORT_NAME("Ins") PORT_CODE(KEYCODE_INSERT)
266
267INPUT_PORTS_END
268
269static INPUT_PORTS_START( subor_keyboard )
270   PORT_START("SUBKEY0")
271   PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(9) PORT_CODE(KEYCODE_4)   PORT_CHAR('4')
272   PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(9) PORT_CODE(KEYCODE_G)   PORT_CHAR('G')
273   PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(9) PORT_CODE(KEYCODE_F)   PORT_CHAR('F')
274   PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(9) PORT_CODE(KEYCODE_C)   PORT_CHAR('C')
275   PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(9) PORT_CODE(KEYCODE_F2) PORT_CHAR(UCHAR_MAMEKEY(F2))
276   PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(9) PORT_CODE(KEYCODE_E)   PORT_CHAR('E')
277   PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(9) PORT_CODE(KEYCODE_5)   PORT_CHAR('5')
278   PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(9) PORT_CODE(KEYCODE_V)   PORT_CHAR('V')
279
280   PORT_START("SUBKEY1")
281   PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(9) PORT_CODE(KEYCODE_2)   PORT_CHAR('2')
282   PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(9) PORT_CODE(KEYCODE_D)   PORT_CHAR('D')
283   PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(9) PORT_CODE(KEYCODE_S)   PORT_CHAR('S')
284   PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(9) PORT_CODE(KEYCODE_END) PORT_CHAR(UCHAR_MAMEKEY(END))
285   PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(9) PORT_CODE(KEYCODE_F1) PORT_CHAR(UCHAR_MAMEKEY(F1))
286   PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(9) PORT_CODE(KEYCODE_W)   PORT_CHAR('W')
287   PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(9) PORT_CODE(KEYCODE_3)   PORT_CHAR('3')
288   PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(9) PORT_CODE(KEYCODE_X)   PORT_CHAR('X')
289
290   PORT_START("SUBKEY2")
291   PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(9) PORT_CODE(KEYCODE_INSERT) PORT_CHAR(UCHAR_MAMEKEY(INSERT))
292   PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(9) PORT_CODE(KEYCODE_BACKSPACE)   PORT_CHAR(8)
293   PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(9) PORT_NAME("NEXT")
294   PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(9) PORT_CODE(KEYCODE_RIGHT) PORT_CHAR(UCHAR_MAMEKEY(RIGHT))
295   PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(9) PORT_CODE(KEYCODE_F8) PORT_CHAR(UCHAR_MAMEKEY(F8))
296   PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(9) PORT_NAME("PRIOR")
297   PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(9) PORT_CODE(KEYCODE_DEL) PORT_CHAR(UCHAR_MAMEKEY(DEL))
298   PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(9) PORT_CODE(KEYCODE_HOME) PORT_CHAR(UCHAR_MAMEKEY(HOME))
299
300   PORT_START("SUBKEY3")
301   PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(9) PORT_CODE(KEYCODE_9)   PORT_CHAR('9')
302   PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(9) PORT_CODE(KEYCODE_I)   PORT_CHAR('I')
303   PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(9) PORT_CODE(KEYCODE_L)   PORT_CHAR('L')
304   PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(9) PORT_CODE(KEYCODE_COMMA)   PORT_CHAR(',')
305   PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(9) PORT_CODE(KEYCODE_F5) PORT_CHAR(UCHAR_MAMEKEY(F5))
306   PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(9) PORT_CODE(KEYCODE_O)   PORT_CHAR('O')
307   PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(9) PORT_CODE(KEYCODE_0)   PORT_CHAR('0')
308   PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(9) PORT_CODE(KEYCODE_STOP)   PORT_CHAR('.')
309
310   PORT_START("SUBKEY4")
311   PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(9) PORT_CODE(KEYCODE_CLOSEBRACE)   PORT_CHAR(']')
312   PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(9) PORT_CODE(KEYCODE_ENTER)   PORT_CHAR(13)
313   PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(9) PORT_CODE(KEYCODE_UP) PORT_CHAR(UCHAR_MAMEKEY(UP))
314   PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(9) PORT_CODE(KEYCODE_LEFT) PORT_CHAR(UCHAR_MAMEKEY(LEFT))
315   PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(9) PORT_CODE(KEYCODE_F7) PORT_CHAR(UCHAR_MAMEKEY(F7))
316   PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(9) PORT_CODE(KEYCODE_OPENBRACE)   PORT_CHAR('[')
317   PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(9) PORT_CODE(KEYCODE_BACKSLASH)   PORT_CHAR('\\')
318   PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(9) PORT_CODE(KEYCODE_DOWN) PORT_CHAR(UCHAR_MAMEKEY(DOWN))
319
320   PORT_START("SUBKEY5")
321   PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(9) PORT_CODE(KEYCODE_Q)   PORT_CHAR('Q')
322   PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(9) PORT_CODE(KEYCODE_CAPSLOCK) PORT_CHAR(UCHAR_MAMEKEY(CAPSLOCK))
323   PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(9) PORT_CODE(KEYCODE_Z)   PORT_CHAR('Z')
324   PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(9) PORT_CODE(KEYCODE_TAB)   PORT_CHAR('\t')
325   PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(9) PORT_CODE(KEYCODE_ESC) PORT_CHAR(UCHAR_MAMEKEY(ESC))
326   PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(9) PORT_CODE(KEYCODE_A)   PORT_CHAR('A')
327   PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(9) PORT_CODE(KEYCODE_1)   PORT_CHAR('1')
328   PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(9) PORT_CODE(KEYCODE_LCONTROL)      PORT_CHAR(UCHAR_SHIFT_2)
329
330   PORT_START("SUBKEY6")
331   PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(9) PORT_CODE(KEYCODE_7)   PORT_CHAR('7')
332   PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(9) PORT_CODE(KEYCODE_Y)   PORT_CHAR('Y')
333   PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(9) PORT_CODE(KEYCODE_K)   PORT_CHAR('K')
334   PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(9) PORT_CODE(KEYCODE_M)   PORT_CHAR('M')
335   PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(9) PORT_CODE(KEYCODE_F4) PORT_CHAR(UCHAR_MAMEKEY(F4))
336   PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(9) PORT_CODE(KEYCODE_U)   PORT_CHAR('U')
337   PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(9) PORT_CODE(KEYCODE_8)   PORT_CHAR('8')
338   PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(9) PORT_CODE(KEYCODE_J)   PORT_CHAR('J')
339
340   PORT_START("SUBKEY7")
341   PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(9) PORT_CODE(KEYCODE_MINUS)   PORT_CHAR('-')
342   PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(9) PORT_CODE(KEYCODE_COLON)   PORT_CHAR(':')
343   PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(9) PORT_CODE(KEYCODE_QUOTE)   PORT_CHAR('\'')
344   PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(9) PORT_CODE(KEYCODE_SLASH)   PORT_CHAR('/')
345   PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(9) PORT_CODE(KEYCODE_F6) PORT_CHAR(UCHAR_MAMEKEY(F6))
346   PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(9) PORT_CODE(KEYCODE_P)      PORT_CHAR('P')
347   PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(9) PORT_CODE(KEYCODE_EQUALS)   PORT_CHAR('=')
348   PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(9) PORT_CODE(KEYCODE_LSHIFT)   PORT_CHAR(UCHAR_SHIFT_1)
349
350   PORT_START("SUBKEY8")
351   PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(9) PORT_CODE(KEYCODE_T)   PORT_CHAR('T')
352   PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(9) PORT_CODE(KEYCODE_H)   PORT_CHAR('H')
353   PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(9) PORT_CODE(KEYCODE_N)   PORT_CHAR('N')
354   PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(9) PORT_CODE(KEYCODE_SPACE)   PORT_CHAR(' ')
355   PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(9) PORT_CODE(KEYCODE_F3) PORT_CHAR(UCHAR_MAMEKEY(F3))
356   PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(9) PORT_CODE(KEYCODE_R)   PORT_CHAR('R')
357   PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(9) PORT_CODE(KEYCODE_6)   PORT_CHAR('6')
358   PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(9) PORT_CODE(KEYCODE_B)   PORT_CHAR('B')
359
360   PORT_START("SUBKEY9")
361   PORT_BIT( 0xff, IP_ACTIVE_HIGH, IPT_UNUSED ) PORT_CATEGORY(9)
362
363   PORT_START("SUBKEY10")
364   PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(9) PORT_NAME("LMENU")
365   PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(9) PORT_CODE(KEYCODE_4_PAD)   PORT_CHAR(UCHAR_MAMEKEY(4_PAD))
366   PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(9) PORT_CODE(KEYCODE_7_PAD)   PORT_CHAR(UCHAR_MAMEKEY(7_PAD))
367   PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(9) PORT_CODE(KEYCODE_F11)      PORT_CHAR(UCHAR_MAMEKEY(F11))
368   PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(9) PORT_CODE(KEYCODE_F12)      PORT_CHAR(UCHAR_MAMEKEY(F12))
369   PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(9) PORT_CODE(KEYCODE_1_PAD)   PORT_CHAR(UCHAR_MAMEKEY(1_PAD))
370   PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(9) PORT_CODE(KEYCODE_2_PAD)   PORT_CHAR(UCHAR_MAMEKEY(2_PAD))
371   PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(9) PORT_CODE(KEYCODE_8_PAD)   PORT_CHAR(UCHAR_MAMEKEY(8_PAD))
372
373   PORT_START("SUBKEY11")
374   PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(9) PORT_CODE(KEYCODE_MINUS_PAD)PORT_CHAR(UCHAR_MAMEKEY(MINUS_PAD))
375   PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(9) PORT_CODE(KEYCODE_PLUS_PAD)   PORT_CHAR(UCHAR_MAMEKEY(PLUS_PAD))
376   PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(9) PORT_CODE(KEYCODE_ASTERISK)   PORT_CHAR(UCHAR_MAMEKEY(ASTERISK))
377   PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(9) PORT_CODE(KEYCODE_9_PAD)   PORT_CHAR(UCHAR_MAMEKEY(9_PAD))
378   PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(9) PORT_CODE(KEYCODE_F10) PORT_CHAR(UCHAR_MAMEKEY(F10))
379   PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(9) PORT_CODE(KEYCODE_5_PAD)   PORT_CHAR(UCHAR_MAMEKEY(5_PAD))
380   PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(9) PORT_CODE(KEYCODE_SLASH_PAD)PORT_CHAR(UCHAR_MAMEKEY(SLASH_PAD))
381   PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(9) PORT_CODE(KEYCODE_NUMLOCK)   PORT_CHAR(UCHAR_MAMEKEY(NUMLOCK))
382
383   PORT_START("SUBKEY12")
384   PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(9) PORT_CODE(KEYCODE_TILDE)   PORT_CHAR('`')
385   PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(9) PORT_CODE(KEYCODE_6_PAD)   PORT_CHAR(UCHAR_MAMEKEY(6_PAD))
386   PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(9) PORT_NAME("PAUSE")
387   PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(9) PORT_NAME("SPACE2")
388   PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(9) PORT_CODE(KEYCODE_F9) PORT_CHAR(UCHAR_MAMEKEY(F9))
389   PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(9) PORT_CODE(KEYCODE_3_PAD)   PORT_CHAR(UCHAR_MAMEKEY(3_PAD))
390   PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(9) PORT_NAME("Keypad .") PORT_CODE(KEYCODE_DEL_PAD)
391   PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(9) PORT_CODE(KEYCODE_0_PAD)   PORT_CHAR(UCHAR_MAMEKEY(0_PAD))
392
393INPUT_PORTS_END
394
395static INPUT_PORTS_START( famikey )
396   PORT_INCLUDE( famicom )
397   PORT_INCLUDE( fc_keyboard )
398   PORT_INCLUDE( subor_keyboard )
399
400   PORT_MODIFY("CTRLSEL")  /* Select Controller Type */
401   PORT_CATEGORY_CLASS( 0x000f, 0x0004, "P1 Controller")
402   PORT_CATEGORY_ITEM(  0x0000, "Unconnected",      0 )
403   PORT_CATEGORY_ITEM(  0x0001, "Gamepad",         1 )
404   PORT_CATEGORY_ITEM(  0x0002, "Zapper",         5 )
405   PORT_CATEGORY_ITEM(  0x0006, "Crazy Climber pad", 10 )
406   PORT_CATEGORY_ITEM(  0x0007, "FC Keyboard",      8 )
407   PORT_CATEGORY_ITEM(  0x0008, "Subor Keyboard",   9 )
408   PORT_CATEGORY_CLASS( 0x00f0, 0x0010, "P2 Controller")
409   PORT_CATEGORY_ITEM(  0x0000, "Unconnected",      0 )
410   PORT_CATEGORY_ITEM(  0x0010, "Gamepad",         2 )
411   PORT_CATEGORY_ITEM(  0x0030, "Zapper",         6 )
412   PORT_CATEGORY_ITEM(  0x0040, "Arkanoid paddle",   7 )
413//  PORT_CATEGORY_ITEM(  0x0050, "Family Trainer",  11 )
414   PORT_CATEGORY_CLASS( 0x0f00, 0x0000, "P3 Controller")
415   PORT_CATEGORY_ITEM(  0x0000, "Unconnected",      0 )
416   PORT_CATEGORY_ITEM(  0x0100, "Gamepad",         3 )
417   PORT_CATEGORY_CLASS( 0xf000, 0x0000, "P4 Controller")
418   PORT_CATEGORY_ITEM(  0x0000, "Unconnected",      0 )
419   PORT_CATEGORY_ITEM(  0x1000, "Gamepad",         4 )
420INPUT_PORTS_END
421
422#ifdef UNUSED_FUNCTION
423/* This layout is not changed at runtime */
424gfx_layout nes_vram_charlayout =
425{
426    8,8,    /* 8*8 characters */
427    512,    /* 512 characters */
428    2,  /* 2 bits per pixel */
429    { 8*8, 0 }, /* the two bitplanes are separated */
430    { 0, 1, 2, 3, 4, 5, 6, 7 },
431    { 0*8, 1*8, 2*8, 3*8, 4*8, 5*8, 6*8, 7*8 },
432    16*8    /* every char takes 16 consecutive bytes */
433};
434#endif
435
436static const nes_interface nes_apu_interface =
437{
438   "maincpu"
439};
440
441
442static void ppu_nmi(device_t *device, int *ppu_regs)
443{
444   cputag_set_input_line(device->machine(), "maincpu", INPUT_LINE_NMI, PULSE_LINE);
445}
446
447
448static const ppu2c0x_interface nes_ppu_interface =
449{
450   0,
451   0,
452   PPU_MIRROR_NONE,
453   ppu_nmi
454};
455
456static const floppy_config nes_floppy_config =
457{
458   DEVCB_NULL,
459   DEVCB_NULL,
460   DEVCB_NULL,
461   DEVCB_NULL,
462   DEVCB_NULL,
463   FLOPPY_STANDARD_5_25_DSHD,
464   FLOPPY_OPTIONS_NAME(nes_only),
465   NULL
466};
467
468
469static MACHINE_CONFIG_START( nes, nes_state )
470   /* basic machine hardware */
471   MCFG_CPU_ADD("maincpu", N2A03, NTSC_CLOCK)
472   MCFG_CPU_PROGRAM_MAP(nes_map)
473
474   MCFG_MACHINE_START( nes )
475   MCFG_MACHINE_RESET( nes )
476
477   MCFG_SCREEN_ADD("screen", RASTER)
478   MCFG_SCREEN_REFRESH_RATE(60.098)
479   // This isn't used so much to calulate the vblank duration (the PPU code tracks that manually) but to determine
480   // the number of cycles in each scanline for the PPU scanline timer. Since the PPU has 20 vblank scanlines + 2
481   // non-rendering scanlines, we compensate. This ends up being 2500 cycles for the non-rendering portion, 2273
482   // cycles for the actual vblank period.
483   MCFG_SCREEN_VBLANK_TIME(ATTOSECONDS_IN_USEC((113.66/(NTSC_CLOCK/1000000)) * (PPU_VBLANK_LAST_SCANLINE_NTSC-PPU_VBLANK_FIRST_SCANLINE+1+2)))
484   MCFG_SCREEN_FORMAT(BITMAP_FORMAT_INDEXED16)
485   MCFG_SCREEN_SIZE(32*8, 262)
486   MCFG_SCREEN_VISIBLE_AREA(0*8, 32*8-1, 0*8, 30*8-1)
487   MCFG_SCREEN_UPDATE(nes)
488
489   MCFG_PALETTE_INIT(nes)
490   MCFG_VIDEO_START(nes)
491
492   MCFG_PALETTE_LENGTH(4*16*8)
493
494   MCFG_PPU2C02_ADD( "ppu", nes_ppu_interface )
495
496   /* sound hardware */
497   MCFG_SPEAKER_STANDARD_MONO("mono")
498   MCFG_SOUND_ADD("nessound", NES, NTSC_CLOCK)
499   MCFG_SOUND_CONFIG(nes_apu_interface)
500   MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.90)
501
502   MCFG_CARTSLOT_ADD("cart")
503   MCFG_CARTSLOT_EXTENSION_LIST("nes,unf")
504   MCFG_CARTSLOT_MANDATORY
505   MCFG_CARTSLOT_INTERFACE("nes_cart")
506   MCFG_CARTSLOT_LOAD(nes_cart)
507   MCFG_CARTSLOT_PARTIALHASH(nes_partialhash)
508   MCFG_SOFTWARE_LIST_ADD("cart_list","nes")
509MACHINE_CONFIG_END
510
511static MACHINE_CONFIG_DERIVED( nespal, nes )
512
513   /* basic machine hardware */
514   MCFG_CPU_MODIFY( "maincpu" )
515   MCFG_CPU_CLOCK( PAL_CLOCK )
516
517   MCFG_DEVICE_REMOVE( "ppu" )
518   MCFG_PPU2C07_ADD( "ppu", nes_ppu_interface )
519
520   /* video hardware */
521   MCFG_SCREEN_MODIFY("screen")
522   MCFG_SCREEN_REFRESH_RATE(53.355)
523   MCFG_SCREEN_VBLANK_TIME(ATTOSECONDS_IN_USEC((106.53/(PAL_CLOCK/1000000)) * (PPU_VBLANK_LAST_SCANLINE_PAL-PPU_VBLANK_FIRST_SCANLINE+1+2)))
524   MCFG_VIDEO_START(nes)
525
526   /* sound hardware */
527   MCFG_SOUND_REPLACE("nessound", NES, PAL_CLOCK)
528   MCFG_SOUND_CONFIG(nes_apu_interface)
529   MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.90)
530MACHINE_CONFIG_END
531
532static MACHINE_CONFIG_DERIVED( dendy, nes )
533
534   /* basic machine hardware */
535   MCFG_CPU_MODIFY( "maincpu" )
536   MCFG_CPU_CLOCK( 26601712/15 ) /* 26.601712MHz / 15 == 1.77344746666... MHz */
537
538   MCFG_DEVICE_REMOVE( "ppu" )
539   MCFG_PPU2C07_ADD( "ppu", nes_ppu_interface )
540
541   /* video hardware */
542   MCFG_SCREEN_MODIFY("screen")
543   MCFG_SCREEN_REFRESH_RATE(50.00697796827)
544   MCFG_SCREEN_VBLANK_TIME(ATTOSECONDS_IN_USEC((106.53/(PAL_CLOCK/1000000)) * (PPU_VBLANK_LAST_SCANLINE_PAL-PPU_VBLANK_FIRST_SCANLINE+1+2)))
545   MCFG_VIDEO_START(nes)
546
547   /* sound hardware */
548   MCFG_SOUND_REPLACE("nessound", NES, 26601712/15) /* 26.601712MHz / 15 == 1.77344746666... MHz */
549   MCFG_SOUND_CONFIG(nes_apu_interface)
550   MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.90)
551MACHINE_CONFIG_END
552
553static MACHINE_CONFIG_DERIVED( famicom, nes )
554
555   MCFG_CARTSLOT_MODIFY("cart")
556   MCFG_CARTSLOT_EXTENSION_LIST("nes,unf")
557   MCFG_CARTSLOT_NOT_MANDATORY
558   MCFG_CARTSLOT_LOAD(nes_cart)
559   MCFG_CARTSLOT_PARTIALHASH(nes_partialhash)
560
561   MCFG_FLOPPY_DRIVE_ADD(FLOPPY_0, nes_floppy_config)
562MACHINE_CONFIG_END
563
564
565/* rom regions are just place-holders: they get removed and re-allocated when a cart is loaded */
566ROM_START( nes )
567   ROM_REGION( 0x10000, "maincpu", ROMREGION_ERASE00 )  /* Main RAM + program banks */
568   ROM_REGION( 0x2000,  "gfx1", ROMREGION_ERASE00 )  /* VROM */
569   ROM_REGION( 0x4000,  "gfx2", ROMREGION_ERASE00 )  /* VRAM */
570   ROM_REGION( 0x800,   "gfx3", ROMREGION_ERASE00 )  /* CI RAM */
571ROM_END
572
573ROM_START( nespal )
574   ROM_REGION( 0x10000, "maincpu", ROMREGION_ERASE00 )  /* Main RAM + program banks */
575   ROM_REGION( 0x2000,  "gfx1", ROMREGION_ERASE00 )  /* VROM */
576   ROM_REGION( 0x4000,  "gfx2", ROMREGION_ERASE00 )  /* VRAM */
577   ROM_REGION( 0x800,   "gfx3", ROMREGION_ERASE00 )  /* CI RAM */
578ROM_END
579
580ROM_START( famicom )
581   ROM_REGION( 0x10000, "maincpu", 0 )  /* Main RAM + program banks */
582   ROM_LOAD_OPTIONAL( "disksys.rom", 0xe000, 0x2000, CRC(5e607dcf) SHA1(57fe1bdee955bb48d357e463ccbf129496930b62) )
583
584   ROM_REGION( 0x2000,  "gfx1", ROMREGION_ERASE00 )  /* VROM */
585   ROM_REGION( 0x4000,  "gfx2", ROMREGION_ERASE00 )  /* VRAM */
586   ROM_REGION( 0x800,   "gfx3", ROMREGION_ERASE00 )  /* CI RAM */
587ROM_END
588
589#define rom_fami_key rom_famicom
590
591ROM_START( famitwin )
592   ROM_REGION( 0x10000, "maincpu", 0 )  /* Main RAM + program banks */
593   ROM_LOAD_OPTIONAL( "disksyst.rom", 0xe000, 0x2000, CRC(4df24a6c) SHA1(e4e41472c454f928e53eb10e0509bf7d1146ecc1) )
594
595   ROM_REGION( 0x2000,  "gfx1", ROMREGION_ERASE00 )  /* VROM */
596   ROM_REGION( 0x4000,  "gfx2", ROMREGION_ERASE00 )  /* VRAM */
597   ROM_REGION( 0x800,   "gfx3", ROMREGION_ERASE00 )  /* CI RAM */
598ROM_END
599
600ROM_START( m82 )
601   ROM_REGION( 0x14000, "maincpu", 0 )  /* Main RAM + program banks */
602   /* Banks to be mapped at 0xe000? More investigations needed... */
603   ROM_LOAD( "m82_v1_0.bin", 0x10000, 0x4000, CRC(7d56840a) SHA1(cbd2d14fa073273ba58367758f40d67fd8a9106d) )
604
605   ROM_REGION( 0x2000,  "gfx1", ROMREGION_ERASE00 )  /* VROM */
606   ROM_REGION( 0x4000,  "gfx2", ROMREGION_ERASE00 )  /* VRAM */
607   ROM_REGION( 0x800,   "gfx3", ROMREGION_ERASE00 )  /* CI RAM */
608ROM_END
609
610// see http://www.disgruntleddesigner.com/chrisc/drpcjr/index.html
611// and http://www.disgruntleddesigner.com/chrisc/drpcjr/DrPCJrMemMap.txt
612ROM_START( drpcjr )
613   ROM_REGION( 0x18000, "maincpu", 0 )  /* Main RAM + program banks */
614   /* 4 banks to be mapped in 0xe000-0xffff (or 8 banks to be mapped in 0xe000-0xefff & 0xf000-0xffff).
615    Banks selected by writing at 0x4180 */
616   ROM_LOAD("drpcjr_bios.bin", 0x10000, 0x8000, CRC(c8fbef89) SHA1(2cb0a817b31400cdf27817d09bae7e69f41b062b) )   // bios vers. 1.0a
617   // Not sure if we should support this: hacked version 1.5a by Chris Covell with bugfixes and GameGenie support
618//  ROM_LOAD("drpcjr_v1_5_gg.bin", 0x10000, 0x8000, CRC(98f2033b) SHA1(93c114da787a19279d1a46667c2f69b49e25d4f1) )
619
620   ROM_REGION( 0x2000,  "gfx1", ROMREGION_ERASE00 )  /* VROM */
621   ROM_REGION( 0x4000,  "gfx2", ROMREGION_ERASE00 )  /* VRAM */
622   ROM_REGION( 0x800,   "gfx3", ROMREGION_ERASE00 )  /* CI RAM */
623ROM_END
624
625ROM_START( dendy )
626   ROM_REGION( 0x10000, "maincpu", ROMREGION_ERASE00 )  /* Main RAM + program banks */
627   ROM_REGION( 0x2000,  "gfx1", ROMREGION_ERASE00 )  /* VROM */
628   ROM_REGION( 0x4000,  "gfx2", ROMREGION_ERASE00 )  /* VRAM */
629   ROM_REGION( 0x800,   "gfx3", ROMREGION_ERASE00 )  /* CI RAM */
630ROM_END
631
632/***************************************************************************
633
634  Game driver(s)
635
636***************************************************************************/
637
638/*     YEAR  NAME      PARENT  COMPAT MACHINE   INPUT    INIT    COMPANY       FULLNAME */
639CONS( 1985, nes,       0,      0,     nes,      nes,     0,       "Nintendo",  "Nintendo Entertainment System / Famicom (NTSC)", GAME_IMPERFECT_GRAPHICS )
640CONS( 1987, nespal,    nes,    0,     nespal,   nes,     0,       "Nintendo",  "Nintendo Entertainment System (PAL)", GAME_IMPERFECT_GRAPHICS )
641CONS( 1983, famicom,   nes,    0,     famicom,  famicom, famicom, "Nintendo",  "Famicom (w/ Disk System add-on)", GAME_IMPERFECT_GRAPHICS )
642CONS( 1983, fami_key,  nes,    0,     famicom,  famikey, famicom, "Nintendo",  "Famicom (w/ Disk System add-on + Keyboard add-on)", GAME_IMPERFECT_GRAPHICS )
643CONS( 1986, famitwin,  nes,    0,     famicom,  famicom, famicom, "Sharp",     "Famicom Twin", GAME_IMPERFECT_GRAPHICS )
644CONS( 198?, m82,       nes,    0,     nes,      nes,     0,       "Nintendo",  "M82 Display Unit", GAME_IMPERFECT_GRAPHICS )
645CONS( 1996, drpcjr,    nes,    0,     famicom,  famicom, famicom, "Bung",      "Doctor PC Jr", GAME_IMPERFECT_GRAPHICS )
646CONS( 1992, dendy,     nes,    0,     dendy,    nes,     0,       "Steepler",  "Dendy Classic", GAME_IMPERFECT_GRAPHICS )
src/mame/drivers/snes.c
r11531r11532
1/***************************************************************************
2
3  snes.c
4
5  Driver file to handle emulation of the Nintendo Super NES.
6
7  R. Belmont
8  Anthony Kruize
9  Angelo Salese
10  Fabio Priuli
11  byuu
12  Based on the original MESS driver by Lee Hammerton (aka Savoury Snax)
13
14  Driver is preliminary right now.
15
16  The memory map included below is setup in a way to make it easier to handle
17  Mode 20 and Mode 21 ROMs.
18
19  Todo (in no particular order):
20    - Fix additional sound bugs
21    - Emulate extra chips - superfx, dsp2, sa-1 etc.
22    - Add horizontal mosaic, hi-res. interlaced etc to video emulation.
23    - Fix support for Mode 7. (In Progress)
24    - Handle interleaved roms (maybe even multi-part roms, but how?)
25    - Add support for running at 3.58 MHz at the appropriate time.
26    - I'm sure there's lots more ...
27
28***************************************************************************/
29
30#include "emu.h"
31#include "audio/snes_snd.h"
32#include "cpu/spc700/spc700.h"
33#include "cpu/superfx/superfx.h"
34#include "cpu/g65816/g65816.h"
35#include "cpu/upd7725/upd7725.h"
36#include "includes/snes.h"
37#include "machine/snescart.h"
38#include "crsshair.h"
39
40#define MAX_SNES_CART_SIZE 0x600000
41
42/*************************************
43 *
44 *  Memory handlers
45 *
46 *************************************/
47
48static READ8_DEVICE_HANDLER( spc_ram_100_r )
49{
50   return spc_ram_r(device, offset + 0x100);
51}
52
53static WRITE8_DEVICE_HANDLER( spc_ram_100_w )
54{
55   spc_ram_w(device, offset + 0x100, data);
56}
57
58/*************************************
59 *
60 *  Address maps
61 *
62 *************************************/
63
64static ADDRESS_MAP_START( snes_map, AS_PROGRAM, 8)
65   AM_RANGE(0x000000, 0x2fffff) AM_READWRITE(snes_r_bank1, snes_w_bank1)   /* I/O and ROM (repeats for each bank) */
66   AM_RANGE(0x300000, 0x3fffff) AM_READWRITE(snes_r_bank2, snes_w_bank2)   /* I/O and ROM (repeats for each bank) */
67   AM_RANGE(0x400000, 0x5fffff) AM_READ(snes_r_bank3)      /* ROM (and reserved in Mode 20) */
68   AM_RANGE(0x600000, 0x6fffff) AM_READWRITE(snes_r_bank4, snes_w_bank4)   /* used by Mode 20 DSP-1 */
69   AM_RANGE(0x700000, 0x7dffff) AM_READWRITE(snes_r_bank5, snes_w_bank5)
70   AM_RANGE(0x7e0000, 0x7fffff) AM_RAM               /* 8KB Low RAM, 24KB High RAM, 96KB Expanded RAM */
71   AM_RANGE(0x800000, 0xbfffff) AM_READWRITE(snes_r_bank6, snes_w_bank6)   /* Mirror and ROM */
72   AM_RANGE(0xc00000, 0xffffff) AM_READWRITE(snes_r_bank7, snes_w_bank7)   /* Mirror and ROM */
73ADDRESS_MAP_END
74
75static ADDRESS_MAP_START( superfx_map, AS_PROGRAM, 8)
76   AM_RANGE(0x000000, 0x3fffff) AM_READWRITE(superfx_r_bank1, superfx_w_bank1)
77   AM_RANGE(0x400000, 0x5fffff) AM_READWRITE(superfx_r_bank2, superfx_w_bank2)
78   AM_RANGE(0x600000, 0x7dffff) AM_READWRITE(superfx_r_bank3, superfx_w_bank3)
79   AM_RANGE(0x800000, 0xbfffff) AM_READWRITE(superfx_r_bank1, superfx_w_bank1)
80   AM_RANGE(0xc00000, 0xdfffff) AM_READWRITE(superfx_r_bank2, superfx_w_bank2)
81   AM_RANGE(0xe00000, 0xffffff) AM_READWRITE(superfx_r_bank3, superfx_w_bank3)
82ADDRESS_MAP_END
83
84static ADDRESS_MAP_START( spc_map, AS_PROGRAM, 8)
85   AM_RANGE(0x0000, 0x00ef) AM_DEVREADWRITE("spc700", spc_ram_r, spc_ram_w)   /* lower 32k ram */
86   AM_RANGE(0x00f0, 0x00ff) AM_DEVREADWRITE("spc700", spc_io_r, spc_io_w)     /* spc io */
87   AM_RANGE(0x0100, 0xffff) AM_DEVWRITE("spc700", spc_ram_100_w)
88   AM_RANGE(0x0100, 0xffbf) AM_DEVREAD("spc700", spc_ram_100_r)
89   AM_RANGE(0xffc0, 0xffff) AM_DEVREAD("spc700", spc_ipl_r)
90ADDRESS_MAP_END
91
92static ADDRESS_MAP_START( dsp_prg_map, AS_PROGRAM, 32 )
93   AM_RANGE(0x0000, 0x07ff) AM_ROM AM_REGION("dspprg", 0)
94ADDRESS_MAP_END
95
96static ADDRESS_MAP_START( dsp_data_map, AS_DATA, 16 )
97   AM_RANGE(0x0000, 0x03ff) AM_ROM AM_REGION("dspdata", 0)
98ADDRESS_MAP_END
99
100static ADDRESS_MAP_START( setadsp_prg_map, AS_PROGRAM, 32 )
101   AM_RANGE(0x0000, 0x3fff) AM_ROM AM_REGION("dspprg", 0)
102ADDRESS_MAP_END
103
104static ADDRESS_MAP_START( setadsp_data_map, AS_DATA, 16 )
105   AM_RANGE(0x0000, 0x07ff) AM_ROM AM_REGION("dspdata", 0)
106ADDRESS_MAP_END
107
108/*************************************
109 *
110 *  Input ports
111 *
112 *************************************/
113
114static CUSTOM_INPUT( snes_mouse_speed_input )
115{
116   snes_state *state = field.machine().driver_data<snes_state>();
117   int port = (FPTR)param;
118
119   if (snes_ram[OLDJOY1] & 0x1)
120   {
121      state->m_mouse[port].speed++;
122      if ((state->m_mouse[port].speed & 0x03) == 0x03)
123         state->m_mouse[port].speed = 0;
124   }
125
126   return state->m_mouse[port].speed;
127}
128
129static CUSTOM_INPUT( snes_superscope_offscreen_input )
130{
131   snes_state *state = field.machine().driver_data<snes_state>();
132   int port = (FPTR)param;
133   static const char *const portnames[2][3] =
134         {
135            { "SUPERSCOPE1", "SUPERSCOPE1_X", "SUPERSCOPE1_Y" },
136            { "SUPERSCOPE2", "SUPERSCOPE2_X", "SUPERSCOPE2_Y" },
137         };
138
139   INT16 x = input_port_read(field.machine(), portnames[port][1]);
140   INT16 y = input_port_read(field.machine(), portnames[port][2]);
141
142   /* these are the theoretical boundaries, but we currently are always onscreen... */
143   if (x < 0 || x >= SNES_SCR_WIDTH || y < 0 || y >= snes_ppu.beam.last_visible_line)
144      state->m_scope[port].offscreen = 1;
145   else
146      state->m_scope[port].offscreen = 0;
147
148   return state->m_scope[port].offscreen;
149}
150
151static TIMER_CALLBACK( lightgun_tick )
152{
153   if ((input_port_read(machine, "CTRLSEL") & 0x0f) == 0x03 || (input_port_read(machine, "CTRLSEL") & 0x0f) == 0x04)
154   {
155      /* enable lightpen crosshair */
156      crosshair_set_screen(machine, 0, CROSSHAIR_SCREEN_ALL);
157   }
158   else
159   {
160      /* disable lightpen crosshair */
161      crosshair_set_screen(machine, 0, CROSSHAIR_SCREEN_NONE);
162   }
163
164   if ((input_port_read(machine, "CTRLSEL") & 0xf0) == 0x30 || (input_port_read(machine, "CTRLSEL") & 0xf0) == 0x40)
165   {
166      /* enable lightpen crosshair */
167      crosshair_set_screen(machine, 1, CROSSHAIR_SCREEN_ALL);
168   }
169   else
170   {
171      /* disable lightpen crosshair */
172      crosshair_set_screen(machine, 1, CROSSHAIR_SCREEN_NONE);
173   }
174}
175
176
177static INPUT_PORTS_START( snes_joypads )
178   PORT_START("SERIAL1_DATA1_L")
179   PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_BUTTON3 ) PORT_NAME("P1 Button A") PORT_PLAYER(1) PORT_CATEGORY(11)
180   PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_BUTTON4 ) PORT_NAME("P1 Button X") PORT_PLAYER(1) PORT_CATEGORY(11)
181   PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_BUTTON5 ) PORT_NAME("P1 Button L") PORT_PLAYER(1) PORT_CATEGORY(11)
182   PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_BUTTON6 ) PORT_NAME("P1 Button R") PORT_PLAYER(1) PORT_CATEGORY(11)
183   PORT_START("SERIAL1_DATA1_H")
184   PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_BUTTON1 ) PORT_NAME("P1 Button B") PORT_PLAYER(1) PORT_CATEGORY(11)
185   PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_BUTTON2 ) PORT_NAME("P1 Button Y") PORT_PLAYER(1) PORT_CATEGORY(11)
186   PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_SELECT ) PORT_PLAYER(1) PORT_CATEGORY(11)
187   PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_START1 ) PORT_PLAYER(1) PORT_CATEGORY(11)
188   PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_JOYSTICK_UP ) PORT_PLAYER(1) PORT_CATEGORY(11)
189   PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_JOYSTICK_DOWN ) PORT_PLAYER(1) PORT_CATEGORY(11)
190   PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_JOYSTICK_LEFT ) PORT_PLAYER(1) PORT_CATEGORY(11)
191   PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_JOYSTICK_RIGHT ) PORT_PLAYER(1) PORT_CATEGORY(11)
192
193   PORT_START("SERIAL2_DATA1_L")
194   PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_BUTTON3 ) PORT_NAME("P2 Button A") PORT_PLAYER(2) PORT_CATEGORY(21)
195   PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_BUTTON4 ) PORT_NAME("P2 Button X") PORT_PLAYER(2) PORT_CATEGORY(21)
196   PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_BUTTON5 ) PORT_NAME("P2 Button L") PORT_PLAYER(2) PORT_CATEGORY(21)
197   PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_BUTTON6 ) PORT_NAME("P2 Button R") PORT_PLAYER(2) PORT_CATEGORY(21)
198   PORT_START("SERIAL2_DATA1_H")
199   PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_BUTTON1 ) PORT_NAME("P2 Button B") PORT_PLAYER(2) PORT_CATEGORY(21)
200   PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_BUTTON2 ) PORT_NAME("P2 Button Y") PORT_PLAYER(2) PORT_CATEGORY(21)
201   PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_SELECT ) PORT_PLAYER(2) PORT_CATEGORY(21)
202   PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_START2 ) PORT_PLAYER(2) PORT_CATEGORY(21)
203   PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_JOYSTICK_UP ) PORT_PLAYER(2) PORT_CATEGORY(21)
204   PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_JOYSTICK_DOWN ) PORT_PLAYER(2) PORT_CATEGORY(21)
205   PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_JOYSTICK_LEFT ) PORT_PLAYER(2) PORT_CATEGORY(21)
206   PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_JOYSTICK_RIGHT ) PORT_PLAYER(2) PORT_CATEGORY(21)
207
208   PORT_START("SERIAL1_DATA2_L")
209   PORT_BIT( 0xff, IP_ACTIVE_HIGH, IPT_UNUSED )
210   PORT_START("SERIAL1_DATA2_H")
211   PORT_BIT( 0xff, IP_ACTIVE_HIGH, IPT_UNUSED )
212
213   PORT_START("SERIAL2_DATA2_L")
214   PORT_BIT( 0xff, IP_ACTIVE_HIGH, IPT_UNUSED )
215   PORT_START("SERIAL2_DATA2_H")
216   PORT_BIT( 0xff, IP_ACTIVE_HIGH, IPT_UNUSED )
217INPUT_PORTS_END
218
219static INPUT_PORTS_START( snes_mouse )
220   PORT_START("MOUSE1")
221   /* bits 0,3 = mouse signature (must be 1) */
222   PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_UNUSED )
223   PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_UNUSED )
224   PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_UNUSED )
225   PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_UNUSED )
226   /* bits 4,5 = mouse speed: 0 = slow, 1 = normal, 2 = fast, 3 = unused */
227   PORT_BIT( 0x30, IP_ACTIVE_HIGH, IPT_SPECIAL ) PORT_CUSTOM(snes_mouse_speed_input, (void *)0)
228   /* bits 6,7 = mouse buttons */
229   PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_BUTTON1 ) PORT_NAME("P1 Mouse Button Left") PORT_PLAYER(1) PORT_CATEGORY(12)
230   PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_BUTTON2 ) PORT_NAME("P1 Mouse Button Right") PORT_PLAYER(1) PORT_CATEGORY(12)
231
232   PORT_START("MOUSE1_X")
233   PORT_BIT( 0xff, 0x00, IPT_TRACKBALL_X) PORT_SENSITIVITY(100) PORT_KEYDELTA(0) PORT_PLAYER(1) PORT_CATEGORY(12)
234
235   PORT_START("MOUSE1_Y")
236   PORT_BIT( 0xff, 0x00, IPT_TRACKBALL_Y) PORT_SENSITIVITY(100) PORT_KEYDELTA(0) PORT_PLAYER(1) PORT_CATEGORY(12)
237
238   PORT_START("MOUSE2")
239   /* bits 0,3 = mouse signature (must be 1) */
240   PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_UNUSED )
241   PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_UNUSED )
242   PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_UNUSED )
243   PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_UNUSED )
244   /* bits 4,5 = mouse speed: 0 = slow, 1 = normal, 2 = fast, 3 = unused */
245   PORT_BIT( 0x30, IP_ACTIVE_HIGH, IPT_SPECIAL ) PORT_CUSTOM(snes_mouse_speed_input, (void *)1)
246   /* bits 6,7 = mouse buttons */
247   PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_BUTTON1 ) PORT_NAME("P2 Mouse Button Left") PORT_PLAYER(2) PORT_CATEGORY(22)
248   PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_BUTTON2 ) PORT_NAME("P2 Mouse Button Right") PORT_PLAYER(2) PORT_CATEGORY(22)
249
250   PORT_START("MOUSE2_X")
251   PORT_BIT( 0xff, 0x00, IPT_TRACKBALL_X) PORT_SENSITIVITY(100) PORT_KEYDELTA(0) PORT_PLAYER(2) PORT_CATEGORY(22)
252
253   PORT_START("MOUSE2_Y")
254   PORT_BIT( 0xff, 0x00, IPT_TRACKBALL_Y) PORT_SENSITIVITY(100) PORT_KEYDELTA(0) PORT_PLAYER(2) PORT_CATEGORY(22)
255INPUT_PORTS_END
256
257static INPUT_PORTS_START( snes_superscope )
258   PORT_START("SUPERSCOPE1")
259   PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_UNUSED )   // Noise
260   PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_SPECIAL ) PORT_CUSTOM(snes_superscope_offscreen_input, (void *)0)
261   PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_UNUSED )
262   PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_UNUSED )
263   PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_BUTTON4 ) PORT_NAME("Port1 Superscope Pause") PORT_PLAYER(1) PORT_CATEGORY(13)
264   PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_BUTTON3 ) PORT_NAME("Port1 Superscope Turbo") PORT_TOGGLE PORT_PLAYER(1) PORT_CATEGORY(13)
265   PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_BUTTON2 ) PORT_NAME("Port1 Superscope Cursor") PORT_PLAYER(1) PORT_CATEGORY(13)
266   PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_BUTTON1 ) PORT_NAME("Port1 Superscope Fire") PORT_PLAYER(1) PORT_CATEGORY(13)
267
268   PORT_START("SUPERSCOPE1_X")
269   PORT_BIT( 0xff, 0x80, IPT_LIGHTGUN_X ) PORT_NAME("Port1 Superscope X Axis") PORT_CROSSHAIR(X, 1.0, 0.0, 0) PORT_SENSITIVITY(25) PORT_KEYDELTA(15) PORT_PLAYER(1) PORT_CATEGORY(13)
270
271   PORT_START("SUPERSCOPE1_Y")
272   PORT_BIT( 0xff, 0x80, IPT_LIGHTGUN_Y) PORT_NAME("Port1 Superscope Y Axis") PORT_CROSSHAIR(Y, 1.0, 0.0, 0) PORT_SENSITIVITY(25) PORT_KEYDELTA(15) PORT_PLAYER(1) PORT_CATEGORY(13)
273
274   PORT_START("SUPERSCOPE2")
275   PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_UNUSED )   // Noise
276   PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_SPECIAL ) PORT_CUSTOM(snes_superscope_offscreen_input, (void *)1)
277   PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_UNUSED )
278   PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_UNUSED )
279   PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_BUTTON4 ) PORT_NAME("Port2 Superscope Pause") PORT_PLAYER(2) PORT_CATEGORY(23)
280   PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_BUTTON3 ) PORT_NAME("Port2 Superscope Turbo") PORT_PLAYER(2) PORT_CATEGORY(23)
281   PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_BUTTON2 ) PORT_NAME("Port2 Superscope Cursor") PORT_PLAYER(2) PORT_CATEGORY(23)
282   PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_BUTTON1 ) PORT_NAME("Port2 Superscope Fire") PORT_PLAYER(2) PORT_CATEGORY(23)
283
284   PORT_START("SUPERSCOPE2_X")
285   PORT_BIT( 0xff, 0x80, IPT_LIGHTGUN_X ) PORT_NAME("Port2 Superscope X Axis") PORT_CROSSHAIR(X, 1.0, 0.0, 0) PORT_SENSITIVITY(25) PORT_KEYDELTA(15) PORT_PLAYER(2) PORT_CATEGORY(23)
286
287   PORT_START("SUPERSCOPE2_Y")
288   PORT_BIT( 0xff, 0x80, IPT_LIGHTGUN_Y) PORT_NAME("Port2 Superscope Y Axis") PORT_CROSSHAIR(Y, 1.0, 0.0, 0) PORT_SENSITIVITY(25) PORT_KEYDELTA(15) PORT_PLAYER(2) PORT_CATEGORY(23)
289INPUT_PORTS_END
290
291static INPUT_PORTS_START( snes )
292   PORT_START("CTRLSEL")  /* Select Controller Type */
293   PORT_CATEGORY_CLASS( 0x0f, 0x01, "P1 Controller")
294   PORT_CATEGORY_ITEM(  0x00, "Unconnected",      10 )
295   PORT_CATEGORY_ITEM(  0x01, "Gamepad",      11 )
296   PORT_CATEGORY_ITEM(  0x02, "Mouse",         12 )
297   PORT_CATEGORY_ITEM(  0x03, "Superscope",      13 )
298//  PORT_CATEGORY_ITEM(  0x04, "Justfier",      14 )
299//  PORT_CATEGORY_ITEM(  0x05, "Multitap",      15 )
300   PORT_CATEGORY_CLASS( 0xf0, 0x10, "P2 Controller")
301   PORT_CATEGORY_ITEM(  0x00, "Unconnected",      20 )
302   PORT_CATEGORY_ITEM(  0x10, "Gamepad",      21 )
303   PORT_CATEGORY_ITEM(  0x20, "Mouse",         22 )
304   PORT_CATEGORY_ITEM(  0x30, "Superscope",      23 )
305//  PORT_CATEGORY_ITEM(  0x40, "Justfier",      24 )
306//  PORT_CATEGORY_ITEM(  0x50, "Multitap",      25 )
307
308   PORT_INCLUDE(snes_joypads)
309   PORT_INCLUDE(snes_mouse)
310   PORT_INCLUDE(snes_superscope)
311
312   PORT_START("OPTIONS")
313   PORT_CONFNAME( 0x01, 0x00, "Hi-Res pixels blurring (TV effect)")
314   PORT_CONFSETTING(    0x00, DEF_STR( Off ) )
315   PORT_CONFSETTING(    0x01, DEF_STR( On ) )
316
317#if SNES_LAYER_DEBUG
318   PORT_START("DEBUG1")
319   PORT_CONFNAME( 0x03, 0x00, "Select BG1 priority" )
320   PORT_CONFSETTING(    0x00, "All" )
321   PORT_CONFSETTING(    0x01, "BG1B (lower) only" )
322   PORT_CONFSETTING(    0x02, "BG1A (higher) only" )
323   PORT_CONFNAME( 0x0c, 0x00, "Select BG2 priority" )
324   PORT_CONFSETTING(    0x00, "All" )
325   PORT_CONFSETTING(    0x04, "BG2B (lower) only" )
326   PORT_CONFSETTING(    0x08, "BG2A (higher) only" )
327   PORT_CONFNAME( 0x30, 0x00, "Select BG3 priority" )
328   PORT_CONFSETTING(    0x00, "All" )
329   PORT_CONFSETTING(    0x10, "BG3B (lower) only" )
330   PORT_CONFSETTING(    0x20, "BG3A (higher) only" )
331   PORT_CONFNAME( 0xc0, 0x00, "Select BG4 priority" )
332   PORT_CONFSETTING(    0x00, "All" )
333   PORT_CONFSETTING(    0x40, "BG4B (lower) only" )
334   PORT_CONFSETTING(    0x80, "BG4A (higher) only" )
335
336   PORT_START("DEBUG2")
337   PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Toggle BG 1") PORT_CODE(KEYCODE_1_PAD) PORT_TOGGLE
338   PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Toggle BG 2") PORT_CODE(KEYCODE_2_PAD) PORT_TOGGLE
339   PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Toggle BG 3") PORT_CODE(KEYCODE_3_PAD) PORT_TOGGLE
340   PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Toggle BG 4") PORT_CODE(KEYCODE_4_PAD) PORT_TOGGLE
341   PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Toggle Objects") PORT_CODE(KEYCODE_5_PAD) PORT_TOGGLE
342   PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Toggle Main/Sub") PORT_CODE(KEYCODE_6_PAD) PORT_TOGGLE
343   PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Toggle Color Math") PORT_CODE(KEYCODE_7_PAD) PORT_TOGGLE
344   PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Toggle Windows") PORT_CODE(KEYCODE_8_PAD) PORT_TOGGLE
345
346   PORT_START("DEBUG3")
347   PORT_BIT( 0x4, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Toggle Mosaic") PORT_CODE(KEYCODE_9_PAD) PORT_TOGGLE
348   PORT_CONFNAME( 0x70, 0x00, "Select OAM priority" )
349   PORT_CONFSETTING(    0x00, "All" )
350   PORT_CONFSETTING(    0x10, "OAM0 only" )
351   PORT_CONFSETTING(    0x20, "OAM1 only" )
352   PORT_CONFSETTING(    0x30, "OAM2 only" )
353   PORT_CONFSETTING(    0x40, "OAM3 only" )
354   PORT_CONFNAME( 0x80, 0x00, "Draw sprite in reverse order" )
355   PORT_CONFSETTING(    0x00, DEF_STR( Off ) )
356   PORT_CONFSETTING(    0x80, DEF_STR( On ) )
357
358   PORT_START("DEBUG4")
359   PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Toggle Mode 0 draw") PORT_TOGGLE
360   PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Toggle Mode 1 draw") PORT_TOGGLE
361   PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Toggle Mode 2 draw") PORT_TOGGLE
362   PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Toggle Mode 3 draw") PORT_TOGGLE
363   PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Toggle Mode 4 draw") PORT_TOGGLE
364   PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Toggle Mode 5 draw") PORT_TOGGLE
365   PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Toggle Mode 6 draw") PORT_TOGGLE
366   PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Toggle Mode 7 draw") PORT_TOGGLE
367#endif
368INPUT_PORTS_END
369
370
371/*************************************
372 *
373 *  Input callbacks
374 *
375 *************************************/
376
377static void snes_gun_latch( running_machine &machine, INT16 x, INT16 y )
378{
379   /* these are the theoretical boundaries */
380   if (x < 0)
381      x = 0;
382   if (x > (SNES_SCR_WIDTH - 1))
383      x = SNES_SCR_WIDTH - 1;
384
385   if (y < 0)
386      y = 0;
387   if (y > (snes_ppu.beam.last_visible_line - 1))
388      y = snes_ppu.beam.last_visible_line - 1;
389
390   snes_ppu.beam.latch_horz = x;
391   snes_ppu.beam.latch_vert = y;
392   snes_ram[STAT78] |= 0x40;
393}
394
395static void snes_input_read_joy( running_machine &machine, int port )
396{
397   snes_state *state = machine.driver_data<snes_state>();
398   static const char *const portnames[2][4] =
399         {
400            { "SERIAL1_DATA1_L", "SERIAL1_DATA1_H", "SERIAL1_DATA2_L", "SERIAL1_DATA2_H" },
401            { "SERIAL2_DATA1_L", "SERIAL2_DATA1_H", "SERIAL2_DATA2_L", "SERIAL2_DATA2_H" },
402         };
403
404   state->m_data1[port] = input_port_read(machine, portnames[port][0]) | (input_port_read(machine, portnames[port][1]) << 8);
405   state->m_data2[port] = input_port_read(machine, portnames[port][2]) | (input_port_read(machine, portnames[port][3]) << 8);
406
407   // avoid sending signals that could crash games
408   // if left, no right
409   if (state->m_data1[port] & 0x200)
410      state->m_data1[port] &= ~0x100;
411   // if up, no down
412   if (state->m_data1[port] & 0x800)
413      state->m_data1[port] &= ~0x400;
414
415   state->m_joypad[port].buttons = state->m_data1[port];
416}
417
418static void snes_input_read_mouse( running_machine &machine, int port )
419{
420   snes_state *state = machine.driver_data<snes_state>();
421   INT16 var;
422   static const char *const portnames[2][3] =
423         {
424            { "MOUSE1", "MOUSE1_X", "MOUSE1_Y" },
425            { "MOUSE2", "MOUSE2_X", "MOUSE2_Y" },
426         };
427
428   state->m_mouse[port].buttons = input_port_read(machine, portnames[port][0]);
429   state->m_mouse[port].x = input_port_read(machine, portnames[port][1]);
430   state->m_mouse[port].y = input_port_read(machine, portnames[port][2]);
431   var = state->m_mouse[port].x - state->m_mouse[port].oldx;
432
433   if (var < -127)
434   {
435      state->m_mouse[port].deltax = 0xff;
436      state->m_mouse[port].oldx -= 127;
437   }
438   else if (var < 0)
439   {
440      state->m_mouse[port].deltax = 0x80 | (-var);
441      state->m_mouse[port].oldx = state->m_mouse[port].x;
442   }
443   else if (var > 127)
444   {
445      state->m_mouse[port].deltax = 0x7f;
446      state->m_mouse[port].oldx += 127;
447   }
448   else
449   {
450      state->m_mouse[port].deltax = var & 0xff;
451      state->m_mouse[port].oldx = state->m_mouse[port].x;
452   }
453
454   var = state->m_mouse[port].y - state->m_mouse[port].oldy;
455
456   if (var < -127)
457   {
458      state->m_mouse[port].deltay = 0xff;
459      state->m_mouse[port].oldy -= 127;
460   }
461   else if (var < 0)
462   {
463      state->m_mouse[port].deltay = 0x80 | (-var);
464      state->m_mouse[port].oldy = state->m_mouse[port].y;
465   }
466   else if (var > 127)
467   {
468      state->m_mouse[port].deltay = 0x7f;
469      state->m_mouse[port].oldy += 127;
470   }
471   else
472   {
473      state->m_mouse[port].deltay = var & 0xff;
474      state->m_mouse[port].oldy = state->m_mouse[port].y;
475   }
476
477   state->m_data1[port] = state->m_mouse[port].buttons | (0x00 << 8);
478   state->m_data2[port] = 0;
479}
480
481static void snes_input_read_superscope( running_machine &machine, int port )
482{
483   snes_state *state = machine.driver_data<snes_state>();
484   static const char *const portnames[2][3] =
485         {
486            { "SUPERSCOPE1", "SUPERSCOPE1_X", "SUPERSCOPE1_Y" },
487            { "SUPERSCOPE2", "SUPERSCOPE2_X", "SUPERSCOPE2_Y" },
488         };
489   UINT8 input;
490
491   /* first read input bits */
492   state->m_scope[port].x = input_port_read(machine, portnames[port][1]);
493   state->m_scope[port].y = input_port_read(machine, portnames[port][2]);
494   input = input_port_read(machine, portnames[port][0]);
495
496   /* then start elaborating input bits: only keep old turbo value */
497   state->m_scope[port].buttons &= 0x20;
498
499   /* set onscreen/offscreen */
500   state->m_scope[port].buttons |= BIT(input, 1);
501
502   /* turbo is a switch; toggle is edge sensitive */
503   if (BIT(input, 5) && !state->m_scope[port].turbo_lock)
504   {
505      state->m_scope[port].buttons ^= 0x20;
506      state->m_scope[port].turbo_lock = 1;
507   }
508   else if (!BIT(input, 5))
509      state->m_scope[port].turbo_lock = 0;
510
511   /* fire is a button; if turbo is active, trigger is level sensitive; otherwise it is edge sensitive */
512   if (BIT(input, 7) && (BIT(state->m_scope[port].buttons, 5) || !state->m_scope[port].fire_lock))
513   {
514      state->m_scope[port].buttons |= 0x80;
515      state->m_scope[port].fire_lock = 1;
516   }
517   else if (!BIT(input, 7))
518      state->m_scope[port].fire_lock = 0;
519
520   /* cursor is a button; it is always level sensitive */
521   state->m_scope[port].buttons |= BIT(input, 6);
522
523   /* pause is a button; it is always edge sensitive */
524   if (BIT(input, 4) && !state->m_scope[port].pause_lock)
525   {
526      state->m_scope[port].buttons |= 0x10;
527      state->m_scope[port].pause_lock = 1;
528   }
529   else if (!BIT(input, 4))
530      state->m_scope[port].pause_lock = 0;
531
532   /* If we have pressed fire or cursor and we are on-screen and SuperScope is in Port2, then latch video signal.
533    Notice that we only latch Port2 because its IOBit pin is connected to bit7 of the IO Port, while Port1 has
534    IOBit pin connected to bit6 of the IO Port, and the latter is not detected by the H/V Counters. In other
535    words, you can connect SuperScope to Port1, but there is no way SNES could detect its on-screen position */
536   if ((state->m_scope[port].buttons & 0xc0) && !(state->m_scope[port].buttons & 0x02) && port == 1)
537      snes_gun_latch(machine, state->m_scope[port].x, state->m_scope[port].y);
538
539   state->m_data1[port] = 0xff | (state->m_scope[port].buttons << 8);
540   state->m_data2[port] = 0;
541}
542
543static void snes_input_read( running_machine &machine )
544{
545   snes_state *state = machine.driver_data<snes_state>();
546   UINT8 ctrl1 = input_port_read(machine, "CTRLSEL") & 0x0f;
547   UINT8 ctrl2 = (input_port_read(machine, "CTRLSEL") & 0xf0) >> 4;
548
549   /* Check if lightgun has been chosen as input: if so, enable crosshair */
550   machine.scheduler().timer_set(attotime::zero, FUNC(lightgun_tick));
551
552   switch (ctrl1)
553   {
554   case 1:   /* SNES joypad */
555      snes_input_read_joy(machine, 0);
556      break;
557   case 2:   /* SNES Mouse */
558      snes_input_read_mouse(machine, 0);
559      break;
560   case 3:   /* SNES Superscope */
561      snes_input_read_superscope(machine, 0);
562      break;
563   case 0:   /* no controller in port1 */
564   default:
565      state->m_data1[0] = 0;
566      state->m_data2[0] = 0;
567      break;
568   }
569
570   switch (ctrl2)
571   {
572   case 1:   /* SNES joypad */
573      snes_input_read_joy(machine, 1);
574      break;
575   case 2:   /* SNES Mouse */
576      snes_input_read_mouse(machine, 1);
577      break;
578   case 3:   /* SNES Superscope */
579      snes_input_read_superscope(machine, 1);
580      break;
581   case 0:   /* no controller in port2 */
582   default:
583      state->m_data1[1] = 0;
584      state->m_data2[1] = 0;
585      break;
586   }
587
588   // is automatic reading on? if so, copy port data1/data2 to joy1l->joy4h
589   // this actually works like reading the first 16bits from oldjoy1/2 in reverse order
590   if (snes_ram[NMITIMEN] & 1)
591   {
592      state->m_joy1l = (state->m_data1[0] & 0x00ff) >> 0;
593      state->m_joy1h = (state->m_data1[0] & 0xff00) >> 8;
594      state->m_joy2l = (state->m_data1[1] & 0x00ff) >> 0;
595      state->m_joy2h = (state->m_data1[1] & 0xff00) >> 8;
596      state->m_joy3l = (state->m_data2[0] & 0x00ff) >> 0;
597      state->m_joy3h = (state->m_data2[0] & 0xff00) >> 8;
598      state->m_joy4l = (state->m_data2[1] & 0x00ff) >> 0;
599      state->m_joy4h = (state->m_data2[1] & 0xff00) >> 8;
600
601      // make sure read_idx starts returning all 1s because the auto-read reads it :-)
602      state->m_read_idx[0] = 16;
603      state->m_read_idx[1] = 16;
604   }
605
606}
607
608static UINT8 snes_oldjoy1_read( running_machine &machine )
609{
610   snes_state *state = machine.driver_data<snes_state>();
611   UINT8 ctrl1 = input_port_read(machine, "CTRLSEL") & 0x0f;
612   UINT8 res = 0;
613
614   switch (ctrl1)
615   {
616   case 1:   /* SNES joypad */
617      if (state->m_read_idx[0] >= 16)
618         res = 0x01;
619      else
620         res = (state->m_joypad[0].buttons >> (15 - state->m_read_idx[0]++)) & 0x01;
621      break;
622   case 2:   /* SNES Mouse */
623      if (state->m_read_idx[0] >= 32)
624         res = 0x01;
625      else if (state->m_read_idx[0] >= 24)
626         res = (state->m_mouse[0].deltax >> (31 - state->m_read_idx[0]++)) & 0x01;
627      else if (state->m_read_idx[0] >= 16)
628         res = (state->m_mouse[0].deltay >> (23 - state->m_read_idx[0]++)) & 0x01;
629      else if (state->m_read_idx[0] >= 8)
630         res = (state->m_mouse[0].buttons >> (15 - state->m_read_idx[0]++)) & 0x01;
631      else
632         res = 0;
633      break;
634   case 3:   /* SNES Superscope */
635      if (state->m_read_idx[0] >= 8)
636         res = 0x01;
637      else
638         res = (state->m_scope[0].buttons >> (7 - state->m_read_idx[0]++)) & 0x01;
639      break;
640   case 0:   /* no controller in port2 */
641   default:
642      break;
643   }
644
645   return res;
646}
647
648static UINT8 snes_oldjoy2_read( running_machine &machine )
649{
650   snes_state *state = machine.driver_data<snes_state>();
651   UINT8 ctrl2 = (input_port_read(machine, "CTRLSEL") & 0xf0) >> 4;
652   UINT8 res = 0;
653
654   switch (ctrl2)
655   {
656   case 1:   /* SNES joypad */
657      if (state->m_read_idx[1] >= 16)
658         res = 0x01;
659      else
660         res = (state->m_joypad[1].buttons >> (15 - state->m_read_idx[1]++)) & 0x01;
661      break;
662   case 2:   /* SNES Mouse */
663      if (state->m_read_idx[1] >= 32)
664         res = 0x01;
665      else if (state->m_read_idx[1] >= 24)
666         res = (state->m_mouse[1].deltax >> (31 - state->m_read_idx[1]++)) & 0x01;
667      else if (state->m_read_idx[1] >= 16)
668         res = (state->m_mouse[1].deltay >> (23 - state->m_read_idx[1]++)) & 0x01;
669      else if (state->m_read_idx[1] >= 8)
670         res = (state->m_mouse[1].buttons >> (15 - state->m_read_idx[1]++)) & 0x01;
671      else
672         res = 0;
673      break;
674   case 3:   /* SNES Superscope */
675      if (state->m_read_idx[1] >= 8)
676         res = 0x01;
677      else
678         res = (state->m_scope[1].buttons >> (7 - state->m_read_idx[1]++)) & 0x01;
679      break;
680   case 0:   /* no controller in port2 */
681   default:
682      break;
683   }
684
685   return res;
686}
687
688/*************************************
689 *
690 *  Machine driver
691 *
692 *************************************/
693
694static MACHINE_RESET( snes_mess )
695{
696   snes_state *state = machine.driver_data<snes_state>();
697
698   MACHINE_RESET_CALL(snes);
699
700   state->m_io_read = snes_input_read;
701   state->m_oldjoy1_read = snes_oldjoy1_read;
702   state->m_oldjoy2_read = snes_oldjoy2_read;
703}
704
705static MACHINE_CONFIG_START( snes_base, snes_state )
706
707   /* basic machine hardware */
708   MCFG_CPU_ADD("maincpu", _5A22, MCLK_NTSC)   /* 2.68 MHz, also 3.58 MHz */
709   MCFG_CPU_PROGRAM_MAP(snes_map)
710
711   MCFG_CPU_ADD("soundcpu", SPC700, 1024000)   /* 1.024 MHz */
712   MCFG_CPU_PROGRAM_MAP(spc_map)
713
714   //MCFG_QUANTUM_TIME(attotime::from_hz(48000))
715   MCFG_QUANTUM_PERFECT_CPU("maincpu")
716
717   MCFG_MACHINE_START(snes_mess)
718   MCFG_MACHINE_RESET(snes_mess)
719
720   /* video hardware */
721   MCFG_VIDEO_START(snes)
722
723   MCFG_SCREEN_ADD("screen", RASTER)
724   MCFG_SCREEN_FORMAT(BITMAP_FORMAT_RGB32)
725   MCFG_SCREEN_RAW_PARAMS(DOTCLK_NTSC, SNES_HTOTAL, 0, SNES_SCR_WIDTH, SNES_VTOTAL_NTSC, 0, SNES_SCR_HEIGHT_NTSC)
726   MCFG_SCREEN_UPDATE(snes)
727
728   /* sound hardware */
729   MCFG_SPEAKER_STANDARD_STEREO("lspeaker", "rspeaker")
730   MCFG_SOUND_ADD("spc700", SNES, 0)
731   MCFG_SOUND_ROUTE(0, "lspeaker", 1.00)
732   MCFG_SOUND_ROUTE(1, "rspeaker", 1.00)
733MACHINE_CONFIG_END
734
735static MACHINE_CONFIG_DERIVED( snes, snes_base )
736
737   MCFG_FRAGMENT_ADD(snes_cartslot)
738MACHINE_CONFIG_END
739
740static SUPERFX_CONFIG( snes_superfx_config )
741{
742   DEVCB_LINE(snes_extern_irq_w)   /* IRQ line from cart */
743};
744
745static MACHINE_CONFIG_DERIVED( snessfx, snes )
746
747   MCFG_CPU_ADD("superfx", SUPERFX, 21480000)   /* 21.48MHz */
748   MCFG_CPU_PROGRAM_MAP(superfx_map)
749   MCFG_CPU_CONFIG(snes_superfx_config)
750MACHINE_CONFIG_END
751
752static MACHINE_CONFIG_DERIVED( snesdsp, snes )
753
754   MCFG_CPU_ADD("dsp", UPD7725, 8000000)
755   MCFG_CPU_PROGRAM_MAP(dsp_prg_map)
756   MCFG_CPU_DATA_MAP(dsp_data_map)
757MACHINE_CONFIG_END
758
759static MACHINE_CONFIG_DERIVED( snesst10, snes )
760
761   MCFG_CPU_ADD("setadsp", UPD96050, 10000000)
762   MCFG_CPU_PROGRAM_MAP(setadsp_prg_map)
763   MCFG_CPU_DATA_MAP(setadsp_data_map)
764MACHINE_CONFIG_END
765
766static MACHINE_CONFIG_DERIVED( snesst11, snes )
767
768   MCFG_CPU_ADD("setadsp", UPD96050, 15000000)
769   MCFG_CPU_PROGRAM_MAP(setadsp_prg_map)
770   MCFG_CPU_DATA_MAP(setadsp_data_map)
771MACHINE_CONFIG_END
772
773static MACHINE_CONFIG_DERIVED( snespal, snes )
774   MCFG_CPU_MODIFY( "maincpu" )
775   MCFG_CPU_CLOCK( MCLK_PAL )
776
777   MCFG_SCREEN_MODIFY("screen")
778   MCFG_SCREEN_RAW_PARAMS(DOTCLK_PAL, SNES_HTOTAL, 0, SNES_SCR_WIDTH, SNES_VTOTAL_PAL, 0, SNES_SCR_HEIGHT_PAL)
779MACHINE_CONFIG_END
780
781static MACHINE_CONFIG_DERIVED( snespsfx, snespal )
782
783   MCFG_CPU_ADD("superfx", SUPERFX, 21480000)   /* 21.48MHz */
784   MCFG_CPU_PROGRAM_MAP(superfx_map)
785   MCFG_CPU_CONFIG(snes_superfx_config)
786MACHINE_CONFIG_END
787
788static MACHINE_CONFIG_DERIVED( snespdsp, snespal )
789
790   MCFG_CPU_ADD("dsp", UPD7725, 8000000)
791   MCFG_CPU_PROGRAM_MAP(dsp_prg_map)
792   MCFG_CPU_DATA_MAP(dsp_data_map)
793MACHINE_CONFIG_END
794
795static MACHINE_CONFIG_DERIVED( snesst, snes_base )
796
797   MCFG_MACHINE_START(snesst)
798
799   MCFG_FRAGMENT_ADD(sufami_cartslot)
800MACHINE_CONFIG_END
801
802static MACHINE_CONFIG_DERIVED( snesbsx, snes_base )
803
804   MCFG_FRAGMENT_ADD(bsx_cartslot)
805MACHINE_CONFIG_END
806
807
808/*************************************
809 *
810 *  ROM definition(s)
811 *
812 *************************************/
813
814ROM_START( snes )
815   ROM_REGION( 0x1000000, "maincpu", ROMREGION_ERASE00 )
816
817   ROM_REGION( 0x100, "user5", 0 )      /* IPL ROM */
818   ROM_LOAD( "spc700.rom", 0, 0x40, CRC(44bb3a40) SHA1(97e352553e94242ae823547cd853eecda55c20f0) )   /* boot rom */
819
820   ROM_REGION( 0x10000, "addons", ROMREGION_ERASE00 )      /* add-on chip ROMs (DSP, SFX, etc) */
821
822   ROM_REGION( MAX_SNES_CART_SIZE, "cart", ROMREGION_ERASE00 )
823   ROM_REGION( 0x2000, "dspprg", ROMREGION_ERASEFF)
824   ROM_REGION( 0x800, "dspdata", ROMREGION_ERASEFF)
825ROM_END
826
827ROM_START( snesdsp )
828   ROM_REGION( 0x1000000, "maincpu", ROMREGION_ERASE00 )
829
830   ROM_REGION( 0x100, "user5", 0 )      /* IPL ROM */
831   ROM_LOAD( "spc700.rom", 0, 0x40, CRC(44bb3a40) SHA1(97e352553e94242ae823547cd853eecda55c20f0) )   /* boot rom */
832
833   ROM_REGION( 0x10000, "addons", 0 )      /* add-on chip ROMs (DSP, SFX, etc) */
834   ROM_LOAD( "dsp1b.bin", SNES_DSP1B_OFFSET, 0x002800, CRC(453557e0) SHA1(3a218b0e4572a8eba6d0121b17fdac9529609220) )
835   ROM_LOAD( "dsp1.bin",  SNES_DSP1_OFFSET,  0x002800, CRC(2838f9f5) SHA1(0a03ccb1fd2bea91151c745a4d1f217ae784f889) )
836   ROM_LOAD( "dsp2.bin",  SNES_DSP2_OFFSET,  0x002800, CRC(8e9fbd9b) SHA1(06dd9fcb118d18f6bbe234e013cb8780e06d6e63) )
837   ROM_LOAD( "dsp3.bin",  SNES_DSP3_OFFSET,  0x002800, CRC(6b86728a) SHA1(1b133741fad810eb7320c21ecfdd427d25a46da1) )
838   ROM_LOAD( "dsp4.bin",  SNES_DSP4_OFFSET,  0x002800, CRC(ce0c7783) SHA1(76fd25f7dc26c3b3f7868a3aa78c7684068713e5) )
839
840   ROM_REGION( MAX_SNES_CART_SIZE, "cart", ROMREGION_ERASE00 )
841   ROM_REGION( 0x2000, "dspprg", ROMREGION_ERASEFF)
842   ROM_REGION( 0x800, "dspdata", ROMREGION_ERASEFF)
843ROM_END
844
845ROM_START( snesst10 )
846   ROM_REGION( 0x1000000, "maincpu", ROMREGION_ERASE00 )
847
848   ROM_REGION( 0x100, "user5", 0 )      /* IPL ROM */
849   ROM_LOAD( "spc700.rom", 0, 0x40, CRC(44bb3a40) SHA1(97e352553e94242ae823547cd853eecda55c20f0) )   /* boot rom */
850
851   ROM_REGION( 0x11000, "addons", 0 )      /* add-on chip ROMs (DSP, SFX, etc) */
852   ROM_LOAD( "st010.bin",    0x000000, 0x011000, CRC(aa11ee2d) SHA1(cc1984e989cb94e3dcbb5f99e085b5414e18a017) )
853
854   ROM_REGION( MAX_SNES_CART_SIZE, "cart", ROMREGION_ERASE00 )
855   ROM_REGION( 0x10000, "dspprg", ROMREGION_ERASEFF)
856   ROM_REGION( 0x1000, "dspdata", ROMREGION_ERASEFF)
857ROM_END
858
859ROM_START( snesst11 )
860   ROM_REGION( 0x1000000, "maincpu", ROMREGION_ERASE00 )
861
862   ROM_REGION( 0x100, "user5", 0 )      /* IPL ROM */
863   ROM_LOAD( "spc700.rom", 0, 0x40, CRC(44bb3a40) SHA1(97e352553e94242ae823547cd853eecda55c20f0) )   /* boot rom */
864
865   ROM_REGION( 0x11000, "addons", 0 )      /* add-on chip ROMs (DSP, SFX, etc) */
866   ROM_LOAD( "st011.bin",    0x000000, 0x011000, CRC(34d2952c) SHA1(1375b8c1efc8cae4962b57dfe22f6b78e1ddacc8) )
867
868   ROM_REGION( MAX_SNES_CART_SIZE, "cart", ROMREGION_ERASE00 )
869   ROM_REGION( 0x10000, "dspprg", ROMREGION_ERASEFF)
870   ROM_REGION( 0x1000, "dspdata", ROMREGION_ERASEFF)
871ROM_END
872
873ROM_START( snessfx )
874   ROM_REGION( 0x1000000, "maincpu", ROMREGION_ERASE00 )
875
876   ROM_REGION( 0x100, "user5", 0 )      /* IPL ROM */
877   ROM_LOAD( "spc700.rom", 0, 0x40, CRC(44bb3a40) SHA1(97e352553e94242ae823547cd853eecda55c20f0) )   /* boot rom */
878
879   ROM_REGION( 0x10000, "addons", ROMREGION_ERASE00 )      /* add-on chip ROMs (DSP, SFX, etc) */
880
881   ROM_REGION( MAX_SNES_CART_SIZE, "cart", ROMREGION_ERASE00 )
882   ROM_REGION( 0x2000, "dspprg", ROMREGION_ERASEFF)
883   ROM_REGION( 0x800, "dspdata", ROMREGION_ERASEFF)
884ROM_END
885
886ROM_START( snespal )
887   ROM_REGION( 0x1000000, "maincpu", ROMREGION_ERASE00 )
888
889   ROM_REGION( 0x100, "user5", 0 )      /* IPL ROM */
890   ROM_LOAD( "spc700.rom", 0, 0x40, CRC(44bb3a40) SHA1(97e352553e94242ae823547cd853eecda55c20f0) )   /* boot rom */
891
892   ROM_REGION( 0x10000, "addons", ROMREGION_ERASE00 )      /* add-on chip ROMs (DSP, SFX, etc) */
893
894   ROM_REGION( MAX_SNES_CART_SIZE, "cart", ROMREGION_ERASE00 )
895   ROM_REGION( 0x2000, "dspprg", ROMREGION_ERASEFF)
896   ROM_REGION( 0x800, "dspdata", ROMREGION_ERASEFF)
897ROM_END
898
899ROM_START( snespdsp )
900   ROM_REGION( 0x1000000, "maincpu", ROMREGION_ERASE00 )
901
902   ROM_REGION( 0x100, "user5", 0 )      /* IPL ROM */
903   ROM_LOAD( "spc700.rom", 0, 0x40, CRC(44bb3a40) SHA1(97e352553e94242ae823547cd853eecda55c20f0) )   /* boot rom */
904
905   ROM_REGION( 0x10000, "addons", 0 )      /* add-on chip ROMs (DSP, SFX, etc) */
906   ROM_LOAD( "dsp1b.bin", SNES_DSP1B_OFFSET, 0x002800, CRC(453557e0) SHA1(3a218b0e4572a8eba6d0121b17fdac9529609220) )
907   ROM_LOAD( "dsp1.bin",  SNES_DSP1_OFFSET,  0x002800, CRC(2838f9f5) SHA1(0a03ccb1fd2bea91151c745a4d1f217ae784f889) )
908   ROM_LOAD( "dsp2.bin",  SNES_DSP2_OFFSET,  0x002800, CRC(8e9fbd9b) SHA1(06dd9fcb118d18f6bbe234e013cb8780e06d6e63) )
909   ROM_LOAD( "dsp3.bin",  SNES_DSP3_OFFSET,  0x002800, CRC(6b86728a) SHA1(1b133741fad810eb7320c21ecfdd427d25a46da1) )
910   ROM_LOAD( "dsp4.bin",  SNES_DSP4_OFFSET,  0x002800, CRC(ce0c7783) SHA1(76fd25f7dc26c3b3f7868a3aa78c7684068713e5) )
911
912   ROM_REGION( MAX_SNES_CART_SIZE, "cart", ROMREGION_ERASE00 )
913   ROM_REGION( 0x2000, "dspprg", ROMREGION_ERASEFF)
914   ROM_REGION( 0x800, "dspdata", ROMREGION_ERASEFF)
915ROM_END
916
917ROM_START( snespsfx )
918   ROM_REGION( 0x1000000, "maincpu", ROMREGION_ERASE00 )
919
920   ROM_REGION( 0x100, "user5", 0 )      /* IPL ROM */
921   ROM_LOAD( "spc700.rom", 0, 0x40, CRC(44bb3a40) SHA1(97e352553e94242ae823547cd853eecda55c20f0) )   /* boot rom */
922
923   ROM_REGION( 0x10000, "addons", ROMREGION_ERASE00 )      /* add-on chip ROMs (DSP, SFX, etc) */
924
925   ROM_REGION( MAX_SNES_CART_SIZE, "cart", ROMREGION_ERASE00 )
926   ROM_REGION( 0x2000, "dspprg", ROMREGION_ERASEFF)
927   ROM_REGION( 0x800, "dspdata", ROMREGION_ERASEFF)
928ROM_END
929
930ROM_START( snesst )
931   ROM_REGION( 0x1000000, "maincpu", ROMREGION_ERASE00 )
932
933   ROM_REGION( 0x100, "user5", 0 )      /* IPL ROM */
934   ROM_LOAD( "spc700.rom", 0, 0x40, CRC(44bb3a40) SHA1(97e352553e94242ae823547cd853eecda55c20f0) )   /* boot rom */
935
936   ROM_REGION( 0x10000, "addons", ROMREGION_ERASE00 )      /* add-on chip ROMs (DSP, SFX, etc) */
937
938   ROM_REGION( 0x40000, "sufami", 0 )      /* add-on chip ROMs (DSP, SFX, etc) */
939   ROM_LOAD( "shvc-qh-0.bin", 0,   0x40000, CRC(9b4ca911) SHA1(ef86ea192eed03d5c413fdbbfd46043be1d7a127) )
940
941   ROM_REGION( MAX_SNES_CART_SIZE, "slot_a", ROMREGION_ERASE00 )
942   ROM_REGION( MAX_SNES_CART_SIZE, "slot_b", ROMREGION_ERASE00 )
943   ROM_REGION( 0x2000, "dspprg", ROMREGION_ERASEFF)
944   ROM_REGION( 0x800, "dspdata", ROMREGION_ERASEFF)
945ROM_END
946
947ROM_START( snesbsx )
948   ROM_REGION( 0x1000000, "maincpu", ROMREGION_ERASE00 )
949
950   ROM_REGION( 0x100, "user5", 0 )      /* IPL ROM */
951   ROM_LOAD( "spc700.rom", 0, 0x40, CRC(44bb3a40) SHA1(97e352553e94242ae823547cd853eecda55c20f0) )   /* boot rom */
952
953   ROM_REGION( 0x10000, "addons", 0 )      /* add-on chip ROMs (DSP, SFX, etc) */
954   ROM_LOAD( "dsp1b.bin", SNES_DSP1B_OFFSET, 0x002800, CRC(453557e0) SHA1(3a218b0e4572a8eba6d0121b17fdac9529609220) )
955   ROM_LOAD( "dsp1.bin",  SNES_DSP1_OFFSET,  0x002800, CRC(2838f9f5) SHA1(0a03ccb1fd2bea91151c745a4d1f217ae784f889) )
956   ROM_LOAD( "dsp2.bin",  SNES_DSP2_OFFSET,  0x002800, CRC(8e9fbd9b) SHA1(06dd9fcb118d18f6bbe234e013cb8780e06d6e63) )
957   ROM_LOAD( "dsp3.bin",  SNES_DSP3_OFFSET,  0x002800, CRC(6b86728a) SHA1(1b133741fad810eb7320c21ecfdd427d25a46da1) )
958   ROM_LOAD( "dsp4.bin",  SNES_DSP4_OFFSET,  0x002800, CRC(ce0c7783) SHA1(76fd25f7dc26c3b3f7868a3aa78c7684068713e5) )
959
960   ROM_REGION( MAX_SNES_CART_SIZE, "cart", ROMREGION_ERASE00 )
961   ROM_REGION( MAX_SNES_CART_SIZE, "flash", ROMREGION_ERASE00 )
962   ROM_REGION( 0x2000, "dspprg", ROMREGION_ERASEFF)
963   ROM_REGION( 0x800, "dspdata", ROMREGION_ERASEFF)
964ROM_END
965
966
967
968/*************************************
969 *
970 *  Game driver(s)
971 *
972 *************************************/
973
974/*    YEAR  NAME      PARENT  COMPAT  MACHINE   INPUT  INIT          COMPANY     FULLNAME                                      FLAGS */
975CONS( 1989, snes,     0,      0,      snes,     snes,  snes_mess,    "Nintendo", "Super Nintendo Entertainment System / Super Famicom (NTSC)", GAME_IMPERFECT_GRAPHICS | GAME_IMPERFECT_SOUND )
976CONS( 1991, snespal,  snes,   0,      snespal,  snes,  snes_mess,    "Nintendo", "Super Nintendo Entertainment System (PAL)",  GAME_IMPERFECT_GRAPHICS | GAME_IMPERFECT_SOUND )
977
978// FIXME: the "hacked" drivers below, currently needed due to limitations in the core device design, should eventually be removed
979
980// These would require CPU to be added/removed depending on the cart which is loaded
981CONS( 1989, snesdsp,  snes,   0,      snesdsp,  snes,  snes_mess,    "Nintendo", "Super Nintendo Entertainment System / Super Famicom (NTSC, w/DSP-x)", GAME_IMPERFECT_GRAPHICS | GAME_IMPERFECT_SOUND )
982CONS( 1991, snespdsp, snes,   0,      snespdsp, snes,  snes_mess,    "Nintendo", "Super Nintendo Entertainment System (PAL, w/DSP-x)",  GAME_IMPERFECT_GRAPHICS | GAME_IMPERFECT_SOUND )
983CONS( 1989, snessfx,  snes,   0,      snessfx,  snes,  snes_mess,    "Nintendo", "Super Nintendo Entertainment System / Super Famicom (NTSC, w/SuperFX)", GAME_IMPERFECT_GRAPHICS | GAME_IMPERFECT_SOUND )
984CONS( 1991, snespsfx, snes,   0,      snespsfx, snes,  snes_mess,    "Nintendo", "Super Nintendo Entertainment System (PAL, w/SuperFX)",  GAME_IMPERFECT_GRAPHICS | GAME_IMPERFECT_SOUND )
985CONS( 1989, snesst10,  snes,   0,      snesst10,  snes,  snes_mess,    "Nintendo", "Super Nintendo Entertainment System / Super Famicom (NTSC, w/ST-010)", GAME_IMPERFECT_GRAPHICS | GAME_IMPERFECT_SOUND )
986CONS( 1989, snesst11,  snes,   0,      snesst11,  snes,  snes_mess,    "Nintendo", "Super Nintendo Entertainment System / Super Famicom (NTSC, w/ST-011)", GAME_IMPERFECT_GRAPHICS | GAME_IMPERFECT_SOUND )
987//CONS( 1989, snessa1,  snes,   0,      snessa1,  snes,  snes_mess,    "Nintendo", "Super Nintendo Entertainment System / Super Famicom (NTSC, w/SA-1)", GAME_IMPERFECT_GRAPHICS | GAME_IMPERFECT_SOUND )
988//CONS( 1991, snespsa1, snes,   0,      snespsa1, snes,  snes_mess,    "Nintendo", "Super Nintendo Entertainment System (PAL, w/SA-1)",  GAME_IMPERFECT_GRAPHICS | GAME_IMPERFECT_SOUND )
989
990// These would require cartslot to be added/removed depending on the cart which is loaded
991CONS( 1989, snesst,   snes,   0,      snesst,  snes,  snesst,       "Nintendo", "Super Nintendo Entertainment System / Super Famicom (NTSC, w/Sufami Turbo)", GAME_NOT_WORKING )
992CONS( 1989, snesbsx,  snes,   0,      snesbsx, snes,  snes_mess,    "Nintendo", "Super Nintendo Entertainment System / Super Famicom (NTSC, w/BS-X Satellaview slotted cart)",  GAME_NOT_WORKING )
src/mame/drivers/a3000.c
r11531r11532
1/***************************************************************************
2
3    Commodore Amiga 3000
4
5    Skeleton driver
6
7***************************************************************************/
8
9#include "emu.h"
10#include "cpu/m68000/m68000.h"
11
12
13class a3000_state : public driver_device
14{
15public:
16   a3000_state(const machine_config &mconfig, device_type type, const char *tag)
17      : driver_device(mconfig, type, tag) { }
18
19};
20
21
22
23/***************************************************************************
24    CONSTANTS
25***************************************************************************/
26
27#define XTAL_U104   XTAL_32MHz
28
29
30/***************************************************************************
31    ADDRESS MAPS
32***************************************************************************/
33
34static ADDRESS_MAP_START( a3000_mem, AS_PROGRAM, 32 )
35   ADDRESS_MAP_UNMAP_HIGH
36   AM_RANGE(0x000000, 0x1fffff) AM_RAMBANK("chipram")
37   AM_RANGE(0xf80000, 0xffffff) AM_ROM AM_REGION("kickstart", 0)
38ADDRESS_MAP_END
39
40
41/***************************************************************************
42    INPUT PORTS
43***************************************************************************/
44
45static INPUT_PORTS_START( a3000 )
46INPUT_PORTS_END
47
48
49/***************************************************************************
50    MACHINE DRIVERS
51***************************************************************************/
52
53static MACHINE_CONFIG_START( a3000, a3000_state )
54   MCFG_CPU_ADD("maincpu", M68030, XTAL_U104 / 2)
55   MCFG_CPU_PROGRAM_MAP(a3000_mem)
56
57   MCFG_SCREEN_ADD("screen", RASTER)
58   MCFG_SCREEN_REFRESH_RATE(60)
59   MCFG_SCREEN_VBLANK_TIME(ATTOSECONDS_IN_USEC(0))
60   MCFG_SCREEN_FORMAT(BITMAP_FORMAT_RGB32)
61   MCFG_SCREEN_SIZE(512*2, 312)
62   MCFG_SCREEN_VISIBLE_AREA((129-8-8)*2, (449+8-1+8)*2, 44-8, 300+8-1)
63MACHINE_CONFIG_END
64
65
66/***************************************************************************
67    ROM DEFINITIONS
68***************************************************************************/
69
70/* Note: I think those ROMs are correct, but they should be verified */
71ROM_START( a3000 )
72   ROM_REGION32_BE(0x80000, "kickstart", 0)
73   ROM_DEFAULT_BIOS("kick14")
74   ROM_SYSTEM_BIOS(0, "kick14", "Kickstart 1.4 (36.16)")
75   /* COPYRIGHT 1990 CAI // ALL RIGHTS RESERVED // ALPHA 5 ROM 0 CS=9713 */
76   ROMX_LOAD("390629-02.u182", 0x00000, 0x40000, CRC(58327536) SHA1(d1713d7f31474a5948e6d488e33686061cf3d1e2), ROM_GROUPWORD | ROM_REVERSE | ROM_SKIP(2) | ROM_BIOS(1))
77   /* COPYRIGHT 1990 CAI // ALL RIGHTS RESERVED // ALPHA 5 ROM 1 CS=9B21 */
78   ROMX_LOAD("390630-02.u183", 0x00002, 0x40000, CRC(fe2f7fb9) SHA1(c05c9c52d014c66f9019152b3f2a2adc2c678794), ROM_GROUPWORD | ROM_REVERSE | ROM_SKIP(2) | ROM_BIOS(1))
79   ROM_SYSTEM_BIOS(1, "kick204", "Kickstart 2.04 (37.175)")
80   ROMX_LOAD("390629-03.u182", 0x00000, 0x40000, CRC(a245dbdf) SHA1(83bab8e95d378b55b0c6ae6561385a96f638598f), ROM_GROUPWORD | ROM_REVERSE | ROM_SKIP(2) | ROM_BIOS(2))
81   ROMX_LOAD("390630-03.u183", 0x00002, 0x40000, CRC(7db1332b) SHA1(48f14b31279da6757848df6feb5318818f8f576c), ROM_GROUPWORD | ROM_REVERSE | ROM_SKIP(2) | ROM_BIOS(2))
82   ROM_SYSTEM_BIOS(2, "kick31", "Kickstart 3.1 (40.68)")
83   ROMX_LOAD("kick31.u182",    0x00000, 0x40000, CRC(286b9a0d) SHA1(6763a2258ec493f7408cf663110dae9a17803ad1), ROM_GROUPWORD | ROM_REVERSE | ROM_SKIP(2) | ROM_BIOS(3))
84   ROMX_LOAD("kick31.u183",    0x00002, 0x40000, CRC(0b8cde6a) SHA1(5f02e97b48ebbba87d516a56b0400c6fc3434d8d), ROM_GROUPWORD | ROM_REVERSE | ROM_SKIP(2) | ROM_BIOS(3))
85ROM_END
86
87
88/***************************************************************************
89    GAME DRIVERS
90***************************************************************************/
91
92/*    YEAR  NAME   PARENT  COMPAT  MACHINE  INPUT  INIT  COMPANY      FULLNAME      FLAGS */
93COMP( 1990, a3000, 0,      0,      a3000,   a3000, 0,    "Commodore Business Machines", "Amiga 3000", GAME_NOT_WORKING | GAME_NO_SOUND )
src/mame/drivers/atari400.c
r11531r11532
1/******************************************************************************
2    Atari 400/800
3
4    MESS Driver
5
6    Juergen Buchmueller, June 1998
7
8    2009-05 FP changes:
9     Factored out MESS specific code from MAME
10     Added skeleton support for other XL/XE machines (VERY preliminary):
11     - a600xl based on maxaflex emulation in MAME
12     - a1200xl sharing a800xl code without BASIC
13     - a65xe, a65xea, a130xe, a800xe, xegs sharing a800xl code (and this is wrong
14      at least for xegs)
15     Added proper dumps and labels, thanks to Freddy Offenga researches (a few
16     are still marked BAD_DUMP while waiting for crc confirmation, since they
17     have been obtained by splitting whole dumps)
18
19     To Do:
20     - Find out why a600xl and a800xl don't work (xe machines should then follow)
21     - Investigate supported RAM sizes and OS versions in different models
22     - Implement differences between various models (currently most of the
23      XL/XE are exactly an a800xl, but this will change as soon as emulation
24      starts to work)
25     - Fix various keyboard differences
26     - Freddy emulation for 800XLF?
27     - Add support for proto boards and expansions (a1400xl, C/PM board, etc.)
28     - Clean up the whole driver + cart + floppy structure
29
30******************************************************************************/
31
32#include "emu.h"
33#include "deprecat.h"
34#include "cpu/m6502/m6502.h"
35#include "includes/atari.h"
36#include "machine/ataridev.h"
37#include "imagedev/cartslot.h"
38#include "sound/pokey.h"
39#include "machine/6821pia.h"
40#include "video/gtia.h"
41#include "sound/dac.h"
42#include "machine/ram.h"
43
44/******************************************************************************
45    Atari 800 memory map (preliminary)
46
47    ***************** read access *******************
48    range     short   description
49    0000-9FFF RAM     main memory
50    A000-BFFF RAM/ROM RAM or (banked) ROM cartridges
51    C000-CFFF ROM     unused or monitor ROM
52
53    ********* GTIA    ********************************
54
55    D000      m0pf    missile 0 playfield collisions
56    D001      m1pf    missile 1 playfield collisions
57    D002      m2pf    missile 2 playfield collisions
58    D003      m3pf    missile 3 playfield collisions
59    D004      p0pf    player 0 playfield collisions
60    D005      p1pf    player 1 playfield collisions
61    D006      p2pf    player 2 playfield collisions
62    D007      p3pf    player 3 playfield collisions
63    D008      m0pl    missile 0 player collisions
64    D009      m1pl    missile 1 player collisions
65    D00A      m2pl    missile 2 player collisions
66    D00B      m3pl    missile 3 player collisions
67    D00C      p0pl    player 0 player collisions
68    D00D      p1pl    player 1 player collisions
69    D00E      p2pl    player 2 player collisions
70    D00F      p3pl    player 3 player collisions
71    D010      but0    button stick 0
72    D011      but1    button stick 1
73    D012      but2    button stick 2
74    D013      but3    button stick 3
75    D014      xff     unused
76    D015      xff     unused
77    D016      xff     unused
78    D017      xff     unused
79    D018      xff     unused
80    D019      xff     unused
81    D01A      xff     unused
82    D01B      xff     unused
83    D01C      xff     unused
84    D01D      xff     unused
85    D01E      xff     unused
86    D01F      cons    console keys
87    D020-D0FF repeated 7 times
88
89    D100-D1FF xff
90
91    ********* POKEY   ********************************
92    D200      pot0    paddle 0
93    D201      pot1    paddle 1
94    D202      pot2    paddle 2
95    D203      pot3    paddle 3
96    D204      pot4    paddle 4
97    D205      pot5    paddle 5
98    D206      pot6    paddle 6
99    D207      pot7    paddle 7
100    D208      potb    all paddles
101    D209      kbcode  keyboard scan code
102    D20A      random  random number generator
103    D20B      xff     unused
104    D20C      xff     unused
105    D20D      serin   serial input
106    D20E      irqst   IRQ status
107    D20F      skstat  sk status
108    D210-D2FF repeated 15 times
109
110    ********* PIO     ********************************
111    D300      porta   read pio port A
112    D301      portb   read pio port B
113    D302      pactl   read pio port A control
114    D303      pbctl   read pio port B control
115    D304-D3FF repeated 63 times
116
117    ********* ANTIC   ********************************
118    D400      xff     unused
119    D401      xff     unused
120    D402      xff     unused
121    D403      xff     unused
122    D404      xff     unused
123    D405      xff     unused
124    D406      xff     unused
125    D407      xff     unused
126    D408      xff     unused
127    D409      xff     unused
128    D40A      xff     unused
129    D40B      vcount  vertical (scanline) counter
130    D40C      penh    light pen horizontal pos
131    D40D      penv    light pen vertical pos
132    D40E      xff     unused
133    D40F      nmist   NMI status
134
135    D500-D7FF xff     unused memory
136
137    D800-DFFF ROM     floating point ROM
138    E000-FFFF ROM     bios ROM
139
140    ***************** write access *******************
141    range     short   description
142    0000-9FFF RAM     main memory
143    A000-BFFF RAM/ROM RAM or (banked) ROM
144    C000-CFFF ROM     unused or monitor ROM
145
146    ********* GTIA    ********************************
147    D000      hposp0  player 0 horz position
148    D001      hposp1  player 1 horz position
149    D002      hposp2  player 2 horz position
150    D003      hposp3  player 3 horz position
151    D004      hposm0  missile 0 horz position
152    D005      hposm1  missile 0 horz position
153    D006      hposm2  missile 0 horz position
154    D007      hposm3  missile 0 horz position
155    D008      sizep0  size player 0
156    D009      sizep1  size player 0
157    D00A      sizep2  size player 0
158    D00B      sizep3  size player 0
159    D00C      sizem   size missiles
160    D00D      grafp0  graphics data for player 0
161    D00E      grafp1  graphics data for player 1
162    D00F      grafp2  graphics data for player 2
163    D010      grafp3  graphics data for player 3
164    D011      grafm   graphics data for missiles
165    D012      colpm0  color for player/missile 0
166    D013      colpm1  color for player/missile 1
167    D014      colpm2  color for player/missile 2
168    D015      colpm3  color for player/missile 3
169    D016      colpf0  color 0 playfield
170    D017      colpf1  color 1 playfield
171    D018      colpf2  color 2 playfield
172    D019      colpf3  color 3 playfield
173    D01A      colbk   background playfield
174    D01B      prior   priority select
175    D01C      vdelay  delay until vertical retrace
176    D01D      gractl  graphics control
177    D01E      hitclr  clear collisions
178    D01F      wcons   write console (speaker)
179    D020-D0FF repeated 7 times
180
181    D100-D1FF xff     unused
182
183    ********* POKEY   ********************************
184    D200      audf1   frequency audio chan #1
185    D201      audc1   control audio chan #1
186    D202      audf2   frequency audio chan #2
187    D203      audc2   control audio chan #2
188    D204      audf3   frequency audio chan #3
189    D205      audc3   control audio chan #3
190    D206      audf4   frequency audio chan #4
191    D207      audc4   control audio chan #4
192    D208      audctl  audio control
193    D209      stimer  start timer
194    D20A      skres   sk reset
195    D20B      potgo   start pot AD conversion
196    D20C      xff     unused
197    D20D      serout  serial output
198    D20E      irqen   IRQ enable
199    D20F      skctl   sk control
200    D210-D2FF repeated 15 times
201
202    ********* PIO     ********************************
203    D300      porta   write pio port A (output or mask)
204    D301      portb   write pio port B (output or mask)
205    D302      pactl   write pio port A control
206    D303      pbctl   write pio port B control
207    D304-D3FF         repeated
208
209    ********* ANTIC   ********************************
210    D400      dmactl  write DMA control
211    D401      chactl  write character control
212    D402      dlistl  write display list lo
213    D403      dlisth  write display list hi
214    D404      hscrol  write horz scroll
215    D405      vscrol  write vert scroll
216    D406      xff     unused
217    D407      pmbash  player/missile base addr hi
218    D408      xff     unused
219    D409      chbash  character generator base addr hi
220    D40A      wsync   wait for hsync
221    D40B      xff     unused
222    D40C      xff     unused
223    D40D      xff     unused
224    D40E      nmien   NMI enable
225    D40F      nmires  NMI reset
226
227    D500-D7FF xff     unused memory
228
229    D800-DFFF ROM     floating point ROM
230    E000-FFFF ROM     BIOS ROM
231******************************************************************************/
232
233/**************************************************************
234 *
235 * Memory maps
236 *
237 **************************************************************/
238
239
240static ADDRESS_MAP_START(a400_mem, AS_PROGRAM, 8)
241   AM_RANGE(0x0000, 0x9fff) AM_NOP   /* RAM installed at runtime */
242   AM_RANGE(0xa000, 0xbfff) AM_RAMBANK("a000")
243   AM_RANGE(0xc000, 0xcfff) AM_ROM
244   AM_RANGE(0xd000, 0xd0ff) AM_READWRITE(atari_gtia_r, atari_gtia_w)
245   AM_RANGE(0xd100, 0xd1ff) AM_NOP
246   AM_RANGE(0xd200, 0xd2ff) AM_DEVREADWRITE("pokey", pokey_r, pokey_w)
247   AM_RANGE(0xd300, 0xd3ff) AM_DEVREADWRITE_MODERN("pia", pia6821_device, read_alt, write_alt)
248   AM_RANGE(0xd400, 0xd4ff) AM_READWRITE(atari_antic_r, atari_antic_w)
249   AM_RANGE(0xd500, 0xd7ff) AM_NOP
250   AM_RANGE(0xd800, 0xffff) AM_ROM
251ADDRESS_MAP_END
252
253
254static ADDRESS_MAP_START(a800_mem, AS_PROGRAM, 8)
255   AM_RANGE(0x0000, 0x7fff) AM_RAMBANK("0000")
256   AM_RANGE(0x8000, 0x9fff) AM_RAMBANK("8000")
257   AM_RANGE(0xa000, 0xbfff) AM_RAMBANK("a000")
258   AM_RANGE(0xc000, 0xcfff) AM_ROM
259   AM_RANGE(0xd000, 0xd0ff) AM_READWRITE(atari_gtia_r, atari_gtia_w)
260   AM_RANGE(0xd100, 0xd1ff) AM_NOP
261   AM_RANGE(0xd200, 0xd2ff) AM_DEVREADWRITE("pokey", pokey_r, pokey_w)
262   AM_RANGE(0xd300, 0xd3ff) AM_DEVREADWRITE_MODERN("pia", pia6821_device, read_alt, write_alt)
263   AM_RANGE(0xd400, 0xd4ff) AM_READWRITE(atari_antic_r, atari_antic_w)
264   AM_RANGE(0xd500, 0xd7ff) AM_NOP
265   AM_RANGE(0xd800, 0xffff) AM_ROM
266ADDRESS_MAP_END
267
268
269static ADDRESS_MAP_START(a600xl_mem, AS_PROGRAM, 8)
270   AM_RANGE(0x0000, 0x3fff) AM_RAM
271   AM_RANGE(0x5000, 0x57ff) AM_ROM AM_REGION("maincpu", 0x5000)   /* self test */
272   AM_RANGE(0xa000, 0xbfff) AM_ROM   /* BASIC */
273   AM_RANGE(0xc000, 0xcfff) AM_ROM /* OS */
274   AM_RANGE(0xd000, 0xd0ff) AM_READWRITE(atari_gtia_r, atari_gtia_w)
275   AM_RANGE(0xd100, 0xd1ff) AM_NOP
276   AM_RANGE(0xd200, 0xd2ff) AM_DEVREADWRITE("pokey", pokey_r, pokey_w)
277   AM_RANGE(0xd300, 0xd3ff) AM_DEVREADWRITE_MODERN("pia", pia6821_device, read_alt, write_alt)
278   AM_RANGE(0xd400, 0xd4ff) AM_READWRITE(atari_antic_r, atari_antic_w)
279   AM_RANGE(0xd500, 0xd7ff) AM_NOP
280   AM_RANGE(0xd800, 0xffff) AM_ROM /* OS */
281ADDRESS_MAP_END
282
283
284static ADDRESS_MAP_START(a800xl_mem, AS_PROGRAM, 8)
285   AM_RANGE(0x0000, 0x4fff) AM_RAM
286   AM_RANGE(0x5000, 0x57ff) AM_RAMBANK("bank2")
287   AM_RANGE(0x5800, 0x9fff) AM_RAM
288   AM_RANGE(0xa000, 0xbfff) AM_RAMBANK("bank1")
289   AM_RANGE(0xc000, 0xcfff) AM_RAMBANK("bank3")
290   AM_RANGE(0xd000, 0xd0ff) AM_READWRITE(atari_gtia_r, atari_gtia_w)
291   AM_RANGE(0xd100, 0xd1ff) AM_NOP
292   AM_RANGE(0xd200, 0xd2ff) AM_DEVREADWRITE("pokey", pokey_r, pokey_w)
293   AM_RANGE(0xd300, 0xd3ff) AM_DEVREADWRITE_MODERN("pia", pia6821_device, read_alt, write_alt)
294   AM_RANGE(0xd400, 0xd4ff) AM_READWRITE(atari_antic_r, atari_antic_w)
295   AM_RANGE(0xd500, 0xd7ff) AM_NOP
296   AM_RANGE(0xd800, 0xffff) AM_RAMBANK("bank4")
297ADDRESS_MAP_END
298
299static ADDRESS_MAP_START(xegs_mem, AS_PROGRAM, 8)
300   AM_RANGE(0x0000, 0x4fff) AM_RAM
301   AM_RANGE(0x5000, 0x57ff) AM_RAMBANK("bank2")
302   AM_RANGE(0x5800, 0x7fff) AM_RAM
303   AM_RANGE(0x8000, 0x9fff) AM_ROMBANK("bank0")
304   AM_RANGE(0xa000, 0xbfff) AM_ROMBANK("bank1")
305   AM_RANGE(0xc000, 0xcfff) AM_RAMBANK("bank3")
306   AM_RANGE(0xd000, 0xd0ff) AM_READWRITE(atari_gtia_r, atari_gtia_w)
307   AM_RANGE(0xd100, 0xd1ff) AM_NOP
308   AM_RANGE(0xd200, 0xd2ff) AM_DEVREADWRITE("pokey", pokey_r, pokey_w)
309   AM_RANGE(0xd300, 0xd3ff) AM_DEVREADWRITE_MODERN("pia", pia6821_device, read_alt, write_alt)
310   AM_RANGE(0xd400, 0xd4ff) AM_READWRITE(atari_antic_r, atari_antic_w)
311   AM_RANGE(0xd500, 0xd7ff) AM_NOP
312   AM_RANGE(0xd800, 0xffff) AM_RAMBANK("bank4")
313ADDRESS_MAP_END
314
315
316static ADDRESS_MAP_START(a5200_mem, AS_PROGRAM, 8)
317   AM_RANGE(0x0000, 0x3fff) AM_RAM
318   AM_RANGE(0x4000, 0xbfff) AM_ROM
319   AM_RANGE(0xc000, 0xc0ff) AM_READWRITE(atari_gtia_r, atari_gtia_w)
320   AM_RANGE(0xd400, 0xd5ff) AM_READWRITE(atari_antic_r, atari_antic_w)
321   AM_RANGE(0xe800, 0xe8ff) AM_DEVREADWRITE("pokey", pokey_r, pokey_w)
322   AM_RANGE(0xf800, 0xffff) AM_ROM
323ADDRESS_MAP_END
324
325
326#ifdef MESS
327int atari_input_disabled(running_machine &machine)
328{
329   return 0;
330}
331#endif
332
333/**************************************************************
334 *
335 * Input ports
336 *
337 **************************************************************/
338
339
340#define JOYSTICK_DELTA         10
341#define JOYSTICK_SENSITIVITY   200
342
343static INPUT_PORTS_START( atari_artifacting )
344   PORT_START("artifacts")
345   PORT_CONFNAME(0x40, 0x00, "Television Artifacts" )
346   PORT_CONFSETTING(0x00, DEF_STR( Off ) )
347   PORT_CONFSETTING(0x40, DEF_STR( On ) )
348INPUT_PORTS_END
349
350
351
352static INPUT_PORTS_START( atari_console )
353   PORT_START("console")
354   PORT_BIT(0x04, 0x04, IPT_KEYBOARD) PORT_NAME("CONS.2: Option") PORT_CODE(KEYCODE_F3)
355   PORT_BIT(0x02, 0x02, IPT_KEYBOARD) PORT_NAME("CONS.1: Select") PORT_CODE(KEYCODE_F2)
356   PORT_BIT(0x01, 0x01, IPT_KEYBOARD) PORT_NAME("CONS.0: Start") PORT_CODE(KEYCODE_F1)
357INPUT_PORTS_END
358
359
360
361static INPUT_PORTS_START( atari_digital_joystick2 )
362   PORT_START("djoy_0_1")   /* IN1 digital joystick #1 + #2 (PIA port A) */
363   PORT_BIT(0x01, 0x01, IPT_JOYSTICK_UP)    PORT_CODE(KEYCODE_8_PAD) PORT_CODE(JOYCODE_Y_UP_SWITCH)    PORT_PLAYER(1)
364   PORT_BIT(0x02, 0x02, IPT_JOYSTICK_DOWN)  PORT_CODE(KEYCODE_2_PAD) PORT_CODE(JOYCODE_Y_DOWN_SWITCH)  PORT_PLAYER(1)
365   PORT_BIT(0x04, 0x04, IPT_JOYSTICK_LEFT)  PORT_CODE(KEYCODE_4_PAD) PORT_CODE(JOYCODE_X_LEFT_SWITCH)  PORT_PLAYER(1)
366   PORT_BIT(0x08, 0x08, IPT_JOYSTICK_RIGHT) PORT_CODE(KEYCODE_6_PAD) PORT_CODE(JOYCODE_X_RIGHT_SWITCH) PORT_PLAYER(1)
367   PORT_BIT(0x10, 0x10, IPT_JOYSTICK_UP)    PORT_CODE(KEYCODE_8_PAD) PORT_CODE(JOYCODE_Y_UP_SWITCH)    PORT_PLAYER(2)
368   PORT_BIT(0x20, 0x20, IPT_JOYSTICK_DOWN)  PORT_CODE(KEYCODE_2_PAD) PORT_CODE(JOYCODE_Y_DOWN_SWITCH)  PORT_PLAYER(2)
369   PORT_BIT(0x40, 0x40, IPT_JOYSTICK_LEFT)  PORT_CODE(KEYCODE_4_PAD) PORT_CODE(JOYCODE_X_LEFT_SWITCH)  PORT_PLAYER(2)
370   PORT_BIT(0x80, 0x80, IPT_JOYSTICK_RIGHT) PORT_CODE(KEYCODE_6_PAD) PORT_CODE(JOYCODE_X_RIGHT_SWITCH) PORT_PLAYER(2)
371
372   PORT_START("djoy_2_3")   /* IN2 digital joystick #3 + #4 (PIA port B) */
373   PORT_BIT(0x01, 0x01, IPT_UNUSED)
374   PORT_BIT(0x02, 0x02, IPT_UNUSED)
375   PORT_BIT(0x04, 0x04, IPT_UNUSED)
376   PORT_BIT(0x08, 0x08, IPT_UNUSED)
377   PORT_BIT(0x10, 0x10, IPT_UNUSED)
378   PORT_BIT(0x20, 0x20, IPT_UNUSED)
379   PORT_BIT(0x40, 0x40, IPT_UNUSED)
380   PORT_BIT(0x80, 0x80, IPT_UNUSED)
381
382   PORT_START("djoy_b")   /* IN3 digital joystick buttons (GTIA button bits) */
383   PORT_BIT(0x01, 0x01, IPT_BUTTON1) PORT_CODE(KEYCODE_0_PAD) PORT_CODE(JOYCODE_BUTTON1) PORT_PLAYER(1)
384   PORT_BIT(0x02, 0x02, IPT_BUTTON1) PORT_CODE(KEYCODE_0_PAD) PORT_CODE(JOYCODE_BUTTON2) PORT_PLAYER(2)
385   PORT_BIT(0x04, 0x04, IPT_UNUSED)
386   PORT_BIT(0x08, 0x08, IPT_UNUSED)
387   PORT_BIT(0x10, 0x10, IPT_BUTTON2) PORT_CODE(KEYCODE_DEL_PAD) PORT_CODE(JOYCODE_BUTTON1) PORT_PLAYER(1)
388   PORT_BIT(0x20, 0x20, IPT_BUTTON2) PORT_CODE(KEYCODE_DEL_PAD) PORT_CODE(JOYCODE_BUTTON2) PORT_PLAYER(2)
389   PORT_BIT(0x40, 0x40, IPT_UNUSED)
390   PORT_BIT(0x80, 0x80, IPT_UNUSED)
391INPUT_PORTS_END
392
393
394
395static INPUT_PORTS_START( atari_digital_joystick4 )
396   PORT_START("djoy_0_1")   /* digital joystick #1 + #2 (PIA port A) */
397   PORT_BIT(0x01, 0x01, IPT_JOYSTICK_UP)    PORT_CODE(KEYCODE_8_PAD) PORT_CODE(JOYCODE_Y_UP_SWITCH)    PORT_PLAYER(1)
398   PORT_BIT(0x02, 0x02, IPT_JOYSTICK_DOWN)  PORT_CODE(KEYCODE_2_PAD) PORT_CODE(JOYCODE_Y_DOWN_SWITCH)  PORT_PLAYER(1)
399   PORT_BIT(0x04, 0x04, IPT_JOYSTICK_LEFT)  PORT_CODE(KEYCODE_4_PAD) PORT_CODE(JOYCODE_X_LEFT_SWITCH)  PORT_PLAYER(1)
400   PORT_BIT(0x08, 0x08, IPT_JOYSTICK_RIGHT) PORT_CODE(KEYCODE_6_PAD) PORT_CODE(JOYCODE_X_RIGHT_SWITCH) PORT_PLAYER(1)
401   PORT_BIT(0x10, 0x10, IPT_JOYSTICK_UP)    PORT_CODE(KEYCODE_8_PAD) PORT_CODE(JOYCODE_Y_UP_SWITCH)    PORT_PLAYER(2)
402   PORT_BIT(0x20, 0x20, IPT_JOYSTICK_DOWN)  PORT_CODE(KEYCODE_2_PAD) PORT_CODE(JOYCODE_Y_DOWN_SWITCH)  PORT_PLAYER(2)
403   PORT_BIT(0x40, 0x40, IPT_JOYSTICK_LEFT)  PORT_CODE(KEYCODE_4_PAD) PORT_CODE(JOYCODE_X_LEFT_SWITCH)  PORT_PLAYER(2)
404   PORT_BIT(0x80, 0x80, IPT_JOYSTICK_RIGHT) PORT_CODE(KEYCODE_6_PAD) PORT_CODE(JOYCODE_X_RIGHT_SWITCH) PORT_PLAYER(2)
405
406   PORT_START("djoy_2_3")   /* digital joystick #3 + #4 (PIA port B) */
407   PORT_BIT(0x01, 0x01, IPT_JOYSTICK_UP)    PORT_CODE(KEYCODE_8_PAD) PORT_CODE(JOYCODE_Y_UP_SWITCH)    PORT_PLAYER(3)
408   PORT_BIT(0x02, 0x02, IPT_JOYSTICK_DOWN)  PORT_CODE(KEYCODE_2_PAD) PORT_CODE(JOYCODE_Y_DOWN_SWITCH)  PORT_PLAYER(3)
409   PORT_BIT(0x04, 0x04, IPT_JOYSTICK_LEFT)  PORT_CODE(KEYCODE_4_PAD) PORT_CODE(JOYCODE_X_LEFT_SWITCH)  PORT_PLAYER(3)
410   PORT_BIT(0x08, 0x08, IPT_JOYSTICK_RIGHT) PORT_CODE(KEYCODE_6_PAD) PORT_CODE(JOYCODE_X_RIGHT_SWITCH) PORT_PLAYER(3)
411   PORT_BIT(0x10, 0x10, IPT_JOYSTICK_UP)    PORT_CODE(KEYCODE_8_PAD) PORT_CODE(JOYCODE_Y_UP_SWITCH)    PORT_PLAYER(4)
412   PORT_BIT(0x20, 0x20, IPT_JOYSTICK_DOWN)  PORT_CODE(KEYCODE_2_PAD) PORT_CODE(JOYCODE_Y_DOWN_SWITCH)  PORT_PLAYER(4)
413   PORT_BIT(0x40, 0x40, IPT_JOYSTICK_LEFT)  PORT_CODE(KEYCODE_4_PAD) PORT_CODE(JOYCODE_X_LEFT_SWITCH)  PORT_PLAYER(4)
414   PORT_BIT(0x80, 0x80, IPT_JOYSTICK_RIGHT) PORT_CODE(KEYCODE_6_PAD) PORT_CODE(JOYCODE_X_RIGHT_SWITCH) PORT_PLAYER(4)
415
416   PORT_START("djoy_b")   /* digital joystick buttons (GTIA button bits) */
417   PORT_BIT(0x01, 0x01, IPT_BUTTON1) PORT_CODE(KEYCODE_0_PAD) PORT_CODE(JOYCODE_BUTTON1) PORT_PLAYER(1)
418   PORT_BIT(0x02, 0x02, IPT_BUTTON1) PORT_CODE(KEYCODE_0_PAD) PORT_CODE(JOYCODE_BUTTON2) PORT_PLAYER(2)
419   PORT_BIT(0x04, 0x04, IPT_BUTTON1) PORT_CODE(KEYCODE_0_PAD) PORT_CODE(JOYCODE_BUTTON3) PORT_PLAYER(3)
420   PORT_BIT(0x08, 0x08, IPT_BUTTON1) PORT_CODE(KEYCODE_0_PAD) PORT_CODE(JOYCODE_BUTTON4) PORT_PLAYER(4)
421   PORT_BIT(0x10, 0x10, IPT_BUTTON2) PORT_CODE(KEYCODE_DEL_PAD) PORT_CODE(JOYCODE_BUTTON1) PORT_PLAYER(1)
422   PORT_BIT(0x20, 0x20, IPT_BUTTON2) PORT_CODE(KEYCODE_DEL_PAD) PORT_CODE(JOYCODE_BUTTON2) PORT_PLAYER(2)
423   PORT_BIT(0x40, 0x40, IPT_BUTTON2) PORT_CODE(KEYCODE_DEL_PAD) PORT_CODE(JOYCODE_BUTTON3) PORT_PLAYER(3)
424   PORT_BIT(0x80, 0x80, IPT_BUTTON2) PORT_CODE(KEYCODE_DEL_PAD) PORT_CODE(JOYCODE_BUTTON4) PORT_PLAYER(4)
425INPUT_PORTS_END
426
427
428
429/* 2009-04 FP:
430Small note about natural keyboard support: currently,
431- "Break" is mapped to 'F1'
432- "Clear" is mapped to 'F2'
433- "Atari" is mapped to 'F3'                         */
434
435static INPUT_PORTS_START( atari_keyboard )
436   PORT_START("keyboard_0")
437   PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_L) PORT_CHAR('l') PORT_CHAR('L')
438   PORT_BIT(0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_J) PORT_CHAR('j') PORT_CHAR('J')
439   PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_COLON) PORT_CHAR(';') PORT_CHAR(':')
440   PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("Break") PORT_CODE(KEYCODE_BACKSPACE) PORT_CHAR(UCHAR_MAMEKEY(F1))
441   PORT_BIT(0x10, IP_ACTIVE_HIGH, IPT_UNUSED)
442   PORT_BIT(0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_K) PORT_CHAR('k') PORT_CHAR('K')
443   PORT_BIT(0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_QUOTE) PORT_CHAR('+') PORT_CHAR('\\')
444   PORT_BIT(0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_BACKSLASH) PORT_CHAR('*') PORT_CHAR('^')
445
446   PORT_START("keyboard_1")
447   PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_O) PORT_CHAR('o') PORT_CHAR('O')
448   PORT_BIT(0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD) // None!
449   PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_P) PORT_CHAR('p') PORT_CHAR('P')
450   PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_U) PORT_CHAR('u') PORT_CHAR('U')
451   PORT_BIT(0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("Return") PORT_CODE(KEYCODE_ENTER) PORT_CHAR(13)
452   PORT_BIT(0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_I) PORT_CHAR('i') PORT_CHAR('I')
453   PORT_BIT(0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_OPENBRACE) PORT_CHAR('-') PORT_CHAR('_')
454   PORT_BIT(0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_CLOSEBRACE) PORT_CHAR('=') PORT_CHAR('|')
455
456   PORT_START("keyboard_2")
457   PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_V) PORT_CHAR('v') PORT_CHAR('V')
458   PORT_BIT(0x02, IP_ACTIVE_HIGH, IPT_UNUSED)
459   PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_C) PORT_CHAR('c') PORT_CHAR('C')
460   PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_UNUSED)
461   PORT_BIT(0x10, IP_ACTIVE_HIGH, IPT_UNUSED)
462   PORT_BIT(0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_B) PORT_CHAR('b') PORT_CHAR('B')
463   PORT_BIT(0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_X) PORT_CHAR('x') PORT_CHAR('X')
464   PORT_BIT(0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_Z) PORT_CHAR('z') PORT_CHAR('Z')
465
466   PORT_START("keyboard_3")
467   PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_4) PORT_CHAR('4') PORT_CHAR('$')
468   PORT_BIT(0x02, IP_ACTIVE_HIGH, IPT_UNUSED)
469   PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_3) PORT_CHAR('3') PORT_CHAR('#')
470   PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_6) PORT_CHAR('6') PORT_CHAR('&')
471   PORT_BIT(0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("Escape") PORT_CODE(KEYCODE_ESC) PORT_CHAR(27)
472   PORT_BIT(0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_5) PORT_CHAR('5') PORT_CHAR('%')
473   PORT_BIT(0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_2) PORT_CHAR('2') PORT_CHAR('\"')
474   PORT_BIT(0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_1) PORT_CHAR('1') PORT_CHAR('!')
475
476   PORT_START("keyboard_4")
477   PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_COMMA) PORT_CHAR(',') PORT_CHAR('[')
478   PORT_BIT(0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_SPACE) PORT_CHAR(' ')
479   PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_STOP) PORT_CHAR('.') PORT_CHAR(']')
480   PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_N) PORT_CHAR('n') PORT_CHAR('N')
481   PORT_BIT(0x10, IP_ACTIVE_HIGH, IPT_UNUSED)
482   PORT_BIT(0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_M) PORT_CHAR('m') PORT_CHAR('M')
483   PORT_BIT(0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_SLASH) PORT_CHAR('/') PORT_CHAR('?')
484   PORT_BIT(0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("Atari") PORT_CODE(KEYCODE_RCONTROL) PORT_CHAR(UCHAR_MAMEKEY(F3))
485
486   PORT_START("keyboard_5")
487   PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_R) PORT_CHAR('r') PORT_CHAR('R')
488   PORT_BIT(0x02, IP_ACTIVE_HIGH, IPT_UNUSED)
489   PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_E) PORT_CHAR('e') PORT_CHAR('E')
490   PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_Y) PORT_CHAR('y') PORT_CHAR('Y')
491   PORT_BIT(0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_TAB) PORT_CHAR(UCHAR_MAMEKEY(TAB))
492   PORT_BIT(0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_T) PORT_CHAR('t') PORT_CHAR('T')
493   PORT_BIT(0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_W) PORT_CHAR('w') PORT_CHAR('W')
494   PORT_BIT(0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_Q) PORT_CHAR('q') PORT_CHAR('Q')
495
496   PORT_START("keyboard_6")
497   PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_9) PORT_CHAR('9') PORT_CHAR('(')
498   PORT_BIT(0x02, IP_ACTIVE_HIGH, IPT_UNUSED)
499   PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_0) PORT_CHAR('0') PORT_CHAR(')')
500   PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_7) PORT_CHAR('7') PORT_CHAR('\'')
501   PORT_BIT(0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("BackS  Delete") PORT_CODE(KEYCODE_BACKSLASH2) PORT_CHAR(8) PORT_CHAR(UCHAR_MAMEKEY(DEL))
502   PORT_BIT(0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_8) PORT_CHAR('8') PORT_CHAR('@')
503   PORT_BIT(0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("<  Clear") PORT_CODE(KEYCODE_MINUS) PORT_CHAR('<') PORT_CHAR(UCHAR_MAMEKEY(F2))
504   PORT_BIT(0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME(">  Insert") PORT_CODE(KEYCODE_EQUALS) PORT_CHAR('>') PORT_CHAR(UCHAR_MAMEKEY(INSERT))
505
506   PORT_START("keyboard_7")
507   PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_F) PORT_CHAR('f') PORT_CHAR('F')
508   PORT_BIT(0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_H) PORT_CHAR('h') PORT_CHAR('H')
509   PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_D) PORT_CHAR('d') PORT_CHAR('D')
510   PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_UNUSED)
511   PORT_BIT(0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("Caps") PORT_CODE(KEYCODE_CAPSLOCK) PORT_TOGGLE PORT_CHAR(UCHAR_MAMEKEY(CAPSLOCK))
512   PORT_BIT(0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_G) PORT_CHAR('g') PORT_CHAR('G')
513   PORT_BIT(0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_S) PORT_CHAR('s') PORT_CHAR('S')
514   PORT_BIT(0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_A) PORT_CHAR('a') PORT_CHAR('A')
515
516   PORT_START("fake")
517   PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("Shift") PORT_CODE(KEYCODE_LSHIFT) PORT_CODE(KEYCODE_RSHIFT) PORT_CHAR(UCHAR_SHIFT_1)
518   PORT_BIT(0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("Ctrl") PORT_CODE(KEYCODE_LCONTROL) PORT_CHAR(UCHAR_SHIFT_2)
519INPUT_PORTS_END
520
521
522static INPUT_PORTS_START( atari_analog_paddles )
523   PORT_START("analog_0") /* IN8 analog in #1 */
524   PORT_BIT(0xff, 0x74, IPT_PADDLE) PORT_SENSITIVITY(JOYSTICK_SENSITIVITY) PORT_KEYDELTA(JOYSTICK_DELTA) PORT_MINMAX(0x00,0xe4) PORT_PLAYER(1) PORT_REVERSE
525
526   PORT_START("analog_1") /* IN9 analog in #2 */
527   PORT_BIT(0xff, 0x74, IPT_PADDLE) PORT_SENSITIVITY(JOYSTICK_SENSITIVITY) PORT_KEYDELTA(JOYSTICK_DELTA) PORT_MINMAX(0x00,0xe4) PORT_PLAYER(2) PORT_REVERSE
528
529   PORT_START("analog_2") /* IN10 analog in #3 */
530   PORT_BIT(0xff, 0x74, IPT_PADDLE) PORT_SENSITIVITY(JOYSTICK_SENSITIVITY) PORT_KEYDELTA(JOYSTICK_DELTA) PORT_MINMAX(0x00,0xe4) PORT_PLAYER(3) PORT_REVERSE
531
532   PORT_START("analog_3") /* IN11 analog in #4 */
533   PORT_BIT(0xff, 0x74, IPT_PADDLE) PORT_SENSITIVITY(JOYSTICK_SENSITIVITY) PORT_KEYDELTA(JOYSTICK_DELTA) PORT_MINMAX(0x00,0xe4) PORT_PLAYER(4) PORT_REVERSE
534
535   PORT_START("analog_4") /* IN12 analog in #5 */
536   PORT_BIT(0xff, 0x74, IPT_PADDLE) PORT_SENSITIVITY(JOYSTICK_SENSITIVITY) PORT_KEYDELTA(JOYSTICK_DELTA) PORT_MINMAX(0x00,0xe4) PORT_REVERSE /* PORT_PLAYER(5) */
537
538   PORT_START("analog_5") /* IN13 analog in #6 */
539   PORT_BIT(0xff, 0x74, IPT_PADDLE) PORT_SENSITIVITY(JOYSTICK_SENSITIVITY) PORT_KEYDELTA(JOYSTICK_DELTA) PORT_MINMAX(0x00,0xe4) PORT_REVERSE /* PORT_PLAYER(6) */
540
541   PORT_START("analog_6") /* IN14 analog in #7 */
542   PORT_BIT(0xff, 0x74, IPT_PADDLE) PORT_SENSITIVITY(JOYSTICK_SENSITIVITY) PORT_KEYDELTA(JOYSTICK_DELTA) PORT_MINMAX(0x00,0xe4) PORT_REVERSE /* PORT_PLAYER(7) */
543
544   PORT_START("analog_7") /* IN15 analog in #8 */
545   PORT_BIT(0xff, 0x74, IPT_PADDLE) PORT_SENSITIVITY(JOYSTICK_SENSITIVITY) PORT_KEYDELTA(JOYSTICK_DELTA) PORT_MINMAX(0x00,0xe4) PORT_REVERSE /* PORT_PLAYER(8) */
546INPUT_PORTS_END
547
548
549
550static INPUT_PORTS_START( a800 )
551   PORT_INCLUDE( atari_artifacting )
552   PORT_INCLUDE( atari_console )
553   PORT_INCLUDE( atari_digital_joystick4 )
554   PORT_INCLUDE( atari_keyboard )
555   PORT_INCLUDE( atari_analog_paddles )
556INPUT_PORTS_END
557
558
559
560static INPUT_PORTS_START( a800xl )
561   PORT_INCLUDE( atari_artifacting )
562   PORT_INCLUDE( atari_console )
563   PORT_INCLUDE( atari_digital_joystick2 )
564   PORT_INCLUDE( atari_keyboard )
565   PORT_INCLUDE( atari_analog_paddles )
566INPUT_PORTS_END
567
568
569
570static INPUT_PORTS_START( a5200 )
571   PORT_INCLUDE( atari_artifacting )
572
573   PORT_START("djoy_b")   /* lower/upper buttons */
574   PORT_BIT(0x01, 0x01, IPT_BUTTON1) PORT_PLAYER(1)
575   PORT_BIT(0x02, 0x02, IPT_BUTTON1) PORT_PLAYER(2)
576   PORT_BIT(0x04, 0x04, IPT_BUTTON1) PORT_PLAYER(3)
577   PORT_BIT(0x08, 0x08, IPT_BUTTON1) PORT_PLAYER(4)
578   PORT_BIT(0x10, 0x10, IPT_BUTTON2) PORT_PLAYER(1)
579   PORT_BIT(0x20, 0x20, IPT_BUTTON2) PORT_PLAYER(2)
580   PORT_BIT(0x40, 0x40, IPT_BUTTON2) PORT_PLAYER(3)
581   PORT_BIT(0x80, 0x80, IPT_BUTTON2) PORT_PLAYER(4)
582
583   PORT_START("keypad_0")
584   PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_NAME("(Break)") PORT_CODE(KEYCODE_PAUSE)   // is this correct?
585   PORT_BIT(0x02, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_NAME("[#]") PORT_CODE(KEYCODE_ENTER_PAD)
586   PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_NAME("[0]") PORT_CODE(KEYCODE_0_PAD)
587   PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_NAME("[*]") PORT_CODE(KEYCODE_PLUS_PAD)
588   PORT_BIT(0xf0, IP_ACTIVE_HIGH, IPT_UNUSED)
589
590   PORT_START("keypad_1")
591   PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_NAME("Reset") PORT_CODE(KEYCODE_F3)
592   PORT_BIT(0x02, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_NAME("[9]") PORT_CODE(KEYCODE_9_PAD)
593   PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_NAME("[8]") PORT_CODE(KEYCODE_8_PAD)
594   PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_NAME("[7]") PORT_CODE(KEYCODE_7_PAD)
595   PORT_BIT(0xf0, IP_ACTIVE_HIGH, IPT_UNUSED)
596
597   PORT_START("keypad_2")
598   PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_NAME(DEF_STR(Pause)) PORT_CODE(KEYCODE_F2)
599   PORT_BIT(0x02, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_NAME("[6]") PORT_CODE(KEYCODE_6_PAD)
600   PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_NAME("[5]") PORT_CODE(KEYCODE_5_PAD)
601   PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_NAME("[4]") PORT_CODE(KEYCODE_4_PAD)
602   PORT_BIT(0xf0, IP_ACTIVE_HIGH, IPT_UNUSED)
603
604   PORT_START("keypad_3")
605   PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_START)    PORT_NAME("Start")
606   PORT_BIT(0x02, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_NAME("[3]") PORT_CODE(KEYCODE_3_PAD)
607   PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_NAME("[2]") PORT_CODE(KEYCODE_2_PAD)
608   PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_NAME("[1]") PORT_CODE(KEYCODE_1_PAD)
609   PORT_BIT(0xf0, IP_ACTIVE_HIGH, IPT_UNUSED)
610
611   PORT_START("analog_0")
612   PORT_BIT(0xff, 0x72, IPT_AD_STICK_X) PORT_SENSITIVITY(JOYSTICK_SENSITIVITY) PORT_KEYDELTA(JOYSTICK_DELTA) PORT_MINMAX(0x00,0xe4) PORT_PLAYER(1)
613
614   PORT_START("analog_1")
615   PORT_BIT(0xff, 0x72, IPT_AD_STICK_Y) PORT_SENSITIVITY(JOYSTICK_SENSITIVITY) PORT_KEYDELTA(JOYSTICK_DELTA) PORT_MINMAX(0x00,0xe4) PORT_PLAYER(1)
616
617   PORT_START("analog_2")
618   PORT_BIT(0xff, 0x72, IPT_AD_STICK_X) PORT_SENSITIVITY(JOYSTICK_SENSITIVITY) PORT_KEYDELTA(JOYSTICK_DELTA) PORT_MINMAX(0x00,0xe4) PORT_PLAYER(2)
619
620   PORT_START("analog_3")
621   PORT_BIT(0xff, 0x72, IPT_AD_STICK_Y) PORT_SENSITIVITY(JOYSTICK_SENSITIVITY) PORT_KEYDELTA(JOYSTICK_DELTA) PORT_MINMAX(0x00,0xe4) PORT_PLAYER(2)
622
623   PORT_START("analog_4")
624   PORT_BIT(0xff, 0x72, IPT_AD_STICK_X) PORT_SENSITIVITY(JOYSTICK_SENSITIVITY) PORT_KEYDELTA(JOYSTICK_DELTA) PORT_MINMAX(0x00,0xe4) PORT_PLAYER(3)
625
626   PORT_START("analog_5")
627   PORT_BIT(0xff, 0x72, IPT_AD_STICK_Y) PORT_SENSITIVITY(JOYSTICK_SENSITIVITY) PORT_KEYDELTA(JOYSTICK_DELTA) PORT_MINMAX(0x00,0xe4) PORT_PLAYER(3)
628
629   PORT_START("analog_6")
630   PORT_BIT(0xff, 0x72, IPT_AD_STICK_X) PORT_SENSITIVITY(JOYSTICK_SENSITIVITY) PORT_KEYDELTA(JOYSTICK_DELTA) PORT_MINMAX(0x00,0xe4) PORT_PLAYER(4)
631
632   PORT_START("analog_7")
633   PORT_BIT(0xff, 0x72, IPT_AD_STICK_Y) PORT_SENSITIVITY(JOYSTICK_SENSITIVITY) PORT_KEYDELTA(JOYSTICK_DELTA) PORT_MINMAX(0x00,0xe4) PORT_PLAYER(4)
634
635INPUT_PORTS_END
636
637
638/**************************************************************
639 *
640 * Palette
641 *
642 **************************************************************/
643
644static const UINT8 atari_palette[256*3] =
645{
646   /* Grey */
647   0x00,0x00,0x00, 0x25,0x25,0x25, 0x34,0x34,0x34, 0x4e,0x4e,0x4e,
648   0x68,0x68,0x68, 0x75,0x75,0x75, 0x8e,0x8e,0x8e, 0xa4,0xa4,0xa4,
649   0xb8,0xb8,0xb8, 0xc5,0xc5,0xc5, 0xd0,0xd0,0xd0, 0xd7,0xd7,0xd7,
650   0xe1,0xe1,0xe1, 0xea,0xea,0xea, 0xf4,0xf4,0xf4, 0xff,0xff,0xff,
651   /* Gold */
652   0x41,0x20,0x00, 0x54,0x28,0x00, 0x76,0x37,0x00, 0x9a,0x50,0x00,
653   0xc3,0x68,0x06, 0xe4,0x7b,0x07, 0xff,0x91,0x1a, 0xff,0xab,0x1d,
654   0xff,0xc5,0x1f, 0xff,0xd0,0x3b, 0xff,0xd8,0x4c, 0xff,0xe6,0x51,
655   0xff,0xf4,0x56, 0xff,0xf9,0x70, 0xff,0xff,0x90, 0xff,0xff,0xaa,
656   /* Orange */
657   0x45,0x19,0x04, 0x72,0x1e,0x11, 0x9f,0x24,0x1e, 0xb3,0x3a,0x20,
658   0xc8,0x51,0x20, 0xe3,0x69,0x20, 0xfc,0x81,0x20, 0xfd,0x8c,0x25,
659   0xfe,0x98,0x2c, 0xff,0xae,0x38, 0xff,0xb9,0x46, 0xff,0xbf,0x51,
660   0xff,0xc6,0x6d, 0xff,0xd5,0x87, 0xff,0xe4,0x98, 0xff,0xe6,0xab,
661   /* Red-Orange */
662   0x5d,0x1f,0x0c, 0x7a,0x24,0x0d, 0x98,0x2c,0x0e, 0xb0,0x2f,0x0f,
663   0xbf,0x36,0x24, 0xd3,0x4e,0x2a, 0xe7,0x62,0x3e, 0xf3,0x6e,0x4a,
664   0xfd,0x78,0x54, 0xff,0x8a,0x6a, 0xff,0x98,0x7c, 0xff,0xa4,0x8b,
665   0xff,0xb3,0x9e, 0xff,0xc2,0xb2, 0xff,0xd0,0xc3, 0xff,0xda,0xd0,
666   /* Pink */
667   0x4a,0x17,0x00, 0x72,0x1f,0x00, 0xa8,0x13,0x00, 0xc8,0x21,0x0a,
668   0xdf,0x25,0x12, 0xec,0x3b,0x24, 0xfa,0x52,0x36, 0xfc,0x61,0x48,
669   0xff,0x70,0x5f, 0xff,0x7e,0x7e, 0xff,0x8f,0x8f, 0xff,0x9d,0x9e,
670   0xff,0xab,0xad, 0xff,0xb9,0xbd, 0xff,0xc7,0xce, 0xff,0xca,0xde,
671   /* Purple */
672   0x49,0x00,0x36, 0x66,0x00,0x4b, 0x80,0x03,0x5f, 0x95,0x0f,0x74,
673   0xaa,0x22,0x88, 0xba,0x3d,0x99, 0xca,0x4d,0xa9, 0xd7,0x5a,0xb6,
674   0xe4,0x67,0xc3, 0xef,0x72,0xce, 0xfb,0x7e,0xda, 0xff,0x8d,0xe1,
675   0xff,0x9d,0xe5, 0xff,0xa5,0xe7, 0xff,0xaf,0xea, 0xff,0xb8,0xec,
676   /* Purple-Blue */
677   0x48,0x03,0x6c, 0x5c,0x04,0x88, 0x65,0x0d,0x90, 0x7b,0x23,0xa7,
678   0x93,0x3b,0xbf, 0x9d,0x45,0xc9, 0xa7,0x4f,0xd3, 0xb2,0x5a,0xde,
679   0xbd,0x65,0xe9, 0xc5,0x6d,0xf1, 0xce,0x76,0xfa, 0xd5,0x83,0xff,
680   0xda,0x90,0xff, 0xde,0x9c,0xff, 0xe2,0xa9,0xff, 0xe6,0xb6,0xff,
681   /* Blue 1 */
682   0x05,0x1e,0x81, 0x06,0x26,0xa5, 0x08,0x2f,0xca, 0x26,0x3d,0xd4,
683   0x44,0x4c,0xde, 0x4f,0x5a,0xec, 0x5a,0x68,0xff, 0x65,0x75,0xff,
684   0x71,0x83,0xff, 0x80,0x91,0xff, 0x90,0xa0,0xff, 0x97,0xa9,0xff,
685   0x9f,0xb2,0xff, 0xaf,0xbe,0xff, 0xc0,0xcb,0xff, 0xcd,0xd3,0xff,
686   /* Blue 2 */
687   0x0b,0x07,0x79, 0x20,0x1c,0x8e, 0x35,0x31,0xa3, 0x46,0x42,0xb4,
688   0x57,0x53,0xc5, 0x61,0x5d,0xcf, 0x6d,0x69,0xdb, 0x7b,0x77,0xe9,
689   0x89,0x85,0xf7, 0x91,0x8d,0xff, 0x9c,0x98,0xff, 0xa7,0xa4,0xff,
690   0xb2,0xaf,0xff, 0xbb,0xb8,0xff, 0xc3,0xc1,0xff, 0xd3,0xd1,0xff,
691   /* Light-Blue */
692   0x1d,0x29,0x5a, 0x1d,0x38,0x76, 0x1d,0x48,0x92, 0x1d,0x5c,0xac,
693   0x1d,0x71,0xc6, 0x32,0x86,0xcf, 0x48,0x9b,0xd9, 0x4e,0xa8,0xec,
694   0x55,0xb6,0xff, 0x69,0xca,0xff, 0x74,0xcb,0xff, 0x82,0xd3,0xff,
695   0x8d,0xda,0xff, 0x9f,0xd4,0xff, 0xb4,0xe2,0xff, 0xc0,0xeb,0xff,
696   /* Turquoise */
697   0x00,0x4b,0x59, 0x00,0x5d,0x6e, 0x00,0x6f,0x84, 0x00,0x84,0x9c,
698   0x00,0x99,0xbf, 0x00,0xab,0xca, 0x00,0xbc,0xde, 0x00,0xd0,0xf5,
699   0x10,0xdc,0xff, 0x3e,0xe1,0xff, 0x64,0xe7,0xff, 0x76,0xea,0xff,
700   0x8b,0xed,0xff, 0x9a,0xef,0xff, 0xb1,0xf3,0xff, 0xc7,0xf6,0xff,
701   /* Green-Blue */
702   0x00,0x48,0x00, 0x00,0x54,0x00, 0x03,0x6b,0x03, 0x0e,0x76,0x0e,
703   0x18,0x80,0x18, 0x27,0x92,0x27, 0x36,0xa4,0x36, 0x4e,0xb9,0x4e,
704   0x51,0xcd,0x51, 0x72,0xda,0x72, 0x7c,0xe4,0x7c, 0x85,0xed,0x85,
705   0x99,0xf2,0x99, 0xb3,0xf7,0xb3, 0xc3,0xf9,0xc3, 0xcd,0xfc,0xcd,
706   /* Green */
707   0x16,0x40,0x00, 0x1c,0x53,0x00, 0x23,0x66,0x00, 0x28,0x78,0x00,
708   0x2e,0x8c,0x00, 0x3a,0x98,0x0c, 0x47,0xa5,0x19, 0x51,0xaf,0x23,
709   0x5c,0xba,0x2e, 0x71,0xcf,0x43, 0x85,0xe3,0x57, 0x8d,0xeb,0x5f,
710   0x97,0xf5,0x69, 0xa0,0xfe,0x72, 0xb1,0xff,0x8a, 0xbc,0xff,0x9a,
711   /* Yellow-Green */
712   0x2c,0x35,0x00, 0x38,0x44,0x00, 0x44,0x52,0x00, 0x49,0x56,0x00,
713   0x60,0x71,0x00, 0x6c,0x7f,0x00, 0x79,0x8d,0x0a, 0x8b,0x9f,0x1c,
714   0x9e,0xb2,0x2f, 0xab,0xbf,0x3c, 0xb8,0xcc,0x49, 0xc2,0xd6,0x53,
715   0xcd,0xe1,0x53, 0xdb,0xef,0x6c, 0xe8,0xfc,0x79, 0xf2,0xff,0xab,
716   /* Orange-Green */
717   0x46,0x3a,0x09, 0x4d,0x3f,0x09, 0x54,0x45,0x09, 0x6c,0x58,0x09,
718   0x90,0x76,0x09, 0xab,0x8b,0x0a, 0xc1,0xa1,0x20, 0xd0,0xb0,0x2f,
719   0xde,0xbe,0x3d, 0xe6,0xc6,0x45, 0xed,0xcd,0x4c, 0xf5,0xd8,0x62,
720   0xfb,0xe2,0x76, 0xfc,0xee,0x98, 0xfd,0xf3,0xa9, 0xfd,0xf3,0xbe,
721   /* Light-Orange */
722   0x40,0x1a,0x02, 0x58,0x1f,0x05, 0x70,0x24,0x08, 0x8d,0x3a,0x13,
723   0xab,0x51,0x1f, 0xb5,0x64,0x27, 0xbf,0x77,0x30, 0xd0,0x85,0x3a,
724   0xe1,0x93,0x44, 0xed,0xa0,0x4e, 0xf9,0xad,0x58, 0xfc,0xb7,0x5c,
725   0xff,0xc1,0x60, 0xff,0xca,0x69, 0xff,0xcf,0x7e, 0xff,0xda,0x96
726};
727
728
729/* Initialise the palette */
730static PALETTE_INIT( mess_atari )
731{
732   int i;
733
734   for ( i = 0; i < sizeof(atari_palette) / 3; i++ )
735   {
736      palette_set_color_rgb(machine, i, atari_palette[i*3], atari_palette[i*3+1], atari_palette[i*3+2]);
737   }
738}
739
740/**************************************************************
741 *
742 * Memory banking
743 *
744 **************************************************************/
745
746static void a800xl_mmu(running_machine &machine, UINT8 new_mmu)
747{
748   UINT8 *base = machine.region("maincpu")->base();
749   UINT8 *base1, *base2, *base3, *base4;
750
751   /* check if memory C000-FFFF changed */
752   if( new_mmu & 0x01 )
753   {
754      logerror("%s MMU BIOS ROM\n", machine.system().name);
755      base3 = base + 0x14000;  /* 8K lo BIOS */
756      base4 = base + 0x15800;  /* 4K FP ROM + 8K hi BIOS */
757      machine.device("maincpu")->memory().space(AS_PROGRAM)->install_read_bank(0xc000, 0xcfff, "bank3");
758      machine.device("maincpu")->memory().space(AS_PROGRAM)->unmap_write(0xc000, 0xcfff);
759      machine.device("maincpu")->memory().space(AS_PROGRAM)->install_read_bank(0xd800, 0xffff, "bank4");
760      machine.device("maincpu")->memory().space(AS_PROGRAM)->unmap_write(0xd800, 0xffff);
761   }
762   else
763   {
764      logerror("%s MMU BIOS RAM\n", machine.system().name);
765      base3 = base + 0x0c000;  /* 8K RAM */
766      base4 = base + 0x0d800;  /* 4K RAM + 8K RAM */
767      machine.device("maincpu")->memory().space(AS_PROGRAM)->install_readwrite_bank(0xc000, 0xcfff, "bank3");
768      machine.device("maincpu")->memory().space(AS_PROGRAM)->install_readwrite_bank(0xd800, 0xffff, "bank4");
769   }
770   memory_set_bankptr(machine, "bank3", base3);
771   memory_set_bankptr(machine, "bank4", base4);
772
773   /* check if BASIC changed */
774   if( new_mmu & 0x02 )
775   {
776      logerror("%s MMU BASIC RAM\n", machine.system().name);
777      machine.device("maincpu")->memory().space(AS_PROGRAM)->install_readwrite_bank(0xa000, 0xbfff, "bank1");
778      base1 = base + 0x0a000;  /* 8K RAM */
779   }
780   else
781   {
782      logerror("%s MMU BASIC ROM\n", machine.system().name);
783      machine.device("maincpu")->memory().space(AS_PROGRAM)->install_read_bank(0xa000, 0xbfff, "bank1");
784      machine.device("maincpu")->memory().space(AS_PROGRAM)->nop_write(0xa000, 0xbfff);
785      base1 = base + 0x10000;  /* 8K BASIC */
786   }
787
788   memory_set_bankptr(machine, "bank1", base1);
789
790   /* check if self-test ROM changed */
791   if( new_mmu & 0x80 )
792   {
793      logerror("%s MMU SELFTEST RAM\n", machine.system().name);
794      machine.device("maincpu")->memory().space(AS_PROGRAM)->install_readwrite_bank(0x5000, 0x57ff, "bank2");
795      base2 = base + 0x05000;  /* 0x0800 bytes */
796   }
797   else
798   {
799      logerror("%s MMU SELFTEST ROM\n", machine.system().name);
800      machine.device("maincpu")->memory().space(AS_PROGRAM)->install_read_bank(0x5000, 0x57ff, "bank2");
801      machine.device("maincpu")->memory().space(AS_PROGRAM)->nop_write(0x5000, 0x57ff);
802      base2 = base + 0x15000;  /* 0x0800 bytes */
803   }
804   memory_set_bankptr(machine, "bank2", base2);
805}
806
807/* BASIC was available in a separate cart, so we don't test it */
808static void a1200xl_mmu(running_machine &machine, UINT8 new_mmu)
809{
810   UINT8 *base = machine.region("maincpu")->base();
811   UINT8 *base2, *base3, *base4;
812
813   /* check if memory C000-FFFF changed */
814   if( new_mmu & 0x01 )
815   {
816      logerror("%s MMU BIOS ROM\n", machine.system().name);
817      base3 = base + 0x14000;  /* 8K lo BIOS */
818      base4 = base + 0x15800;  /* 4K FP ROM + 8K hi BIOS */
819      machine.device("maincpu")->memory().space(AS_PROGRAM)->install_read_bank(0xc000, 0xcfff, "bank3");
820      machine.device("maincpu")->memory().space(AS_PROGRAM)->unmap_write(0xc000, 0xcfff);
821      machine.device("maincpu")->memory().space(AS_PROGRAM)->install_read_bank(0xd800, 0xffff, "bank4");
822      machine.device("maincpu")->memory().space(AS_PROGRAM)->unmap_write(0xd800, 0xffff);
823   }
824   else
825   {
826      logerror("%s MMU BIOS RAM\n", machine.system().name);
827      base3 = base + 0x0c000;  /* 8K RAM */
828      base4 = base + 0x0d800;  /* 4K RAM + 8K RAM */
829      machine.device("maincpu")->memory().space(AS_PROGRAM)->install_readwrite_bank(0xc000, 0xcfff, "bank3");
830      machine.device("maincpu")->memory().space(AS_PROGRAM)->install_readwrite_bank(0xd800, 0xffff, "bank4");
831   }
832   memory_set_bankptr(machine, "bank3", base3);
833   memory_set_bankptr(machine, "bank4", base4);
834
835   /* check if self-test ROM changed */
836   if( new_mmu & 0x80 )
837   {
838      logerror("%s MMU SELFTEST RAM\n", machine.system().name);
839      base2 = base + 0x05000;  /* 0x0800 bytes */
840      machine.device("maincpu")->memory().space(AS_PROGRAM)->install_readwrite_bank(0x5000, 0x57ff, "bank2");
841   }
842   else
843   {
844      logerror("%s MMU SELFTEST ROM\n", machine.system().name);
845      base2 = base + 0x15000;  /* 0x0800 bytes */
846      machine.device("maincpu")->memory().space(AS_PROGRAM)->install_read_bank(0x5000, 0x57ff, "bank2");
847      machine.device("maincpu")->memory().space(AS_PROGRAM)->unmap_write(0x5000, 0x57ff);
848   }
849   memory_set_bankptr(machine, "bank2", base2);
850}
851
852static void xegs_mmu(running_machine &machine, UINT8 new_mmu)
853{
854   UINT8 *base = machine.region("maincpu")->base();
855   UINT8 *base2, *base3, *base4;
856
857   /* check if memory C000-FFFF changed */
858   if( new_mmu & 0x01 )
859   {
860      logerror("%s MMU BIOS ROM\n", machine.system().name);
861      base3 = base + 0x14000;  /* 8K lo BIOS */
862      base4 = base + 0x15800;  /* 4K FP ROM + 8K hi BIOS */
863      machine.device("maincpu")->memory().space(AS_PROGRAM)->install_read_bank(0xc000, 0xcfff, "bank3");
864      machine.device("maincpu")->memory().space(AS_PROGRAM)->unmap_write(0xc000, 0xcfff);
865      machine.device("maincpu")->memory().space(AS_PROGRAM)->install_read_bank(0xd800, 0xffff, "bank4");
866      machine.device("maincpu")->memory().space(AS_PROGRAM)->unmap_write(0xd800, 0xffff);
867   }
868   else
869   {
870      logerror("%s MMU BIOS RAM\n", machine.system().name);
871      base3 = base + 0x0c000;  /* 8K RAM */
872      base4 = base + 0x0d800;  /* 4K RAM + 8K RAM */
873      machine.device("maincpu")->memory().space(AS_PROGRAM)->install_readwrite_bank(0xc000, 0xcfff, "bank3");
874      machine.device("maincpu")->memory().space(AS_PROGRAM)->install_readwrite_bank(0xd800, 0xffff, "bank4");
875   }
876   memory_set_bankptr(machine, "bank3", base3);
877   memory_set_bankptr(machine, "bank4", base4);
878
879
880   /* check if self-test ROM changed */
881   if( new_mmu & 0x80 )
882   {
883      logerror("%s MMU SELFTEST RAM\n", machine.system().name);
884      machine.device("maincpu")->memory().space(AS_PROGRAM)->install_readwrite_bank(0x5000, 0x57ff, "bank2");
885      base2 = base + 0x05000;  /* 0x0800 bytes */
886   }
887   else
888   {
889      logerror("%s MMU SELFTEST ROM\n", machine.system().name);
890      machine.device("maincpu")->memory().space(AS_PROGRAM)->install_read_bank(0x5000, 0x57ff, "bank2");
891      machine.device("maincpu")->memory().space(AS_PROGRAM)->nop_write(0x5000, 0x57ff);
892      base2 = base + 0x15000;  /* 0x0800 bytes */
893   }
894   memory_set_bankptr(machine, "bank2", base2);
895}
896
897/**************************************************************
898 *
899 * PIA interface
900 *
901 **************************************************************/
902
903static WRITE8_DEVICE_HANDLER(a1200xl_pia_pb_w) { a1200xl_mmu(device->machine(), data); }
904static WRITE8_DEVICE_HANDLER(a800xl_pia_pb_w)
905{
906   if (downcast<pia6821_device *>(device)->port_b_z_mask() != 0xff)
907      a800xl_mmu(device->machine(), data);
908}
909
910static WRITE8_DEVICE_HANDLER(xegs_pia_pb_w)
911{
912   if (downcast<pia6821_device *>(device)->port_b_z_mask() != 0xff)
913      xegs_mmu(device->machine(), data);
914}
915
916static const pokey_interface atari_pokey_interface =
917{
918   {
919      DEVCB_INPUT_PORT("analog_0"),
920      DEVCB_INPUT_PORT("analog_1"),
921      DEVCB_INPUT_PORT("analog_2"),
922      DEVCB_INPUT_PORT("analog_3"),
923      DEVCB_INPUT_PORT("analog_4"),
924      DEVCB_INPUT_PORT("analog_5"),
925      DEVCB_INPUT_PORT("analog_6"),
926      DEVCB_INPUT_PORT("analog_7")
927   },
928   DEVCB_NULL,
929   DEVCB_DEVICE_HANDLER("fdc", atari_serin_r),
930   DEVCB_DEVICE_HANDLER("fdc", atari_serout_w),
931   atari_interrupt_cb,
932};
933
934
935static const pia6821_interface atari_pia_interface =
936{
937   DEVCB_HANDLER(atari_pia_pa_r),      /* port A in */
938   DEVCB_HANDLER(atari_pia_pb_r),   /* port B in */
939   DEVCB_NULL,      /* line CA1 in */
940   DEVCB_NULL,      /* line CB1 in */
941   DEVCB_NULL,      /* line CA2 in */
942   DEVCB_NULL,      /* line CB2 in */
943   DEVCB_NULL,      /* port A out */
944   DEVCB_NULL,      /* port B out */
945   DEVCB_NULL,      /* line CA2 out */
946   DEVCB_DEVICE_LINE("fdc",atarifdc_pia_cb2_w),      /* port CB2 out */
947   DEVCB_NULL,      /* IRQA */
948   DEVCB_NULL      /* IRQB */
949};
950
951static const pia6821_interface a600xl_pia_interface =
952{
953   DEVCB_HANDLER(atari_pia_pa_r),      /* port A in */
954   DEVCB_HANDLER(atari_pia_pb_r),   /* port B in */
955   DEVCB_NULL,      /* line CA1 in */
956   DEVCB_NULL,      /* line CB1 in */
957   DEVCB_NULL,      /* line CA2 in */
958   DEVCB_NULL,      /* line CB2 in */
959   DEVCB_NULL,      /* port A out */
960   DEVCB_HANDLER(a600xl_pia_pb_w),      /* port B out */
961   DEVCB_NULL,      /* line CA2 out */
962   DEVCB_DEVICE_LINE("fdc",atarifdc_pia_cb2_w),      /* port CB2 out */
963   DEVCB_NULL,      /* IRQA */
964   DEVCB_NULL      /* IRQB */
965};
966
967static const pia6821_interface a1200xl_pia_interface =
968{
969   DEVCB_HANDLER(atari_pia_pa_r),      /* port A in */
970   DEVCB_HANDLER(atari_pia_pb_r),   /* port B in */
971   DEVCB_NULL,      /* line CA1 in */
972   DEVCB_NULL,      /* line CB1 in */
973   DEVCB_NULL,      /* line CA2 in */
974   DEVCB_NULL,      /* line CB2 in */
975   DEVCB_NULL,      /* port A out */
976   DEVCB_HANDLER(a1200xl_pia_pb_w),      /* port B out */
977   DEVCB_NULL,      /* line CA2 out */
978   DEVCB_DEVICE_LINE("fdc",atarifdc_pia_cb2_w),      /* port CB2 out */
979   DEVCB_NULL,      /* IRQA */
980   DEVCB_NULL      /* IRQB */
981};
982
983static const pia6821_interface a800xl_pia_interface =
984{
985   DEVCB_HANDLER(atari_pia_pa_r),      /* port A in */
986   DEVCB_HANDLER(atari_pia_pb_r),   /* port B in */
987   DEVCB_NULL,      /* line CA1 in */
988   DEVCB_NULL,      /* line CB1 in */
989   DEVCB_NULL,      /* line CA2 in */
990   DEVCB_NULL,      /* line CB2 in */
991   DEVCB_NULL,      /* port A out */
992   DEVCB_HANDLER(a800xl_pia_pb_w),      /* port B out */
993   DEVCB_NULL,      /* line CA2 out */
994   DEVCB_DEVICE_LINE("fdc",atarifdc_pia_cb2_w),      /* port CB2 out */
995   DEVCB_NULL,      /* IRQA */
996   DEVCB_NULL      /* IRQB */
997};
998
999static const pia6821_interface xegs_pia_interface =
1000{
1001   DEVCB_HANDLER(atari_pia_pa_r),      /* port A in */
1002   DEVCB_HANDLER(atari_pia_pb_r),   /* port B in */
1003   DEVCB_NULL,      /* line CA1 in */
1004   DEVCB_NULL,      /* line CB1 in */
1005   DEVCB_NULL,      /* line CA2 in */
1006   DEVCB_NULL,      /* line CB2 in */
1007   DEVCB_NULL,      /* port A out */
1008   DEVCB_HANDLER(xegs_pia_pb_w),      /* port B out */
1009   DEVCB_NULL,      /* line CA2 out */
1010   DEVCB_DEVICE_LINE("fdc",atarifdc_pia_cb2_w),      /* port CB2 out */
1011   DEVCB_NULL,      /* IRQA */
1012   DEVCB_NULL      /* IRQB */
1013};
1014
1015// FIXME: should there be anything connected where other system have the fdc?
1016static const pokey_interface a5200_pokey_interface =
1017{
1018   {
1019      DEVCB_INPUT_PORT("analog_0"),
1020      DEVCB_INPUT_PORT("analog_1"),
1021      DEVCB_INPUT_PORT("analog_2"),
1022      DEVCB_INPUT_PORT("analog_3"),
1023      DEVCB_INPUT_PORT("analog_4"),
1024      DEVCB_INPUT_PORT("analog_5"),
1025      DEVCB_INPUT_PORT("analog_6"),
1026      DEVCB_INPUT_PORT("analog_7")
1027   },
1028   DEVCB_NULL,
1029   DEVCB_NULL,   // FIXME: is there anything connected here?
1030   DEVCB_NULL,   // FIXME: is there anything connected here?
1031   atari_interrupt_cb,
1032};
1033
1034static const pia6821_interface a5200_pia_interface =
1035{
1036   DEVCB_HANDLER(atari_pia_pa_r),      /* port A in */
1037   DEVCB_HANDLER(atari_pia_pb_r),   /* port B in */
1038   DEVCB_NULL,      /* line CA1 in */
1039   DEVCB_NULL,      /* line CB1 in */
1040   DEVCB_NULL,      /* line CA2 in */
1041   DEVCB_NULL,      /* line CB2 in */
1042   DEVCB_NULL,      /* port A out */
1043   DEVCB_NULL,      /* port B out */
1044   DEVCB_NULL,      /* line CA2 out */
1045   DEVCB_NULL,      /* port CB2 out */   // FIXME: is there anything connected here
1046   DEVCB_NULL,      /* IRQA */
1047   DEVCB_NULL      /* IRQB */
1048};
1049
1050
1051/**************************************************************
1052 *
1053 * Machine drivers
1054 *
1055 **************************************************************/
1056
1057static MACHINE_CONFIG_FRAGMENT( a400_cartslot )
1058   MCFG_CARTSLOT_ADD("cart1")
1059   MCFG_CARTSLOT_EXTENSION_LIST("rom,bin")
1060   MCFG_CARTSLOT_NOT_MANDATORY
1061   MCFG_CARTSLOT_LOAD(a800_cart)
1062   MCFG_CARTSLOT_UNLOAD(a800_cart)
1063   MCFG_CARTSLOT_INTERFACE("a800_cart")
1064MACHINE_CONFIG_END
1065
1066static MACHINE_CONFIG_FRAGMENT( a800_cartslot )
1067   MCFG_CARTSLOT_ADD("cart1")
1068   MCFG_CARTSLOT_EXTENSION_LIST("rom,bin")
1069   MCFG_CARTSLOT_NOT_MANDATORY
1070   MCFG_CARTSLOT_LOAD(a800_cart)
1071   MCFG_CARTSLOT_UNLOAD(a800_cart)
1072   MCFG_CARTSLOT_INTERFACE("a800_cart")
1073
1074   MCFG_CARTSLOT_ADD("cart2")
1075   MCFG_CARTSLOT_EXTENSION_LIST("rom,bin")
1076   MCFG_CARTSLOT_NOT_MANDATORY
1077   MCFG_CARTSLOT_LOAD(a800_cart_right)
1078   MCFG_CARTSLOT_UNLOAD(a800_cart_right)
1079   MCFG_CARTSLOT_INTERFACE("a800_cart")
1080MACHINE_CONFIG_END
1081
1082static MACHINE_CONFIG_START( atari_common_nodac, driver_device )
1083   /* basic machine hardware */
1084   MCFG_CPU_ADD("maincpu", M6502, FREQ_17_EXACT)
1085
1086   /* video hardware */
1087   MCFG_SCREEN_ADD("screen", RASTER)
1088   MCFG_SCREEN_VBLANK_TIME(ATTOSECONDS_IN_USEC(1))
1089   MCFG_SCREEN_FORMAT(BITMAP_FORMAT_INDEXED16)
1090   MCFG_SCREEN_VISIBLE_AREA(MIN_X, MAX_X, MIN_Y, MAX_Y)
1091   MCFG_PALETTE_LENGTH(sizeof(atari_palette) / 3)
1092   MCFG_PALETTE_INIT(mess_atari)
1093   MCFG_SCREEN_UPDATE(atari)
1094
1095   MCFG_VIDEO_START(atari)
1096
1097   MCFG_PIA6821_ADD( "pia", atari_pia_interface )
1098
1099   /* sound hardware */
1100   MCFG_SPEAKER_STANDARD_MONO("mono")
1101   MCFG_SOUND_ADD("pokey", POKEY, FREQ_17_EXACT)
1102   MCFG_SOUND_CONFIG(atari_pokey_interface)
1103   MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 1.00)
1104
1105   /* internal ram */
1106   MCFG_RAM_ADD(RAM_TAG)
1107   MCFG_RAM_DEFAULT_SIZE("40K")
1108MACHINE_CONFIG_END
1109
1110
1111static MACHINE_CONFIG_DERIVED( atari_common, atari_common_nodac )
1112   MCFG_SOUND_ADD("dac", DAC, 0)
1113   MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.50)
1114
1115   MCFG_ATARI_FDC_ADD("fdc")
1116MACHINE_CONFIG_END
1117
1118
1119static MACHINE_CONFIG_DERIVED( a400, atari_common )
1120
1121   MCFG_CPU_MODIFY( "maincpu" )
1122   MCFG_CPU_PROGRAM_MAP(a400_mem)
1123   MCFG_CPU_VBLANK_INT_HACK(a400_interrupt, TOTAL_LINES_60HZ)
1124
1125   MCFG_MACHINE_START( a400 )
1126
1127   MCFG_SCREEN_MODIFY("screen")
1128   MCFG_SCREEN_REFRESH_RATE(FRAME_RATE_60HZ)
1129   MCFG_SCREEN_SIZE(HWIDTH*8, TOTAL_LINES_60HZ)
1130
1131   MCFG_FRAGMENT_ADD(a400_cartslot)
1132
1133   /* software lists */
1134   MCFG_SOFTWARE_LIST_ADD("cart_list","a800")
1135MACHINE_CONFIG_END
1136
1137
1138static MACHINE_CONFIG_DERIVED( a400pal, atari_common )
1139
1140   MCFG_CPU_MODIFY( "maincpu" )
1141   MCFG_CPU_PROGRAM_MAP(a400_mem)
1142   MCFG_CPU_VBLANK_INT_HACK(a400_interrupt, TOTAL_LINES_50HZ)
1143
1144   MCFG_MACHINE_START( a400 )
1145
1146   MCFG_SCREEN_MODIFY("screen")
1147   MCFG_SCREEN_REFRESH_RATE(FRAME_RATE_50HZ)
1148   MCFG_SCREEN_SIZE(HWIDTH*8, TOTAL_LINES_50HZ)
1149
1150   MCFG_FRAGMENT_ADD(a400_cartslot)
1151
1152   /* software lists */
1153   MCFG_SOFTWARE_LIST_ADD("cart_list","a800")
1154MACHINE_CONFIG_END
1155
1156
1157static MACHINE_CONFIG_DERIVED( a800, atari_common )
1158
1159   MCFG_CPU_MODIFY( "maincpu" )
1160   MCFG_CPU_PROGRAM_MAP(a800_mem)
1161   MCFG_CPU_VBLANK_INT_HACK(a800_interrupt, TOTAL_LINES_60HZ)
1162
1163   MCFG_MACHINE_START( a800 )
1164
1165   MCFG_SCREEN_MODIFY("screen")
1166   MCFG_SCREEN_REFRESH_RATE(FRAME_RATE_60HZ)
1167   MCFG_SCREEN_SIZE(HWIDTH*8, TOTAL_LINES_60HZ)
1168
1169   MCFG_FRAGMENT_ADD(a800_cartslot)
1170
1171   /* software lists */
1172   MCFG_SOFTWARE_LIST_ADD("cart_list","a800")
1173MACHINE_CONFIG_END
1174
1175
1176static MACHINE_CONFIG_DERIVED( a800pal, atari_common )
1177
1178   MCFG_CPU_MODIFY( "maincpu" )
1179   MCFG_CPU_PROGRAM_MAP(a800_mem)
1180   MCFG_CPU_VBLANK_INT_HACK(a800_interrupt, TOTAL_LINES_50HZ)
1181
1182   MCFG_MACHINE_START( a800 )
1183
1184   MCFG_SCREEN_MODIFY("screen")
1185   MCFG_SCREEN_REFRESH_RATE(FRAME_RATE_50HZ)
1186   MCFG_SCREEN_SIZE(HWIDTH*8, TOTAL_LINES_50HZ)
1187
1188   MCFG_FRAGMENT_ADD(a800_cartslot)
1189
1190   /* software lists */
1191   MCFG_SOFTWARE_LIST_ADD("cart_list","a800")
1192MACHINE_CONFIG_END
1193
1194
1195static MACHINE_CONFIG_DERIVED( a600xl, atari_common )
1196
1197   MCFG_CPU_MODIFY( "maincpu" )
1198   MCFG_CPU_PROGRAM_MAP(a600xl_mem)   // FIXME?
1199   MCFG_CPU_VBLANK_INT_HACK(a800xl_interrupt, TOTAL_LINES_60HZ)
1200
1201   MCFG_PIA6821_MODIFY( "pia", a600xl_pia_interface )
1202
1203   MCFG_MACHINE_START( a800xl )   // FIXME?
1204
1205   MCFG_SCREEN_MODIFY("screen")
1206   MCFG_SCREEN_REFRESH_RATE(FRAME_RATE_60HZ)
1207   MCFG_SCREEN_SIZE(HWIDTH*8, TOTAL_LINES_60HZ)
1208
1209   MCFG_FRAGMENT_ADD(a400_cartslot)
1210
1211   /* software lists */
1212   MCFG_SOFTWARE_LIST_ADD("cart_list","a800")
1213
1214   /* internal ram */
1215   MCFG_RAM_MODIFY(RAM_TAG)
1216   MCFG_RAM_DEFAULT_SIZE("16K")
1217MACHINE_CONFIG_END
1218
1219
1220static MACHINE_CONFIG_DERIVED( a800xl, atari_common )
1221
1222   MCFG_CPU_MODIFY( "maincpu" )
1223   MCFG_CPU_PROGRAM_MAP(a800xl_mem)
1224   MCFG_CPU_VBLANK_INT_HACK(a800xl_interrupt, TOTAL_LINES_60HZ)
1225
1226   MCFG_PIA6821_MODIFY( "pia", a800xl_pia_interface )
1227
1228   MCFG_MACHINE_START( a800xl )
1229
1230   MCFG_SCREEN_MODIFY("screen")
1231   MCFG_SCREEN_REFRESH_RATE(FRAME_RATE_60HZ)
1232   MCFG_SCREEN_SIZE(HWIDTH*8, TOTAL_LINES_60HZ)
1233
1234   MCFG_FRAGMENT_ADD(a400_cartslot)
1235
1236   /* software lists */
1237   MCFG_SOFTWARE_LIST_ADD("cart_list","a800")
1238MACHINE_CONFIG_END
1239
1240static MACHINE_CONFIG_DERIVED( a800xlpal, a800xl )
1241
1242   MCFG_CPU_MODIFY( "maincpu" )
1243   MCFG_CPU_CLOCK( 1773000 )
1244   MCFG_CPU_VBLANK_INT_HACK(a800xl_interrupt, TOTAL_LINES_50HZ)
1245   MCFG_SCREEN_MODIFY("screen")
1246   MCFG_SCREEN_REFRESH_RATE(FRAME_RATE_50HZ)
1247   MCFG_SCREEN_SIZE(HWIDTH*8, TOTAL_LINES_50HZ)
1248
1249   MCFG_SOUND_MODIFY("pokey")
1250   MCFG_SOUND_CLOCK(1773000)
1251MACHINE_CONFIG_END
1252
1253static MACHINE_CONFIG_DERIVED( a1200xl, a800xl )
1254
1255   MCFG_PIA6821_MODIFY( "pia", a1200xl_pia_interface )
1256MACHINE_CONFIG_END
1257
1258static MACHINE_CONFIG_DERIVED( xegs, a800xl )
1259
1260   MCFG_CPU_MODIFY( "maincpu" )
1261   MCFG_CPU_PROGRAM_MAP(xegs_mem)
1262
1263   MCFG_MACHINE_START( xegs )
1264
1265   MCFG_PIA6821_MODIFY( "pia", xegs_pia_interface )
1266
1267   MCFG_DEVICE_REMOVE("cart1")
1268   MCFG_DEVICE_REMOVE("cart_list")
1269
1270   MCFG_CARTSLOT_ADD("cart1")
1271   MCFG_CARTSLOT_EXTENSION_LIST("rom,bin")
1272   MCFG_CARTSLOT_NOT_MANDATORY
1273   MCFG_CARTSLOT_LOAD(xegs_cart)
1274   MCFG_CARTSLOT_UNLOAD(xegs_cart)
1275   MCFG_CARTSLOT_INTERFACE("xegs_cart")
1276
1277   /* software lists */
1278   MCFG_SOFTWARE_LIST_ADD("cart_list","xegs")
1279MACHINE_CONFIG_END
1280
1281
1282static MACHINE_CONFIG_DERIVED( a5200, atari_common_nodac )
1283
1284   MCFG_CPU_MODIFY( "maincpu" )
1285   MCFG_CPU_PROGRAM_MAP(a5200_mem)
1286   MCFG_CPU_VBLANK_INT_HACK(a5200_interrupt, TOTAL_LINES_60HZ)
1287
1288   MCFG_DEVICE_REMOVE("pokey")
1289   MCFG_SOUND_ADD("pokey", POKEY, FREQ_17_EXACT)
1290   MCFG_SOUND_CONFIG(a5200_pokey_interface)
1291   MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 1.00)
1292
1293   MCFG_PIA6821_MODIFY( "pia", a5200_pia_interface )
1294
1295   MCFG_MACHINE_START( a5200 )
1296
1297   MCFG_SCREEN_MODIFY( "screen" )
1298   MCFG_SCREEN_REFRESH_RATE(FRAME_RATE_60HZ)
1299   MCFG_SCREEN_SIZE(HWIDTH*8, TOTAL_LINES_60HZ)
1300
1301   MCFG_CARTSLOT_ADD("cart")
1302   MCFG_CARTSLOT_EXTENSION_LIST("rom,bin,a52")
1303   MCFG_CARTSLOT_NOT_MANDATORY
1304   MCFG_CARTSLOT_LOAD(a5200_cart)
1305   MCFG_CARTSLOT_UNLOAD(a5200_cart)
1306   MCFG_CARTSLOT_INTERFACE("a5200_cart")
1307
1308   /* Software lists */
1309   MCFG_SOFTWARE_LIST_ADD("cart_list","a5200")
1310
1311   /* internal ram */
1312   MCFG_RAM_MODIFY(RAM_TAG)
1313   MCFG_RAM_DEFAULT_SIZE("16K")
1314MACHINE_CONFIG_END
1315
1316
1317/**************************************************************
1318 *
1319 * ROM loading
1320 *
1321 **************************************************************/
1322
1323ROM_START(a400)
1324   ROM_REGION(0x14000, "maincpu", 0) /* 64K for the CPU + 2 * 8K for cartridges */
1325   ROM_LOAD( "co12399b.rom", 0xd800, 0x0800, CRC(6a5d766e) SHA1(01a6044f7a81d409c938e7dfde0a1af5832229d2) )
1326   ROM_SYSTEM_BIOS(0, "default", "OS Rev. B")
1327   ROMX_LOAD( "co12499b.rom",  0xe000, 0x1000, BAD_DUMP CRC(d818f3e8) SHA1(bcdec2188f6a6a5bfc1df4e383bd828d34b5c4ac), ROM_BIOS(1) )   // CRC and label waiting for confirmation
1328   ROMX_LOAD( "co14599b.rom",  0xf000, 0x1000, BAD_DUMP CRC(c1690a9b) SHA1(c5248e8565574fd39ae1c3f4f356aa4cac07df95), ROM_BIOS(1) )   // CRC and label waiting for confirmation
1329   ROM_SYSTEM_BIOS(1, "reva", "OS Rev. A")
1330   ROMX_LOAD( "co12499a.rom",  0xe000, 0x1000, BAD_DUMP CRC(29f64e17) SHA1(abf7ec488c6b600f1b7f30bdc7f8a2bf6a727675), ROM_BIOS(2) )   // CRC and label waiting for confirmation
1331   ROMX_LOAD( "co14599a.rom",  0xf000, 0x1000, BAD_DUMP CRC(bc533f0c) SHA1(e217148495fa747fe5488132d8d22533e68c7e58), ROM_BIOS(2) )   // CRC and label waiting for confirmation
1332
1333   ROM_REGION(0x10000, "lslot", ROMREGION_ERASEFF)
1334ROM_END
1335
1336ROM_START(a400pal)
1337   ROM_REGION(0x14000, "maincpu", 0) /* 64K for the CPU + 2 * 8K for cartridges */
1338   ROM_LOAD( "co12399b.rom", 0xd800, 0x0800, CRC(6a5d766e) SHA1(01a6044f7a81d409c938e7dfde0a1af5832229d2) )
1339   ROM_LOAD( "co15199.rom", 0xe000, 0x1000, BAD_DUMP CRC(8e547f56) SHA1(1bd746ea798b723bfb18495a7facca113183d713) )   // Rev. A - CRC and label waiting for confirmation
1340   ROM_LOAD( "co15299.rom", 0xf000, 0x1000, BAD_DUMP CRC(be55b413) SHA1(d88afae49b08e75943d0258cb580e5d34756414a) )   // Rev. A - CRC and label waiting for confirmation
1341
1342   ROM_REGION(0x10000, "lslot", ROMREGION_ERASEFF)
1343ROM_END
1344
1345ROM_START(a800)
1346   ROM_REGION(0x14000, "maincpu", 0) /* 64K for the CPU + 2 * 8K for cartridges */
1347   ROM_LOAD( "co12399b.rom", 0xd800, 0x0800, CRC(6a5d766e) SHA1(01a6044f7a81d409c938e7dfde0a1af5832229d2) )
1348   ROM_SYSTEM_BIOS(0, "default", "OS Rev. B")
1349   ROMX_LOAD( "co12499b.rom",  0xe000, 0x1000, BAD_DUMP CRC(d818f3e8) SHA1(bcdec2188f6a6a5bfc1df4e383bd828d34b5c4ac), ROM_BIOS(1) )   // CRC and label waiting for confirmation
1350   ROMX_LOAD( "co14599b.rom",  0xf000, 0x1000, BAD_DUMP CRC(c1690a9b) SHA1(c5248e8565574fd39ae1c3f4f356aa4cac07df95), ROM_BIOS(1) )   // CRC and label waiting for confirmation
1351   ROM_SYSTEM_BIOS(1, "reva", "OS Rev. A")
1352   ROMX_LOAD( "co12499a.rom",  0xe000, 0x1000, BAD_DUMP CRC(29f64e17) SHA1(abf7ec488c6b600f1b7f30bdc7f8a2bf6a727675), ROM_BIOS(2) )   // CRC and label waiting for confirmation
1353   ROMX_LOAD( "co14599a.rom",  0xf000, 0x1000, BAD_DUMP CRC(bc533f0c) SHA1(e217148495fa747fe5488132d8d22533e68c7e58), ROM_BIOS(2) )   // CRC and label waiting for confirmation
1354
1355   ROM_REGION(0x10000, "lslot", ROMREGION_ERASEFF)
1356
1357   ROM_REGION(0x2000, "rslot", ROMREGION_ERASEFF)
1358ROM_END
1359
1360ROM_START(a800pal)
1361   ROM_REGION(0x14000, "maincpu", 0) /* 64K for the CPU + 2 * 8K for cartridges */
1362   ROM_LOAD( "co12399b.rom", 0xd800, 0x0800, CRC(6a5d766e) SHA1(01a6044f7a81d409c938e7dfde0a1af5832229d2) )
1363   ROM_LOAD( "co15199.rom", 0xe000, 0x1000, BAD_DUMP CRC(8e547f56) SHA1(1bd746ea798b723bfb18495a7facca113183d713) )   // Rev. A - CRC and label waiting for confirmation
1364   ROM_LOAD( "co15299.rom", 0xf000, 0x1000, BAD_DUMP CRC(be55b413) SHA1(d88afae49b08e75943d0258cb580e5d34756414a) )   // Rev. A - CRC and label waiting for confirmation
1365
1366   ROM_REGION(0x10000, "lslot", ROMREGION_ERASEFF)
1367
1368   ROM_REGION(0x2000, "rslot", ROMREGION_ERASEFF)
1369ROM_END
1370
1371ROM_START(a1200xl)
1372   ROM_REGION(0x18000, "maincpu", 0)
1373   ROM_SYSTEM_BIOS(0, "default", "OS Rev. 11")
1374   ROMX_LOAD( "co60616b.rom", 0x14000, 0x2000, BAD_DUMP CRC(6e29ec8d) SHA1(3f9c06d6b4d261f3d5bf4354e3cff0c17b9347b9), ROM_BIOS(1) )   // CRC and label waiting for confirmation
1375   ROMX_LOAD( "co60617b.rom", 0x16000, 0x2000, BAD_DUMP CRC(d73ce29a) SHA1(64790242d902643fe0c40dd842749f1fe461831b), ROM_BIOS(1) )   // CRC and label waiting for confirmation
1376   ROM_SYSTEM_BIOS(1, "rev10", "OS Rev. 10")
1377   ROMX_LOAD( "co60616a.rom", 0x14000, 0x2000, BAD_DUMP CRC(0391386b) SHA1(7c176657c88b89b8a69bf021fa8e0939efc0dff2), ROM_BIOS(2) )   // CRC and label waiting for confirmation
1378   ROMX_LOAD( "co60617a.rom", 0x16000, 0x2000, BAD_DUMP CRC(b502f1e7) SHA1(6688db57d97fa570aef5c15cef3e5fb2688879c2), ROM_BIOS(2) )   // CRC and label waiting for confirmation
1379
1380   ROM_REGION(0x10000, "lslot", ROMREGION_ERASEFF)
1381ROM_END
1382
1383ROM_START(a600xl)
1384   ROM_REGION(0x10000, "maincpu", 0)
1385   ROM_LOAD( "co60302a.rom", 0xa000, 0x2000, CRC(f0202fb3) SHA1(7ad88dd99ff4a6ee66f6d162074db6f8bef7a9b6) )   // Rev. B
1386   ROM_LOAD( "co62024.rom",  0xc000, 0x4000, CRC(643bcc98) SHA1(881d030656b40bbe48f15a696b28f22c0b752ab0) )   // Rev. 1
1387
1388   ROM_REGION(0x10000, "lslot", ROMREGION_ERASEFF)
1389ROM_END
1390
1391ROM_START(a800xl)
1392   ROM_REGION(0x18000, "maincpu", 0)
1393   ROM_FILL( 0, 0x10000, 0x00 )
1394   ROM_LOAD( "co60302a.rom", 0x10000, 0x2000, CRC(f0202fb3) SHA1(7ad88dd99ff4a6ee66f6d162074db6f8bef7a9b6) )   // Rev. B
1395   ROM_LOAD( "co61598b.rom", 0x14000, 0x4000, CRC(1f9cd270) SHA1(ae4f523ba08b6fd59f3cae515a2b2410bbd98f55) )   // Rev. 2
1396
1397   ROM_REGION(0x10000, "lslot", ROMREGION_ERASEFF)
1398ROM_END
1399
1400#define rom_a800xlp rom_a800xl
1401
1402ROM_START(a65xe)
1403   ROM_REGION(0x18000, "maincpu", 0)
1404   ROM_LOAD( "co24947a.rom", 0x10000, 0x2000, CRC(7d684184) SHA1(3693c9cb9bf3b41bae1150f7a8264992468fc8c0) )   // Rev. C
1405   ROM_LOAD( "co61598b.rom", 0x14000, 0x4000, CRC(1f9cd270) SHA1(ae4f523ba08b6fd59f3cae515a2b2410bbd98f55) )   // Rev. 2
1406
1407   ROM_REGION(0x10000, "lslot", ROMREGION_ERASEFF)
1408ROM_END
1409
1410ROM_START(a65xea)
1411   ROM_REGION(0x18000, "maincpu", 0)
1412   ROM_LOAD( "basic_ar.rom", 0x10000, 0x2000, CRC(c899f4d6) SHA1(043df191d1fe402e792266a108e147ffcda35130) )   // is this correct? or shall we use Rev. C?
1413//  ROM_LOAD( "c101700.rom",  0x14000, 0x4000, CRC(7f9a76c8) SHA1(57eb6d87850a763f11767f53d4eaede186f831a2) )   // this was from Savetz and has wrong bits!
1414   ROM_LOAD( "c101700.rom",  0x14000, 0x4000, CRC(45f47988) SHA1(a36b8b20f657580f172749bb0625c08706ed824c) )   // Rev. 3B ?
1415
1416   ROM_REGION(0x10000, "lslot", ROMREGION_ERASEFF)
1417ROM_END
1418
1419ROM_START(a130xe)
1420   ROM_REGION(0x18000, "maincpu", 0)
1421   ROM_LOAD( "co24947a.rom", 0x10000, 0x2000, CRC(7d684184) SHA1(3693c9cb9bf3b41bae1150f7a8264992468fc8c0) )   // Rev. C
1422   ROM_LOAD( "co61598b.rom", 0x14000, 0x4000, CRC(1f9cd270) SHA1(ae4f523ba08b6fd59f3cae515a2b2410bbd98f55) )   // Rev. 2
1423
1424   ROM_REGION(0x10000, "lslot", ROMREGION_ERASEFF)
1425ROM_END
1426
1427ROM_START(a800xe)
1428   ROM_REGION(0x18000, "maincpu", 0)
1429   ROM_LOAD( "co24947a.rom", 0x10000, 0x2000, CRC(7d684184) SHA1(3693c9cb9bf3b41bae1150f7a8264992468fc8c0) )   // Rev. C
1430   ROM_LOAD( "c300717.rom",  0x14000, 0x4000, CRC(29f133f7) SHA1(f03b9b93000ee84abb9cf8d6367241006f172182) )   // Rev. 3
1431
1432   ROM_REGION(0x10000, "lslot", ROMREGION_ERASEFF)
1433ROM_END
1434
1435ROM_START(xegs)
1436   ROM_REGION(0x1a000, "maincpu", 0)
1437   ROM_LOAD( "c101687.rom", 0x10000, 0x8000, CRC(d50260d1) SHA1(0e0625ab2473f8431640df3ac8af61925760b9b9) )   // Rev. C + Rev. 4 + Missile Command
1438
1439   ROM_REGION(0x20000, "user1", ROMREGION_ERASE00)
1440ROM_END
1441
1442
1443ROM_START(a5200)
1444   ROM_REGION(0x14000, "maincpu", 0) /* 64K for the CPU + 16K for cartridges */
1445   ROM_SYSTEM_BIOS(0, "default", "a5200")
1446   ROMX_LOAD( "5200.rom",  0xf800, 0x0800, CRC(4248d3e3) SHA1(6ad7a1e8c9fad486fbec9498cb48bf5bc3adc530), ROM_BIOS(1) )
1447   ROM_SYSTEM_BIOS(1, "alt", "a5200 (alt)")
1448   ROMX_LOAD( "5200a.rom", 0xf800, 0x0800, CRC(c2ba2613) SHA1(1d2a3f00109d75d2d79fecb565775eb95b7d04d5), ROM_BIOS(2) )
1449ROM_END
1450
1451/**************************************************************
1452 *
1453 * Driver initializations
1454 *
1455 **************************************************************/
1456
1457static DRIVER_INIT( a800xl )
1458{
1459   a800xl_mmu(machine, 0xff);
1460}
1461
1462static DRIVER_INIT( xegs )
1463{
1464   xegs_mmu(machine, 0xff);
1465}
1466
1467static DRIVER_INIT( a600xl )
1468{
1469   UINT8 *rom = machine.region("maincpu")->base();
1470   memcpy( rom + 0x5000, rom + 0xd000, 0x800 );
1471}
1472
1473/**************************************************************
1474 *
1475 * Game driver(s)
1476 *
1477 **************************************************************/
1478
1479/*     YEAR  NAME      PARENT    COMPAT MACHINE     INPUT    INIT      COMPANY    FULLNAME */
1480COMP ( 1979, a400,     0,        0,     a400,       a800,    0,      "Atari",   "Atari 400 (NTSC)", 0)
1481COMP ( 1979, a400pal,  a400,     0,     a400pal,    a800,    0,      "Atari",   "Atari 400 (PAL)",  0)
1482COMP ( 1979, a800,     0,        0,     a800,       a800,    0,      "Atari",   "Atari 800 (NTSC)", 0)
1483COMP ( 1979, a800pal,  a800,     0,     a800pal,    a800,    0,      "Atari",   "Atari 800 (PAL)",  0)
1484COMP ( 1982, a1200xl,  a800,     0,     a1200xl,    a800xl,  a800xl, "Atari",   "Atari 1200XL",     GAME_NOT_WORKING )      // 64k RAM
1485COMP ( 1983, a600xl,   a800xl,   0,     a600xl,     a800xl,  a600xl, "Atari",   "Atari 600XL",      GAME_NOT_WORKING )      // 16k RAM
1486COMP ( 1983, a800xl,   0,       0,     a800xl,     a800xl,  a800xl, "Atari",   "Atari 800XL (NTSC)",GAME_IMPERFECT_GRAPHICS )      // 64k RAM
1487COMP ( 1983, a800xlp,  a800xl,    0,     a800xlpal,  a800xl,  a800xl, "Atari",   "Atari 800XL (PAL)", GAME_IMPERFECT_GRAPHICS )      // 64k RAM
1488COMP ( 1986, a65xe,    a800xl,   0,     a800xl,     a800xl,  a800xl, "Atari",   "Atari 65XE",       GAME_NOT_WORKING )      // 64k RAM
1489COMP ( 1986, a65xea,   a800xl,   0,     a800xl,     a800xl,  a800xl, "Atari",   "Atari 65XE (Arabic)", GAME_NOT_WORKING )
1490COMP ( 1986, a130xe,   a800xl,   0,     a800xl,     a800xl,  a800xl, "Atari",   "Atari 130XE",      GAME_NOT_WORKING )      // 128k RAM
1491COMP ( 1986, a800xe,   a800xl,   0,     a800xl,     a800xl,  a800xl, "Atari",   "Atari 800XE",      GAME_NOT_WORKING )      // 64k RAM
1492COMP ( 1987, xegs,     0,        0,     xegs,       a800xl,  xegs,   "Atari",   "Atari XE Game System", GAME_NOT_WORKING )   // 64k RAM
1493
1494CONS ( 1982, a5200,    0,        0,     a5200,      a5200,   0,      "Atari",   "Atari 5200",       0)
src/mame/drivers/amiga.c
r11531r11532
1/***************************************************************************
2Commodore Amiga - (c) 1985, Commodore Business Machines Co.
3
4Preliminary driver by:
5
6Ernesto Corvi
7
8Note 1: The 'fast-mem' memory detector in Kickstart 1.2 expects to
9see the custom chips at the end of any present fast memory (mapped
10from $C00000 onwards). I assume this is a bug, given that the routine
11was entirely rewritten for Kickstart 1.3. So the strategy is, for
12any machine that can run Kickstart 1.2 (a500,a1000 and a2000), we
13map a mirror of the custom chips right after any fast-mem we mapped.
14If we didn't map any, then we still put a mirror, but where fast-mem
15would commence ($C00000).
16
17***************************************************************************/
18
19/* Core includes */
20#include "emu.h"
21#include "includes/amiga.h"
22
23/* Components */
24#include "cpu/m68000/m68000.h"
25#include "cpu/m6502/m6502.h"
26#include "machine/6525tpi.h"
27#include "machine/6526cia.h"
28#include "machine/amigafdc.h"
29#include "machine/amigakbd.h"
30#include "machine/amigacd.h"
31#include "machine/amigacrt.h"
32#include "machine/msm6242.h"
33#include "machine/ctronics.h"
34#include "machine/nvram.h"
35#include "sound/cdda.h"
36
37/* Devices */
38#include "imagedev/chd_cd.h"
39#include "imagedev/cartslot.h"
40
41
42static READ8_DEVICE_HANDLER( amiga_cia_0_portA_r );
43static READ8_DEVICE_HANDLER( amiga_cia_0_cdtv_portA_r );
44static WRITE8_DEVICE_HANDLER( amiga_cia_0_portA_w );
45
46/***************************************************************************
47  Battery Backed-Up Clock (MSM6264)
48***************************************************************************/
49
50static READ16_HANDLER( amiga_clock_r )
51{
52   device_t *rtc = space->machine().device("rtc");
53   return msm6242_r(rtc, offset / 2);
54}
55
56
57static WRITE16_HANDLER( amiga_clock_w )
58{
59   device_t *rtc = space->machine().device("rtc");
60   msm6242_w(rtc, offset / 2, data);
61}
62
63
64/***************************************************************************
65    CENTRONICS PORT
66***************************************************************************/
67
68static READ8_DEVICE_HANDLER( amiga_cia_1_porta_r )
69{
70   UINT8 result = 0;
71
72   /* centronics status is stored in PA0 to PA2 */
73   result |= centronics_busy_r(device) << 0;
74   result |= !centronics_pe_r(device) << 1;
75   result |= centronics_vcc_r(device) << 2;
76
77   /* PA3 to PA7 store the serial line status (not emulated) */
78
79   return result;
80}
81
82static const centronics_interface amiga_centronics_config =
83{
84   FALSE,
85   DEVCB_DEVICE_LINE("cia_0", mos6526_flag_w),
86   DEVCB_NULL,
87   DEVCB_NULL
88};
89
90
91/***************************************************************************
92  Address maps
93***************************************************************************/
94
95static ADDRESS_MAP_START(amiga_mem, AS_PROGRAM, 16)
96   ADDRESS_MAP_UNMAP_HIGH
97   AM_RANGE(0x000000, 0x07ffff) AM_MIRROR(0x80000) AM_RAMBANK("bank1") AM_BASE_SIZE_MEMBER(amiga_state, m_chip_ram, m_chip_ram_size)
98   AM_RANGE(0xbfd000, 0xbfefff) AM_READWRITE(amiga_cia_r, amiga_cia_w)
99   AM_RANGE(0xc00000, 0xc7ffff) AM_RAM /* slow-mem */
100   AM_RANGE(0xc80000, 0xcfffff) AM_READWRITE(amiga_custom_r, amiga_custom_w)   /* see Note 1 above */
101   AM_RANGE(0xdf0000, 0xdfffff) AM_READWRITE(amiga_custom_r, amiga_custom_w) AM_BASE_MEMBER(amiga_state, m_custom_regs)   /* Custom Chips */
102   AM_RANGE(0xe80000, 0xe8ffff) AM_READWRITE(amiga_autoconfig_r, amiga_autoconfig_w)
103   AM_RANGE(0xf80000, 0xffffff) AM_ROM AM_REGION("user1", 0)   /* System ROM - mirror */
104ADDRESS_MAP_END
105
106static ADDRESS_MAP_START(keyboard_mem, AS_PROGRAM, 8)
107   AM_RANGE(0x0000, 0x003f) AM_RAM /* internal user ram */
108   AM_RANGE(0x0040, 0x007f) AM_NOP /* unassigned */
109   AM_RANGE(0x0080, 0x0080) AM_NOP /* port a */
110   AM_RANGE(0x0081, 0x0081) AM_NOP /* port b */
111   AM_RANGE(0x0082, 0x0082) AM_NOP /* port c */
112   AM_RANGE(0x0083, 0x0083) AM_NOP /* port d */
113   AM_RANGE(0x0084, 0x0085) AM_NOP /* latch */
114   AM_RANGE(0x0086, 0x0087) AM_NOP /* count */
115   AM_RANGE(0x0088, 0x0088) AM_NOP /* upper latch & transfer latch to counter */
116   AM_RANGE(0x0089, 0x0089) AM_NOP /* clear pa0 pos edge detected */
117   AM_RANGE(0x008a, 0x008a) AM_NOP /* clear pa1 neg edge detected */
118   AM_RANGE(0x008b, 0x008e) AM_NOP /* unassigned */
119   AM_RANGE(0x008f, 0x008f) AM_NOP /* control register */
120   AM_RANGE(0x0090, 0x07ff) AM_NOP /* unassigned */
121   AM_RANGE(0x0800, 0x0fff) AM_ROM AM_REGION("keyboard", 0) /* internal mask rom */
122ADDRESS_MAP_END
123
124
125/*
126 * CDTV memory map (source: http://www.l8r.net/technical/cdtv-technical.html)
127 *
128 * 000000-0FFFFF Chip memory
129 * 100000-1FFFFF Space for extra chip memory (Megachip)
130 * 200000-9FFFFF Space for AutoConfig memory
131 * A00000-BFFFFF CIA chips
132 * C00000-C7FFFF Space for slow-fast memory
133 * C80000-DBFFFF Space
134 * DC0000-DC7FFF Power backed-up real time clock
135 * DC8000-DC87FF Non-volatile RAM
136 * DC8800-DCFFFF Space in non-volatile RAM decoded area
137 * DD0000-DEFFFF Space
138 * DF0000-DFFFFF Custom chips
139 * E00000-E7FFFF Memory card address space for front panel memory card
140 * E80000-E8FFFF AutoConfig configuration space
141 * E90000-E9FFFF First AutoConfig device, used by DMAC
142 * EA0000-EFFFFF Space for other AutoConfig devices
143 * F00000-F3FFFF CDTV ROM
144 * F40000-F7FFFF Space in CDTV ROM decoded area
145 * F80000-FBFFFF Space in Kickstart ROM decoded area (used by Kickstart 2)
146 * FC0000-FFFFFF Kickstart ROM
147 *
148 */
149
150static ADDRESS_MAP_START(cdtv_mem, AS_PROGRAM, 16)
151   AM_RANGE(0x000000, 0x0fffff) AM_RAMBANK("bank1") AM_BASE_SIZE_MEMBER(amiga_state, m_chip_ram, m_chip_ram_size)
152   AM_RANGE(0xbfd000, 0xbfefff) AM_READWRITE(amiga_cia_r, amiga_cia_w)
153   AM_RANGE(0xdc0000, 0xdc003f) AM_READWRITE(amiga_clock_r, amiga_clock_w)
154   AM_RANGE(0xdc8000, 0xdc87ff) AM_RAM AM_SHARE("nvram")
155   AM_RANGE(0xdf0000, 0xdfffff) AM_READWRITE(amiga_custom_r, amiga_custom_w) AM_BASE_MEMBER(amiga_state, m_custom_regs)   /* Custom Chips */
156   AM_RANGE(0xe80000, 0xe8ffff) AM_READWRITE(amiga_autoconfig_r, amiga_autoconfig_w)
157   AM_RANGE(0xf00000, 0xffffff) AM_ROM AM_REGION("user1", 0)   /* CDTV & System ROM */
158ADDRESS_MAP_END
159
160static ADDRESS_MAP_START(cdtv_rcmcu_mem, AS_PROGRAM, 8)
161   AM_RANGE(0x0000, 0x003f) AM_RAM /* internal user ram */
162   AM_RANGE(0x0040, 0x007f) AM_NOP /* unassigned */
163   AM_RANGE(0x0080, 0x0080) AM_NOP /* port a */
164   AM_RANGE(0x0081, 0x0081) AM_NOP /* port b */
165   AM_RANGE(0x0082, 0x0082) AM_NOP /* port c */
166   AM_RANGE(0x0083, 0x0083) AM_NOP /* port d */
167   AM_RANGE(0x0084, 0x0085) AM_NOP /* latch */
168   AM_RANGE(0x0086, 0x0087) AM_NOP /* count */
169   AM_RANGE(0x0088, 0x0088) AM_NOP /* upper latch & transfer latch to counter */
170   AM_RANGE(0x0089, 0x0089) AM_NOP /* clear pa0 pos edge detected */
171   AM_RANGE(0x008a, 0x008a) AM_NOP /* clear pa1 neg edge detected */
172   AM_RANGE(0x008b, 0x008e) AM_NOP /* unassigned */
173   AM_RANGE(0x008f, 0x008f) AM_NOP /* control register */
174   AM_RANGE(0x0090, 0x07ff) AM_NOP /* unassigned */
175   AM_RANGE(0x0800, 0x0fff) AM_ROM AM_REGION("rcmcu", 0) /* internal mask rom */
176ADDRESS_MAP_END
177
178static ADDRESS_MAP_START(a1000_mem, AS_PROGRAM, 16)
179   AM_RANGE(0x000000, 0x03ffff) AM_MIRROR(0xc0000) AM_RAMBANK("bank1") AM_BASE_SIZE_MEMBER(amiga_state, m_chip_ram, m_chip_ram_size)
180   AM_RANGE(0xbfd000, 0xbfefff) AM_READWRITE(amiga_cia_r, amiga_cia_w)
181   AM_RANGE(0xc00000, 0xc3ffff) AM_READWRITE(amiga_custom_r, amiga_custom_w) /* See Note 1 above */
182   AM_RANGE(0xdf0000, 0xdfffff) AM_READWRITE(amiga_custom_r, amiga_custom_w) AM_BASE_MEMBER(amiga_state, m_custom_regs)   /* Custom Chips */
183   AM_RANGE(0xe80000, 0xe8ffff) AM_READWRITE(amiga_autoconfig_r, amiga_autoconfig_w)
184   AM_RANGE(0xf80000, 0xfbffff) AM_ROM AM_REGION("user1", 0)   /* Bootstrap ROM */
185   AM_RANGE(0xfc0000, 0xffffff) AM_RAMBANK("bank2")   /* Writable Control Store RAM */
186ADDRESS_MAP_END
187
188
189/***************************************************************************
190  Inputs
191***************************************************************************/
192
193static INPUT_PORTS_START( amiga_common )
194   PORT_START("input")
195   PORT_CONFNAME( 0x20, 0x00, "Input Port 0 Device")
196   PORT_CONFSETTING( 0x00, "Mouse" )
197   PORT_CONFSETTING( 0x20, DEF_STR(Joystick) )
198   PORT_CONFNAME( 0x10, 0x10, "Input Port 1 Device")
199   PORT_CONFSETTING( 0x00, "Mouse" )
200   PORT_CONFSETTING( 0x10, DEF_STR(Joystick) )
201
202   PORT_START("CIA0PORTA")
203   PORT_BIT( 0x3f, IP_ACTIVE_LOW, IPT_SPECIAL )
204   PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_PLAYER(1)
205   PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_PLAYER(2)
206
207   PORT_START("JOY0DAT")
208   PORT_BIT( 0x0303, IP_ACTIVE_HIGH, IPT_SPECIAL ) PORT_CUSTOM(amiga_joystick_convert, "P1JOY")
209   PORT_BIT( 0xfcfc, IP_ACTIVE_HIGH, IPT_UNUSED )
210
211   PORT_START("JOY1DAT")
212   PORT_BIT( 0x0303, IP_ACTIVE_HIGH, IPT_SPECIAL ) PORT_CUSTOM(amiga_joystick_convert, "P2JOY")
213   PORT_BIT( 0xfcfc, IP_ACTIVE_HIGH, IPT_UNUSED )
214
215   PORT_START("POTGO")
216   PORT_BIT( 0x0100, IP_ACTIVE_LOW, IPT_UNUSED )
217   PORT_BIT( 0x0400, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_PLAYER(1)
218   PORT_BIT( 0x1000, IP_ACTIVE_LOW, IPT_UNUSED )
219   PORT_BIT( 0x4000, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_PLAYER(2)
220   PORT_BIT( 0xaaff, IP_ACTIVE_HIGH, IPT_UNUSED )
221
222   PORT_START("P1JOY")
223   PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_JOYSTICK_UP ) PORT_PLAYER(1)
224   PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_JOYSTICK_DOWN ) PORT_PLAYER(1)
225   PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_JOYSTICK_LEFT ) PORT_PLAYER(1)
226   PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_JOYSTICK_RIGHT ) PORT_PLAYER(1)
227
228   PORT_START("P2JOY")
229   PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_JOYSTICK_UP ) PORT_PLAYER(2)
230   PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_JOYSTICK_DOWN ) PORT_PLAYER(2)
231   PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_JOYSTICK_LEFT ) PORT_PLAYER(2)
232   PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_JOYSTICK_RIGHT ) PORT_PLAYER(2)
233
234   PORT_START("P0MOUSEX")
235   PORT_BIT( 0xff, 0x00, IPT_MOUSE_X) PORT_SENSITIVITY(100) PORT_KEYDELTA(5) PORT_MINMAX(0, 255) PORT_PLAYER(1)
236
237   PORT_START("P0MOUSEY")
238   PORT_BIT( 0xff, 0x00, IPT_MOUSE_Y) PORT_SENSITIVITY(100) PORT_KEYDELTA(5) PORT_MINMAX(0, 255) PORT_PLAYER(1)
239
240   PORT_START("P1MOUSEX")
241   PORT_BIT( 0xff, 0x00, IPT_MOUSE_X) PORT_SENSITIVITY(100) PORT_KEYDELTA(5) PORT_MINMAX(0, 255) PORT_PLAYER(2)
242
243   PORT_START("P1MOUSEY")
244   PORT_BIT( 0xff, 0x00, IPT_MOUSE_Y) PORT_SENSITIVITY(100) PORT_KEYDELTA(5) PORT_MINMAX(0, 255) PORT_PLAYER(2)
245
246   PORT_INCLUDE( amiga_us_keyboard )
247
248INPUT_PORTS_END
249
250
251static INPUT_PORTS_START( amiga )
252   PORT_START("hardware")
253   PORT_CONFNAME( 0x08, 0x08, "Battery backed-up RTC")
254   PORT_CONFSETTING( 0x00, "Not Installed" )
255   PORT_CONFSETTING( 0x08, "Installed" )
256
257   PORT_INCLUDE( amiga_common )
258INPUT_PORTS_END
259
260
261/* TODO: Support for the CDTV remote control */
262static INPUT_PORTS_START( cdtv )
263   PORT_INCLUDE( amiga_common )
264INPUT_PORTS_END
265
266/***************************************************************************
267  Machine drivers
268***************************************************************************/
269
270static MACHINE_START( cdtv )
271{
272   MACHINE_START_CALL( amigacd );
273}
274
275
276static MACHINE_RESET( cdtv )
277{
278   MACHINE_RESET_CALL( amiga );
279
280   /* initialize the cdrom controller */
281   MACHINE_RESET_CALL( amigacd );
282}
283
284static const mos6526_interface cia_0_ntsc_intf =
285{
286   60,                                          /* tod_clock */
287   DEVCB_LINE(amiga_cia_0_irq),                     /* irq_func */
288   DEVCB_DEVICE_LINE("centronics", centronics_strobe_w),   /* pc_func */
289   DEVCB_NULL,
290   DEVCB_NULL,
291   DEVCB_HANDLER(amiga_cia_0_portA_r),
292   DEVCB_HANDLER(amiga_cia_0_portA_w),                  /* port A */
293   DEVCB_NULL,
294   DEVCB_DEVICE_HANDLER("centronics", centronics_data_w)   /* port B */
295};
296
297static const mos6526_interface cia_0_pal_intf =
298{
299   50,                                          /* tod_clock */
300   DEVCB_LINE(amiga_cia_0_irq),                     /* irq_func */
301   DEVCB_DEVICE_LINE("centronics", centronics_strobe_w),   /* pc_func */
302   DEVCB_NULL,
303   DEVCB_NULL,
304   DEVCB_HANDLER(amiga_cia_0_portA_r),
305   DEVCB_HANDLER(amiga_cia_0_portA_w),                  /* port A */
306   DEVCB_NULL,
307   DEVCB_DEVICE_HANDLER("centronics", centronics_data_w)   /* port B */
308};
309
310static const mos6526_interface cia_1_intf =
311{
312   0,                                          /* tod_clock */
313   DEVCB_LINE(amiga_cia_1_irq),                     /* irq_func */
314   DEVCB_NULL,                                    /* pc_func */
315   DEVCB_NULL,
316   DEVCB_NULL,
317   DEVCB_DEVICE_HANDLER("centronics", amiga_cia_1_porta_r),
318   DEVCB_NULL,                                    /* port A */
319   DEVCB_NULL,
320   DEVCB_DEVICE_HANDLER("fdc", amiga_fdc_control_w)      /* port B */
321};
322
323static const mos6526_interface cia_0_cdtv_intf =
324{
325   0,                                          /* tod_clock */
326   DEVCB_LINE(amiga_cia_0_irq),                     /* irq_func */
327   DEVCB_DEVICE_LINE("centronics", centronics_strobe_w),   /* pc_func */
328   DEVCB_NULL,
329   DEVCB_NULL,
330   DEVCB_HANDLER(amiga_cia_0_cdtv_portA_r),
331   DEVCB_HANDLER(amiga_cia_0_portA_w),                  /* port A */
332   DEVCB_NULL,
333   DEVCB_DEVICE_HANDLER("centronics", centronics_data_w)   /* port B */
334};
335
336static const mos6526_interface cia_1_cdtv_intf =
337{
338   0,                                          /* tod_clock */
339   DEVCB_LINE(amiga_cia_1_irq),                     /* irq_func */
340   DEVCB_NULL,   /* pc_func */
341   DEVCB_NULL,
342   DEVCB_NULL,
343   DEVCB_DEVICE_HANDLER("centronics", amiga_cia_1_porta_r),
344   DEVCB_NULL,                                    /* port A */
345   DEVCB_NULL,
346   DEVCB_NULL                                    /* port B */
347};
348
349static const tpi6525_interface cdtv_tpi_intf =
350{
351   DEVCB_LINE(amigacd_tpi6525_irq),
352   DEVCB_NULL,
353   DEVCB_NULL,
354   DEVCB_NULL,
355   DEVCB_HANDLER(amigacd_tpi6525_portb_w),
356   DEVCB_HANDLER(amigacd_tpi6525_portc_r),
357   DEVCB_NULL,
358   DEVCB_NULL,
359   DEVCB_NULL
360};
361
362
363static MACHINE_CONFIG_FRAGMENT( amiga_cartslot )
364   MCFG_CARTSLOT_ADD("cart")
365   MCFG_CARTSLOT_EXTENSION_LIST("rom,bin")
366   MCFG_CARTSLOT_NOT_MANDATORY
367MACHINE_CONFIG_END
368
369static MACHINE_CONFIG_START( ntsc, amiga_state )
370   /* basic machine hardware */
371   MCFG_CPU_ADD("maincpu", M68000, AMIGA_68000_NTSC_CLOCK)
372   MCFG_CPU_PROGRAM_MAP(amiga_mem)
373
374   MCFG_CPU_ADD("keyboard", M6502, XTAL_1MHz) /* 1 MHz? */
375   MCFG_CPU_PROGRAM_MAP(keyboard_mem)
376
377   MCFG_SCREEN_ADD("screen", RASTER)
378   MCFG_SCREEN_REFRESH_RATE(59.997)
379   MCFG_SCREEN_VBLANK_TIME(ATTOSECONDS_IN_USEC(0))
380
381   MCFG_MACHINE_RESET( amiga )
382
383    /* video hardware */
384   MCFG_VIDEO_ATTRIBUTES(VIDEO_UPDATE_BEFORE_VBLANK)
385   MCFG_SCREEN_FORMAT(BITMAP_FORMAT_INDEXED16)
386   MCFG_SCREEN_SIZE(228*4, 262)
387   MCFG_SCREEN_VISIBLE_AREA(214, (228*4)-1, 34, 262-1)
388   MCFG_SCREEN_UPDATE(amiga)
389
390   MCFG_PALETTE_LENGTH(4096)
391   MCFG_PALETTE_INIT( amiga )
392
393   MCFG_VIDEO_START(amiga)
394
395   /* devices */
396   MCFG_MSM6242_ADD("rtc")
397   MCFG_CENTRONICS_ADD("centronics", amiga_centronics_config)
398
399   /* sound hardware */
400   MCFG_SPEAKER_STANDARD_STEREO("lspeaker", "rspeaker")
401
402   MCFG_SOUND_ADD("amiga", AMIGA, 3579545)
403   MCFG_SOUND_ROUTE(0, "lspeaker", 0.50)
404   MCFG_SOUND_ROUTE(1, "rspeaker", 0.50)
405   MCFG_SOUND_ROUTE(2, "rspeaker", 0.50)
406   MCFG_SOUND_ROUTE(3, "lspeaker", 0.50)
407
408   /* cia */
409   MCFG_MOS8520_ADD("cia_0", AMIGA_68000_NTSC_CLOCK / 10, cia_0_ntsc_intf)
410   MCFG_MOS8520_ADD("cia_1", AMIGA_68000_NTSC_CLOCK, cia_1_intf)
411
412   MCFG_AMIGA_FDC_ADD("fdc")
413MACHINE_CONFIG_END
414
415static MACHINE_CONFIG_DERIVED( a1000n, ntsc )
416   MCFG_CPU_MODIFY("maincpu")
417   MCFG_CPU_PROGRAM_MAP(a1000_mem)
418MACHINE_CONFIG_END
419
420static MACHINE_CONFIG_DERIVED( a500n, ntsc )
421   MCFG_FRAGMENT_ADD(amiga_cartslot)
422MACHINE_CONFIG_END
423
424
425static MACHINE_CONFIG_DERIVED( cdtv, ntsc )
426   MCFG_CPU_REPLACE("maincpu", M68000, CDTV_CLOCK_X1 / 4)
427   MCFG_CPU_PROGRAM_MAP(cdtv_mem)
428
429   MCFG_DEVICE_REMOVE("keyboard")
430
431   MCFG_CPU_ADD("rcmcu", M6502, XTAL_1MHz) /* 1 MHz? */
432   MCFG_CPU_PROGRAM_MAP(cdtv_rcmcu_mem)
433   MCFG_DEVICE_DISABLE()
434
435//  MCFG_CPU_ADD("lcd", LC6554, XTAL_4MHz) /* 4 MHz? */
436//  MCFG_CPU_PROGRAM_MAP(cdtv_lcd_mem)
437
438   MCFG_MACHINE_START( cdtv )
439   MCFG_MACHINE_RESET( cdtv )
440
441   MCFG_NVRAM_ADD_0FILL("nvram")
442
443   MCFG_SOUND_ADD( "cdda", CDDA, 0 )
444   MCFG_SOUND_ROUTE( 0, "lspeaker", 1.0 )
445   MCFG_SOUND_ROUTE( 1, "rspeaker", 1.0 )
446
447   /* cdrom */
448   MCFG_CDROM_ADD( "cdrom" )
449   MCFG_CDROM_INTERFACE("cdrom")
450   MCFG_SOFTWARE_LIST_ADD("cd_list", "cdtv")
451
452   MCFG_TPI6525_ADD("tpi6525", cdtv_tpi_intf)
453
454   /* cia */
455   MCFG_DEVICE_REMOVE("cia_0")
456   MCFG_DEVICE_REMOVE("cia_1")
457   MCFG_MOS8520_ADD("cia_0", CDTV_CLOCK_X1 / 40, cia_0_cdtv_intf)
458   MCFG_MOS8520_ADD("cia_1", CDTV_CLOCK_X1 / 4, cia_1_cdtv_intf)
459MACHINE_CONFIG_END
460
461
462static MACHINE_CONFIG_DERIVED( pal, ntsc )
463
464   /* adjust for PAL specs */
465   MCFG_CPU_MODIFY("maincpu")
466   MCFG_CPU_CLOCK( AMIGA_68000_PAL_CLOCK)
467
468   MCFG_SCREEN_MODIFY("screen")
469   MCFG_SCREEN_REFRESH_RATE(50)
470   MCFG_SCREEN_SIZE(228*4, 312)
471   MCFG_SCREEN_VISIBLE_AREA(214, (228*4)-1, 34, 312-1)
472
473   /* cia */
474   MCFG_DEVICE_REMOVE("cia_0")
475   MCFG_MOS8520_ADD("cia_0", AMIGA_68000_PAL_CLOCK / 10, cia_0_pal_intf)
476MACHINE_CONFIG_END
477
478static MACHINE_CONFIG_DERIVED( a500p, pal )
479   MCFG_FRAGMENT_ADD(amiga_cartslot)
480MACHINE_CONFIG_END
481
482static MACHINE_CONFIG_DERIVED( a1000p, pal )
483   MCFG_CPU_MODIFY("maincpu")
484   MCFG_CPU_PROGRAM_MAP(a1000_mem)
485MACHINE_CONFIG_END
486
487/***************************************************************************
488
489  Amiga specific stuff
490
491***************************************************************************/
492
493
494static READ8_DEVICE_HANDLER( amiga_cia_0_portA_r )
495{
496   UINT8 ret = input_port_read(device->machine(), "CIA0PORTA") & 0xc0;   /* Gameport 1 and 0 buttons */
497   ret |= amiga_fdc_status_r(device->machine().device("fdc"));
498   return ret;
499}
500
501
502static READ8_DEVICE_HANDLER( amiga_cia_0_cdtv_portA_r )
503{
504   return input_port_read(device->machine(), "CIA0PORTA") & 0xc0;   /* Gameport 1 and 0 buttons */
505}
506
507
508static WRITE8_DEVICE_HANDLER( amiga_cia_0_portA_w )
509{
510   amiga_state *state = device->machine().driver_data<amiga_state>();
511   /* switch banks as appropriate */
512   memory_set_bank(device->machine(), "bank1", data & 1);
513
514   /* swap the write handlers between ROM and bank 1 based on the bit */
515   if ((data & 1) == 0) {
516      UINT32 mirror_mask = state->m_chip_ram_size;
517
518      while( (mirror_mask<<1) < 0x100000 ) {
519         mirror_mask |= ( mirror_mask << 1 );
520      }
521
522      /* overlay disabled, map RAM on 0x000000 */
523      device->machine().device("maincpu")->memory().space(AS_PROGRAM)->install_write_bank(0x000000, state->m_chip_ram_size - 1, 0, mirror_mask, "bank1");
524
525      /* if there is a cart region, check for cart overlay */
526      if (device->machine().region("user2")->base() != NULL)
527         amiga_cart_check_overlay(device->machine());
528   }
529   else
530      /* overlay enabled, map Amiga system ROM on 0x000000 */
531      device->machine().device("maincpu")->memory().space(AS_PROGRAM)->unmap_write(0x000000, state->m_chip_ram_size - 1);
532
533   set_led_status( device->machine(), 0, ( data & 2 ) ? 0 : 1 ); /* bit 2 = Power Led on Amiga */
534   output_set_value("power_led", ( data & 2 ) ? 0 : 1);
535}
536
537static UINT16 amiga_read_joy0dat(running_machine &machine)
538{
539   if ( input_port_read(machine, "input") & 0x20 ) {
540      /* Joystick */
541      return input_port_read_safe(machine, "JOY0DAT", 0xffff);
542   } else {
543      /* Mouse */
544      int input;
545      input  = ( input_port_read(machine, "P0MOUSEX") & 0xff );
546      input |= ( input_port_read(machine, "P0MOUSEY") & 0xff ) << 8;
547      return input;
548   }
549}
550
551static UINT16 amiga_read_joy1dat(running_machine &machine)
552{
553   if ( input_port_read(machine, "input") & 0x10 ) {
554      /* Joystick */
555      return input_port_read_safe(machine, "JOY1DAT", 0xffff);
556   } else {
557      /* Mouse */
558      int input;
559      input  = ( input_port_read(machine, "P1MOUSEX") & 0xff );
560      input |= ( input_port_read(machine, "P1MOUSEY") & 0xff ) << 8;
561      return input;
562   }
563}
564
565static UINT16 amiga_read_dskbytr(running_machine &machine)
566{
567   return amiga_fdc_get_byte(machine.device("fdc"));
568}
569
570static void amiga_write_dsklen(running_machine &machine, UINT16 data)
571{
572   amiga_state *state = machine.driver_data<amiga_state>();
573   if ( data & 0x8000 ) {
574      if ( CUSTOM_REG(REG_DSKLEN) & 0x8000 )
575         amiga_fdc_setup_dma(machine.device("fdc"));
576   }
577}
578
579
580static void amiga_reset(running_machine &machine)
581{
582   if (input_port_read(machine, "hardware") & 0x08)
583   {
584      /* Install RTC */
585      machine.device("maincpu")->memory().space(AS_PROGRAM)->install_legacy_readwrite_handler(0xdc0000, 0xdc003f, FUNC(amiga_clock_r), FUNC(amiga_clock_w));
586   }
587   else
588   {
589      /* No RTC support */
590      machine.device("maincpu")->memory().space(AS_PROGRAM)->unmap_readwrite(0xdc0000, 0xdc003f);
591   }
592}
593
594static DRIVER_INIT( amiga )
595{
596   amiga_state *state = machine.driver_data<amiga_state>();
597   static const amiga_machine_interface amiga_intf =
598   {
599      ANGUS_CHIP_RAM_MASK,
600      amiga_read_joy0dat,   amiga_read_joy1dat,  /* joy0dat_r & joy1dat_r */
601      NULL,                                    /* potgo_w */
602      amiga_read_dskbytr,   amiga_write_dsklen,  /* dskbytr_r & dsklen_w */
603      NULL,                                    /* serdat_w */
604      NULL,                                    /* scanline0_callback */
605      amiga_reset,                             /* reset_callback */
606      amiga_cart_nmi,                          /* nmi_callback */
607      0                                        /* flags */
608   };
609
610   amiga_machine_config(machine, &amiga_intf);
611
612   /* set up memory */
613   memory_configure_bank(machine, "bank1", 0, 1, state->m_chip_ram, 0);
614   memory_configure_bank(machine, "bank1", 1, 1, machine.region("user1")->base(), 0);
615
616   /* initialize cartridge (if present) */
617   amiga_cart_init(machine);
618
619   /* initialize keyboard */
620   amigakbd_init(machine);
621}
622
623#ifdef UNUSED_FUNCTION
624static DRIVER_INIT( amiga_ecs )
625{
626   static const amiga_machine_interface amiga_intf =
627   {
628      ECS_CHIP_RAM_MASK,
629      amiga_cia_0_portA_r, NULL,               /* CIA0 port A & B read */
630      amiga_cia_0_portA_w, NULL,               /* CIA0 port A & B write */
631      NULL, NULL,                              /* CIA1 port A & B read */
632      NULL, amiga_fdc_control_w,               /* CIA1 port A & B write */
633      amiga_read_joy0dat,   amiga_read_joy1dat,  /* joy0dat_r & joy1dat_r */
634      NULL,                                    /* potgo_w */
635      amiga_read_dskbytr,   amiga_write_dsklen,  /* dskbytr_r & dsklen_w */
636      NULL,                                    /* serdat_w */
637      NULL,                                    /* scanline0_callback */
638      amiga_reset,                             /* reset_callback */
639      amiga_cart_nmi,                          /* nmi_callback */
640      0                                        /* flags */
641   };
642
643   amiga_machine_config(machine, &amiga_intf);
644
645   /* set up memory */
646   memory_configure_bank(1, 0, 1, state->m_chip_ram, 0);
647   memory_configure_bank(1, 1, 1, machine.region("user1")->base(), 0);
648
649   /* initialize Action Replay (if present) */
650   amiga_cart_init(machine);
651
652   /* initialize keyboard */
653   amigakbd_init(machine);
654}
655#endif
656
657static DRIVER_INIT( cdtv )
658{
659   amiga_state *state = machine.driver_data<amiga_state>();
660   static const amiga_machine_interface amiga_intf =
661   {
662      ECS_CHIP_RAM_MASK,
663      amiga_read_joy0dat,   amiga_read_joy1dat,  /* joy0dat_r & joy1dat_r */
664      NULL,                                    /* potgo_w */
665      amiga_read_dskbytr,   amiga_write_dsklen,  /* dskbytr_r & dsklen_w */
666      NULL,                                    /* serdat_w */
667      NULL,                                    /* scanline0_callback */
668      NULL,                                    /* reset_callback */
669      NULL,                                    /* nmi_callback */
670      0                                        /* flags */
671   };
672
673   amiga_machine_config(machine, &amiga_intf);
674
675   /* set up memory */
676   memory_configure_bank(machine, "bank1", 0, 1, state->m_chip_ram, 0);
677   memory_configure_bank(machine, "bank1", 1, 1, machine.region("user1")->base(), 0);
678
679   /* initialize keyboard - in cdtv we can use a standard Amiga keyboard*/
680   amigakbd_init(machine);
681}
682
683
684/***************************************************************************
685    ROM DEFINITIONS
686***************************************************************************/
687
688ROM_START( a500n )
689   ROM_REGION16_BE(0x080000, "user1", 0)
690   ROM_DEFAULT_BIOS("kick13")
691   ROM_SYSTEM_BIOS(0, "kick12",  "Kickstart 1.2 (33.180)")
692   ROMX_LOAD("315093-01.u6", 0x000000, 0x040000, CRC(a6ce1636) SHA1(11f9e62cf299f72184835b7b2a70a16333fc0d88), ROM_GROUPWORD | ROM_BIOS(1))
693   ROM_SYSTEM_BIOS(1, "kick13",  "Kickstart 1.3 (34.5)")
694   ROMX_LOAD("315093-02.u6", 0x000000, 0x040000, CRC(c4f0f55f) SHA1(891e9a547772fe0c6c19b610baf8bc4ea7fcb785), ROM_GROUPWORD | ROM_BIOS(2))
695   ROM_COPY("user1", 0x000000, 0x040000, 0x040000)
696   ROM_SYSTEM_BIOS(2, "kick204", "Kickstart 2.04 (37.175)")
697   ROMX_LOAD("390979-01.u6", 0x000000, 0x080000, CRC(c3bdb240) SHA1(c5839f5cb98a7a8947065c3ed2f14f5f42e334a1), ROM_GROUPWORD | ROM_BIOS(3))   /* identical to 363968.01 */
698   ROM_SYSTEM_BIOS(3, "kick31",  "Kickstart 3.1 (40.63)")
699   ROMX_LOAD("kick40063.u6", 0x000000, 0x080000, CRC(fc24ae0d) SHA1(3b7f1493b27e212830f989f26ca76c02049f09ca), ROM_GROUPWORD | ROM_BIOS(4))   /* part number? */
700
701   /* action replay cartridge */
702   ROM_REGION16_BE(0x080000, "user2", ROMREGION_ERASEFF )
703   ROM_CART_LOAD("cart", 0x0000, 0x080000, ROM_NOMIRROR | ROM_OPTIONAL)
704
705   /* keyboard controller, mos 6500/1 mcu */
706   ROM_REGION(0x800, "keyboard", 0)
707   ROM_LOAD("328191-02.ic1", 0x000, 0x800, NO_DUMP)
708ROM_END
709
710#define rom_a500p    rom_a500n
711
712
713ROM_START( a1000n )
714   ROM_REGION16_BE(0x080000, "user1", 0)
715   ROM_LOAD16_BYTE("252179-01.u5n", 0x000000, 0x001000, CRC(42553bc4) SHA1(8855a97f7a44e3f62d1c88d938fee1f4c606af5b))
716   ROM_LOAD16_BYTE("252180-01.u5p", 0x000001, 0x001000, CRC(8e5b9a37) SHA1(d10f1564b99f5ffe108fa042362e877f569de2c3))
717
718   /* keyboard controller, mos 6500/1 mcu */
719   ROM_REGION(0x800, "keyboard", 0)
720   ROM_LOAD("328191-01.bin", 0x000, 0x800, NO_DUMP)
721ROM_END
722
723#define rom_a1000p    rom_a1000n
724
725
726ROM_START( cdtv )
727   ROM_REGION16_BE(0x100000, "user1", 0)
728   ROM_LOAD16_BYTE("391008-01.u34", 0x000000, 0x020000, CRC(791cb14b) SHA1(277a1778924496353ffe56be68063d2a334360e4))
729   ROM_LOAD16_BYTE("391009-01.u35", 0x000001, 0x020000, CRC(accbbc2e) SHA1(41b06d1679c6e6933c3378b7626025f7641ebc5c))
730   ROM_COPY("user1", 0x000000, 0x040000, 0x040000)
731   ROMX_LOAD(      "315093-02.u13", 0x080000, 0x040000, CRC(c4f0f55f) SHA1(891e9a547772fe0c6c19b610baf8bc4ea7fcb785), ROM_GROUPWORD)
732   ROM_COPY("user1", 0x080000, 0x0c0000, 0x040000)
733
734   /* remote control input converter, mos 6500/1 mcu */
735   ROM_REGION(0x800, "rcmcu", 0)
736   ROM_LOAD("252609-02.u75", 0x000, 0x800, NO_DUMP)
737
738   /* lcd controller, sanyo lc6554h */
739   ROM_REGION(0x1000, "lcd", 0)
740   ROM_LOAD("252608-01.u62", 0x000, 0x1000, NO_DUMP)
741ROM_END
742
743/***************************************************************************
744    GAME DRIVERS
745***************************************************************************/
746
747/*    YEAR  NAME    PARENT  COMPAT  MACHINE INPUT   INIT    COMPANY                             FULLNAME                 FLAGS */
748COMP( 1985, a1000n, 0,      0,      a1000n, amiga,  amiga,  "Commodore Business Machines",  "Amiga 1000 (NTSC)",     GAME_IMPERFECT_GRAPHICS )
749COMP( 1985, a1000p, a1000n, 0,      a1000p, amiga,  amiga,  "Commodore Business Machines",  "Amiga 1000 (PAL)",      GAME_IMPERFECT_GRAPHICS )
750COMP( 1987, a500n,  0,      0,      a500n,  amiga,  amiga,  "Commodore Business Machines",  "Amiga 500 (NTSC, OCS)", GAME_IMPERFECT_GRAPHICS )
751COMP( 1987, a500p,  a500n,  0,      a500p,  amiga,  amiga,  "Commodore Business Machines",  "Amiga 500 (PAL, OCS)",  GAME_IMPERFECT_GRAPHICS )
752COMP( 1991, cdtv,   0,      0,      cdtv,   cdtv,   cdtv,   "Commodore Business Machines",  "CDTV (NTSC)",           GAME_IMPERFECT_GRAPHICS )
src/mame/drivers/a7000.c
r11531r11532
1/***************************************************************************
2
3    Acorn Archimedes 7000/7000+
4
5    preliminary driver by Angelo Salese,
6    based on work by Tomasz Slanina and Tom Walker
7
8    ???
9    bp (0382827C) (second trigger)
10    do R13 = SR13
11
12****************************************************************************/
13
14#include "emu.h"
15#include "cpu/arm7/arm7.h"
16#include "cpu/arm7/arm7core.h"
17
18
19class a7000_state : public driver_device
20{
21public:
22   a7000_state(const machine_config &mconfig, device_type type, const char *tag)
23      : driver_device(mconfig, type, tag) { }
24
25   UINT8 m_vidc20_pal_index;
26   UINT16 m_vidc20_horz_reg[0x10];
27   UINT16 m_vidc20_vert_reg[0x10];
28   UINT8 m_vidc20_bpp_mode;
29   emu_timer *m_flyback_timer;
30   UINT16 m_timer_in[2];
31   UINT16 m_timer_out[2];
32   int m_timer_counter[2];
33   emu_timer *m_IOMD_timer[2];
34   UINT8 m_IRQ_status_A;
35   UINT8 m_IRQ_mask_A;
36   UINT8 m_IOMD_IO_ctrl;
37   UINT8 m_IOMD_keyb_ctrl;
38   UINT16 m_io_id;
39   UINT8 m_viddma_status;
40   UINT32 m_viddma_addr_start;
41   UINT32 m_viddma_addr_end;
42   UINT8 m_t0readinc;
43   UINT8 m_t1readinc;
44};
45
46
47/*
48 *
49 * VIDC20 chip emulation
50 *
51 */
52
53
54static const char *const vidc20_regnames[] =
55{
56   "Video Palette",               // 0
57   "Video Palette Address",         // 1
58   "RESERVED",                   // 2
59   "LCD offset",                  // 3
60   "Border Colour",               // 4
61   "Cursor Palette Logical Colour 1",   // 5
62   "Cursor Palette Logical Colour 2",   // 6
63   "Cursor Palette Logical Colour 3",   // 7
64   "Horizontal",                  // 8
65   "Vertical",                     // 9
66   "Stereo Image",                  // A
67   "Sound",                     // B
68   "External",                     // C
69   "Frequency Synthesis",            // D
70   "Control",                     // E
71   "Data Control"                  // F
72};
73
74static const char *const vidc20_horz_regnames[] =
75{
76   "Horizontal Cycle",             // 0x80 HCR
77   "Horizontal Sync Width",         // 0x81 HSWR
78   "Horizontal Border Start",         // 0x82 HBSR
79   "Horizontal Display Start",         // 0x83 HDSR
80   "Horizontal Display End",         // 0x84 HDER
81   "Horizontal Border End",         // 0x85 HBER
82   "Horizontal Cursor Start",         // 0x86 HCSR
83   "Horizontal Interlace",          // 0x87 HIR
84   "Horizontal Counter TEST",         // 0x88
85   "Horizontal <UNDEFINED>",         // 0x89
86   "Horizontal <UNDEFINED>",         // 0x8a
87   "Horizontal <UNDEFINED>",         // 0x8b
88   "Horizontal All TEST",            // 0x8c
89   "Horizontal <UNDEFINED>",         // 0x8d
90   "Horizontal <UNDEFINED>",         // 0x8e
91   "Horizontal <UNDEFINED>"         // 0x8f
92};
93
94#define HCR  0
95#define HSWR 1
96#define HBSR 2
97#define HDSR 3
98#define HDER 4
99#define HBER 5
100#define HCSR 6
101#define HIR  7
102
103static const char *const vidc20_vert_regnames[] =
104{
105   "Vertical Cycle",               // 0x90 VCR
106   "Vertical Sync Width",            // 0x91 VSWR
107   "Vertical Border Start",         // 0x92 VBSR
108   "Vertical Display Start",         // 0x93 VDSR
109   "Vertical Display End",          // 0x94 VDER
110   "Vertical Border End",            // 0x95 VBER
111   "Vertical Cursor Start",         // 0x96 VCSR
112   "Vertical Cursor End",            // 0x97 VCER
113   "Vertical Counter TEST",         // 0x98
114   "Horizontal <UNDEFINED>",         // 0x99
115   "Vertical Counter Increment TEST",   // 0x9a
116   "Horizontal <UNDEFINED>",         // 0x9b
117   "Vertical All TEST",            // 0x9c
118   "Horizontal <UNDEFINED>",         // 0x9d
119   "Horizontal <UNDEFINED>",         // 0x9e
120   "Horizontal <UNDEFINED>"         // 0x9f
121};
122
123#define VCR  0
124#define VSWR 1
125#define VBSR 2
126#define VDSR 3
127#define VDER 4
128#define VBER 5
129#define VCSR 6
130#define VCER 7
131
132static void vidc20_dynamic_screen_change(running_machine &machine)
133{
134   a7000_state *state = machine.driver_data<a7000_state>();
135   /* sanity checks - first pass */
136   /*
137    total cycles + border start/end
138    */
139   if(state->m_vidc20_horz_reg[HCR] && state->m_vidc20_horz_reg[HBSR] && state->m_vidc20_horz_reg[HBER] &&
140      state->m_vidc20_vert_reg[VCR] && state->m_vidc20_vert_reg[VBSR] && state->m_vidc20_vert_reg[VBER])
141   {
142      /* sanity checks - second pass */
143      /*
144        total cycles > border end > border start
145        */
146      if((state->m_vidc20_horz_reg[HCR] > state->m_vidc20_horz_reg[HBER]) &&
147         (state->m_vidc20_horz_reg[HBER] > state->m_vidc20_horz_reg[HBSR]) &&
148         (state->m_vidc20_vert_reg[VCR] > state->m_vidc20_vert_reg[VBER]) &&
149         (state->m_vidc20_vert_reg[VBER] > state->m_vidc20_vert_reg[VBSR]))
150      {
151         /* finally ready to change the resolution */
152         int hblank_period,vblank_period;
153         rectangle visarea = machine.primary_screen->visible_area();
154         hblank_period = (state->m_vidc20_horz_reg[HCR] & 0x3ffc);
155         vblank_period = (state->m_vidc20_vert_reg[VCR] & 0x3fff);
156         /* note that we use the border registers as the visible area */
157         visarea.min_x = (state->m_vidc20_horz_reg[HBSR] & 0x3ffe);
158         visarea.max_x = (state->m_vidc20_horz_reg[HBER] & 0x3ffe)-1;
159         visarea.min_y = (state->m_vidc20_vert_reg[VBSR] & 0x1fff);
160         visarea.max_y = (state->m_vidc20_vert_reg[VBER] & 0x1fff)-1;
161
162         machine.primary_screen->configure(hblank_period, vblank_period, visarea, machine.primary_screen->frame_period().attoseconds );
163         logerror("VIDC20: successfully changed the screen to:\n Display Size = %d x %d\n Border Size %d x %d\n Cycle Period %d x %d\n",
164                    (state->m_vidc20_horz_reg[HDER]-state->m_vidc20_horz_reg[HDSR]),(state->m_vidc20_vert_reg[VDER]-state->m_vidc20_vert_reg[VDSR]),
165                    (state->m_vidc20_horz_reg[HBER]-state->m_vidc20_horz_reg[HBSR]),(state->m_vidc20_vert_reg[VBER]-state->m_vidc20_vert_reg[VBSR]),
166                    hblank_period,vblank_period);
167      }
168   }
169}
170
171static WRITE32_HANDLER( a7000_vidc20_w )
172{
173   a7000_state *state = space->machine().driver_data<a7000_state>();
174   int reg = data >> 28;
175
176   switch(reg)
177   {
178      case 0: // Video Palette
179      {
180         int r,g,b;
181
182         r = (data & 0x0000ff) >> 0;
183         g = (data & 0x00ff00) >> 8;
184         b = (data & 0xff0000) >> 16;
185
186         palette_set_color_rgb(space->machine(),state->m_vidc20_pal_index & 0xff,r,g,b);
187
188         /* auto-increment & wrap-around */
189         state->m_vidc20_pal_index++;
190         state->m_vidc20_pal_index &= 0xff;
191      }
192      break;
193      case 1: // Video Palette Address
194      {
195         // according to RPCEmu, these mustn't be set
196         if (data & 0x0fffff00)
197            return;
198
199         state->m_vidc20_pal_index = data & 0xff;
200      }
201      break;
202
203      case 4: // Border Color
204      {
205         int r,g,b;
206
207         r = (data & 0x0000ff) >> 0;
208         g = (data & 0x00ff00) >> 8;
209         b = (data & 0xff0000) >> 16;
210
211         palette_set_color_rgb(space->machine(),0x100,r,g,b);
212      }
213      break;
214      case 5: // Cursor Palette Logical Colour n
215      case 6:
216      case 7:
217      {
218         int r,g,b;
219         int cursor_index = 0x100 + reg - 4; // 0x101,0x102 and 0x103 (plus 0x100 of above, 2bpp)
220
221         r = (data & 0x0000ff) >> 0;
222         g = (data & 0x00ff00) >> 8;
223         b = (data & 0xff0000) >> 16;
224
225         palette_set_color_rgb(space->machine(),cursor_index,r,g,b);
226      }
227      break;
228      case 8: // Horizontal
229      {
230         int horz_reg;
231
232         horz_reg = (data >> 24) & 0xf;
233         state->m_vidc20_horz_reg[horz_reg] = data & 0x3fff;
234         if(horz_reg == 0 || horz_reg == 2 || horz_reg == 5)
235            vidc20_dynamic_screen_change(space->machine());
236
237         // logerror("VIDC20: %s Register write = %08x (%d)\n",vidc20_horz_regnames[horz_reg],val,val);
238      }
239      break;
240      case 9: // Vertical
241      {
242         int vert_reg;
243
244         vert_reg = (data >> 24) & 0xf;
245         state->m_vidc20_vert_reg[vert_reg] = data & 0x1fff;
246         if(vert_reg == 0 || vert_reg == 2 || vert_reg == 5)
247            vidc20_dynamic_screen_change(space->machine());
248
249         if(vert_reg == 4)
250         {
251            if(state->m_vidc20_vert_reg[VDER] != 0)
252               state->m_flyback_timer->adjust(space->machine().primary_screen->time_until_pos(state->m_vidc20_vert_reg[VDER]));
253            else
254               state->m_flyback_timer->adjust(attotime::never);
255         }
256
257         // logerror("VIDC20: %s Register write = %08x (%d)\n",vidc20_vert_regnames[vert_reg],val,val);
258
259      }
260      break;
261      case 0x0e: // Control
262      {
263         state->m_vidc20_bpp_mode = (data & 0xe0) >> 5;
264      }
265      break;
266      default: logerror("VIDC20: %s Register write = %08x\n",vidc20_regnames[reg],data & 0xfffffff);
267   }
268}
269
270static VIDEO_START( a7000 )
271{
272}
273
274static SCREEN_UPDATE( a7000 )
275{
276   a7000_state *state = screen->machine().driver_data<a7000_state>();
277   int x_size,y_size,x_start,y_start;
278   int x,y,xi;
279   UINT32 count;
280   UINT8 *vram = screen->machine().region("vram")->base();
281
282   bitmap_fill(bitmap, cliprect, screen->machine().pens[0x100]);
283
284   x_size = (state->m_vidc20_horz_reg[HDER]-state->m_vidc20_horz_reg[HDSR]);
285   y_size = (state->m_vidc20_vert_reg[VDER]-state->m_vidc20_vert_reg[VDSR]);
286   x_start = state->m_vidc20_horz_reg[HDSR];
287   y_start = state->m_vidc20_vert_reg[VDSR];
288
289   /* check if display is enabled */
290   if(x_size <= 0 || y_size <= 0)
291      return 0;
292
293//  popmessage("%d",state->m_vidc20_bpp_mode);
294
295   count = 0;
296
297   switch(state->m_vidc20_bpp_mode)
298   {
299      case 0: /* 1 bpp */
300      {
301         for(y=0;y<y_size;y++)
302         {
303            for(x=0;x<x_size;x+=8)
304            {
305               for(xi=0;xi<8;xi++)
306                  *BITMAP_ADDR32(bitmap, y+y_start, x+xi+x_start) = screen->machine().pens[(vram[count]>>(xi))&1];
307
308               count++;
309            }
310         }
311      }
312      break;
313      case 1: /* 2 bpp */
314      {
315         for(y=0;y<y_size;y++)
316         {
317            for(x=0;x<x_size;x+=4)
318            {
319               for(xi=0;xi<4;xi++)
320                  *BITMAP_ADDR32(bitmap, y+y_start, x+xi+x_start) = screen->machine().pens[(vram[count]>>(xi*2))&3];
321
322               count++;
323            }
324         }
325      }
326      break;
327      case 2: /* 4 bpp */
328      {
329         for(y=0;y<y_size;y++)
330         {
331            for(x=0;x<x_size;x+=2)
332            {
333               for(xi=0;xi<2;xi++)
334                  *BITMAP_ADDR32(bitmap, y+y_start, x+xi+x_start) = screen->machine().pens[(vram[count]>>(xi*4))&0xf];
335
336               count++;
337            }
338         }
339      }
340      break;
341      case 3: /* 8 bpp */
342      {
343         for(y=0;y<y_size;y++)
344         {
345            for(x=0;x<x_size;x++)
346            {
347               *BITMAP_ADDR32(bitmap, y+y_start, x+x_start) = screen->machine().pens[(vram[count])&0xff];
348
349               count++;
350            }
351         }
352      }
353      break;
354      case 4: /* 16 bpp */
355      {
356         for(y=0;y<y_size;y++)
357         {
358            for(x=0;x<x_size;x++)
359            {
360               int r,g,b,pen;
361
362               pen = ((vram[count]<<8)|(vram[count+1]))&0xffff;
363               r = (pen & 0x000f);
364               g = (pen & 0x00f0) >> 4;
365               b = (pen & 0x0f00) >> 8;
366               r = (r << 4) | (r & 0xf);
367               g = (g << 4) | (g & 0xf);
368               b = (b << 4) | (b & 0xf);
369
370               *BITMAP_ADDR32(bitmap, y+y_start, x+x_start) =  b | g << 8 | r << 16;
371
372               count+=2;
373            }
374         }
375      }
376      break;
377      case 6: /* 32 bpp */
378      {
379         for(y=0;y<y_size;y++)
380         {
381            for(x=0;x<x_size;x++)
382            {
383               int r,g,b,pen;
384
385               pen = ((vram[count]<<24)|(vram[count+1]<<16)|(vram[count+2]<<8)|(vram[count+3]<<0));
386               r = (pen & 0x0000ff);
387               g = (pen & 0x00ff00) >> 8;
388               b = (pen & 0xff0000) >> 16;
389
390               *BITMAP_ADDR32(bitmap, y+y_start, x+x_start) =  b | g << 8 | r << 16;
391
392               count+=4;
393            }
394         }
395      }
396      break;
397      default:
398         //fatalerror("VIDC20 %08x BPP mode not supported\n",state->m_vidc20_bpp_mode);
399         break;
400   }
401
402    return 0;
403}
404
405/*
406*
407* IOMD / ARM7500 / ARM7500FE chip emulation
408*
409*/
410
411/* TODO: some of these registers are actually ARM7500 specific */
412static const char *const iomd_regnames[] =
413{
414   "I/O Control",                  // 0x000 IOCR
415   "Keyboard Data",               // 0x004 KBDDAT
416   "Keyboard Control",               // 0x008 KBDCR
417   "General Purpose I/O Lines",      // 0x00c IOLINES
418   "IRQA Status",                  // 0x010 IRQSTA
419   "IRQA Request/clear",            // 0x014 IRQRQA
420   "IRQA Mask",                  // 0x018 IRQMSKA
421   "Enter SUSPEND Mode",            // 0x01c SUSMODE
422   "IRQB Status",                  // 0x020 IRQSTB
423   "IRQB Request/clear",            // 0x024 IRQRQB
424   "IRQB Mask",                  // 0x028 IRQMSKB
425   "Enter STOP Mode",               // 0x02c STOPMODE
426   "FIQ Status",                  // 0x030 FIQST
427   "FIQ Request/clear",            // 0x034 FIQRQ
428   "FIQ Mask",                     // 0x038 FIQMSK
429   "Clock divider control",         // 0x03c CLKCTL
430   "Timer 0 Low Bits",               // 0x040 T0LOW
431   "Timer 0 High Bits",            // 0x044 T0HIGH
432   "Timer 0 Go Command",            // 0x048 T0GO
433   "Timer 0 Latch Command",         // 0x04c T0LATCH
434   "Timer 1 Low Bits",               // 0x050 T1LOW
435   "Timer 1 High Bits",            // 0x054 T1HIGH
436   "Timer 1 Go Command",            // 0x058 T1GO
437   "Timer 1 Latch Command",         // 0x05c T1LATCH
438   "IRQC Status",                  // 0x060 IRQSTC
439   "IRQC Request/clear",            // 0x064 IRQRQC
440   "IRQC Mask",                  // 0x068 IRQMSKC
441   "LCD and IIS Control Bits",         // 0x06c VIDIMUX
442   "IRQD Status",                  // 0x070 IRQSTD
443   "IRQD Request/clear",            // 0x074 IRQRQD
444   "IRQD Mask",                  // 0x078 IRQMSKD
445   "<RESERVED>",                  // 0x07c
446   "ROM Control Bank 0",            // 0x080 ROMCR0
447   "ROM Control Bank 1",            // 0x084 ROMCR1
448   "DRAM Control (IOMD)",            // 0x088 DRAMCR
449   "VRAM and Refresh Control",         // 0x08c VREFCR
450   "Flyback Line Size",            // 0x090 FSIZE
451   "Chip ID no. Low Byte",            // 0x094 ID0
452   "Chip ID no. High Byte",         // 0x098 ID1
453   "Chip Version Number",            // 0x09c VERSION
454   "Mouse X Position",               // 0x0a0 MOUSEX
455   "Mouse Y Position",               // 0x0a4 MOUSEY
456   "Mouse Data",                  // 0x0a8 MSEDAT
457   "Mouse Control",               // 0x0ac MSECR
458   "<RESERVED>",                  // 0x0b0
459   "<RESERVED>",                  // 0x0b4
460   "<RESERVED>",                  // 0x0b8
461   "<RESERVED>",                  // 0x0bc
462   "DACK Timing Control",            // 0x0c0 DMATCR
463   "I/O Timing Control",            // 0x0c4 IOTCR
464   "Expansion Card Timing",         // 0x0c8 ECTCR
465   "DMA External Control",            // 0x0cc DMAEXT (IOMD) / ASTCR (ARM7500)
466   "DRAM Width Control",            // 0x0d0 DRAMWID
467   "Force CAS/RAS Lines Low",         // 0x0d4 SELFREF
468   "<RESERVED>",                  // 0x0d8
469   "<RESERVED>",                  // 0x0dc
470   "A to D IRQ Control",            // 0x0e0 ATODICR
471   "A to D IRQ Status",            // 0x0e4 ATODCC
472   "A to D IRQ Converter Control",      // 0x0e8 ATODICR
473   "A to D IRQ Counter 1",            // 0x0ec ATODCNT1
474   "A to D IRQ Counter 2",            // 0x0f0 ATODCNT2
475   "A to D IRQ Counter 3",            // 0x0f4 ATODCNT3
476   "A to D IRQ Counter 4",            // 0x0f8 ATODCNT4
477   "<RESERVED>",                  // 0x0fc
478   "I/O DMA 0 CurA",               // 0x100 IO0CURA
479   "I/O DMA 0 EndA",               // 0x104 IO0ENDA
480   "I/O DMA 0 CurB",               // 0x108 IO0CURB
481   "I/O DMA 0 EndB",               // 0x10c IO0ENDB
482   "I/O DMA 0 Control",            // 0x110 IO0CR
483   "I/O DMA 0 Status",               // 0x114 IO0ST
484   "<RESERVED>",                  // 0x118
485   "<RESERVED>",                  // 0x11c
486   "I/O DMA 1 CurA",               // 0x120 IO1CURA
487   "I/O DMA 1 EndA",               // 0x124 IO1ENDA
488   "I/O DMA 1 CurB",               // 0x128 IO1CURB
489   "I/O DMA 1 EndB",               // 0x12c IO1ENDB
490   "I/O DMA 1 Control",            // 0x130 IO1CR
491   "I/O DMA 1 Status",               // 0x134 IO1ST
492   "<RESERVED>",                  // 0x138
493   "<RESERVED>",                  // 0x13c
494   "I/O DMA 2 CurA",               // 0x140 IO2CURA
495   "I/O DMA 2 EndA",               // 0x144 IO2ENDA
496   "I/O DMA 2 CurB",               // 0x148 IO2CURB
497   "I/O DMA 2 EndB",               // 0x14c IO2ENDB
498   "I/O DMA 2 Control",            // 0x150 IO2CR
499   "I/O DMA 2 Status",               // 0x154 IO2ST
500   "<RESERVED>",                  // 0x158
501   "<RESERVED>",                  // 0x15c
502   "I/O DMA 3 CurA",               // 0x160 IO3CURA
503   "I/O DMA 3 EndA",               // 0x164 IO3ENDA
504   "I/O DMA 3 CurB",               // 0x168 IO3CURB
505   "I/O DMA 3 EndB",               // 0x16c IO3ENDB
506   "I/O DMA 3 Control",            // 0x170 IO3CR
507   "I/O DMA 3 Status",               // 0x174 IO3ST
508   "<RESERVED>",                  // 0x178
509   "<RESERVED>",                  // 0x17c
510   "Sound DMA 0 CurA",               // 0x180 SD0CURA
511   "Sound DMA 0 EndA",               // 0x184 SD0ENDA
512   "Sound DMA 0 CurB",               // 0x188 SD0CURB
513   "Sound DMA 0 EndB",               // 0x18c SD0ENDB
514   "Sound DMA 0 Control",            // 0x190 SD0CR
515   "Sound DMA 0 Status",            // 0x194 SD0ST
516   "<RESERVED>",                  // 0x198
517   "<RESERVED>",                  // 0x19c
518   "Sound DMA 1 CurA",               // 0x1a0 SD1CURA
519   "Sound DMA 1 EndA",               // 0x1a4 SD1ENDA
520   "Sound DMA 1 CurB",               // 0x1a8 SD1CURB
521   "Sound DMA 1 EndB",               // 0x1ac SD1ENDB
522   "Sound DMA 1 Control",            // 0x1b0 SD1CR
523   "Sound DMA 1 Status",            // 0x1b4 SD1ST
524   "<RESERVED>",                  // 0x1b8
525   "<RESERVED>",                  // 0x1bc
526   "Cursor DMA Current",            // 0x1c0 CURSCUR
527   "Cursor DMA Init",               // 0x1c4 CURSINIT
528   "Duplex LCD Current B",            // 0x1c8 VIDCURB
529   "<RESERVED>",                  // 0x1cc
530   "Video DMA Current",            // 0x1d0 VIDCUR
531   "Video DMA End",               // 0x1d4 VIDEND
532   "Video DMA Start",               // 0x1d8 VIDSTART
533   "Video DMA Init",               // 0x1dc VIDINIT
534   "Video DMA Control",            // 0x1e0 VIDCR
535   "<RESERVED>",                  // 0x1e4
536   "Duplex LCD Init B",            // 0x1e8 VIDINITB
537   "<RESERVED>",                  // 0x1ec
538   "DMA IRQ Status",               // 0x1f0 DMAST
539   "DMA IRQ Request",               // 0x1f4 DMARQ
540   "DMA IRQ Mask",                  // 0x1f8 DMAMSK
541   "<RESERVED>"                  // 0x1fc
542};
543
544#define IOMD_IOCR      0x000/4
545#define IOMD_KBDDAT      0x004/4
546#define IOMD_KBDCR      0x008/4
547
548#define IOMD_IRQSTA      0x010/4
549#define IOMD_IRQRQA    0x014/4
550#define IOMD_IRQMSKA   0x018/4
551
552#define IOMD_T0LOW      0x040/4
553#define IOMD_T0HIGH    0x044/4
554#define IOMD_T0GO      0x048/4
555#define IOMD_T0LATCH   0x04c/4
556
557#define IOMD_T1LOW      0x050/4
558#define IOMD_T1HIGH    0x054/4
559#define IOMD_T1GO      0x058/4
560#define IOMD_T1LATCH   0x05c/4
561
562#define IOMD_ID0      0x094/4
563#define IOMD_ID1      0x098/4
564#define IOMD_VERSION   0x09c/4
565
566#define IOMD_VIDCUR      0x1d0/4
567#define IOMD_VIDEND      0x1d4/4
568#define IOMD_VIDSTART   0x1d8/4
569#define IOMD_VIDINIT   0x1dc/4
570#define IOMD_VIDCR      0x1e0/4
571
572
573
574static void fire_iomd_timer(a7000_state *state, int timer)
575{
576   int timer_count = state->m_timer_counter[timer];
577   int val = timer_count / 2; // correct?
578
579   if(val==0)
580      state->m_IOMD_timer[timer]->adjust(attotime::never);
581   else
582      state->m_IOMD_timer[timer]->adjust(attotime::from_usec(val), 0, attotime::from_usec(val));
583}
584
585static TIMER_CALLBACK( IOMD_timer0_callback )
586{
587   a7000_state *state = machine.driver_data<a7000_state>();
588   state->m_IRQ_status_A|=0x20;
589   if(state->m_IRQ_mask_A&0x20)
590   {
591      generic_pulse_irq_line(machine.device("maincpu"), ARM7_IRQ_LINE);
592   }
593}
594
595static TIMER_CALLBACK( IOMD_timer1_callback )
596{
597   a7000_state *state = machine.driver_data<a7000_state>();
598   state->m_IRQ_status_A|=0x40;
599   if(state->m_IRQ_mask_A&0x40)
600   {
601      generic_pulse_irq_line(machine.device("maincpu"), ARM7_IRQ_LINE);
602   }
603}
604
605static TIMER_CALLBACK( flyback_timer_callback )
606{
607   a7000_state *state = machine.driver_data<a7000_state>();
608   state->m_IRQ_status_A|=0x08;
609   if(state->m_IRQ_mask_A&0x08)
610   {
611      generic_pulse_irq_line(machine.device("maincpu"), ARM7_IRQ_LINE);
612   }
613
614   state->m_flyback_timer->adjust(machine.primary_screen->time_until_pos(state->m_vidc20_vert_reg[VDER]));
615}
616
617static void viddma_transfer_start(address_space *space)
618{
619   a7000_state *state = space->machine().driver_data<a7000_state>();
620   UINT32 src = state->m_viddma_addr_start;
621   UINT32 dst = 0;
622   UINT32 size = state->m_viddma_addr_end;
623   UINT32 dma_index;
624   UINT8 *vram = space->machine().region("vram")->base();
625
626   /* TODO: this should actually be a qword transfer */
627   for(dma_index = 0;dma_index < size;dma_index++)
628   {
629      vram[dst] = space->read_byte(src);
630
631      src++;
632      dst++;
633   }
634}
635
636static READ32_HANDLER( a7000_iomd_r )
637{
638   a7000_state *state = space->machine().driver_data<a7000_state>();
639//  if(offset != IOMD_KBDCR)
640//      logerror("IOMD: %s Register (%04x) read\n",iomd_regnames[offset & (0x1ff >> 2)],offset*4);
641
642
643   switch(offset)
644   {
645      case IOMD_IOCR:
646      {
647         UINT8 flyback;
648         int vert_pos;
649
650         vert_pos = space->machine().primary_screen->vpos();
651         flyback = (vert_pos <= state->m_vidc20_vert_reg[VDSR] || vert_pos >= state->m_vidc20_vert_reg[VDER]) ? 0x80 : 0x00;
652
653         return state->m_IOMD_IO_ctrl | 0x34 | flyback;
654      }
655      case IOMD_KBDCR:   return state->m_IOMD_keyb_ctrl | 0x80; //IOMD Keyb status
656
657      /*
658        1--- ---- always high
659        -x-- ---- Timer 1
660        --x- ---- Timer 0
661        ---x ---- Power On Reset
662        ---- x--- Flyback
663        ---- -x-- nINT1
664        ---- --0- always low
665        ---- ---x INT2
666        */
667      case IOMD_IRQSTA:   return (state->m_IRQ_status_A & ~2) | 0x80;
668      case IOMD_IRQRQA:   return (state->m_IRQ_status_A & state->m_IRQ_mask_A) | 0x80;
669      case IOMD_IRQMSKA:   return (state->m_IRQ_mask_A);
670
671      case IOMD_T0LOW:   return state->m_timer_out[0] & 0xff;
672      case IOMD_T0HIGH:   return (state->m_timer_out[0] >> 8) & 0xff;
673
674      case IOMD_T1LOW:   return state->m_timer_out[1] & 0xff;
675      case IOMD_T1HIGH:   return (state->m_timer_out[1] >> 8) & 0xff;
676
677      case IOMD_ID0:      return state->m_io_id & 0xff; // IOMD ID low
678      case IOMD_ID1:      return (state->m_io_id >> 8) & 0xff; // IOMD ID high
679      case IOMD_VERSION:   return 0;
680
681      case IOMD_VIDEND:   return (state->m_viddma_addr_end & 0x00fffff8); //bits 31:24 undefined
682      case IOMD_VIDSTART: return (state->m_viddma_addr_start & 0x1ffffff8); //bits 31, 30, 29 undefined
683      case IOMD_VIDCR:   return (state->m_viddma_status & 0xa0) | 0x50; //bit 6 = DRAM mode, bit 4 = QWORD transfer
684
685      default:   logerror("IOMD: %s Register (%04x) read\n",iomd_regnames[offset & (0x1ff >> 2)],offset*4); break;
686   }
687
688   return 0;
689}
690
691static WRITE32_HANDLER( a7000_iomd_w )
692{
693   a7000_state *state = space->machine().driver_data<a7000_state>();
694//  logerror("IOMD: %s Register (%04x) write = %08x\n",iomd_regnames[offset & (0x1ff >> 2)],offset*4,data);
695
696   switch(offset)
697   {
698      case IOMD_IOCR:      state->m_IOMD_IO_ctrl = data & ~0xf4; break;
699
700      case IOMD_KBDCR:
701         state->m_IOMD_keyb_ctrl = data & ~0xf4;
702         //keyboard_ctrl_write(data & 0x08);
703         break;
704
705      case IOMD_IRQRQA:   state->m_IRQ_status_A &= ~data; break;
706      case IOMD_IRQMSKA:   state->m_IRQ_mask_A = (data & ~2) | 0x80; break;
707
708      case IOMD_T0LOW:   state->m_timer_in[0] = (state->m_timer_in[0] & 0xff00) | (data & 0xff); break;
709      case IOMD_T0HIGH:   state->m_timer_in[0] = (state->m_timer_in[0] & 0x00ff) | ((data & 0xff) << 8); break;
710      case IOMD_T0GO:
711         state->m_timer_counter[0] = state->m_timer_in[0];
712         fire_iomd_timer(state,0);
713         break;
714      case IOMD_T0LATCH:
715         {
716            state->m_t0readinc^=1;
717            state->m_timer_out[0] = state->m_timer_counter[0];
718            if(state->m_t0readinc)
719            {
720               state->m_timer_counter[0]--;
721               if(state->m_timer_counter[0] < 0)
722                  state->m_timer_counter[0]+= state->m_timer_in[0];
723            }
724         }
725         break;
726
727      case IOMD_T1LOW:   state->m_timer_in[1] = (state->m_timer_in[1] & 0xff00) | (data & 0xff); break;
728      case IOMD_T1HIGH:   state->m_timer_in[1] = (state->m_timer_in[1] & 0x00ff) | ((data & 0xff) << 8); break;
729      case IOMD_T1GO:
730         state->m_timer_counter[1] = state->m_timer_in[1];
731         fire_iomd_timer(state,1);
732         break;
733      case IOMD_T1LATCH:
734         {
735            state->m_t1readinc^=1;
736            state->m_timer_out[1] = state->m_timer_counter[1];
737            if(state->m_t1readinc)
738            {
739               state->m_timer_counter[1]--;
740               if(state->m_timer_counter[1] < 0)
741                  state->m_timer_counter[1]+= state->m_timer_in[1];
742            }
743         }
744         break;
745
746      case IOMD_VIDEND:   state->m_viddma_addr_end = data & 0x00fffff8; //bits 31:24 unused
747      case IOMD_VIDSTART: state->m_viddma_addr_start = data & 0x1ffffff8; //bits 31, 30, 29 unused
748      case IOMD_VIDCR:
749         state->m_viddma_status = data & 0xa0; if(data & 0x20) { viddma_transfer_start(space); }
750         break;
751
752
753      default: logerror("IOMD: %s Register (%04x) write = %08x\n",iomd_regnames[offset & (0x1ff >> 2)],offset*4,data);
754   }
755}
756
757static ADDRESS_MAP_START( a7000_mem, AS_PROGRAM, 32)
758   AM_RANGE(0x00000000, 0x003fffff) AM_MIRROR(0x00800000) AM_ROM AM_REGION("user1", 0x0)
759//  AM_RANGE(0x01000000, 0x01ffffff) AM_NOP //expansion ROM
760//  AM_RANGE(0x02000000, 0x02ffffff) AM_RAM //VRAM
761//  I/O 03000000 - 033fffff
762//  AM_RANGE(0x03010000, 0x03011fff) //Super IO
763//  AM_RANGE(0x03012000, 0x03029fff) //FDC
764//  AM_RANGE(0x0302b000, 0x0302bfff) //Network podule
765//  AM_RANGE(0x03040000, 0x0304ffff) //podule space 0,1,2,3
766//  AM_RANGE(0x03070000, 0x0307ffff) //podule space 4,5,6,7
767   AM_RANGE(0x03200000, 0x032001ff) AM_READWRITE(a7000_iomd_r,a7000_iomd_w) //IOMD Registers //mirrored at 0x03000000-0x1ff?
768//  AM_RANGE(0x03310000, 0x03310003) //Mouse Buttons
769
770   AM_RANGE(0x03400000, 0x037fffff) AM_WRITE(a7000_vidc20_w)
771//  AM_RANGE(0x08000000, 0x08ffffff) AM_MIRROR(0x07000000) //EASI space
772   AM_RANGE(0x10000000, 0x13ffffff) AM_RAM //SIMM 0 bank 0
773   AM_RANGE(0x14000000, 0x17ffffff) AM_RAM //SIMM 0 bank 1
774//  AM_RANGE(0x18000000, 0x18ffffff) AM_MIRROR(0x03000000) AM_RAM //SIMM 1 bank 0
775//  AM_RANGE(0x1c000000, 0x1cffffff) AM_MIRROR(0x03000000) AM_RAM //SIMM 1 bank 1
776ADDRESS_MAP_END
777
778
779/* Input ports */
780static INPUT_PORTS_START( a7000 )
781INPUT_PORTS_END
782
783static MACHINE_START(a7000)
784{
785   a7000_state *state = machine.driver_data<a7000_state>();
786   state->m_IOMD_timer[0] = machine.scheduler().timer_alloc(FUNC(IOMD_timer0_callback));
787   state->m_IOMD_timer[1] = machine.scheduler().timer_alloc(FUNC(IOMD_timer1_callback));
788   state->m_flyback_timer = machine.scheduler().timer_alloc(FUNC(flyback_timer_callback));
789
790   state->m_io_id = 0xd4e7;
791}
792
793static MACHINE_RESET(a7000)
794{
795   a7000_state *state = machine.driver_data<a7000_state>();
796   state->m_IOMD_IO_ctrl = 0x0b | 0x34; //bit 0,1 and 3 set high on reset plus 2,4,5 always high
797//  state->m_IRQ_status_A = 0x10; // set POR bit ON
798   state->m_IRQ_mask_A = 0x00;
799
800   state->m_IOMD_keyb_ctrl = 0x00;
801
802   state->m_IOMD_timer[0]->adjust( attotime::never);
803   state->m_IOMD_timer[1]->adjust( attotime::never);
804   state->m_flyback_timer->adjust( attotime::never);
805}
806
807static MACHINE_CONFIG_START( a7000, a7000_state )
808
809   /* Basic machine hardware */
810   MCFG_CPU_ADD( "maincpu", ARM7, XTAL_32MHz )
811   MCFG_CPU_PROGRAM_MAP(a7000_mem)
812
813   MCFG_MACHINE_START( a7000 )
814   MCFG_MACHINE_RESET( a7000 )
815
816   /* video hardware */
817   MCFG_SCREEN_ADD("screen", RASTER)
818   MCFG_SCREEN_REFRESH_RATE(60)
819   MCFG_SCREEN_VBLANK_TIME(ATTOSECONDS_IN_USEC(2500)) /* not accurate */
820   MCFG_SCREEN_FORMAT(BITMAP_FORMAT_RGB32)
821   MCFG_SCREEN_SIZE(1900, 1080) //max available size
822   MCFG_SCREEN_VISIBLE_AREA(0, 1900-1, 0, 1080-1)
823   MCFG_SCREEN_UPDATE(a7000)
824   MCFG_PALETTE_LENGTH(0x200)
825//  MCFG_PALETTE_INIT(black_and_white)
826
827   MCFG_VIDEO_START(a7000)
828MACHINE_CONFIG_END
829
830static MACHINE_CONFIG_DERIVED( a7000p, a7000 )
831
832   MCFG_CPU_MODIFY("maincpu")
833   MCFG_CPU_CLOCK(XTAL_48MHz)
834MACHINE_CONFIG_END
835
836ROM_START(a7000)
837   ROM_REGION( 0x800000, "user1", ROMREGION_ERASEFF )
838   ROM_LOAD( "rom1.bin", 0x000000, 0x100000, CRC(ff0e3d12) SHA1(fa489bebede3d13dc43cddec5b5c9b6829a28914) )
839   ROM_LOAD( "rom2.bin", 0x100000, 0x100000, CRC(4ae4fd8b) SHA1(1b30d5905d5364dfa48bad69257b0ef8190e9bf6) )
840   ROM_LOAD( "rom3.bin", 0x200000, 0x100000, CRC(3108fb2b) SHA1(865b01583f3fb5f4ed5e9201676db327cdeb40b3) )
841   ROM_LOAD( "rom4.bin", 0x300000, 0x100000, CRC(55a51980) SHA1(a7191727edd5babf679ebbdea6585833a1fb34e6) )
842
843   ROM_REGION( 0x800000, "vram", ROMREGION_ERASE00 )
844ROM_END
845
846ROM_START(a7000p)
847   ROM_REGION( 0x800000, "user1", ROMREGION_ERASEFF )
848   ROM_LOAD( "riscos-3.71.rom", 0x000000, 0x400000, CRC(211cf888) SHA1(c5fe0645e48894fb4b245abeefdc9a65d659af59))
849
850   ROM_REGION( 0x800000, "vram", ROMREGION_ERASE00 )
851ROM_END
852
853/***************************************************************************
854
855  Game driver(s)
856
857***************************************************************************/
858
859/*    YEAR  NAME        PARENT  COMPAT  MACHINE     INPUT   INIT    COMPANY FULLNAME        FLAGS */
860COMP( 1995, a7000,      0,      0,      a7000,      a7000,   0,      "Acorn",  "Archimedes A7000",   GAME_NOT_WORKING | GAME_NO_SOUND )
861COMP( 1997, a7000p,     a7000,  0,      a7000p,     a7000,   0,      "Acorn",  "Archimedes A7000+",  GAME_NOT_WORKING | GAME_NO_SOUND )
src/mame/drivers/ami1200.c
r11531r11532
1/*
2    Amiga 1200
3
4    Preliminary MAME driver by Mariusz Wojcieszek
5    CD-ROM controller by Ernesto Corvi
6    Borrowed by incog for MESS
7
8    2009-05 Fabio Priuli:
9    Amiga 1200 support is just sketched (I basically took cd32 and removed Akiko). I connected
10    the floppy drive in the same way as in amiga.c but it seems to be not working, since I
11    tried to load WB3.1 with no success. However, this problem may be due to anything: maybe
12    the floppy code must be connected elsewhere, or the .adf image is broken, or I made some
13    stupid mistake in the CIA interfaces.
14    Later, it could be wise to re-factor this source and merge the non-AGA code with
15    mess/drivers/amiga.c
16*/
17
18#include "emu.h"
19#include "cpu/m68000/m68000.h"
20#include "machine/6526cia.h"
21#include "machine/i2cmem.h"
22#include "machine/amigafdc.h"
23#include "machine/amigakbd.h"
24
25#include "includes/amiga.h"
26#include "includes/cd32.h"
27
28
29
30class ami1200_state : public cd32_state
31{
32public:
33   ami1200_state(const machine_config &mconfig, device_type type, const char *tag)
34      : cd32_state(mconfig, type, tag) { }
35
36   UINT16 potgo_value;
37   int cd32_shifter[2];
38   int oldstate[2];
39};
40
41
42
43#define A1200PAL_XTAL_X1  XTAL_28_37516MHz
44#define A1200PAL_XTAL_X2  XTAL_4_433619MHz
45
46
47
48static void handle_cd32_joystick_cia(ami1200_state *state, UINT8 pra, UINT8 dra);
49
50static WRITE32_HANDLER( aga_overlay_w )
51{
52   if (ACCESSING_BITS_16_23)
53   {
54      data = (data >> 16) & 1;
55
56      /* switch banks as appropriate */
57      memory_set_bank(space->machine(), "bank1", data & 1);
58
59      /* swap the write handlers between ROM and bank 1 based on the bit */
60      if ((data & 1) == 0)
61         /* overlay disabled, map RAM on 0x000000 */
62         space->install_write_bank(0x000000, 0x1fffff, "bank1");
63      else
64         /* overlay enabled, map Amiga system ROM on 0x000000 */
65         space->unmap_write(0x000000, 0x1fffff);
66   }
67}
68
69/*************************************
70 *
71 *  CIA-A port A access:
72 *
73 *  PA7 = game port 1, pin 6 (fire)
74 *  PA6 = game port 0, pin 6 (fire)
75 *  PA5 = /RDY (disk ready)
76 *  PA4 = /TK0 (disk track 00)
77 *  PA3 = /WPRO (disk write protect)
78 *  PA2 = /CHNG (disk change)
79 *  PA1 = /LED (LED, 0=bright / audio filter control)
80 *  PA0 = MUTE
81 *
82 *************************************/
83
84static WRITE8_DEVICE_HANDLER( ami1200_cia_0_porta_w )
85{
86   ami1200_state *state = device->machine().driver_data<ami1200_state>();
87
88   /* bit 2 = Power Led on Amiga */
89   set_led_status(device->machine(), 0, !BIT(data, 1));
90
91   handle_cd32_joystick_cia(state, data, mos6526_r(device, 2));
92}
93
94/*************************************
95 *
96 *  CIA-A port B access:
97 *
98 *  PB7 = parallel data 7
99 *  PB6 = parallel data 6
100 *  PB5 = parallel data 5
101 *  PB4 = parallel data 4
102 *  PB3 = parallel data 3
103 *  PB2 = parallel data 2
104 *  PB1 = parallel data 1
105 *  PB0 = parallel data 0
106 *
107 *************************************/
108
109static READ8_DEVICE_HANDLER( ami1200_cia_0_portb_r )
110{
111   /* parallel port */
112   logerror("%s:CIA0_portb_r\n", device->machine().describe_context());
113   return 0xff;
114}
115
116static WRITE8_DEVICE_HANDLER( ami1200_cia_0_portb_w )
117{
118   /* parallel port */
119   logerror("%s:CIA0_portb_w(%02x)\n", device->machine().describe_context(), data);
120}
121
122static ADDRESS_MAP_START( a1200_map, AS_PROGRAM, 32 )
123   ADDRESS_MAP_UNMAP_HIGH
124   AM_RANGE(0x000000, 0x1fffff) AM_RAMBANK("bank1") AM_BASE_SIZE_MEMBER(cd32_state, m_chip_ram, m_chip_ram_size)
125   AM_RANGE(0xbfa000, 0xbfa003) AM_WRITE(aga_overlay_w)
126   AM_RANGE(0xbfd000, 0xbfefff) AM_READWRITE16(amiga_cia_r, amiga_cia_w, 0xffffffff)
127   AM_RANGE(0xc00000, 0xdfffff) AM_READWRITE16(amiga_custom_r, amiga_custom_w, 0xffffffff) AM_BASE_MEMBER(cd32_state, m_custom_regs)
128   AM_RANGE(0xe80000, 0xe8ffff) AM_READWRITE16(amiga_autoconfig_r, amiga_autoconfig_w, 0xffffffff)
129   AM_RANGE(0xf80000, 0xffffff) AM_ROM AM_REGION("user1", 0)   /* Kickstart */
130ADDRESS_MAP_END
131
132
133//int cd32_input_port_val = 0;
134//int cd32_input_select = 0;
135
136static void cd32_potgo_w(running_machine &machine, UINT16 data)
137{
138   ami1200_state *state = machine.driver_data<ami1200_state>();
139   int i;
140
141   state->m_potgo_value = state->m_potgo_value & 0x5500;
142   state->m_potgo_value |= data & 0xaa00;
143
144   for (i = 0; i < 8; i += 2)
145   {
146      UINT16 dir = 0x0200 << i;
147      if (data & dir)
148      {
149         UINT16 d = 0x0100 << i;
150         state->m_potgo_value &= ~d;
151         state->m_potgo_value |= data & d;
152      }
153   }
154   for (i = 0; i < 2; i++)
155   {
156      UINT16 p5dir = 0x0200 << (i * 4); /* output enable P5 */
157      UINT16 p5dat = 0x0100 << (i * 4); /* data P5 */
158      if ((state->m_potgo_value & p5dir) && (state->m_potgo_value & p5dat))
159         state->m_cd32_shifter[i] = 8;
160   }
161}
162
163static void handle_cd32_joystick_cia(ami1200_state *state, UINT8 pra, UINT8 dra)
164{
165   int i;
166
167   for (i = 0; i < 2; i++)
168   {
169      UINT8 but = 0x40 << i;
170      UINT16 p5dir = 0x0200 << (i * 4); /* output enable P5 */
171      UINT16 p5dat = 0x0100 << (i * 4); /* data P5 */
172      if (!(state->m_potgo_value & p5dir) || !(state->m_potgo_value & p5dat))
173      {
174         if ((dra & but) && (pra & but) != state->m_oldstate[i])
175         {
176            if (!(pra & but))
177            {
178               state->m_cd32_shifter[i]--;
179               if (state->m_cd32_shifter[i] < 0)
180                  state->m_cd32_shifter[i] = 0;
181            }
182         }
183      }
184      state->m_oldstate[i] = pra & but;
185   }
186}
187
188
189static INPUT_PORTS_START( a1200 )
190   PORT_START("CIA0PORTA")
191   PORT_BIT( 0x3f, IP_ACTIVE_LOW, IPT_SPECIAL )
192   PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_PLAYER(1)
193   PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_PLAYER(2)
194
195   PORT_START("CIA0PORTB")
196   PORT_BIT( 0xff, IP_ACTIVE_LOW, IPT_UNUSED )
197
198   PORT_START("JOY0DAT")
199   PORT_BIT( 0x0303, IP_ACTIVE_HIGH, IPT_SPECIAL ) PORT_CUSTOM(amiga_joystick_convert, "P1JOY")
200   PORT_BIT( 0xfcfc, IP_ACTIVE_HIGH, IPT_UNUSED )
201
202   PORT_START("JOY1DAT")
203   PORT_BIT( 0x0303, IP_ACTIVE_HIGH, IPT_SPECIAL ) PORT_CUSTOM(amiga_joystick_convert, "P2JOY")
204   PORT_BIT( 0xfcfc, IP_ACTIVE_HIGH, IPT_UNUSED )
205
206   PORT_START("POTGO")
207   PORT_BIT( 0x0100, IP_ACTIVE_LOW, IPT_UNUSED )
208   PORT_BIT( 0x0400, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_PLAYER(1)
209   PORT_BIT( 0x1000, IP_ACTIVE_LOW, IPT_UNUSED )
210   PORT_BIT( 0x4000, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_PLAYER(2)
211   PORT_BIT( 0xaaff, IP_ACTIVE_HIGH, IPT_UNUSED )
212
213   PORT_START("P1JOY")
214   PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_JOYSTICK_UP ) PORT_PLAYER(1)
215   PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_JOYSTICK_DOWN ) PORT_PLAYER(1)
216   PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_JOYSTICK_LEFT ) PORT_PLAYER(1)
217   PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_JOYSTICK_RIGHT ) PORT_PLAYER(1)
218
219   PORT_START("P2JOY")
220   PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_JOYSTICK_UP ) PORT_PLAYER(2)
221   PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_JOYSTICK_DOWN ) PORT_PLAYER(2)
222   PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_JOYSTICK_LEFT ) PORT_PLAYER(2)
223   PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_JOYSTICK_RIGHT ) PORT_PLAYER(2)
224
225   PORT_START("P0MOUSEX")
226   PORT_BIT( 0xff, 0x00, IPT_MOUSE_X) PORT_SENSITIVITY(100) PORT_KEYDELTA(5) PORT_MINMAX(0, 255) PORT_PLAYER(1)
227
228   PORT_START("P0MOUSEY")
229   PORT_BIT( 0xff, 0x00, IPT_MOUSE_Y) PORT_SENSITIVITY(100) PORT_KEYDELTA(5) PORT_MINMAX(0, 255) PORT_PLAYER(1)
230
231   PORT_START("P1MOUSEX")
232   PORT_BIT( 0xff, 0x00, IPT_MOUSE_X) PORT_SENSITIVITY(100) PORT_KEYDELTA(5) PORT_MINMAX(0, 255) PORT_PLAYER(2)
233
234   PORT_START("P1MOUSEY")
235   PORT_BIT( 0xff, 0x00, IPT_MOUSE_Y) PORT_SENSITIVITY(100) PORT_KEYDELTA(5) PORT_MINMAX(0, 255) PORT_PLAYER(2)
236
237   PORT_INCLUDE( amiga_us_keyboard )
238INPUT_PORTS_END
239
240
241/*************************************
242 *
243 *  Sound definitions
244 *
245 *************************************/
246
247static READ8_DEVICE_HANDLER( a1200_cia_0_portA_r )
248{
249   UINT8 ret = input_port_read(device->machine(), "CIA0PORTA") & 0xc0;   /* Gameport 1 and 0 buttons */
250   ret |= amiga_fdc_status_r(device->machine().device("fdc"));
251   return ret;
252}
253
254
255static const mos6526_interface a1200_cia_0_intf =
256{
257   0,                                       /* tod_clock */
258   DEVCB_LINE(amiga_cia_0_irq),                           /* irq_func */
259   DEVCB_NULL,   /* pc_func */
260   DEVCB_NULL,
261   DEVCB_NULL,
262   DEVCB_HANDLER(a1200_cia_0_portA_r),
263   DEVCB_HANDLER(ami1200_cia_0_porta_w),      /* port A */
264   DEVCB_HANDLER(ami1200_cia_0_portb_r),
265   DEVCB_HANDLER(ami1200_cia_0_portb_w)      /* port B */
266};
267
268static const mos6526_interface a1200_cia_1_intf =
269{
270   0,                                       /* tod_clock */
271   DEVCB_LINE(amiga_cia_1_irq),                           /* irq_func */
272   DEVCB_NULL,   /* pc_func */
273   DEVCB_NULL,
274   DEVCB_NULL,
275   DEVCB_NULL,
276   DEVCB_NULL,                           /* port A */
277   DEVCB_NULL,
278   DEVCB_DEVICE_HANDLER("fdc", amiga_fdc_control_w)         /* port B */
279};
280
281
282static MACHINE_CONFIG_START( a1200n, ami1200_state )
283
284   /* basic machine hardware */
285   MCFG_CPU_ADD("maincpu", M68EC020, AMIGA_68EC020_NTSC_CLOCK) /* 14.3 Mhz */
286   MCFG_CPU_PROGRAM_MAP(a1200_map)
287
288//  MCFG_CPU_ADD("keyboard_mpu", MC68HC05)
289
290   MCFG_MACHINE_RESET(amiga)
291
292   /* video hardware */
293   MCFG_VIDEO_ATTRIBUTES(VIDEO_UPDATE_BEFORE_VBLANK)
294
295   MCFG_SCREEN_ADD("screen", RASTER)
296   MCFG_SCREEN_REFRESH_RATE(59.997)
297   MCFG_SCREEN_VBLANK_TIME(ATTOSECONDS_IN_USEC(0))
298   MCFG_SCREEN_FORMAT(BITMAP_FORMAT_RGB32)
299   MCFG_SCREEN_SIZE(512*2, 312)
300   MCFG_SCREEN_VISIBLE_AREA((129-8-8)*2, (449+8-1+8)*2, 44-8, 300+8-1)
301   MCFG_SCREEN_UPDATE(amiga_aga)
302
303   MCFG_VIDEO_START(amiga_aga)
304
305   /* sound hardware */
306   MCFG_SPEAKER_STANDARD_STEREO("lspeaker", "rspeaker")
307
308   MCFG_SOUND_ADD("amiga", AMIGA, XTAL_28_63636MHz/8)
309   MCFG_SOUND_ROUTE(0, "lspeaker", 0.25)
310   MCFG_SOUND_ROUTE(1, "rspeaker", 0.25)
311   MCFG_SOUND_ROUTE(2, "rspeaker", 0.25)
312   MCFG_SOUND_ROUTE(3, "lspeaker", 0.25)
313
314   /* cia */
315   MCFG_MOS8520_ADD("cia_0", AMIGA_68EC020_NTSC_CLOCK / 10, a1200_cia_0_intf)
316   MCFG_MOS8520_ADD("cia_1", AMIGA_68EC020_NTSC_CLOCK / 10, a1200_cia_1_intf)
317
318   MCFG_AMIGA_FDC_ADD("fdc")
319MACHINE_CONFIG_END
320
321static MACHINE_CONFIG_DERIVED( a1200p, a1200n )
322
323   /* adjust for PAL specs */
324   MCFG_CPU_MODIFY("maincpu")
325   MCFG_CPU_CLOCK(A1200PAL_XTAL_X1/2) /* 14.18758 MHz */
326
327   /* video hardware */
328   MCFG_SCREEN_MODIFY("screen")
329   MCFG_SCREEN_REFRESH_RATE(50)
330
331   /* sound hardware */
332   MCFG_SOUND_MODIFY("amiga")
333   MCFG_SOUND_CLOCK(A1200PAL_XTAL_X1/8) /* 3.546895 MHz */
334
335   /* cia */
336   MCFG_DEVICE_MODIFY("cia_0")
337   MCFG_DEVICE_CLOCK(A1200PAL_XTAL_X1/20)
338   MCFG_DEVICE_MODIFY("cia_1")
339   MCFG_DEVICE_CLOCK(A1200PAL_XTAL_X1/20)
340MACHINE_CONFIG_END
341
342
343/***************************************************************************
344    ROM DEFINITIONS
345***************************************************************************/
346
347ROM_START( a1200n )
348   ROM_REGION32_BE(0x080000, "user1", 0)
349   ROM_DEFAULT_BIOS("kick31")
350   ROM_SYSTEM_BIOS(0, "kick30", "Kickstart 3.0 (39.106)")
351   ROMX_LOAD("391523-01.u6a", 0x000000, 0x040000, CRC(c742a412) SHA1(999eb81c65dfd07a71ee19315d99c7eb858ab186), ROM_GROUPWORD | ROM_REVERSE | ROM_SKIP(2) | ROM_BIOS(1))
352   ROMX_LOAD("391524-01.u6b", 0x000002, 0x040000, CRC(d55c6ec6) SHA1(3341108d3a402882b5ef9d3b242cbf3c8ab1a3e9), ROM_GROUPWORD | ROM_REVERSE | ROM_SKIP(2) | ROM_BIOS(1))
353   ROM_SYSTEM_BIOS(1, "kick31", "Kickstart 3.1 (40.068)")
354   ROMX_LOAD("391773-01.u6a", 0x000000, 0x040000, CRC(08dbf275) SHA1(b8800f5f909298109ea69690b1b8523fa22ddb37), ROM_GROUPWORD | ROM_REVERSE | ROM_SKIP(2) | ROM_BIOS(2))   // ROM_LOAD32_WORD_SWAP!
355   ROMX_LOAD("391774-01.u6b", 0x000002, 0x040000, CRC(16c07bf8) SHA1(90e331be1970b0e53f53a9b0390b51b59b3869c2), ROM_GROUPWORD | ROM_REVERSE | ROM_SKIP(2) | ROM_BIOS(2))
356
357   // COMMODORE | 391508-01 REV0 | KEYBOARD MPU
358   ROM_REGION(0x1040, "keyboard_rev0", 0)
359   ROM_LOAD("391508-01.u13", 0x0000, 0x1040, NO_DUMP)
360
361   // Amiga Tech REV1 Keyboard MPU
362   ROM_REGION(0x2f40, "keyboard_rev1", 0)
363   ROM_LOAD("391508-02.u13", 0x0000, 0x2f40, NO_DUMP)
364ROM_END
365
366#define rom_a1200p    rom_a1200n
367
368
369/***************************************************************************************************/
370
371// these come directly from amiga.c
372
373static UINT16 a1200_read_dskbytr(running_machine &machine)
374{
375   return amiga_fdc_get_byte(machine.device("fdc"));
376}
377
378static void a1200_write_dsklen(running_machine &machine, UINT16 data)
379{
380   cd32_state *state = machine.driver_data<cd32_state>();
381   if ( data & 0x8000 )
382   {
383      if ( CUSTOM_REG(REG_DSKLEN) & 0x8000 )
384         amiga_fdc_setup_dma(machine.device("fdc"));
385   }
386}
387
388
389static DRIVER_INIT( a1200 )
390{
391   cd32_state *state = machine.driver_data<cd32_state>();
392   static const amiga_machine_interface cd32_intf =
393   {
394      AGA_CHIP_RAM_MASK,
395      NULL, NULL,         /* joy0dat_r & joy1dat_r */
396      cd32_potgo_w,      /* potgo_w */
397      a1200_read_dskbytr, a1200_write_dsklen, /* dskbytr_r & dsklen_w */
398      NULL,            /* serdat_w */
399      NULL,            /* scanline0_callback */
400      NULL,            /* reset_callback */
401      NULL,            /* nmi_callback */
402      FLAGS_AGA_CHIPSET   /* flags */
403   };
404
405   /* configure our Amiga setup */
406   amiga_machine_config(machine, &cd32_intf);
407
408   /* set up memory */
409   memory_configure_bank(machine, "bank1", 0, 1, state->m_chip_ram, 0);
410   memory_configure_bank(machine, "bank1", 1, 1, machine.region("user1")->base(), 0);
411
412   /* initialize keyboard */
413   amigakbd_init(machine);
414}
415
416
417/***************************************************************************************************/
418
419/*    YEAR  NAME     PARENT   COMPAT  MACHINE INPUT   INIT      COMPANY       FULLNAME */
420COMP( 1992, a1200n,  0,       0,      a1200n, a1200,  a1200,  "Commodore Business Machines",  "Amiga 1200 (NTSC)" , GAME_NOT_WORKING )
421COMP( 1992, a1200p,  a1200n,  0,      a1200p, a1200,  a1200,  "Commodore Business Machines",  "Amiga 1200 (PAL)" , GAME_NOT_WORKING  )
src/mame/drivers/pce.c
r11531r11532
1/****************************************************************************
2
3 PC-Engine / Turbo Grafx 16 driver
4 by Charles Mac Donald
5 E-Mail: cgfm2@hooked.net
6
7 Thanks to David Shadoff and Brian McPhail for help with the driver.
8
9****************************************************************************/
10
11/**********************************************************************
12          To-Do List:
13- convert h6280-based drivers to internal memory map for the I/O region
14- test sprite collision and overflow interrupts
15- sprite precaching
16- rewrite the base renderer loop
17- Add CD support
18- Add 6 button joystick support
19- Add 263 line mode
20- Sprite DMA should use vdc VRAM functions
21- properly implement the pixel clocks instead of the simple scaling we do now
22
23Banking
24=======
25
26Normally address spacebanks 00-F6 are assigned to regular HuCard ROM space. There
27are a couple of special situations:
28
29Street Fighter II:
30  - address space banks 40-7F switchable by writing to 1FF0-1FF3
31    1FF0 - select rom banks 40-7F
32    1FF1 - select rom banks 80-BF
33    1FF2 - select rom banks C0-FF
34    1FF3 - select rom banks 100-13F
35
36Populous:
37  - address space banks 40-43 contains 32KB RAM
38
39CDRom units:
40  - address space banks 80-87 contains 64KB RAM
41
42Super System Card:
43  - address space banks 68-7F contains 192KB RAM
44
45**********************************************************************/
46
47/**********************************************************************
48                          Known Bugs
49***********************************************************************
50- Benkei Gaiden: hangs after a few Sunsoft logo spins.
51- Busou Keiji Cyber Cross: hangs on attract mode
52- Cadash: After choosing character and name, the game starts and the display 'jiggles' like tracking if off a VCR
53- Fighting Run: has color and sprite issues during gameplay;
54- Hisou Kihei - Xserd: black screen;
55**********************************************************************/
56
57#include "emu.h"
58#include "deprecat.h"
59#include "video/vdc.h"
60#include "cpu/h6280/h6280.h"
61#include "includes/pce.h"
62#include "imagedev/cartslot.h"
63#include "imagedev/chd_cd.h"
64#include "sound/c6280.h"
65#include "sound/cdda.h"
66#include "sound/msm5205.h"
67#include "hash.h"
68
69
70static ADDRESS_MAP_START( pce_mem , AS_PROGRAM, 8)
71   AM_RANGE( 0x000000, 0x07FFFF) AM_ROMBANK("bank1")
72   AM_RANGE( 0x080000, 0x087FFF) AM_ROMBANK("bank2")
73   AM_RANGE( 0x088000, 0x0CFFFF) AM_ROMBANK("bank3")
74   AM_RANGE( 0x0D0000, 0x0FFFFF) AM_ROMBANK("bank4")
75   AM_RANGE( 0x100000, 0x10FFFF) AM_RAM AM_BASE_MEMBER( pce_state, m_cd_ram )
76   AM_RANGE( 0x110000, 0x1EDFFF) AM_NOP
77   AM_RANGE( 0x1EE000, 0x1EE7FF) AM_ROMBANK("bank10") AM_WRITE( pce_cd_bram_w )
78   AM_RANGE( 0x1EE800, 0x1EFFFF) AM_NOP
79   AM_RANGE( 0x1F0000, 0x1F1FFF) AM_RAM AM_MIRROR(0x6000) AM_BASE_MEMBER( pce_state, m_user_ram )
80   AM_RANGE( 0x1FE000, 0x1FE3FF) AM_READWRITE( vdc_0_r, vdc_0_w )
81   AM_RANGE( 0x1FE400, 0x1FE7FF) AM_READWRITE( vce_r, vce_w )
82   AM_RANGE( 0x1FE800, 0x1FEBFF) AM_DEVREADWRITE(C6280_TAG, c6280_r, c6280_w )
83   AM_RANGE( 0x1FEC00, 0x1FEFFF) AM_READWRITE( h6280_timer_r, h6280_timer_w )
84   AM_RANGE( 0x1FF000, 0x1FF3FF) AM_READWRITE( pce_joystick_r, pce_joystick_w )
85   AM_RANGE( 0x1FF400, 0x1FF7FF) AM_READWRITE( h6280_irq_status_r, h6280_irq_status_w )
86   AM_RANGE( 0x1FF800, 0x1FFBFF) AM_READWRITE( pce_cd_intf_r, pce_cd_intf_w )
87ADDRESS_MAP_END
88
89static ADDRESS_MAP_START( pce_io , AS_IO, 8)
90   AM_RANGE( 0x00, 0x03) AM_READWRITE( vdc_0_r, vdc_0_w )
91ADDRESS_MAP_END
92
93static ADDRESS_MAP_START( sgx_mem , AS_PROGRAM, 8)
94   AM_RANGE( 0x000000, 0x07FFFF) AM_ROMBANK("bank1")
95   AM_RANGE( 0x080000, 0x087FFF) AM_ROMBANK("bank2")
96   AM_RANGE( 0x088000, 0x0CFFFF) AM_ROMBANK("bank3")
97   AM_RANGE( 0x0D0000, 0x0FFFFF) AM_ROMBANK("bank4")
98   AM_RANGE( 0x100000, 0x10FFFF) AM_RAM AM_BASE_MEMBER( pce_state, m_cd_ram )
99   AM_RANGE( 0x110000, 0x1EDFFF) AM_NOP
100   AM_RANGE( 0x1EE000, 0x1EE7FF) AM_ROMBANK("bank10") AM_WRITE( pce_cd_bram_w )
101   AM_RANGE( 0x1EE800, 0x1EFFFF) AM_NOP
102   AM_RANGE( 0x1F0000, 0x1F7FFF) AM_RAM AM_BASE_MEMBER( pce_state, m_user_ram )
103   AM_RANGE( 0x1FE000, 0x1FE007) AM_READWRITE( vdc_0_r, vdc_0_w ) AM_MIRROR(0x03E0)
104   AM_RANGE( 0x1FE008, 0x1FE00F) AM_READWRITE( vpc_r, vpc_w ) AM_MIRROR(0x03E0)
105   AM_RANGE( 0x1FE010, 0x1FE017) AM_READWRITE( vdc_1_r, vdc_1_w ) AM_MIRROR(0x03E0)
106   AM_RANGE( 0x1FE400, 0x1FE7FF) AM_READWRITE( vce_r, vce_w )
107   AM_RANGE( 0x1FE800, 0x1FEBFF) AM_DEVREADWRITE(C6280_TAG, c6280_r, c6280_w )
108   AM_RANGE( 0x1FEC00, 0x1FEFFF) AM_READWRITE( h6280_timer_r, h6280_timer_w )
109   AM_RANGE( 0x1FF000, 0x1FF3FF) AM_READWRITE( pce_joystick_r, pce_joystick_w )
110   AM_RANGE( 0x1FF400, 0x1FF7FF) AM_READWRITE( h6280_irq_status_r, h6280_irq_status_w )
111   AM_RANGE( 0x1FF800, 0x1FFBFF) AM_READWRITE( pce_cd_intf_r, pce_cd_intf_w )
112ADDRESS_MAP_END
113
114static ADDRESS_MAP_START( sgx_io , AS_IO, 8)
115   AM_RANGE( 0x00, 0x03) AM_READWRITE( sgx_vdc_r, sgx_vdc_w )
116ADDRESS_MAP_END
117
118/* todo: alternate forms of input (multitap, mouse, etc.) */
119static INPUT_PORTS_START( pce )
120
121   PORT_START("JOY_P1")
122   /* II is left of I on the original pad so we map them in reverse order */
123   PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_NAME("P1 Button I") PORT_PLAYER(1) PORT_CATEGORY(10)
124   PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_NAME("P1 Button II") PORT_PLAYER(1) PORT_CATEGORY(10)
125   PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_SELECT  ) PORT_NAME("P1 Select") PORT_PLAYER(1) PORT_CATEGORY(10)
126   PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_START   ) PORT_NAME("P1 Run") PORT_PLAYER(1) PORT_CATEGORY(10)
127   PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) PORT_PLAYER(1) PORT_CATEGORY(10)
128   PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) PORT_PLAYER(1) PORT_CATEGORY(10)
129   PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) PORT_PLAYER(1) PORT_CATEGORY(10)
130   PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) PORT_PLAYER(1) PORT_CATEGORY(10)
131
132   PORT_START("JOY_P2")
133   /* II is left of I on the original pad so we map them in reverse order */
134   PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_NAME("P2 Button I") PORT_PLAYER(2) PORT_CATEGORY(20)
135   PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_NAME("P2 Button II") PORT_PLAYER(2) PORT_CATEGORY(20)
136   PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_SELECT  ) PORT_NAME("P2 Select") PORT_PLAYER(2) PORT_CATEGORY(20)
137   PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_START   ) PORT_NAME("P2 Run") PORT_PLAYER(2) PORT_CATEGORY(20)
138   PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) PORT_PLAYER(2) PORT_CATEGORY(20)
139   PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) PORT_PLAYER(2) PORT_CATEGORY(20)
140   PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) PORT_PLAYER(2) PORT_CATEGORY(20)
141   PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) PORT_PLAYER(2) PORT_CATEGORY(20)
142
143   PORT_START("JOY_P3")
144   /* II is left of I on the original pad so we map them in reverse order */
145   PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_NAME("P3 Button I") PORT_PLAYER(3) PORT_CATEGORY(30)
146   PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_NAME("P3 Button II") PORT_PLAYER(3) PORT_CATEGORY(30)
147   PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_SELECT  ) PORT_NAME("P3 Select") PORT_PLAYER(3) PORT_CATEGORY(30)
148   PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_START   ) PORT_NAME("P3 Run") PORT_PLAYER(3) PORT_CATEGORY(30)
149   PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) PORT_PLAYER(3) PORT_CATEGORY(30)
150   PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) PORT_PLAYER(3) PORT_CATEGORY(30)
151   PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) PORT_PLAYER(3) PORT_CATEGORY(30)
152   PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) PORT_PLAYER(3) PORT_CATEGORY(30)
153
154   PORT_START("JOY_P4")
155   /* II is left of I on the original pad so we map them in reverse order */
156   PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_NAME("P4 Button I") PORT_PLAYER(4) PORT_CATEGORY(40)
157   PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_NAME("P4 Button II") PORT_PLAYER(4) PORT_CATEGORY(40)
158   PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_SELECT  ) PORT_NAME("P4 Select") PORT_PLAYER(4) PORT_CATEGORY(40)
159   PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_START   ) PORT_NAME("P4 Run") PORT_PLAYER(4) PORT_CATEGORY(40)
160   PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) PORT_PLAYER(4) PORT_CATEGORY(40)
161   PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) PORT_PLAYER(4) PORT_CATEGORY(40)
162   PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) PORT_PLAYER(4) PORT_CATEGORY(40)
163   PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) PORT_PLAYER(4) PORT_CATEGORY(40)
164
165   PORT_START("JOY_P5")
166   /* II is left of I on the original pad so we map them in reverse order */
167   PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_NAME("P5 Button I") PORT_PLAYER(5) PORT_CATEGORY(50)
168   PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_NAME("P5 Button II") PORT_PLAYER(5) PORT_CATEGORY(50)
169   PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_SELECT  ) PORT_NAME("P5 Select") PORT_PLAYER(5) PORT_CATEGORY(50)
170   PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_START   ) PORT_NAME("P5 Run") PORT_PLAYER(5) PORT_CATEGORY(50)
171   PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) PORT_PLAYER(5) PORT_CATEGORY(50)
172   PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) PORT_PLAYER(5) PORT_CATEGORY(50)
173   PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) PORT_PLAYER(5) PORT_CATEGORY(50)
174   PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) PORT_PLAYER(5) PORT_CATEGORY(50)
175
176   PORT_START("JOY6B_P1")
177   /* II is left of I on the original pad so we map them in reverse order */
178   PORT_BIT( 0x0001, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_NAME("P1 Button I") PORT_PLAYER(1) PORT_CATEGORY(11)
179   PORT_BIT( 0x0002, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_NAME("P1 Button II") PORT_PLAYER(1) PORT_CATEGORY(11)
180   PORT_BIT( 0x0004, IP_ACTIVE_LOW, IPT_SELECT  ) PORT_NAME("P1 Select") PORT_PLAYER(1) PORT_CATEGORY(11)
181   PORT_BIT( 0x0008, IP_ACTIVE_LOW, IPT_START   ) PORT_NAME("P1 Run") PORT_PLAYER(1) PORT_CATEGORY(11)
182   PORT_BIT( 0x0010, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) PORT_PLAYER(1) PORT_CATEGORY(11)
183   PORT_BIT( 0x0040, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) PORT_PLAYER(1) PORT_CATEGORY(11)
184   PORT_BIT( 0x0080, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) PORT_PLAYER(1) PORT_CATEGORY(11)
185   PORT_BIT( 0x0020, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) PORT_PLAYER(1) PORT_CATEGORY(11)
186   PORT_BIT( 0x0100, IP_ACTIVE_LOW, IPT_BUTTON3 ) PORT_NAME("P1 Button III") PORT_PLAYER(1) PORT_CATEGORY(11)
187   PORT_BIT( 0x0200, IP_ACTIVE_LOW, IPT_BUTTON4 ) PORT_NAME("P1 Button IV") PORT_PLAYER(1) PORT_CATEGORY(11)
188   PORT_BIT( 0x0400, IP_ACTIVE_LOW, IPT_BUTTON5 ) PORT_NAME("P1 Button V") PORT_PLAYER(1) PORT_CATEGORY(11)
189   PORT_BIT( 0x0800, IP_ACTIVE_LOW, IPT_BUTTON6 ) PORT_NAME("P1 Button VI") PORT_PLAYER(1) PORT_CATEGORY(11)
190   PORT_BIT( 0xf000, IP_ACTIVE_HIGH,IPT_UNUSED ) //6-button pad header
191
192   PORT_START("JOY6B_P2")  /* Player 2 controls */
193   /* II is left of I on the original pad so we map them in reverse order */
194   PORT_BIT( 0x0001, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_NAME("P2 Button I") PORT_PLAYER(2) PORT_CATEGORY(21)
195   PORT_BIT( 0x0002, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_NAME("P2 Button II") PORT_PLAYER(2) PORT_CATEGORY(21)
196   PORT_BIT( 0x0004, IP_ACTIVE_LOW, IPT_SELECT  ) PORT_NAME("P2 Select") PORT_PLAYER(2) PORT_CATEGORY(21)
197   PORT_BIT( 0x0008, IP_ACTIVE_LOW, IPT_START   ) PORT_NAME("P2 Run") PORT_PLAYER(2) PORT_CATEGORY(21)
198   PORT_BIT( 0x0010, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) PORT_PLAYER(2) PORT_CATEGORY(21)
199   PORT_BIT( 0x0040, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) PORT_PLAYER(2) PORT_CATEGORY(21)
200   PORT_BIT( 0x0080, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) PORT_PLAYER(2) PORT_CATEGORY(21)
201   PORT_BIT( 0x0020, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) PORT_PLAYER(2) PORT_CATEGORY(21)
202   PORT_BIT( 0x0100, IP_ACTIVE_LOW, IPT_BUTTON3 ) PORT_NAME("P2 Button III") PORT_PLAYER(2) PORT_CATEGORY(21)
203   PORT_BIT( 0x0200, IP_ACTIVE_LOW, IPT_BUTTON4 ) PORT_NAME("P2 Button IV") PORT_PLAYER(2) PORT_CATEGORY(21)
204   PORT_BIT( 0x0400, IP_ACTIVE_LOW, IPT_BUTTON5 ) PORT_NAME("P2 Button V") PORT_PLAYER(2) PORT_CATEGORY(21)
205   PORT_BIT( 0x0800, IP_ACTIVE_LOW, IPT_BUTTON6 ) PORT_NAME("P2 Button VI") PORT_PLAYER(2) PORT_CATEGORY(21)
206   PORT_BIT( 0xf000, IP_ACTIVE_HIGH,IPT_UNUSED ) //6-button pad header
207
208   PORT_START("JOY6B_P3")  /* Player 3 controls */
209   /* II is left of I on the original pad so we map them in reverse order */
210   PORT_BIT( 0x0001, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_NAME("P3 Button I") PORT_PLAYER(3) PORT_CATEGORY(31)
211   PORT_BIT( 0x0002, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_NAME("P3 Button II") PORT_PLAYER(3) PORT_CATEGORY(31)
212   PORT_BIT( 0x0004, IP_ACTIVE_LOW, IPT_SELECT  ) PORT_NAME("P3 Select") PORT_PLAYER(3) PORT_CATEGORY(31)
213   PORT_BIT( 0x0008, IP_ACTIVE_LOW, IPT_START   ) PORT_NAME("P3 Run") PORT_PLAYER(3) PORT_CATEGORY(31)
214   PORT_BIT( 0x0010, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) PORT_PLAYER(3) PORT_CATEGORY(31)
215   PORT_BIT( 0x0040, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) PORT_PLAYER(3) PORT_CATEGORY(31)
216   PORT_BIT( 0x0080, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) PORT_PLAYER(3) PORT_CATEGORY(31)
217   PORT_BIT( 0x0020, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) PORT_PLAYER(3) PORT_CATEGORY(31)
218   PORT_BIT( 0x0100, IP_ACTIVE_LOW, IPT_BUTTON3 ) PORT_NAME("P3 Button III") PORT_PLAYER(3) PORT_CATEGORY(31)
219   PORT_BIT( 0x0200, IP_ACTIVE_LOW, IPT_BUTTON4 ) PORT_NAME("P3 Button IV") PORT_PLAYER(3) PORT_CATEGORY(31)
220   PORT_BIT( 0x0400, IP_ACTIVE_LOW, IPT_BUTTON5 ) PORT_NAME("P3 Button V") PORT_PLAYER(3) PORT_CATEGORY(31)
221   PORT_BIT( 0x0800, IP_ACTIVE_LOW, IPT_BUTTON6 ) PORT_NAME("P3 Button VI") PORT_PLAYER(3) PORT_CATEGORY(31)
222   PORT_BIT( 0xf000, IP_ACTIVE_HIGH,IPT_UNUSED ) //6-button pad header
223
224   PORT_START("JOY6B_P4")  /* Player 4 controls */
225   /* II is left of I on the original pad so we map them in reverse order */
226   PORT_BIT( 0x0001, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_NAME("P4 Button I") PORT_PLAYER(4) PORT_CATEGORY(41)
227   PORT_BIT( 0x0002, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_NAME("P4 Button II") PORT_PLAYER(4) PORT_CATEGORY(41)
228   PORT_BIT( 0x0004, IP_ACTIVE_LOW, IPT_SELECT  ) PORT_NAME("P4 Select") PORT_PLAYER(4) PORT_CATEGORY(41)
229   PORT_BIT( 0x0008, IP_ACTIVE_LOW, IPT_START   ) PORT_NAME("P4 Run") PORT_PLAYER(4) PORT_CATEGORY(41)
230   PORT_BIT( 0x0010, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) PORT_PLAYER(4) PORT_CATEGORY(41)
231   PORT_BIT( 0x0040, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) PORT_PLAYER(4) PORT_CATEGORY(41)
232   PORT_BIT( 0x0080, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) PORT_PLAYER(4) PORT_CATEGORY(41)
233   PORT_BIT( 0x0020, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) PORT_PLAYER(4) PORT_CATEGORY(41)
234   PORT_BIT( 0x0100, IP_ACTIVE_LOW, IPT_BUTTON3 ) PORT_NAME("P3 Button III") PORT_PLAYER(4) PORT_CATEGORY(41)
235   PORT_BIT( 0x0200, IP_ACTIVE_LOW, IPT_BUTTON4 ) PORT_NAME("P3 Button IV") PORT_PLAYER(4) PORT_CATEGORY(41)
236   PORT_BIT( 0x0400, IP_ACTIVE_LOW, IPT_BUTTON5 ) PORT_NAME("P3 Button V") PORT_PLAYER(4) PORT_CATEGORY(41)
237   PORT_BIT( 0x0800, IP_ACTIVE_LOW, IPT_BUTTON6 ) PORT_NAME("P3 Button VI") PORT_PLAYER(4) PORT_CATEGORY(41)
238   PORT_BIT( 0xf000, IP_ACTIVE_HIGH,IPT_UNUSED ) //6-button pad header
239
240   PORT_START("JOY6B_P5")  /* Player 5 controls */
241   /* II is left of I on the original pad so we map them in reverse order */
242   PORT_BIT( 0x0001, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_NAME("P5 Button I") PORT_PLAYER(5) PORT_CATEGORY(51)
243   PORT_BIT( 0x0002, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_NAME("P5 Button II") PORT_PLAYER(5) PORT_CATEGORY(51)
244   PORT_BIT( 0x0004, IP_ACTIVE_LOW, IPT_SELECT  ) PORT_NAME("P5 Select") PORT_PLAYER(5) PORT_CATEGORY(51)
245   PORT_BIT( 0x0008, IP_ACTIVE_LOW, IPT_START   ) PORT_NAME("P5 Run") PORT_PLAYER(5) PORT_CATEGORY(51)
246   PORT_BIT( 0x0010, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) PORT_PLAYER(5) PORT_CATEGORY(51)
247   PORT_BIT( 0x0040, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) PORT_PLAYER(5) PORT_CATEGORY(51)
248   PORT_BIT( 0x0080, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) PORT_PLAYER(5) PORT_CATEGORY(51)
249   PORT_BIT( 0x0020, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) PORT_PLAYER(5) PORT_CATEGORY(51)
250   PORT_BIT( 0x0100, IP_ACTIVE_LOW, IPT_BUTTON3 ) PORT_NAME("P5 Button III") PORT_PLAYER(5) PORT_CATEGORY(51)
251   PORT_BIT( 0x0200, IP_ACTIVE_LOW, IPT_BUTTON4 ) PORT_NAME("P5 Button IV") PORT_PLAYER(5) PORT_CATEGORY(51)
252   PORT_BIT( 0x0400, IP_ACTIVE_LOW, IPT_BUTTON5 ) PORT_NAME("P5 Button V") PORT_PLAYER(5) PORT_CATEGORY(51)
253   PORT_BIT( 0x0800, IP_ACTIVE_LOW, IPT_BUTTON6 ) PORT_NAME("P5 Button VI") PORT_PLAYER(5) PORT_CATEGORY(51)
254   PORT_BIT( 0xf000, IP_ACTIVE_HIGH,IPT_UNUSED ) //6-button pad header
255
256   PORT_START("JOY_TYPE")
257   PORT_CATEGORY_CLASS(0x0003,0x0000,"Joystick Type Player 1")
258   PORT_CATEGORY_ITEM( 0x0000,"2-buttons", 10)
259//  PORT_CATEGORY_ITEM( 0x0001,"3-buttons", xx)
260   PORT_CATEGORY_ITEM( 0x0002,"6-buttons", 11)
261//  PORT_CATEGORY_ITEM( 0x0003,"Mouse",     xx)
262   PORT_CATEGORY_CLASS(0x000c,0x0000,"Joystick Type Player 2")
263   PORT_CATEGORY_ITEM( 0x0000,"2-buttons", 20)
264//  PORT_CATEGORY_ITEM( 0x0004,"3-buttons", xx)
265   PORT_CATEGORY_ITEM( 0x0008,"6-buttons", 21)
266//  PORT_CATEGORY_ITEM( 0x000c,"Mouse",     xx)
267   PORT_CATEGORY_CLASS(0x0030,0x0000,"Joystick Type Player 3")
268   PORT_CATEGORY_ITEM( 0x0000,"2-buttons", 30)
269//  PORT_CATEGORY_ITEM( 0x0010,"3-buttons", xx)
270   PORT_CATEGORY_ITEM( 0x0020,"6-buttons", 31)
271//  PORT_CATEGORY_ITEM( 0x0030,"Mouse",     xx)
272   PORT_CATEGORY_CLASS(0x00c0,0x0000,"Joystick Type Player 4")
273   PORT_CATEGORY_ITEM( 0x0000,"2-buttons", 40)
274//  PORT_CATEGORY_ITEM( 0x0040,"3-buttons", xx)
275   PORT_CATEGORY_ITEM( 0x0080,"6-buttons", 41)
276//  PORT_CATEGORY_ITEM( 0x00c0,"Mouse",     xx)
277   PORT_CATEGORY_CLASS(0x0300,0x0000,"Joystick Type Player 5")
278   PORT_CATEGORY_ITEM( 0x0000,"2-buttons", 50)
279//  PORT_CATEGORY_ITEM( 0x0100,"3-buttons", xx)
280   PORT_CATEGORY_ITEM( 0x0200,"6-buttons", 51)
281//  PORT_CATEGORY_ITEM( 0x0300,"Mouse",     xx)
282
283   PORT_START("A_CARD")
284   PORT_CONFNAME( 0x01, 0x01, "Arcade Card" )
285   PORT_CONFSETTING(    0x00, DEF_STR( Off ) )
286   PORT_CONFSETTING(    0x01, DEF_STR( On ) )
287INPUT_PORTS_END
288
289
290static void pce_partialhash(hash_collection &dest, const unsigned char *data,
291   unsigned long length, const char *functions)
292{
293   if ( ( length <= PCE_HEADER_SIZE ) || ( length & PCE_HEADER_SIZE ) ) {
294         dest.compute(&data[PCE_HEADER_SIZE], length - PCE_HEADER_SIZE, functions);
295   } else {
296      dest.compute(data, length, functions);
297   }
298}
299
300static const c6280_interface c6280_config =
301{
302   "maincpu"
303};
304static MACHINE_CONFIG_FRAGMENT( pce_cdslot )
305   MCFG_CDROM_ADD( "cdrom" )
306   MCFG_CDROM_INTERFACE("pce_cdrom")
307
308   MCFG_SOFTWARE_LIST_ADD("cd_list","pcecd")
309MACHINE_CONFIG_END
310
311static MACHINE_CONFIG_FRAGMENT( pce_cartslot )
312   MCFG_CARTSLOT_ADD("cart")
313   MCFG_CARTSLOT_EXTENSION_LIST("pce,bin")
314   MCFG_CARTSLOT_MANDATORY
315   MCFG_CARTSLOT_INTERFACE("pce_cart")
316   MCFG_CARTSLOT_LOAD(pce_cart)
317   MCFG_CARTSLOT_PARTIALHASH(pce_partialhash)
318   MCFG_SOFTWARE_LIST_ADD("cart_list","pce")
319MACHINE_CONFIG_END
320
321static MACHINE_CONFIG_FRAGMENT( tg16_cartslot )
322   MCFG_CARTSLOT_ADD("cart")
323   MCFG_CARTSLOT_EXTENSION_LIST("pce,bin")
324   MCFG_CARTSLOT_MANDATORY
325   MCFG_CARTSLOT_INTERFACE("tg16_cart")
326   MCFG_CARTSLOT_LOAD(pce_cart)
327   MCFG_CARTSLOT_PARTIALHASH(pce_partialhash)
328   MCFG_SOFTWARE_LIST_ADD("cart_list","tg16")
329MACHINE_CONFIG_END
330
331static MACHINE_CONFIG_FRAGMENT( sgx_cartslot )
332   MCFG_CARTSLOT_ADD("cart")
333   MCFG_CARTSLOT_EXTENSION_LIST("pce,bin")
334   MCFG_CARTSLOT_MANDATORY
335   MCFG_CARTSLOT_INTERFACE("pce_cart")
336   MCFG_CARTSLOT_LOAD(pce_cart)
337   MCFG_CARTSLOT_PARTIALHASH(pce_partialhash)
338   MCFG_SOFTWARE_LIST_ADD("cart_list","sgx")
339MACHINE_CONFIG_END
340
341static MACHINE_CONFIG_START( pce_common, pce_state )
342   /* basic machine hardware */
343   MCFG_CPU_ADD("maincpu", H6280, MAIN_CLOCK/3)
344   MCFG_CPU_PROGRAM_MAP(pce_mem)
345   MCFG_CPU_IO_MAP(pce_io)
346   MCFG_CPU_VBLANK_INT_HACK(pce_interrupt, VDC_LPF)
347   MCFG_QUANTUM_TIME(attotime::from_hz(60))
348
349   MCFG_MACHINE_START( pce )
350   MCFG_MACHINE_RESET( pce )
351
352    /* video hardware */
353   MCFG_SCREEN_ADD("screen", RASTER)
354   MCFG_SCREEN_REFRESH_RATE(60)
355   MCFG_SCREEN_VBLANK_TIME(ATTOSECONDS_IN_USEC(2500)) /* not accurate */
356   MCFG_SCREEN_FORMAT(BITMAP_FORMAT_INDEXED16)
357   MCFG_SCREEN_RAW_PARAMS(MAIN_CLOCK/2, VDC_WPF, 70, 70 + 512 + 32, VDC_LPF, 14, 14+242)
358   MCFG_SCREEN_UPDATE( pce )
359
360   /* MCFG_GFXDECODE( pce ) */
361   MCFG_PALETTE_LENGTH(1024)
362   MCFG_PALETTE_INIT( vce )
363
364   MCFG_VIDEO_START( pce )
365
366   MCFG_NVRAM_HANDLER( pce )
367   MCFG_SPEAKER_STANDARD_STEREO("lspeaker", "rspeaker")
368   MCFG_SOUND_ADD(C6280_TAG, C6280, MAIN_CLOCK/6)
369   MCFG_SOUND_CONFIG(c6280_config)
370   MCFG_SOUND_ROUTE( 0, "lspeaker", 1.00 )
371   MCFG_SOUND_ROUTE( 1, "rspeaker", 1.00 )
372
373   MCFG_SOUND_ADD( "msm5205", MSM5205, PCE_CD_CLOCK / 6 )
374   MCFG_SOUND_CONFIG( pce_cd_msm5205_interface )
375   MCFG_SOUND_ROUTE( ALL_OUTPUTS, "lspeaker", 0.50 )
376   MCFG_SOUND_ROUTE( ALL_OUTPUTS, "rspeaker", 0.50 )
377
378   MCFG_SOUND_ADD( "cdda", CDDA, 0 )
379   MCFG_SOUND_ROUTE( 0, "lspeaker", 1.00 )
380   MCFG_SOUND_ROUTE( 1, "rspeaker", 1.00 )
381MACHINE_CONFIG_END
382
383static MACHINE_CONFIG_DERIVED( pce, pce_common )
384   MCFG_FRAGMENT_ADD( pce_cartslot )
385   MCFG_FRAGMENT_ADD( pce_cdslot )
386MACHINE_CONFIG_END
387
388static MACHINE_CONFIG_DERIVED( tg16, pce_common )
389   MCFG_FRAGMENT_ADD( tg16_cartslot )
390   MCFG_FRAGMENT_ADD( pce_cdslot )
391MACHINE_CONFIG_END
392
393static MACHINE_CONFIG_START( sgx, pce_state )
394   /* basic machine hardware */
395   MCFG_CPU_ADD("maincpu", H6280, MAIN_CLOCK/3)
396   MCFG_CPU_PROGRAM_MAP(sgx_mem)
397   MCFG_CPU_IO_MAP(sgx_io)
398   MCFG_CPU_VBLANK_INT_HACK(sgx_interrupt, VDC_LPF)
399   MCFG_QUANTUM_TIME(attotime::from_hz(60))
400
401   MCFG_MACHINE_START( pce )
402   MCFG_MACHINE_RESET( pce )
403
404   /* video hardware */
405   MCFG_SCREEN_ADD("screen", RASTER)
406   MCFG_SCREEN_REFRESH_RATE(60)
407   MCFG_SCREEN_VBLANK_TIME(ATTOSECONDS_IN_USEC(2500)) /* not accurate */
408   MCFG_SCREEN_FORMAT(BITMAP_FORMAT_INDEXED16)
409   MCFG_SCREEN_RAW_PARAMS(MAIN_CLOCK/2, VDC_WPF, 70, 70 + 512 + 32, VDC_LPF, 14, 14+242)
410   MCFG_SCREEN_UPDATE( pce )
411
412   MCFG_PALETTE_LENGTH(1024)
413   MCFG_PALETTE_INIT( vce )
414
415   MCFG_VIDEO_START( pce )
416
417   MCFG_NVRAM_HANDLER( pce )
418   MCFG_SPEAKER_STANDARD_STEREO("lspeaker", "rspeaker")
419   MCFG_SOUND_ADD(C6280_TAG, C6280, MAIN_CLOCK/6)
420   MCFG_SOUND_CONFIG(c6280_config)
421   MCFG_SOUND_ROUTE(0, "lspeaker", 1.00)
422   MCFG_SOUND_ROUTE(1, "rspeaker", 1.00)
423
424   MCFG_SOUND_ADD( "msm5205", MSM5205, PCE_CD_CLOCK / 6 )
425   MCFG_SOUND_CONFIG( pce_cd_msm5205_interface )
426   MCFG_SOUND_ROUTE( ALL_OUTPUTS, "lspeaker", 0.00 )
427   MCFG_SOUND_ROUTE( ALL_OUTPUTS, "rspeaker", 0.00 )
428
429   MCFG_SOUND_ADD( "cdda", CDDA, 0 )
430   MCFG_SOUND_ROUTE( 0, "lspeaker", 1.00 )
431   MCFG_SOUND_ROUTE( 1, "rspeaker", 1.00 )
432
433   MCFG_FRAGMENT_ADD( sgx_cartslot )
434   MCFG_FRAGMENT_ADD( pce_cdslot )
435MACHINE_CONFIG_END
436
437/***************************************************************************
438
439  Game driver(s)
440
441***************************************************************************/
442
443ROM_START( pce )
444   ROM_REGION( PCE_ROM_MAXSIZE, "user1", 0 )      /* Cartridge ROM area */
445   ROM_FILL( 0, PCE_ROM_MAXSIZE, 0xFF )
446ROM_END
447
448#define rom_tg16 rom_pce
449#define rom_sgx rom_pce
450
451/*    YEAR  NAME    PARENT  COMPAT  MACHINE INPUT    INIT   COMPANY  FULLNAME */
452CONS( 1987, pce,    0,      0,      pce,    pce,     pce,   "Nippon Electronic Company", "PC Engine", GAME_IMPERFECT_SOUND)
453CONS( 1989, tg16,   pce,    0,      tg16,   pce,     tg16,  "Nippon Electronic Company", "TurboGrafx 16", GAME_IMPERFECT_SOUND)
454CONS( 1989, sgx,    pce,    0,      sgx,    pce,     sgx,   "Nippon Electronic Company", "SuperGrafx", GAME_IMPERFECT_SOUND)
src/mame/drivers/n64.c
r11531r11532
1/*
2    Nintendo 64
3
4    Driver by Ville Linde
5    Reformatted to share hardware by R. Belmont
6    Additional work by Ryan Holtz
7    Porting from Mupen64 by Harmony
8*/
9
10#include "emu.h"
11#include "cpu/rsp/rsp.h"
12#include "cpu/mips/mips3.h"
13#include "sound/dmadac.h"
14#include "imagedev/cartslot.h"
15#include "includes/n64.h"
16
17
18static ADDRESS_MAP_START( n64_map, AS_PROGRAM, 32 )
19   AM_RANGE(0x00000000, 0x007fffff) AM_RAM   AM_BASE(&rdram)            // RDRAM
20   AM_RANGE(0x03f00000, 0x03f00027) AM_READWRITE(n64_rdram_reg_r, n64_rdram_reg_w)
21   AM_RANGE(0x04000000, 0x04000fff) AM_RAM AM_SHARE("dmem")               // RSP DMEM
22   AM_RANGE(0x04001000, 0x04001fff) AM_RAM AM_SHARE("imem")               // RSP IMEM
23   AM_RANGE(0x04040000, 0x040fffff) AM_DEVREADWRITE("rsp", n64_sp_reg_r, n64_sp_reg_w)   // RSP
24   AM_RANGE(0x04100000, 0x041fffff) AM_DEVREADWRITE("rsp", n64_dp_reg_r, n64_dp_reg_w)   // RDP
25   AM_RANGE(0x04300000, 0x043fffff) AM_READWRITE(n64_mi_reg_r, n64_mi_reg_w)   // MIPS Interface
26   AM_RANGE(0x04400000, 0x044fffff) AM_READWRITE(n64_vi_reg_r, n64_vi_reg_w)   // Video Interface
27   AM_RANGE(0x04500000, 0x045fffff) AM_READWRITE(n64_ai_reg_r, n64_ai_reg_w)   // Audio Interface
28   AM_RANGE(0x04600000, 0x046fffff) AM_READWRITE(n64_pi_reg_r, n64_pi_reg_w)   // Peripheral Interface
29   AM_RANGE(0x04700000, 0x047fffff) AM_READWRITE(n64_ri_reg_r, n64_ri_reg_w)   // RDRAM Interface
30   AM_RANGE(0x04800000, 0x048fffff) AM_READWRITE(n64_si_reg_r, n64_si_reg_w)   // Serial Interface
31   //AM_RANGE(0x08000000, 0x08007fff) AM_RAM                                   // Cartridge SRAM
32   AM_RANGE(0x10000000, 0x13ffffff) AM_ROM AM_REGION("user2", 0)   // Cartridge
33   AM_RANGE(0x1fc00000, 0x1fc007bf) AM_ROM AM_REGION("user1", 0)   // PIF ROM
34   AM_RANGE(0x1fc007c0, 0x1fc007ff) AM_READWRITE(n64_pif_ram_r, n64_pif_ram_w)
35ADDRESS_MAP_END
36
37static ADDRESS_MAP_START( rsp_map, AS_PROGRAM, 32 )
38   AM_RANGE(0x00000000, 0x00000fff) AM_RAM AM_SHARE("dmem")
39   AM_RANGE(0x00001000, 0x00001fff) AM_RAM AM_SHARE("imem")
40   AM_RANGE(0x04000000, 0x04000fff) AM_RAM AM_BASE(&rsp_dmem) AM_SHARE("dmem")
41   AM_RANGE(0x04001000, 0x04001fff) AM_RAM AM_BASE(&rsp_imem) AM_SHARE("imem")
42ADDRESS_MAP_END
43
44static INPUT_PORTS_START( n64 )
45   PORT_START("P1")
46   PORT_BIT( 0x8000, IP_ACTIVE_HIGH, IPT_BUTTON1 )        PORT_PLAYER(1) PORT_NAME("P1 Button A")
47   PORT_BIT( 0x4000, IP_ACTIVE_HIGH, IPT_BUTTON2 )        PORT_PLAYER(1) PORT_NAME("P1 Button B")
48   PORT_BIT( 0x2000, IP_ACTIVE_HIGH, IPT_BUTTON3 )        PORT_PLAYER(1) PORT_NAME("P1 Button Z")
49   PORT_BIT( 0x1000, IP_ACTIVE_HIGH, IPT_START )          PORT_PLAYER(1) PORT_NAME("P1 Start")
50   PORT_BIT( 0x0800, IP_ACTIVE_HIGH, IPT_JOYSTICK_UP )    PORT_PLAYER(1) PORT_NAME("P1 Joypad \xE2\x86\x91") /* Up */
51   PORT_BIT( 0x0400, IP_ACTIVE_HIGH, IPT_JOYSTICK_DOWN )  PORT_PLAYER(1) PORT_NAME("P1 Joypad \xE2\x86\x93") /* Down */
52   PORT_BIT( 0x0200, IP_ACTIVE_HIGH, IPT_JOYSTICK_LEFT )  PORT_PLAYER(1) PORT_NAME("P1 Joypad \xE2\x86\x90") /* Left */
53   PORT_BIT( 0x0100, IP_ACTIVE_HIGH, IPT_JOYSTICK_RIGHT ) PORT_PLAYER(1) PORT_NAME("P1 Joypad \xE2\x86\x92") /* Right */
54   PORT_BIT( 0x00c0, IP_ACTIVE_HIGH, IPT_UNUSED )
55   PORT_BIT( 0x0020, IP_ACTIVE_HIGH, IPT_BUTTON4 )        PORT_PLAYER(1) PORT_NAME("P1 Button L")
56   PORT_BIT( 0x0010, IP_ACTIVE_HIGH, IPT_BUTTON5 )        PORT_PLAYER(1) PORT_NAME("P1 Button R")
57   PORT_BIT( 0x0008, IP_ACTIVE_HIGH, IPT_BUTTON6 )        PORT_PLAYER(1) PORT_NAME("P1 Button C \xE2\x86\x91") /* Up */
58   PORT_BIT( 0x0004, IP_ACTIVE_HIGH, IPT_BUTTON7 )        PORT_PLAYER(1) PORT_NAME("P1 Button C \xE2\x86\x93") /* Down */
59   PORT_BIT( 0x0002, IP_ACTIVE_HIGH, IPT_BUTTON8 )        PORT_PLAYER(1) PORT_NAME("P1 Button C \xE2\x86\x90") /* Left */
60   PORT_BIT( 0x0001, IP_ACTIVE_HIGH, IPT_BUTTON9 )        PORT_PLAYER(1) PORT_NAME("P1 Button C \xE2\x86\x92") /* Right */
61
62   PORT_START("P1_ANALOG_X")
63   PORT_BIT( 0xff, 0x80, IPT_AD_STICK_X ) PORT_MINMAX(0x00,0xff) PORT_SENSITIVITY(30) PORT_KEYDELTA(30) PORT_PLAYER(1)
64
65   PORT_START("P1_ANALOG_Y")
66   PORT_BIT( 0xff, 0x80, IPT_AD_STICK_Y ) PORT_MINMAX(0x00,0xff) PORT_SENSITIVITY(30) PORT_KEYDELTA(30) PORT_PLAYER(1) PORT_REVERSE
67
68   PORT_START("P2")
69   PORT_BIT( 0x8000, IP_ACTIVE_HIGH, IPT_BUTTON1 )        PORT_PLAYER(2) PORT_NAME("P2 Button A")
70   PORT_BIT( 0x4000, IP_ACTIVE_HIGH, IPT_BUTTON2 )        PORT_PLAYER(2) PORT_NAME("P2 Button B")
71   PORT_BIT( 0x2000, IP_ACTIVE_HIGH, IPT_BUTTON3 )        PORT_PLAYER(2) PORT_NAME("P2 Button Z")
72   PORT_BIT( 0x1000, IP_ACTIVE_HIGH, IPT_START )          PORT_PLAYER(2) PORT_NAME("P2 Start")
73   PORT_BIT( 0x0800, IP_ACTIVE_HIGH, IPT_JOYSTICK_UP )    PORT_PLAYER(2) PORT_NAME("P2 Joypad \xE2\x86\x91") /* Up */
74   PORT_BIT( 0x0400, IP_ACTIVE_HIGH, IPT_JOYSTICK_DOWN )  PORT_PLAYER(2) PORT_NAME("P2 Joypad \xE2\x86\x93") /* Down */
75   PORT_BIT( 0x0200, IP_ACTIVE_HIGH, IPT_JOYSTICK_LEFT )  PORT_PLAYER(2) PORT_NAME("P2 Joypad \xE2\x86\x90") /* Left */
76   PORT_BIT( 0x0100, IP_ACTIVE_HIGH, IPT_JOYSTICK_RIGHT ) PORT_PLAYER(2) PORT_NAME("P2 Joypad \xE2\x86\x92") /* Right */
77   PORT_BIT( 0x00c0, IP_ACTIVE_HIGH, IPT_UNUSED )
78   PORT_BIT( 0x0020, IP_ACTIVE_HIGH, IPT_BUTTON4 )        PORT_PLAYER(2) PORT_NAME("P2 Button L")
79   PORT_BIT( 0x0010, IP_ACTIVE_HIGH, IPT_BUTTON5 )        PORT_PLAYER(2) PORT_NAME("P2 Button R")
80   PORT_BIT( 0x0008, IP_ACTIVE_HIGH, IPT_BUTTON6 )        PORT_PLAYER(2) PORT_NAME("P2 Button C \xE2\x86\x91") /* Up */
81   PORT_BIT( 0x0004, IP_ACTIVE_HIGH, IPT_BUTTON7 )        PORT_PLAYER(2) PORT_NAME("P2 Button C \xE2\x86\x93") /* Down */
82   PORT_BIT( 0x0002, IP_ACTIVE_HIGH, IPT_BUTTON8 )        PORT_PLAYER(2) PORT_NAME("P2 Button C \xE2\x86\x90") /* Left */
83   PORT_BIT( 0x0001, IP_ACTIVE_HIGH, IPT_BUTTON9 )        PORT_PLAYER(2) PORT_NAME("P2 Button C \xE2\x86\x92") /* Right */
84
85   PORT_START("P2_ANALOG_X")
86   PORT_BIT( 0xff, 0x80, IPT_AD_STICK_X ) PORT_MINMAX(0x00,0xff) PORT_SENSITIVITY(30) PORT_KEYDELTA(30) PORT_PLAYER(2)
87
88   PORT_START("P2_ANALOG_Y")
89   PORT_BIT( 0xff, 0x80, IPT_AD_STICK_Y ) PORT_MINMAX(0x00,0xff) PORT_SENSITIVITY(30) PORT_KEYDELTA(30) PORT_PLAYER(2) PORT_REVERSE
90
91INPUT_PORTS_END
92
93/* ?? */
94static const mips3_config config =
95{
96   16384,            /* code cache size */
97   8192,            /* data cache size */
98   62500000         /* system clock */
99};
100
101static INTERRUPT_GEN( n64_vblank )
102{
103   signal_rcp_interrupt(device->machine(), VI_INTERRUPT);
104}
105
106static DEVICE_IMAGE_LOAD(n64_cart)
107{
108   int i, length;
109   UINT8 *cart = image.device().machine().region("user2")->base();
110
111   if (image.software_entry() == NULL)
112   {
113      length = image.fread( cart, 0x4000000);
114   }
115   else
116   {
117      length = image.get_software_region_length("rom");
118      memcpy(cart, image.get_software_region("rom"), length);
119   }
120
121   if (cart[0] == 0x37 && cart[1] == 0x80)
122   {
123      for (i = 0; i < length; i += 4)
124      {
125         UINT8 b1 = cart[i + 0];
126         UINT8 b2 = cart[i + 1];
127         UINT8 b3 = cart[i + 2];
128         UINT8 b4 = cart[i + 3];
129         cart[i + 0] = b3;
130         cart[i + 1] = b4;
131         cart[i + 2] = b1;
132         cart[i + 3] = b2;
133      }
134   }
135   else
136   {
137      for (i = 0; i < length; i += 4)
138      {
139         UINT8 b1 = cart[i + 0];
140         UINT8 b2 = cart[i + 1];
141         UINT8 b3 = cart[i + 2];
142         UINT8 b4 = cart[i + 3];
143         cart[i + 0] = b4;
144         cart[i + 1] = b3;
145         cart[i + 2] = b2;
146         cart[i + 3] = b1;
147      }
148   }
149
150   logerror("cart length = %d\n", length);
151   return IMAGE_INIT_PASS;
152}
153
154static MACHINE_CONFIG_START( n64, _n64_state )
155
156   /* basic machine hardware */
157   MCFG_CPU_ADD("maincpu", VR4300BE, 93750000)
158   MCFG_CPU_CONFIG(config)
159   MCFG_CPU_PROGRAM_MAP(n64_map)
160   MCFG_CPU_VBLANK_INT("screen", n64_vblank)
161
162   MCFG_CPU_ADD("rsp", RSP, 62500000)
163   MCFG_CPU_CONFIG(n64_rsp_config)
164   MCFG_CPU_PROGRAM_MAP(rsp_map)
165
166   MCFG_MACHINE_START( n64 )
167   MCFG_MACHINE_RESET( n64 )
168   MCFG_QUANTUM_TIME(attotime::from_hz(600))
169
170   /* video hardware */
171   MCFG_SCREEN_ADD("screen", RASTER)
172   MCFG_SCREEN_REFRESH_RATE(60)
173   MCFG_SCREEN_VBLANK_TIME(ATTOSECONDS_IN_USEC(0))
174   MCFG_SCREEN_FORMAT(BITMAP_FORMAT_RGB32)
175   MCFG_SCREEN_SIZE(640, 525)
176   MCFG_SCREEN_VISIBLE_AREA(0, 639, 0, 239)
177   MCFG_SCREEN_UPDATE(n64)
178
179   MCFG_PALETTE_LENGTH(0x1000)
180
181   MCFG_VIDEO_START(n64)
182
183   MCFG_SPEAKER_STANDARD_STEREO("lspeaker", "rspeaker")
184
185   MCFG_SOUND_ADD("dac2", DMADAC, 0)
186   MCFG_SOUND_ROUTE(ALL_OUTPUTS, "lspeaker", 1.0)
187   MCFG_SOUND_ADD("dac1", DMADAC, 0)
188   MCFG_SOUND_ROUTE(ALL_OUTPUTS, "rspeaker", 1.0)
189
190   /* cartridge */
191   MCFG_CARTSLOT_ADD("cart")
192   MCFG_CARTSLOT_EXTENSION_LIST("v64,z64,rom,n64,bin")
193   MCFG_CARTSLOT_MANDATORY
194   MCFG_CARTSLOT_INTERFACE("n64_cart")
195   MCFG_CARTSLOT_LOAD(n64_cart)
196
197   /* software lists */
198   MCFG_SOFTWARE_LIST_ADD("cart_list","n64")
199MACHINE_CONFIG_END
200
201ROM_START( n64 )
202   ROM_REGION( 0x800000, "maincpu", ROMREGION_ERASEFF )      /* dummy region for R4300 */
203
204   ROM_REGION32_BE( 0x800, "user1", 0 )
205   ROM_LOAD( "pifdata.bin", 0x0000, 0x0800, CRC(5ec82be9) SHA1(9174eadc0f0ea2654c95fd941406ab46b9dc9bdd) )
206
207   ROM_REGION32_BE( 0x4000000, "user2", ROMREGION_ERASEFF)
208
209   ROM_REGION16_BE( 0x80, "normpoint", 0 )
210   ROM_LOAD( "normpnt.rom", 0x00, 0x80, CRC(e7f2a005) SHA1(c27b4a364a24daeee6e99fd286753fd6216362b4) )
211
212   ROM_REGION16_BE( 0x80, "normslope", 0 )
213   ROM_LOAD( "normslp.rom", 0x00, 0x80, CRC(4f2ae525) SHA1(eab43f8cc52c8551d9cff6fced18ef80eaba6f05) )
214ROM_END
215
216CONS(1996, n64,    0,      0,      n64,   n64,   0,   "Nintendo", "Nintendo 64", GAME_IMPERFECT_GRAPHICS | GAME_IMPERFECT_SOUND )
src/mame/drivers/a310.c
r11531r11532
1/******************************************************************************
2 *
3 *  Acorn Archimedes 310
4 *
5 *  Skeleton: Juergen Buchmueller <pullmoll@t-online.de>, Jul 2000
6 *  Enhanced: R. Belmont, June 2007
7 *  Angelo Salese, August 2010
8 *
9 *  TODO:
10 *  - try to understand why bios 2 was working at some point and now isn't
11 *  - fix RISC OS / Arthur booting, possible causes:
12 *  \- missing reset page size hook-up
13 *  \- some subtle memory paging fault
14 *  \- missing RAM max size
15 *  \- ARM bug?
16 *
17 *
18=======================================================================================
19 *
20 *      Memory map (from http://b-em.bbcmicro.com/arculator/archdocs.txt)
21 *
22 *  0000000 - 1FFFFFF - logical RAM (32 meg)
23 *  2000000 - 2FFFFFF - physical RAM (supervisor only - max 16MB - requires quad MEMCs)
24 *  3000000 - 33FFFFF - IOC (IO controllers - supervisor only)
25 *  3310000 - FDC - WD1772
26 *  33A0000 - Econet - 6854
27 *  33B0000 - Serial - 6551
28 *  3240000 - 33FFFFF - internal expansion cards
29 *  32D0000 - hard disc controller (not IDE) - HD63463
30 *  3350010 - printer
31 *  3350018 - latch A
32 *  3350040 - latch B
33 *  3270000 - external expansion cards
34 *
35 *  3400000 - 3FFFFFF - ROM (read - 12 meg - Arthur and RiscOS 2 512k, RiscOS 3 2MB)
36 *  3400000 - 37FFFFF - Low ROM  (4 meg, I think this is expansion ROMs)
37 *  3800000 - 3FFFFFF - High ROM (main OS ROM)
38 *
39 *  3400000 - 35FFFFF - VICD10 (write - supervisor only)
40 *  3600000 - 3FFFFFF - MEMC (write - supervisor only)
41 *
42 *****************************************************************************/
43/*
44    DASM of code (bios 2 / RISC OS 2)
45    0x380d4e0: MEMC: control to 0x10c (page size 32 kbytes, DRAM ram refresh only during flyback)
46    0x380d4f0: VIDC: params (screen + sound frequency)
47    0x380d51c: IOC: sets control to 0xff, clear IRQA and FIQ masks, sets IRQB mask to 0x80 (keyboard receive full irq)
48    0x380d530: IOC: sets timer 0 to 0x4e20, go command
49        0x380e0a8: work RAM physical check, max size etc.
50    0x380e1f8: IOC: Disables DRAM ram refresh, sets timer 1 to 0x7ffe, go command, then it tests the latch of this timer, enables DRAM refresh
51        0x380d00c: Set up default logical space
52        0x380d16c: Set up case by case logical space
53
54
55*/
56
57
58#include "emu.h"
59#include "machine/wd17xx.h"
60#include "imagedev/flopdrv.h"
61#include "cpu/arm/arm.h"
62#include "sound/dac.h"
63#include "includes/archimds.h"
64#include "machine/i2cmem.h"
65#include "machine/ram.h"
66
67
68class a310_state : public driver_device
69{
70public:
71   a310_state(const machine_config &mconfig, device_type type, const char *tag)
72      : driver_device(mconfig, type, tag) { }
73
74};
75
76
77static WRITE_LINE_DEVICE_HANDLER( a310_wd177x_intrq_w )
78{
79   if (state)
80      archimedes_request_fiq(device->machine(), ARCHIMEDES_FIQ_FLOPPY);
81   else
82      archimedes_clear_fiq(device->machine(), ARCHIMEDES_FIQ_FLOPPY);
83}
84
85static WRITE_LINE_DEVICE_HANDLER( a310_wd177x_drq_w )
86{
87   if (state)
88      archimedes_request_fiq(device->machine(), ARCHIMEDES_FIQ_FLOPPY_DRQ);
89   else
90      archimedes_clear_fiq(device->machine(), ARCHIMEDES_FIQ_FLOPPY_DRQ);
91}
92
93static READ32_HANDLER( a310_psy_wram_r )
94{
95   return archimedes_memc_physmem[offset];
96}
97
98static WRITE32_HANDLER( a310_psy_wram_w )
99{
100   COMBINE_DATA(&archimedes_memc_physmem[offset]);
101}
102
103
104static DRIVER_INIT(a310)
105{
106   UINT32 ram_size = ram_get_size(machine.device(RAM_TAG));
107
108   archimedes_memc_physmem = auto_alloc_array(machine, UINT32, 0x01000000);
109
110   machine.device("maincpu")->memory().space(AS_PROGRAM)->install_legacy_readwrite_handler( 0x02000000, 0x02000000+(ram_size-1), FUNC(a310_psy_wram_r), FUNC(a310_psy_wram_w) );
111
112   archimedes_driver_init(machine);
113}
114
115static MACHINE_START( a310 )
116{
117   archimedes_init(machine);
118
119   // reset the DAC to centerline
120   //dac_signed_data_w(machine.device("dac"), 0x80);
121}
122
123static MACHINE_RESET( a310 )
124{
125   archimedes_reset(machine);
126}
127
128static ADDRESS_MAP_START( a310_mem, AS_PROGRAM, 32 )
129   AM_RANGE(0x00000000, 0x01ffffff) AM_READWRITE(archimedes_memc_logical_r, archimedes_memc_logical_w)
130//  AM_RANGE(0x02000000, 0x02ffffff) AM_RAM AM_BASE(&archimedes_memc_physmem) /* physical RAM - 16 MB for now, should be 512k for the A310 */
131   AM_RANGE(0x03000000, 0x033fffff) AM_READWRITE(archimedes_ioc_r, archimedes_ioc_w)
132   AM_RANGE(0x03400000, 0x035fffff) AM_READWRITE(archimedes_vidc_r, archimedes_vidc_w)
133   AM_RANGE(0x03600000, 0x037fffff) AM_READWRITE(archimedes_memc_r, archimedes_memc_w)
134   AM_RANGE(0x03800000, 0x03ffffff) AM_ROM AM_REGION("maincpu", 0) AM_WRITE(archimedes_memc_page_w)
135ADDRESS_MAP_END
136
137
138static INPUT_PORTS_START( a310 )
139   PORT_START("dip") /* DIP switches */
140   PORT_BIT(0xfd, 0xfd, IPT_UNUSED)
141
142   PORT_START("key0") /* KEY ROW 0 */
143   PORT_BIT(0x01, 0x00, IPT_KEYBOARD) PORT_NAME("ESC") PORT_CODE(KEYCODE_ESC)
144   PORT_BIT(0x02, 0x00, IPT_KEYBOARD) PORT_NAME("1  !") PORT_CODE(KEYCODE_1)
145   PORT_BIT(0x04, 0x00, IPT_KEYBOARD) PORT_NAME("2  \"") PORT_CODE(KEYCODE_2)
146   PORT_BIT(0x08, 0x00, IPT_KEYBOARD) PORT_NAME("3  #") PORT_CODE(KEYCODE_3)
147   PORT_BIT(0x10, 0x00, IPT_KEYBOARD) PORT_NAME("4  $") PORT_CODE(KEYCODE_4)
148   PORT_BIT(0x20, 0x00, IPT_KEYBOARD) PORT_NAME("5  %") PORT_CODE(KEYCODE_5)
149   PORT_BIT(0x40, 0x00, IPT_KEYBOARD) PORT_NAME("6  &") PORT_CODE(KEYCODE_6)
150   PORT_BIT(0x80, 0x00, IPT_KEYBOARD) PORT_NAME("7  '") PORT_CODE(KEYCODE_7)
151
152   PORT_START("key1") /* KEY ROW 1 */
153   PORT_BIT(0x01, 0x00, IPT_KEYBOARD) PORT_NAME("8  *") PORT_CODE(KEYCODE_8)
154   PORT_BIT(0x02, 0x00, IPT_KEYBOARD) PORT_NAME("9  (") PORT_CODE(KEYCODE_9)
155   PORT_BIT(0x04, 0x00, IPT_KEYBOARD) PORT_NAME("0  )") PORT_CODE(KEYCODE_0)
156   PORT_BIT(0x08, 0x00, IPT_KEYBOARD) PORT_NAME("-  _") PORT_CODE(KEYCODE_MINUS)
157   PORT_BIT(0x10, 0x00, IPT_KEYBOARD) PORT_NAME("=  +") PORT_CODE(KEYCODE_EQUALS)
158   PORT_BIT(0x20, 0x00, IPT_KEYBOARD) PORT_NAME("`  ~") PORT_CODE(KEYCODE_TILDE)
159   PORT_BIT(0x40, 0x00, IPT_KEYBOARD) PORT_NAME("BACK SPACE") PORT_CODE(KEYCODE_BACKSPACE)
160   PORT_BIT(0x80, 0x00, IPT_KEYBOARD) PORT_NAME("TAB") PORT_CODE(KEYCODE_TAB)
161
162   PORT_START("key2") /* KEY ROW 2 */
163   PORT_BIT(0x01, 0x00, IPT_KEYBOARD) PORT_NAME("q  Q") PORT_CODE(KEYCODE_Q)
164   PORT_BIT(0x02, 0x00, IPT_KEYBOARD) PORT_NAME("w  W") PORT_CODE(KEYCODE_W)
165   PORT_BIT(0x04, 0x00, IPT_KEYBOARD) PORT_NAME("e  E") PORT_CODE(KEYCODE_E)
166   PORT_BIT(0x08, 0x00, IPT_KEYBOARD) PORT_NAME("r  R") PORT_CODE(KEYCODE_R)
167   PORT_BIT(0x10, 0x00, IPT_KEYBOARD) PORT_NAME("t  T") PORT_CODE(KEYCODE_T)
168   PORT_BIT(0x20, 0x00, IPT_KEYBOARD) PORT_NAME("y  Y") PORT_CODE(KEYCODE_Y)
169   PORT_BIT(0x40, 0x00, IPT_KEYBOARD) PORT_NAME("u  U") PORT_CODE(KEYCODE_U)
170   PORT_BIT(0x80, 0x00, IPT_KEYBOARD) PORT_NAME("i  I") PORT_CODE(KEYCODE_I)
171
172   PORT_START("key3") /* KEY ROW 3 */
173   PORT_BIT(0x01, 0x00, IPT_KEYBOARD) PORT_NAME("o  O") PORT_CODE(KEYCODE_O)
174   PORT_BIT(0x02, 0x00, IPT_KEYBOARD) PORT_NAME("p  P") PORT_CODE(KEYCODE_P)
175   PORT_BIT(0x04, 0x00, IPT_KEYBOARD) PORT_NAME("[  {") PORT_CODE(KEYCODE_OPENBRACE)
176   PORT_BIT(0x08, 0x00, IPT_KEYBOARD) PORT_NAME("]  }") PORT_CODE(KEYCODE_CLOSEBRACE)
177   PORT_BIT(0x10, 0x00, IPT_KEYBOARD) PORT_NAME("RETURN") PORT_CODE(KEYCODE_ENTER)
178   PORT_BIT(0x20, 0x00, IPT_KEYBOARD) PORT_NAME("DEL") PORT_CODE(KEYCODE_DEL)
179   PORT_BIT(0x40, 0x00, IPT_KEYBOARD) PORT_NAME("CTRL") PORT_CODE(KEYCODE_LCONTROL)
180   PORT_BIT(0x80, 0x80, IPT_KEYBOARD) PORT_NAME("CAPS LOCK") PORT_CODE(KEYCODE_CAPSLOCK) PORT_TOGGLE
181
182   PORT_START("key4") /* KEY ROW 4 */
183   PORT_BIT(0x01, 0x00, IPT_KEYBOARD) PORT_NAME("a  A") PORT_CODE(KEYCODE_A)
184   PORT_BIT(0x02, 0x00, IPT_KEYBOARD) PORT_NAME("s  S") PORT_CODE(KEYCODE_S)
185   PORT_BIT(0x04, 0x00, IPT_KEYBOARD) PORT_NAME("d  D") PORT_CODE(KEYCODE_D)
186   PORT_BIT(0x08, 0x00, IPT_KEYBOARD) PORT_NAME("f  F") PORT_CODE(KEYCODE_F)
187   PORT_BIT(0x10, 0x00, IPT_KEYBOARD) PORT_NAME("g  G") PORT_CODE(KEYCODE_G)
188   PORT_BIT(0x20, 0x00, IPT_KEYBOARD) PORT_NAME("h  H") PORT_CODE(KEYCODE_H)
189   PORT_BIT(0x40, 0x00, IPT_KEYBOARD) PORT_NAME("j  J") PORT_CODE(KEYCODE_J)
190   PORT_BIT(0x80, 0x00, IPT_KEYBOARD) PORT_NAME("k  K") PORT_CODE(KEYCODE_K)
191
192   PORT_START("key5") /* KEY ROW 5 */
193   PORT_BIT(0x01, 0x00, IPT_KEYBOARD) PORT_NAME("l  L") PORT_CODE(KEYCODE_L)
194   PORT_BIT(0x02, 0x00, IPT_KEYBOARD) PORT_NAME(";  :") PORT_CODE(KEYCODE_COLON)
195   PORT_BIT(0x04, 0x00, IPT_KEYBOARD) PORT_NAME("'  \"") PORT_CODE(KEYCODE_QUOTE)
196   PORT_BIT(0x08, 0x00, IPT_KEYBOARD) PORT_NAME("\\  |") PORT_CODE(KEYCODE_ASTERISK)
197   PORT_BIT(0x10, 0x00, IPT_KEYBOARD) PORT_NAME("SHIFT (L)") PORT_CODE(KEYCODE_LSHIFT)
198   PORT_BIT(0x20, 0x00, IPT_KEYBOARD) PORT_NAME("z  Z") PORT_CODE(KEYCODE_Z)
199   PORT_BIT(0x40, 0x00, IPT_KEYBOARD) PORT_NAME("x  X") PORT_CODE(KEYCODE_X)
200   PORT_BIT(0x80, 0x00, IPT_KEYBOARD) PORT_NAME("c  C") PORT_CODE(KEYCODE_C)
201
202   PORT_START("key6") /* KEY ROW 6 */
203   PORT_BIT(0x01, 0x00, IPT_KEYBOARD) PORT_NAME("v  V") PORT_CODE(KEYCODE_V)
204   PORT_BIT(0x02, 0x00, IPT_KEYBOARD) PORT_NAME("b  B") PORT_CODE(KEYCODE_B)
205   PORT_BIT(0x04, 0x00, IPT_KEYBOARD) PORT_NAME("n  N") PORT_CODE(KEYCODE_N)
206   PORT_BIT(0x08, 0x00, IPT_KEYBOARD) PORT_NAME("m  M") PORT_CODE(KEYCODE_M)
207   PORT_BIT(0x10, 0x00, IPT_KEYBOARD) PORT_NAME(",  <") PORT_CODE(KEYCODE_COMMA)
208   PORT_BIT(0x20, 0x00, IPT_KEYBOARD) PORT_NAME(".  >") PORT_CODE(KEYCODE_STOP)
209   PORT_BIT(0x40, 0x00, IPT_KEYBOARD) PORT_NAME("/  ?") PORT_CODE(KEYCODE_SLASH)
210   PORT_BIT(0x80, 0x00, IPT_KEYBOARD) PORT_NAME("SHIFT (R)") PORT_CODE(KEYCODE_RSHIFT)
211
212   PORT_START("key7") /* KEY ROW 7 */
213   PORT_BIT(0x01, 0x00, IPT_KEYBOARD) PORT_NAME("LINE FEED")
214   PORT_BIT(0x02, 0x00, IPT_KEYBOARD) PORT_NAME("SPACE") PORT_CODE(KEYCODE_SPACE)
215   PORT_BIT(0x04, 0x00, IPT_KEYBOARD) PORT_NAME("- (KP)") PORT_CODE(KEYCODE_MINUS_PAD)
216   PORT_BIT(0x08, 0x00, IPT_KEYBOARD) PORT_NAME(", (KP)") PORT_CODE(KEYCODE_PLUS_PAD)
217   PORT_BIT(0x10, 0x00, IPT_KEYBOARD) PORT_NAME("ENTER (KP)") PORT_CODE(KEYCODE_ENTER_PAD)
218   PORT_BIT(0x20, 0x00, IPT_KEYBOARD) PORT_NAME(". (KP)") PORT_CODE(KEYCODE_DEL_PAD)
219   PORT_BIT(0x40, 0x00, IPT_KEYBOARD) PORT_NAME("0 (KP)") PORT_CODE(KEYCODE_0_PAD)
220   PORT_BIT(0x80, 0x00, IPT_KEYBOARD) PORT_NAME("1 (KP)") PORT_CODE(KEYCODE_1_PAD)
221
222   PORT_START("key8") /* KEY ROW 8 */
223   PORT_BIT(0x01, 0x00, IPT_KEYBOARD) PORT_NAME("2 (KP)") PORT_CODE(KEYCODE_2_PAD)
224   PORT_BIT(0x02, 0x00, IPT_KEYBOARD) PORT_NAME("3 (KP)") PORT_CODE(KEYCODE_3_PAD)
225   PORT_BIT(0x04, 0x00, IPT_KEYBOARD) PORT_NAME("4 (KP)") PORT_CODE(KEYCODE_4_PAD)
226   PORT_BIT(0x08, 0x00, IPT_KEYBOARD) PORT_NAME("5 (KP)") PORT_CODE(KEYCODE_5_PAD)
227   PORT_BIT(0x10, 0x00, IPT_KEYBOARD) PORT_NAME("6 (KP)") PORT_CODE(KEYCODE_6_PAD)
228   PORT_BIT(0x20, 0x00, IPT_KEYBOARD) PORT_NAME("7 (KP)") PORT_CODE(KEYCODE_7_PAD)
229   PORT_BIT(0x40, 0x00, IPT_KEYBOARD) PORT_NAME("8 (KP)") PORT_CODE(KEYCODE_8_PAD)
230   PORT_BIT(0x80, 0x00, IPT_KEYBOARD) PORT_NAME("9 (KP)") PORT_CODE(KEYCODE_9_PAD)
231
232   PORT_START("via1a") /* VIA #1 PORT A */
233   PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_START) PORT_PLAYER(1)
234   PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_START) PORT_PLAYER(2)
235   PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_BUTTON1                )
236   PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_BUTTON2                )
237   PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT) PORT_4WAY
238   PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_JOYSTICK_UP) PORT_4WAY
239   PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT) PORT_4WAY
240   PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN) PORT_4WAY
241
242   PORT_START("tape")/* tape control */
243   PORT_BIT(0x01, 0x00, IPT_KEYBOARD) PORT_NAME("TAPE STOP") PORT_CODE(KEYCODE_F5)
244   PORT_BIT(0x02, 0x00, IPT_KEYBOARD) PORT_NAME("TAPE PLAY") PORT_CODE(KEYCODE_F6)
245   PORT_BIT(0x04, 0x00, IPT_KEYBOARD) PORT_NAME("TAPE REW") PORT_CODE(KEYCODE_F7)
246   PORT_BIT (0xf8, 0x80, IPT_UNUSED)
247INPUT_PORTS_END
248
249static const wd17xx_interface a310_wd17xx_interface =
250{
251   DEVCB_NULL,
252   DEVCB_LINE(a310_wd177x_intrq_w),
253   DEVCB_LINE(a310_wd177x_drq_w),
254   {FLOPPY_0, FLOPPY_1, FLOPPY_2, FLOPPY_3}
255};
256
257static const i2cmem_interface i2cmem_interface =
258{
259   I2CMEM_SLAVE_ADDRESS, 0, 0x100
260};
261
262static MACHINE_CONFIG_START( a310, a310_state )
263   /* basic machine hardware */
264   MCFG_CPU_ADD("maincpu", ARM, 8000000)        /* 8 MHz */
265   MCFG_CPU_PROGRAM_MAP(a310_mem)
266
267   MCFG_MACHINE_START( a310 )
268   MCFG_MACHINE_RESET( a310 )
269
270   MCFG_I2CMEM_ADD("i2cmem",i2cmem_interface)
271
272   /* video hardware */
273   MCFG_SCREEN_ADD("screen", RASTER)
274   MCFG_SCREEN_REFRESH_RATE(60)
275   MCFG_SCREEN_VBLANK_TIME(ATTOSECONDS_IN_USEC(2500)) /* not accurate */
276   MCFG_SCREEN_FORMAT(BITMAP_FORMAT_RGB32)
277   MCFG_SCREEN_SIZE(1280, 1024) //TODO: default screen size
278   MCFG_SCREEN_VISIBLE_AREA(0*8, 1280 - 1, 0*16, 1024 - 1)
279   MCFG_SCREEN_UPDATE(archimds_vidc)
280
281   MCFG_PALETTE_LENGTH(32768)
282
283   MCFG_VIDEO_START(archimds_vidc)
284
285   MCFG_RAM_ADD(RAM_TAG)
286   MCFG_RAM_DEFAULT_SIZE("2M")
287   MCFG_RAM_EXTRA_OPTIONS("512K, 1M, 4M, 8M, 16M")
288
289   MCFG_WD1772_ADD("wd1772", a310_wd17xx_interface )
290
291   //MCFG_FLOPPY_4_DRIVES_ADD(a310_floppy_config)
292
293   MCFG_SPEAKER_STANDARD_MONO("mono")
294   MCFG_SOUND_ADD("dac0", DAC, 0)
295   MCFG_SOUND_ROUTE(0, "mono", 0.10)
296
297   MCFG_SOUND_ADD("dac1", DAC, 0)
298   MCFG_SOUND_ROUTE(0, "mono", 0.10)
299
300   MCFG_SOUND_ADD("dac2", DAC, 0)
301   MCFG_SOUND_ROUTE(0, "mono", 0.10)
302
303   MCFG_SOUND_ADD("dac3", DAC, 0)
304   MCFG_SOUND_ROUTE(0, "mono", 0.10)
305
306   MCFG_SOUND_ADD("dac4", DAC, 0)
307   MCFG_SOUND_ROUTE(0, "mono", 0.10)
308
309   MCFG_SOUND_ADD("dac5", DAC, 0)
310   MCFG_SOUND_ROUTE(0, "mono", 0.10)
311
312   MCFG_SOUND_ADD("dac6", DAC, 0)
313   MCFG_SOUND_ROUTE(0, "mono", 0.10)
314
315   MCFG_SOUND_ADD("dac7", DAC, 0)
316   MCFG_SOUND_ROUTE(0, "mono", 0.10)
317MACHINE_CONFIG_END
318
319ROM_START(a310)
320   ROM_REGION( 0x800000, "maincpu", 0 )
321   ROM_SYSTEM_BIOS( 0, "311", "RiscOS 3.11 (29 Sep 1992)" )
322   ROMX_LOAD( "ic24.rom", 0x000000, 0x80000, CRC(c1adde84) SHA1(12d060e0401dd0523d44453f947bdc55dd2c3240), ROM_BIOS(1) )
323   ROMX_LOAD( "ic25.rom", 0x080000, 0x80000, CRC(15d89664) SHA1(78f5d0e6f1e8ee603317807f53ff8fe65a3b3518), ROM_BIOS(1) )
324   ROMX_LOAD( "ic26.rom", 0x100000, 0x80000, CRC(a81ceb7c) SHA1(46b870876bc1f68f242726415f0c49fef7be0c72), ROM_BIOS(1) )
325   ROMX_LOAD( "ic27.rom", 0x180000, 0x80000, CRC(707b0c6c) SHA1(345199a33fed23996374b9db8170a52ab63f0380), ROM_BIOS(1) )
326   ROM_SYSTEM_BIOS( 1, "120", "Arthur/RiscOS 1.20 (25 Sep 1987)" )
327   ROMX_LOAD( "arthur.bin",   0x000000, 0x080000, CRC(eb3fda57) SHA1(1181ff9c2c2f3d6d414054ec33b2260404bafc81), ROM_BIOS(2) )
328   ROM_SYSTEM_BIOS( 2, "200", "RiscOS 2.0 (05 Oct 1988)" )
329   ROMX_LOAD( "riscos2.bin",  0x000000, 0x080000, CRC(89c4ad36) SHA1(b82a78830dac386f9b649b6d32a34f9c6910546d), ROM_BIOS(3) )
330
331   ROM_REGION( 0x200000, "vram", ROMREGION_ERASE00 )
332
333   ROM_REGION( 0x100, "i2cmem", ROMREGION_ERASE00 )
334ROM_END
335
336/*    YEAR  NAME  PARENT  COMPAT  MACHINE  INPUT  INIT   COMPANY  FULLNAME */
337COMP( 1988, a310, 0,      0,      a310,    a310,  a310,   "Acorn", "Archimedes 310", GAME_NOT_WORKING)
src/mess/devices/aescart.c
r0r11532
1/**********************************************************************
2
3    aescart.c
4
5    Neo-Geo AES cartridge management
6    R. Belmont, 2009
7
8    Based on ti99cart.c by Michael Zapf
9
10    We leave the support in place for multiple slots in case MAME
11    uses this at some future point for MVS multi-cart.
12
13*********************************************************************/
14#include "emu.h"
15#include "aescart.h"
16#include "imagedev/cartslot.h"
17#include "imagedev/multcart.h"
18#include "includes/neogeo.h"
19
20typedef int assmfct(running_machine &machine, device_t *);
21
22enum
23{
24   AESCART_FCT_ASSM = DEVINFO_FCT_DEVICE_SPECIFIC,
25   AESCART_FCT_DISASSM
26};
27
28struct _aes_multicart_t
29{
30   /* Reserves space for all cartridges. This is also used in the legacy
31       cartridge system, but only for slot 0. */
32   aescartridge_t cartridge[AES_NUMBER_OF_CARTRIDGE_SLOTS];
33
34   /* Determines which slot is currently active. This value is changed when there
35    are accesses to other GROM base addresses. */
36   int active_slot;
37
38   /* Used in order to enforce a special slot. This value is retrieved
39       from the dipswitch setting. A value of -1 means automatic, that is,
40       the grom base switch is used. Values 0 .. max refer to the
41       respective slot. */
42   int fixed_slot;
43
44   /* Holds the highest index of a cartridge being plugged in plus one.
45       If we only have one cartridge inserted, we don't want to get a
46       selection option, so we just mirror the memory contents. */
47   int next_free_slot;
48
49   /* Counts the number of slots which currently contain legacy format
50       cartridge images. */
51   int legacy_slots;
52
53   /* Counts the number of slots which currently contain new format
54       cartridge images. */
55   int multi_slots;
56};
57typedef struct _aes_multicart_t aes_multicart_t;
58
59#define AUTO -1
60
61/* Access to the pcb. Contained in the token of the pcb instance. */
62struct _aes_pcb_t
63{
64   /* Link up to the cartridge structure which contains this pcb. */
65   aescartridge_t *cartridge;
66
67   /* Function to assemble this cartridge. */
68   assmfct   *assemble;
69
70   /* Function to disassemble this cartridge. */
71   assmfct   *disassemble;
72};
73typedef struct _aes_pcb_t aes_pcb_t;
74
75INLINE aes_multicart_t *get_safe_token(device_t *device)
76{
77   assert(device != NULL);
78   assert(device->type() == AES_MULTICART);
79
80   return (aes_multicart_t *)downcast<legacy_device_base *>(device)->token();
81}
82
83INLINE aes_pcb_t *get_safe_pcb_token(device_t *device)
84{
85   assert(device != NULL);
86   assert(device->type() == AES_CARTRIDGE_PCB_NONE || device->type() == AES_CARTRIDGE_PCB_STD);
87
88   return (aes_pcb_t *)downcast<legacy_device_base *>(device)->token();
89}
90
91INLINE cartslot_t *get_safe_cartslot_token(device_t *device)
92{
93   assert(device != NULL);
94   assert(device->type() == CARTSLOT);
95
96   return (cartslot_t *)downcast<legacy_device_base *>(device)->token();
97}
98
99/*
100    Find the index of the cartridge name. We assume the format
101    <name><number>, i.e. the number is the longest string from the right
102    which can be interpreted as a number.
103*/
104static int get_index_from_tagname(device_t *image)
105{
106   const char *tag = image->tag();
107   int maxlen = strlen(tag);
108   int i;
109   for (i=maxlen-1; i >=0; i--)
110      if (tag[i] < 48 || tag[i] > 57) break;
111
112   return atoi(tag+i+1);
113}
114
115/*
116    Common routine to assemble cartridges from resources.
117*/
118static aescartridge_t *assemble_common(running_machine &machine, device_t *cartslot)
119{
120   /* Pointer to the cartridge structure. */
121   aescartridge_t *cartridge;
122   device_t *cartsys = cartslot->owner();
123   aes_multicart_t *cartslots = get_safe_token(cartsys);
124   UINT8 *socketcont, *romrgn;
125   int reslength, i, blockofs;
126   char sprname1[16], sprname2[16];
127
128   int slotnumber = get_index_from_tagname(cartslot)-1;
129   assert(slotnumber>=0 && slotnumber<AES_NUMBER_OF_CARTRIDGE_SLOTS);
130
131   /* There is a cartridge in this slot, check the maximum slot number. */
132   if (cartslots->next_free_slot <= slotnumber)
133   {
134      cartslots->next_free_slot = slotnumber+1;
135   }
136   cartridge = &cartslots->cartridge[slotnumber];
137
138   // check for up to 4 program ROMs
139   romrgn = (UINT8 *)machine.region("maincpu")->base();
140   blockofs = 0;
141   for (i = 0; i < 4; i++)
142   {
143      sprintf(sprname1, "p%d", i+1);
144
145      socketcont = (UINT8*)cartslot_get_socket(cartslot, sprname1);
146      reslength = cartslot_get_resource_length(cartslot, sprname1);
147
148      if (socketcont != NULL)
149      {
150         memcpy(romrgn+blockofs, socketcont, reslength);
151         blockofs += reslength;
152      }
153   }
154
155   // 1 m1 ROM
156   socketcont = (UINT8*)cartslot_get_socket(cartslot, "m1");
157   reslength = cartslot_get_resource_length(cartslot, "m1");
158   if (socketcont != NULL)
159   {
160      romrgn = (UINT8 *)machine.region("audiocpu")->base();
161
162      memcpy(romrgn, socketcont, reslength);
163      // mirror (how does this really work?)
164      memcpy(romrgn+0x10000, socketcont, reslength);
165   }
166
167   // up to 8 YM sample ROMs
168   romrgn = (UINT8 *)machine.region("ymsnd")->base();
169   blockofs = 0;
170   for (i = 0; i < 8; i++)
171   {
172      sprintf(sprname1, "v1%d", i+1);
173
174      socketcont = (UINT8*)cartslot_get_socket(cartslot, sprname1);
175      reslength = cartslot_get_resource_length(cartslot, sprname1);
176
177      if (socketcont != NULL)
178      {
179         memcpy(romrgn+blockofs, socketcont, reslength);
180         blockofs += reslength;
181      }
182   }
183
184   // up to 8 YM delta-T sample ROMs
185   romrgn = (UINT8 *)machine.region("ymsnd.deltat")->base();
186   blockofs = 0;
187   for (i = 0; i < 8; i++)
188   {
189      sprintf(sprname1, "v2%d", i+1);
190
191      socketcont = (UINT8*)cartslot_get_socket(cartslot, sprname1);
192      reslength = cartslot_get_resource_length(cartslot, sprname1);
193
194      if (socketcont != NULL)
195      {
196         memcpy(romrgn+blockofs, socketcont, reslength);
197         blockofs += reslength;
198      }
199   }
200
201   // 1 s1 ROM
202   socketcont = (UINT8*)cartslot_get_socket(cartslot, "s1");
203   reslength = cartslot_get_resource_length(cartslot, "s1");
204   if (socketcont != NULL)
205   {
206      romrgn = (UINT8 *)machine.region("fixed")->base();
207
208      memcpy(romrgn, socketcont, reslength);
209   }
210
211   // up to 8 sprite ROMs in byte-interleaved pairs
212   romrgn = (UINT8 *)machine.region("sprites")->base();
213   blockofs = 0;
214   for (i = 0; i < 8; i+=2)
215   {
216      UINT8 *spr1, *spr2;
217      int j;
218
219      sprintf(sprname1, "c%d", i+1);
220      sprintf(sprname2, "c%d", i+2);
221
222      spr1 = (UINT8*)cartslot_get_socket(cartslot, sprname1);
223      spr2 = (UINT8*)cartslot_get_socket(cartslot, sprname2);
224      reslength = cartslot_get_resource_length(cartslot, sprname1);
225
226      if ((spr1) && (spr2))
227      {
228         for (j = 0; j < reslength; j++)
229         {
230            romrgn[blockofs + (j*2)] = spr1[j];
231            romrgn[blockofs + (j*2) + 1] = spr2[j];
232         }
233
234         blockofs += reslength*2;
235      }
236   }
237
238   return cartridge;
239}
240
241static void set_pointers(device_t *pcb, int index)
242{
243   device_t *cartsys = pcb->owner()->owner();
244   aes_multicart_t *cartslots = get_safe_token(cartsys);
245   aes_pcb_t *pcb_def = get_safe_pcb_token(pcb);
246
247   pcb_def->assemble = (assmfct *)downcast<const legacy_cart_slot_device_base *>(pcb)->get_legacy_fct(AESCART_FCT_ASSM);
248   pcb_def->disassemble = (assmfct *)downcast<const legacy_cart_slot_device_base *>(pcb)->get_legacy_fct(AESCART_FCT_DISASSM);
249
250   pcb_def->cartridge = &cartslots->cartridge[index];
251   pcb_def->cartridge->pcb = pcb;
252}
253
254/*****************************************************************************
255  Cartridge type: None
256    This PCB device is just a pseudo device; the legacy mode is handled
257    by dedicated functions.
258******************************************************************************/
259static DEVICE_START(aes_pcb_none)
260{
261   /* device is aes_cartslot:cartridge:pcb */
262//  printf("DEVICE_START(aes_pcb_none), tag of device=%s\n", device->tag());
263   set_pointers(device, get_index_from_tagname(device->owner())-1);
264}
265
266/*****************************************************************************
267  Cartridge type: Standard
268    Most cartridges are built in this type. This includes word-swapped program,
269    z80 program, YM samples, delta-T samples, sprites, and sfix.
270******************************************************************************/
271
272static DEVICE_START(aes_pcb_std)
273{
274   /* device is aes_cartslot:cartridge:pcb */
275//  printf("DEVICE_START(aes_pcb_std), tag of device=%s\n", device->tag());
276   set_pointers(device, get_index_from_tagname(device->owner())-1);
277}
278
279/*
280    The standard cartridge assemble routine. We just call the common
281    function here.
282*/
283static int assemble_std(running_machine &machine, device_t *image)
284{
285//  aescartridge_t *cart;
286//  printf("assemble_std, %s\n", image->tag);
287   /*cart = */assemble_common(machine, image);
288
289   return IMAGE_INIT_PASS;
290}
291
292/*
293    Removes pointers and restores the state before plugging in the
294    cartridge.
295    The pointer to the location after the last cartridge is adjusted.
296    As it seems, we can use the same function for the disassembling of all
297    cartridge types.
298*/
299static int disassemble_std(device_t *image)
300{
301//  int slotnumber;
302//  int i;
303//  aescartridge_t *cart;
304//  device_t *cartsys = image->owner();
305//  aes_multicart_t *cartslots = (aes_multicart_t *)cartsys->token;
306
307//  slotnumber = get_index_from_tagname(image)-1;
308//  printf("Disassemble cartridge %d\n", slotnumber);
309#if 0
310   /* Search the highest remaining cartridge. */
311   cartslots->next_free_slot = 0;
312   for (i=AES_NUMBER_OF_CARTRIDGE_SLOTS-1; i >= 0; i--)
313   {
314      if (i != slotnumber)
315      {
316         if (0) //!slot_is_empty(cartsys, i))    (for future use?)
317         {
318            cartslots->next_free_slot = i+1;
319//              printf("Setting new next_free_slot to %d\n", cartslots->next_free_slot);
320            break;
321         }
322      }
323   }
324#endif
325   /* Do we have RAM? If so, swap the bytes (undo the BIG_ENDIANIZE) */
326//  cart = &cartslots->cartridge[slotnumber];
327
328//  clear_slot(cartsys, slotnumber);
329
330   return IMAGE_INIT_PASS;
331}
332
333/*****************************************************************************
334  Device metadata
335******************************************************************************/
336
337static DEVICE_GET_INFO(aes_cart_common)
338{
339   switch(state)
340   {
341      /* --- the following bits of info are returned as 64-bit signed integers --- */
342      case DEVINFO_INT_TOKEN_BYTES:
343         info->i = sizeof(aes_pcb_t);
344         break;
345      case DEVINFO_INT_INLINE_CONFIG_BYTES:
346         info->i = 0;
347         break;
348
349      /* --- the following bits of info are returned as pointers to functions --- */
350      case DEVINFO_FCT_START:
351         info->start = DEVICE_START_NAME(aes_pcb_std);
352         break;
353      case DEVINFO_FCT_STOP:
354         /* Nothing */
355         break;
356      case DEVINFO_FCT_RESET:
357         /* Nothing */
358         break;
359
360      case AESCART_FCT_ASSM:
361         info->f = (genf *) assemble_std;
362         break;
363
364      case AESCART_FCT_DISASSM:
365         info->f = (genf *) disassemble_std;
366         break;
367
368      /* --- the following bits of info are returned as NULL-terminated strings --- */
369      case DEVINFO_STR_NAME:
370         strcpy(info->s, "AES standard cartridge pcb");
371         break;
372      case DEVINFO_STR_FAMILY:
373         strcpy(info->s, "AES cartridge pcb");
374         break;
375      case DEVINFO_STR_VERSION:
376         strcpy(info->s, "1.0");
377         break;
378      case DEVINFO_STR_SOURCE_FILE:
379         strcpy(info->s, __FILE__);
380         break;
381      case DEVINFO_STR_CREDITS:
382         /* Nothing */
383         break;
384   }
385}
386
387DEVICE_GET_INFO(aes_cartridge_pcb_none)
388{
389   switch(state)
390   {
391      case DEVINFO_FCT_START:
392         info->start = DEVICE_START_NAME(aes_pcb_none);
393         break;
394
395      case DEVINFO_STR_NAME:
396         strcpy(info->s, "AES empty cartridge");
397         break;
398
399      default:
400         DEVICE_GET_INFO_CALL(aes_cart_common);
401         break;
402   }
403}
404
405DEVICE_GET_INFO(aes_cartridge_pcb_std)
406{
407   DEVICE_GET_INFO_CALL(aes_cart_common);
408}
409
410/*****************************************************************************
411  The cartridge handling of the multi-cartridge system.
412  Every cartridge contains a PCB device. The memory handlers delegate the calls
413  to the respective handlers of the cartridges.
414******************************************************************************/
415/*
416    Initialize a cartridge. Each cartridge contains a PCB device.
417*/
418static DEVICE_START( aes_cartridge )
419{
420   cartslot_t *cart = get_safe_cartslot_token(device);
421
422   /* find the PCB device */
423   cart->pcb_device = device->subdevice(TAG_PCB);
424}
425
426// handle protected carts
427static void install_protection(device_image_interface& image)
428{
429   neogeo_state *state = image.device().machine().driver_data<neogeo_state>();
430   const char *crypt_feature = image.get_feature( "crypt" );
431
432   if(crypt_feature == NULL)
433      return;
434
435   if(strcmp(crypt_feature,"fatfury2_prot") == 0)
436   {
437      fatfury2_install_protection(image.device().machine());
438      logerror("Installed Fatal Fury 2 protection\n");
439   }
440   if(strcmp(crypt_feature,"kof99_crypt") == 0)
441   {
442      kof99_decrypt_68k(image.device().machine());
443      state->m_fixed_layer_bank_type = 1;
444      kof99_neogeo_gfx_decrypt(image.device().machine(), 0x00);
445      kof99_install_protection(image.device().machine());
446      logerror("Decrypted KOF99 code and graphics.\n");
447   }
448   if(strcmp(crypt_feature,"mslug3_crypt") == 0)
449   {
450      state->m_fixed_layer_bank_type = 1;
451      kof99_neogeo_gfx_decrypt(image.device().machine(), 0xad);
452      logerror("Decrypted Metal Slug 3 graphics\n");
453   }
454   if(strcmp(crypt_feature,"matrim_crypt") == 0)
455   {
456      matrim_decrypt_68k(image.device().machine());
457      neo_pcm2_swap(image.device().machine(), 1);
458      state->m_fixed_layer_bank_type = 2;
459      neogeo_cmc50_m1_decrypt(image.device().machine());
460      kof2000_neogeo_gfx_decrypt(image.device().machine(), 0x6a);
461      logerror("Decrypted Matrimelee code, sound and graphics\n");
462   }
463   if(strcmp(crypt_feature,"svc_crypt") == 0)
464   {
465      svc_px_decrypt(image.device().machine());
466      neo_pcm2_swap(image.device().machine(), 3);
467      state->m_fixed_layer_bank_type = 2;
468      neogeo_cmc50_m1_decrypt(image.device().machine());
469      kof2000_neogeo_gfx_decrypt(image.device().machine(), 0x57);
470      install_pvc_protection(image.device().machine());
471      logerror("Decrypted SvC code, sound and graphics.\n");
472   }
473   if(strcmp(crypt_feature,"samsho5_crypt") == 0)
474   {
475      samsho5_decrypt_68k(image.device().machine());
476      neo_pcm2_swap(image.device().machine(), 4);
477      state->m_fixed_layer_bank_type = 1;
478      neogeo_cmc50_m1_decrypt(image.device().machine());
479      kof2000_neogeo_gfx_decrypt(image.device().machine(), 0x0f);
480      logerror("Decrypted Samurai Shodown V code, sound and graphics.\n");
481   }
482   if(strcmp(crypt_feature,"kof2000_crypt") == 0)
483   {
484      kof2000_decrypt_68k(image.device().machine());
485      state->m_fixed_layer_bank_type = 2;
486      neogeo_cmc50_m1_decrypt(image.device().machine());
487      kof2000_neogeo_gfx_decrypt(image.device().machine(), 0x00);
488      kof2000_install_protection(image.device().machine());
489      logerror("Decrypted KOF2000 code, sound and graphics.\n");
490   }
491   if(strcmp(crypt_feature,"kof2001_crypt") == 0)
492   {
493      state->m_fixed_layer_bank_type = 1;
494      kof2000_neogeo_gfx_decrypt(image.device().machine(), 0x1e);
495      neogeo_cmc50_m1_decrypt(image.device().machine());
496      logerror("Decrypted KOF2001 code and graphics.\n");
497   }
498   if(strcmp(crypt_feature,"kof2002_crypt") == 0)
499   {
500      kof2002_decrypt_68k(image.device().machine());
501      neo_pcm2_swap(image.device().machine(), 0);
502      neogeo_cmc50_m1_decrypt(image.device().machine());
503      kof2000_neogeo_gfx_decrypt(image.device().machine(), 0xec);
504      logerror("Decrypted KOF2002 code, sound and graphics.\n");
505   }
506   if(strcmp(crypt_feature,"mslug4_crypt") == 0)
507   {
508      state->m_fixed_layer_bank_type = 1; /* USA violent content screen is wrong -- not a bug, confirmed on real hardware! */
509      neogeo_cmc50_m1_decrypt(image.device().machine());
510      kof2000_neogeo_gfx_decrypt(image.device().machine(), 0x31);
511      neo_pcm2_snk_1999(image.device().machine(), 8);
512      logerror("Decrypted Metal Slug 4 code, sound and graphics.\n");
513   }
514   if(strcmp(crypt_feature,"mslug5_crypt") == 0)
515   {
516      mslug5_decrypt_68k(image.device().machine());
517      neo_pcm2_swap(image.device().machine(), 2);
518      state->m_fixed_layer_bank_type = 1;
519      neogeo_cmc50_m1_decrypt(image.device().machine());
520      kof2000_neogeo_gfx_decrypt(image.device().machine(), 0x19);
521      install_pvc_protection(image.device().machine());
522      logerror("Decrypted Metal Slug 5 code and graphics, and installed protection routines.\n");
523   }
524   if(strcmp(crypt_feature,"kof2003_crypt") == 0)
525   {
526      kof2003h_decrypt_68k(image.device().machine());
527      neo_pcm2_swap(image.device().machine(), 5);
528      state->m_fixed_layer_bank_type = 2;
529      neogeo_cmc50_m1_decrypt(image.device().machine());
530      kof2000_neogeo_gfx_decrypt(image.device().machine(), 0x9d);
531      install_pvc_protection(image.device().machine());
532      logerror("Decrypted KOF2003 code and graphicss, and installed protection routines.\n");
533   }
534   if(strcmp(crypt_feature,"samsho5s_crypt") == 0)
535   {
536      samsh5sp_decrypt_68k(image.device().machine());
537      neo_pcm2_swap(image.device().machine(), 6);
538      state->m_fixed_layer_bank_type = 1;
539      neogeo_cmc50_m1_decrypt(image.device().machine());
540      kof2000_neogeo_gfx_decrypt(image.device().machine(), 0x0d);
541   }
542}
543
544/*
545    Load the cartridge image files. Apart from reading, we set pointers
546    to the image files so that during runtime we do not need search
547    operations.
548*/
549static DEVICE_IMAGE_LOAD( aes_cartridge )
550{
551   device_t *pcbdev = cartslot_get_pcb(image);
552   aes_pcb_t *pcb;
553   cartslot_t *cart;
554   multicart_open_error me;
555   UINT32 size;
556   device_t* ym = image.device().machine().device("ymsnd");
557
558   // first check software list
559   if(image.software_entry() != NULL)
560   {
561      // create memory regions
562      size = image.get_software_region_length("maincpu");
563      image.device().machine().region_free("maincpu");
564      image.device().machine().region_alloc("maincpu",size,1, ENDIANNESS_LITTLE);
565      memcpy(image.device().machine().region("maincpu")->base(),image.get_software_region("maincpu"),size);
566      size = image.get_software_region_length("fixed");
567      image.device().machine().region_free("fixed");
568      image.device().machine().region_alloc("fixed",size,1, ENDIANNESS_LITTLE);
569      memcpy(image.device().machine().region("fixed")->base(),image.get_software_region("fixed"),size);
570      size = image.get_software_region_length("audiocpu");
571      image.device().machine().region_free("audiocpu");
572      image.device().machine().region_alloc("audiocpu",size,1, ENDIANNESS_LITTLE);
573      memcpy(image.device().machine().region("audiocpu")->base(),image.get_software_region("audiocpu"),size);
574      size = image.get_software_region_length("ymsnd");
575      image.device().machine().region_free("ymsnd");
576      image.device().machine().region_alloc("ymsnd",size,1, ENDIANNESS_LITTLE);
577      memcpy(image.device().machine().region("ymsnd")->base(),image.get_software_region("ymsnd"),size);
578      if(image.get_software_region("ymsnd.deltat") != NULL)
579      {
580         size = image.get_software_region_length("ymsnd.deltat");
581         image.device().machine().region_free("ymsnd.deltat");
582         image.device().machine().region_alloc("ymsnd.deltat",size,1, ENDIANNESS_LITTLE);
583         memcpy(image.device().machine().region("ymsnd.deltat")->base(),image.get_software_region("ymsnd.deltat"),size);
584      }
585      else
586         image.device().machine().region_free("ymsnd.deltat");  // removing the region will fix sound glitches in non-Delta-T games
587      ym->reset();
588      size = image.get_software_region_length("sprites");
589      image.device().machine().region_free("sprites");
590      image.device().machine().region_alloc("sprites",size,1, ENDIANNESS_LITTLE);
591      memcpy(image.device().machine().region("sprites")->base(),image.get_software_region("sprites"),size);
592      if(image.get_software_region("audiocrypt") != NULL)  // encrypted Z80 code
593      {
594         size = image.get_software_region_length("audiocrypt");
595         image.device().machine().region_alloc("audiocrypt",size,1, ENDIANNESS_LITTLE);
596         memcpy(image.device().machine().region("audiocrypt")->base(),image.get_software_region("audiocrypt"),size);
597      }
598
599      // setup cartridge ROM area
600      image.device().machine().device("maincpu")->memory().space(AS_PROGRAM)->install_read_bank(0x000080,0x0fffff,"cart_rom");
601      memory_set_bankptr(image.device().machine(),"cart_rom",&image.device().machine().region("maincpu")->base()[0x80]);
602
603      // handle possible protection
604      install_protection(image);
605
606      return IMAGE_INIT_PASS;
607   }
608
609   if (pcbdev == NULL)
610      fatalerror("Error loading multicart: no pcb found.");
611
612   /* If we are here, we have a multicart. */
613   pcb = get_safe_pcb_token(pcbdev);
614   cart = get_safe_cartslot_token(&image.device());
615
616   /* try opening this as a multicart */
617   /* This line requires that cartslot_t be included in cartslot.h,
618    otherwise one cannot make use of multicart handling within such a
619    custom LOAD function. */
620   me = multicart_open(image.device().machine().options(), image.filename(), image.device().machine().system().name, MULTICART_FLAGS_LOAD_RESOURCES, &cart->mc);
621
622   /* Now that we have loaded the image files, let the PCB put them all
623    together. This means we put the images in a structure which allows
624    for a quick access by the memory handlers. Every PCB defines an
625    own assembly method. */
626    if (me != MCERR_NONE)
627      fatalerror("Error loading multicart: %s", multicart_error_text(me));
628
629   return pcb->assemble(pcbdev->machine(), image);
630}
631
632/*
633    This is called when the cartridge is unplugged (or the emulator is
634    stopped).
635*/
636static DEVICE_IMAGE_UNLOAD( aes_cartridge )
637{
638   device_t *pcbdev;
639
640   if (downcast<legacy_device_base *>(&image.device())->token() == NULL)
641   {
642      /* This means something went wrong during the pcb
643           identification (e.g. one of the cartridge files was not
644           found). We do not need to (and cannot) unload
645           the cartridge. */
646      return;
647   }
648   pcbdev = cartslot_get_pcb(image);
649
650   if (pcbdev != NULL)
651   {
652      aes_pcb_t *pcb = get_safe_pcb_token(pcbdev);
653      cartslot_t *cart = get_safe_cartslot_token(&image.device());
654
655      //  printf("unload\n");
656      if (cart->mc != NULL)
657      {
658         /* Remove pointers and de-big-endianize RAM contents. */
659         pcb->disassemble(pcbdev->machine(), image);
660
661         /* Close the multicart; all RAM resources will be
662               written to disk */
663         multicart_close(pcbdev->machine().options(), cart->mc);
664         cart->mc = NULL;
665      }
666//      else
667//          fatalerror("Lost pointer to multicart in cartridge. Report bug.");
668   }
669}
670
671/*****************************************************************************
672  The overall multi-cartridge slot system. It contains instances of
673  cartridges which contain PCB devices. The memory handlers delegate the calls
674  to the respective handlers of the cartridges.
675
676  Note that the term "multi-cartridge system" and "multicart" are not the same:
677  A "multicart" may contain multiple resources, organized on a PCB. The multi-
678  cart system may thus host multiple multicarts.
679
680  Actually, the name of the device should be changed (however, the device name
681  length is limited)
682******************************************************************************/
683/*
684    Instantiation of a multicart system for the Neo Geo AES.
685*/
686static DEVICE_START(aes_multicart)
687{
688   int i;
689//  printf("DEVICE_START(aes_multicart)\n");
690   aes_multicart_t *cartslots = get_safe_token(device);
691
692   /* Save this in the shortcut; we don't want to look for it each time
693       that we have a memory access. And currently we do not plan for
694       multiple multicart instances. */
695   cartslots->active_slot = 0;
696   cartslots->next_free_slot = 0;
697
698   for (i=0; i < AES_NUMBER_OF_CARTRIDGE_SLOTS; i++)
699   {
700      cartslots->cartridge[i].pcb = NULL;
701   }
702
703   cartslots->multi_slots = 0;
704
705   /* The cartslot system is initialized now. The cartridges themselves
706       need to check whether their parts are available. */
707}
708
709static DEVICE_STOP(aes_multicart)
710{
711//  printf("DEVICE_STOP(aes_multicart)\n");
712}
713
714static MACHINE_CONFIG_FRAGMENT(aes_multicart)
715   MCFG_CARTSLOT_ADD("cartridge1")
716   MCFG_CARTSLOT_EXTENSION_LIST("rpk,bin")
717   MCFG_CARTSLOT_PCBTYPE(0, "none", AES_CARTRIDGE_PCB_NONE)
718   MCFG_CARTSLOT_PCBTYPE(1, "standard", AES_CARTRIDGE_PCB_STD)
719
720   MCFG_CARTSLOT_START(aes_cartridge)
721   MCFG_CARTSLOT_LOAD(aes_cartridge)
722   MCFG_CARTSLOT_UNLOAD(aes_cartridge)
723   MCFG_CARTSLOT_INTERFACE("aes_cart")
724   MCFG_CARTSLOT_MANDATORY
725MACHINE_CONFIG_END
726
727
728DEVICE_GET_INFO(aes_multicart)
729{
730   switch (state)
731   {
732      /* --- the following bits of info are returned as pointers to data --- */
733      case DEVINFO_PTR_MACHINE_CONFIG:
734         info->machine_config = MACHINE_CONFIG_NAME(aes_multicart); break;
735
736      /* --- the following bits of info are returned as NULL-terminated strings --- */
737      case DEVINFO_STR_NAME:
738         strcpy(info->s, "AES Cartridge handler");
739         break;
740
741      case DEVINFO_INT_TOKEN_BYTES: /* private storage, automatically allocated */
742         info->i = sizeof(aes_multicart_t);
743         break;
744
745      case DEVINFO_STR_FAMILY:
746         strcpy(info->s, "Cartridge slot");
747         break;
748      case DEVINFO_STR_VERSION:
749         strcpy(info->s, "1.0");
750         break;
751      case DEVINFO_STR_SOURCE_FILE:
752         strcpy(info->s, __FILE__);
753         break;
754      /* --- the following bits of info are returned as pointers to functions --- */
755      case DEVINFO_FCT_START:
756         info->start = DEVICE_START_NAME(aes_multicart);
757         break;
758      case DEVINFO_FCT_STOP:
759         info->stop = DEVICE_STOP_NAME(aes_multicart);
760         break;
761      case DEVINFO_FCT_RESET:
762         /* Nothing */
763         break;
764   }
765}
766
767DEFINE_LEGACY_CART_SLOT_DEVICE(AES_MULTICART, aes_multicart);
768DEFINE_LEGACY_CART_SLOT_DEVICE(AES_CARTRIDGE_PCB_NONE, aes_cartridge_pcb_none);
769DEFINE_LEGACY_CART_SLOT_DEVICE(AES_CARTRIDGE_PCB_STD, aes_cartridge_pcb_std);
src/mess/devices/aescart.h
r0r11532
1/*********************************************************************
2
3    aescart.h
4
5    AES cartridge management
6
7*********************************************************************/
8
9#ifndef __AESCART_H__
10#define __AESCART_H__
11
12#include "image.h"
13#include "imagedev/cartslot.h"
14
15DECLARE_LEGACY_CART_SLOT_DEVICE(AES_MULTICART, aes_multicart);
16DECLARE_LEGACY_CART_SLOT_DEVICE(AES_CARTRIDGE_PCB_NONE, aes_cartridge_pcb_none);
17DECLARE_LEGACY_CART_SLOT_DEVICE(AES_CARTRIDGE_PCB_STD, aes_cartridge_pcb_std);
18
19/* There's only 1 slot in an AES */
20#define AES_NUMBER_OF_CARTRIDGE_SLOTS 1
21
22/* Generic AES cartridge structure. */
23struct _aescartridge_t
24{
25   /* PCB device associated to this cartridge. If NULL, the slot is empty. */
26   device_t *pcb;
27};
28typedef struct _aescartridge_t aescartridge_t;
29
30#define MCFG_AES_CARTRIDGE_ADD(_tag) \
31   MCFG_DEVICE_ADD(_tag, AES_MULTICART, 0)
32
33#endif /* __AESCART_H__ */
src/mess/machine/ataricrt.c
r0r11532
1/***************************************************************************
2
3    MESS specific Atari init and Cartridge code for Atari 8 bit systems
4
5***************************************************************************/
6
7#include "emu.h"
8#include "emuopts.h"
9#include "includes/atari.h"
10#include "ataridev.h"
11#include "machine/ram.h"
12#include "hashfile.h"
13
14#define LEFT_CARTSLOT_MOUNTED  1
15#define RIGHT_CARTSLOT_MOUNTED 2
16
17/* PCB */
18enum
19{
20    A800_UNKNOWN = 0,
21   A800_4K, A800_8K, A800_12K, A800_16K,
22   A800_RIGHT_4K, A800_RIGHT_8K,
23   OSS_034M, OSS_M091, PHOENIX_8K, XEGS_32K,
24   BBSB, DIAMOND_64K, WILLIAMS_64K, EXPRESS_64,
25   SPARTADOS_X
26};
27
28static int a800_cart_loaded = 0;
29static int atari = 0;
30static int a800_cart_type = A800_UNKNOWN;
31
32/*************************************
33 *
34 *  Generic code
35 *
36 *************************************/
37
38
39// Currently, the drivers have fixed 40k RAM, however the function here is ready for different sizes too
40static void a800_setbank(running_machine &machine, int cart_mounted)
41{
42   offs_t ram_top;
43
44   // take care of 0x0000-0x7fff: RAM or NOP
45   ram_top = MIN(ram_get_size(machine.device(RAM_TAG)), 0x8000) - 1;
46   machine.device("maincpu")->memory().space(AS_PROGRAM)->install_readwrite_bank(0x0000, ram_top, "0000");
47   memory_set_bankptr(machine, "0000", ram_get_ptr(machine.device(RAM_TAG)));
48
49   // take care of 0x8000-0x9fff: A800 -> either right slot or RAM or NOP, others -> RAM or NOP
50   // is there anything in the right slot?
51   if (cart_mounted & RIGHT_CARTSLOT_MOUNTED)
52   {
53      machine.device("maincpu")->memory().space(AS_PROGRAM)->install_read_bank(0x8000, 0x9fff, "8000");
54      memory_set_bankptr(machine, "8000", machine.region("rslot")->base());
55      machine.device("maincpu")->memory().space(AS_PROGRAM)->unmap_write(0x8000, 0x9fff);
56   }
57   else if (a800_cart_type != BBSB)
58   {
59      ram_top = MIN(ram_get_size(machine.device(RAM_TAG)), 0xa000) - 1;
60      if (ram_top > 0x8000)
61      {
62         machine.device("maincpu")->memory().space(AS_PROGRAM)->install_readwrite_bank(0x8000, ram_top, "8000");
63         memory_set_bankptr(machine, "8000", ram_get_ptr(machine.device(RAM_TAG)) + 0x8000);
64      }
65   }
66
67   // take care of 0xa000-0xbfff: is there anything in the left slot?
68   if (cart_mounted & LEFT_CARTSLOT_MOUNTED)
69   {
70      // FIXME: this is an hack to keep XL working until we clean up its memory map as well!
71      if (atari == ATARI_800XL)
72      {
73         if (a800_cart_type == A800_16K)
74         {
75            machine.device("maincpu")->memory().space(AS_PROGRAM)->install_read_bank(0x8000, 0x9fff, "8000");
76            memory_set_bankptr(machine, "8000", machine.region("lslot")->base());
77            machine.device("maincpu")->memory().space(AS_PROGRAM)->unmap_write(0x8000, 0x9fff);
78
79            memcpy(machine.region("maincpu")->base() + 0x10000, machine.region("lslot")->base() + 0x2000, 0x2000);
80         }
81         else if (a800_cart_type == A800_8K)
82            memcpy(machine.region("maincpu")->base() + 0x10000, machine.region("lslot")->base(), 0x2000);
83         else
84            fatalerror("This type of cart is not supported yet in this driver. Please use a400 or a800.\n");
85      }
86      else if (a800_cart_type == A800_16K)
87      {
88         memory_set_bankptr(machine, "8000", machine.region("lslot")->base());
89         memory_set_bankptr(machine, "a000", machine.region("lslot")->base() + 0x2000);
90         machine.device("maincpu")->memory().space(AS_PROGRAM)->unmap_write(0x8000, 0xbfff);
91      }
92      else if (a800_cart_type == BBSB)
93      {
94         // this requires separate banking in 0x8000 & 0x9000!
95         machine.device("maincpu")->memory().space(AS_PROGRAM)->install_read_bank(0x8000, 0x8fff, "8000");
96         machine.device("maincpu")->memory().space(AS_PROGRAM)->install_read_bank(0x9000, 0x9fff, "9000");
97         memory_set_bankptr(machine, "8000", machine.region("lslot")->base() + 0x0000);
98         memory_set_bankptr(machine, "9000", machine.region("lslot")->base() + 0x4000);
99         memory_set_bankptr(machine, "a000", machine.region("lslot")->base() + 0x8000);
100         machine.device("maincpu")->memory().space(AS_PROGRAM)->unmap_write(0xa000, 0xbfff);
101      }
102      else if (a800_cart_type == OSS_034M)
103      {
104         // this requires separate banking in 0xa000 & 0xb000!
105         machine.device("maincpu")->memory().space(AS_PROGRAM)->install_read_bank(0xa000, 0xafff, "a000");
106         machine.device("maincpu")->memory().space(AS_PROGRAM)->install_read_bank(0xb000, 0xbfff, "b000");
107         memory_set_bankptr(machine, "b000", machine.region("lslot")->base() + 0x3000);
108         machine.device("maincpu")->memory().space(AS_PROGRAM)->unmap_write(0xa000, 0xbfff);
109      }
110      else if (a800_cart_type == OSS_M091)
111      {
112         // this requires separate banking in 0xa000 & 0xb000!
113         machine.device("maincpu")->memory().space(AS_PROGRAM)->install_read_bank(0xa000, 0xafff, "a000");
114         machine.device("maincpu")->memory().space(AS_PROGRAM)->install_read_bank(0xb000, 0xbfff, "b000");
115         memory_set_bankptr(machine, "b000", machine.region("lslot")->base());
116         machine.device("maincpu")->memory().space(AS_PROGRAM)->unmap_write(0xa000, 0xbfff);
117      }
118      else if (a800_cart_type == XEGS_32K)
119      {
120         memory_set_bankptr(machine, "8000", machine.region("lslot")->base());
121         memory_set_bankptr(machine, "a000", machine.region("lslot")->base() + 0x6000);
122         machine.device("maincpu")->memory().space(AS_PROGRAM)->unmap_write(0x8000, 0xbfff);
123      }
124      else
125      {
126         memory_set_bankptr(machine, "a000", machine.region("lslot")->base());
127         machine.device("maincpu")->memory().space(AS_PROGRAM)->unmap_write(0xa000, 0xbfff);
128      }
129   }
130}
131
132/* MESS specific parts that have to be started */
133static void ms_atari_machine_start(running_machine &machine, int type, int has_cart)
134{
135   /* set atari type (temporarily not used) */
136   atari = type;
137   a800_setbank(machine, a800_cart_loaded);
138}
139
140static void ms_atari800xl_machine_start(running_machine &machine, int type, int has_cart)
141{
142   /* set atari type (temporarily not used) */
143   atari = type;
144   a800_setbank(machine, a800_cart_loaded);
145}
146
147/*************************************
148 *
149 *  Atari 400
150 *
151 *************************************/
152
153MACHINE_START( a400 )
154{
155   atari_machine_start(machine);
156   ms_atari_machine_start(machine, ATARI_400, TRUE);
157}
158
159
160/*************************************
161 *
162 *  Atari 800
163 *
164 *************************************/
165
166MACHINE_START( a800 )
167{
168   atari_machine_start(machine);
169   ms_atari_machine_start(machine, ATARI_800, TRUE);
170}
171
172static WRITE8_HANDLER( x32_bank_w )
173{
174   //  printf("written %x\n", data);
175   int bank = data & 0x03;
176   memory_set_bankptr(space->machine(), "8000", space->machine().region("lslot")->base() + bank * 0x2000);
177}
178
179static WRITE8_HANDLER( w64_bank_w )
180{
181//  printf("write to %x\n", offset);
182
183   if (offset < 8)
184      memory_set_bankptr(space->machine(), "a000", space->machine().region("lslot")->base() + offset * 0x2000);
185   else
186      memory_set_bankptr(space->machine(), "a000", space->machine().region("maincpu")->base());
187   // FIXME: writes to 0x8-0xf should disable the cart
188}
189
190// this covers Express 64, Diamond 64 and SpartaDOS (same bankswitch, but at different addresses)
191static WRITE8_HANDLER( ex64_bank_w )
192{
193//  printf("write to %x\n", offset);
194
195   if (offset < 8)
196      memory_set_bankptr(space->machine(), "a000", space->machine().region("lslot")->base() + (7 - offset) * 0x2000);
197   else
198      memory_set_bankptr(space->machine(), "a000", space->machine().region("maincpu")->base());
199   // FIXME: writes to 0x8-0xf should disable the cart
200}
201
202static WRITE8_HANDLER( bbsb_bankl_w )
203{
204//  printf("write to %x\n", 0x8000 + offset);
205   if (offset >= 0xff6 && offset <= 0xff9)
206      memory_set_bankptr(space->machine(), "8000", space->machine().region("lslot")->base() + 0x0000 + (offset - 0xff6) * 0x1000);
207}
208
209static WRITE8_HANDLER( bbsb_bankh_w )
210{
211//  printf("write to %x\n", 0x9000 + offset);
212   if (offset >= 0xff6 && offset <= 0xff9)
213      memory_set_bankptr(space->machine(), "9000", space->machine().region("lslot")->base() + 0x4000 + (offset - 0xff6) * 0x1000);
214}
215
216static WRITE8_HANDLER( oss_034m_w )
217{
218   switch (offset & 0x0f)
219   {
220      case 0:
221      case 1:
222         memory_set_bankptr(space->machine(), "a000", space->machine().region("lslot")->base());
223         memory_set_bankptr(space->machine(), "b000", space->machine().region("lslot")->base() + 0x3000);
224         break;
225      case 2:
226      case 6:
227         // docs says this should put 0xff in the 0xa000 bank -> let's point to the end of the cart
228         memory_set_bankptr(space->machine(), "a000", space->machine().region("lslot")->base() + 0x4000);
229         memory_set_bankptr(space->machine(), "b000", space->machine().region("lslot")->base() + 0x3000);
230         break;
231      case 3:
232      case 7:
233         memory_set_bankptr(space->machine(), "a000", space->machine().region("lslot")->base() + 0x1000);
234         memory_set_bankptr(space->machine(), "b000", space->machine().region("lslot")->base() + 0x3000);
235         break;
236      case 4:
237      case 5:
238         memory_set_bankptr(space->machine(), "a000", space->machine().region("lslot")->base() + 0x2000);
239         memory_set_bankptr(space->machine(), "b000", space->machine().region("lslot")->base() + 0x3000);
240         break;
241      default:
242         memory_set_bankptr(space->machine(), "a000", space->machine().region("maincpu")->base() + 0xa000);
243         memory_set_bankptr(space->machine(), "b000", space->machine().region("maincpu")->base() + 0xb000);
244         break;
245   }
246}
247
248static WRITE8_HANDLER( oss_m091_w )
249{
250   switch (offset & 0x09)
251   {
252      case 0:
253         memory_set_bankptr(space->machine(), "a000", space->machine().region("lslot")->base() + 0x1000);
254         memory_set_bankptr(space->machine(), "b000", space->machine().region("lslot")->base());
255         break;
256      case 1:
257         memory_set_bankptr(space->machine(), "a000", space->machine().region("lslot")->base() + 0x3000);
258         memory_set_bankptr(space->machine(), "b000", space->machine().region("lslot")->base());
259         break;
260      case 8:
261         memory_set_bankptr(space->machine(), "a000", space->machine().region("maincpu")->base() + 0xa000);
262         memory_set_bankptr(space->machine(), "b000", space->machine().region("maincpu")->base() + 0xb000);
263         break;
264      case 9:
265         memory_set_bankptr(space->machine(), "a000", space->machine().region("lslot")->base() + 0x2000);
266         memory_set_bankptr(space->machine(), "b000", space->machine().region("lslot")->base());
267         break;
268   }
269}
270
271#if 0
272static int bbsb_bankl = 0;
273static int bbsb_bankh = 0;
274
275static WRITE8_HANDLER( bbsb_bankl_w )
276{
277   bbsb_bankl = offset; // 0,1,2,3
278}
279
280static WRITE8_HANDLER( bbsb_bankh_w )
281{
282   bbsb_bankh = offset; // 4,5,6,7
283}
284
285static READ8_HANDLER( bbsb_bankl_r )
286{
287   // return data from the selected bank (0,1,2,3)
288   UINT8 *mem = space->machine().region("lslot")->base();
289   return &mem[0x0000 + bbsb_bankl * 0x1000];
290}
291
292static READ8_HANDLER( bbsb_bankh_r )
293{
294   // return data from the selected bank (4,5,6,7)
295   UINT8 *mem = space->machine().region("lslot")->base();
296   return &mem[0x4000 + bbsb_bankh * 0x1000];
297}
298#endif
299
300typedef struct _a800_pcb  a800_pcb;
301struct _a800_pcb
302{
303   const char              *pcb_name;
304   int                     pcb_id;
305};
306
307// Here, we take the feature attribute from .xml (i.e. the PCB name) and we assign a unique ID to it
308// WARNING: most of these are still unsupported by the driver
309static const a800_pcb pcb_list[] =
310{
311   {"standard 4k", A800_8K},
312   {"standard 8k", A800_8K},
313   {"standard 12k", A800_16K},
314   {"standard 16k", A800_16K},
315   {"right slot 4k", A800_RIGHT_4K},
316   {"right slot 8k", A800_RIGHT_8K},
317
318   {"oss 034m", OSS_034M},
319   {"oss m091", OSS_M091},
320   {"phoenix 8k", PHOENIX_8K},
321   {"xegs 32k", XEGS_32K},
322   {"bbsb", BBSB},
323   {"diamond 64k", DIAMOND_64K},
324   {"williams 64k", WILLIAMS_64K},
325   {"express 64", EXPRESS_64},
326   {"spartados x", SPARTADOS_X},
327   {"N/A", A800_UNKNOWN}
328};
329
330static int a800_get_pcb_id(const char *pcb)
331{
332   int   i;
333
334   for (i = 0; i < ARRAY_LENGTH(pcb_list); i++)
335   {
336      if (!mame_stricmp(pcb_list[i].pcb_name, pcb))
337         return pcb_list[i].pcb_id;
338   }
339
340   return A800_UNKNOWN;
341}
342
343// currently this does nothing, but it will eventually install the memory handlers required by the mappers
344static void a800_setup_mappers(running_machine &machine, int type)
345{
346   switch (type)
347   {
348      case A800_4K:
349      case A800_RIGHT_4K:
350      case A800_12K:
351      case A800_8K:
352      case A800_16K:
353      case A800_RIGHT_8K:
354      case PHOENIX_8K:   // as normal 8k cart, but it can be disabled by writing to 0xd500-0xdfff
355         break;
356      case XEGS_32K:
357         machine.device("maincpu")->memory().space(AS_PROGRAM)->install_legacy_write_handler(0xd500, 0xd5ff, FUNC(x32_bank_w));
358         break;
359      case OSS_034M:
360         machine.device("maincpu")->memory().space(AS_PROGRAM)->install_legacy_write_handler(0xd500, 0xd5ff, FUNC(oss_034m_w));
361         break;
362      case OSS_M091:
363         machine.device("maincpu")->memory().space(AS_PROGRAM)->install_legacy_write_handler(0xd500, 0xd5ff, FUNC(oss_m091_w));
364         break;
365      case BBSB:
366         machine.device("maincpu")->memory().space(AS_PROGRAM)->install_legacy_write_handler(0x8000, 0x8fff, FUNC(bbsb_bankl_w));
367         machine.device("maincpu")->memory().space(AS_PROGRAM)->install_legacy_write_handler(0x9000, 0x9fff, FUNC(bbsb_bankh_w));
368         break;
369      case WILLIAMS_64K:
370         machine.device("maincpu")->memory().space(AS_PROGRAM)->install_legacy_write_handler(0xd500, 0xd50f, FUNC(w64_bank_w));
371         break;
372      case DIAMOND_64K:
373         machine.device("maincpu")->memory().space(AS_PROGRAM)->install_legacy_write_handler(0xd5d0, 0xd5df, FUNC(ex64_bank_w));
374         break;
375      case EXPRESS_64:
376         machine.device("maincpu")->memory().space(AS_PROGRAM)->install_legacy_write_handler(0xd570, 0xd57f, FUNC(ex64_bank_w));
377         break;
378      case SPARTADOS_X:
379         machine.device("maincpu")->memory().space(AS_PROGRAM)->install_legacy_write_handler(0xd5e0, 0xd5ef, FUNC(ex64_bank_w));
380         break;
381      default:
382         break;
383   }
384}
385
386static int a800_get_type(device_image_interface &image)
387{
388   UINT8 header[16];
389   image.fread(header, 0x10);
390   int hdr_type, cart_type = A800_UNKNOWN;
391
392   // add check of CART format
393   if (strncmp((const char *)header, "CART", 4))
394      fatalerror("Invalid header detected!\n");
395
396   hdr_type = (header[4] << 24) + (header[5] << 16) +  (header[6] << 8) + (header[7] << 0);
397   switch (hdr_type)
398   {
399      case 1:
400         cart_type = A800_8K;
401         break;
402      case 2:
403         cart_type = A800_16K;
404         break;
405      case 3:
406         cart_type = OSS_034M;
407         break;
408      case 8:
409         cart_type = WILLIAMS_64K;
410         break;
411      case 9:
412         cart_type = DIAMOND_64K;
413         break;
414      case 10:
415         cart_type = EXPRESS_64;
416         break;
417      case 11:
418         cart_type = SPARTADOS_X;
419         break;
420      case 12:
421         cart_type = XEGS_32K;
422         break;
423      case 15:
424         cart_type = OSS_M091;
425         break;
426      case 18:
427         cart_type = BBSB;
428         break;
429      case 21:
430         cart_type = A800_RIGHT_8K;
431         break;
432      case 39:
433         cart_type = PHOENIX_8K;
434         break;
435      case 4:
436      case 6:
437      case 7:
438      case 16:
439      case 19:
440      case 20:
441         fatalerror("Cart type \"%d\" means this is an Atari 5200 cart.\n", hdr_type);
442         break;
443      default:
444         mame_printf_info("Cart type \"%d\" is currently unsupported.\n", hdr_type);
445         break;
446   }
447   return cart_type;
448}
449
450static int a800_check_cart_type(device_image_interface &image)
451{
452   const char   *pcb_name;
453   int type = A800_UNKNOWN;
454
455   if (image.software_entry() == NULL)
456   {
457      UINT32 size = image.length();
458
459      // check if there is an header, if so extract cart_type from it, otherwise
460      // try to guess the cart_type from the file size (notice that after the
461      // a800_get_type call, we point at the start of the data)
462      if ((size % 0x1000) == 0x10)
463         type = a800_get_type(image);
464      else if (size == 0x4000)
465         type = A800_16K;
466      else if (size == 0x2000)
467      {
468         if (strcmp(image.device().tag(),"cart2") == 0)
469            type = A800_RIGHT_8K;
470         else
471            type = A800_8K;
472      }
473   }
474   else
475   {
476      if ((pcb_name = image.get_feature("cart_type")) != NULL)
477         type = a800_get_pcb_id(pcb_name);
478
479      switch (type)
480      {
481         case A800_UNKNOWN:
482         case A800_4K:
483         case A800_RIGHT_4K:
484         case A800_12K:
485         case A800_8K:
486         case A800_16K:
487         case A800_RIGHT_8K:
488            break;
489         default:
490            mame_printf_info("Cart type \"%s\" currently unsupported.\n", pcb_name);
491            break;
492      }
493   }
494
495   if ((strcmp(image.device().tag(),"cart2") == 0) && (type != A800_RIGHT_8K))
496      fatalerror("You cannot load this image '%s' in the right slot", image.filename());
497
498   return type;
499}
500
501DEVICE_IMAGE_LOAD( a800_cart )
502{
503   UINT32 size, start = 0;
504
505   a800_cart_loaded = a800_cart_loaded & ~LEFT_CARTSLOT_MOUNTED;
506   a800_cart_type = a800_check_cart_type(image);
507
508   a800_setup_mappers(image.device().machine(), a800_cart_type);
509
510   if (image.software_entry() == NULL)
511   {
512      size = image.length();
513      // if there is an header, skip it
514      if ((size % 0x1000) == 0x10)
515      {
516         size -= 0x10;
517         start = 0x10;
518      }
519      image.fread(image.device().machine().region("lslot")->base(), size - start);
520   }
521   else
522   {
523      size = image.get_software_region_length("rom");
524      memcpy(image.device().machine().region("lslot")->base(), image.get_software_region("rom"), size);
525   }
526
527   a800_cart_loaded |= (size > 0x0000) ? 1 : 0;
528
529   logerror("%s loaded left cartridge '%s' size %dK\n", image.device().machine().system().name, image.filename(), size/1024);
530   return IMAGE_INIT_PASS;
531}
532
533DEVICE_IMAGE_LOAD( a800_cart_right )
534{
535   UINT32 size, start = 0;
536
537   a800_cart_loaded = a800_cart_loaded & ~RIGHT_CARTSLOT_MOUNTED;
538   a800_cart_type = a800_check_cart_type(image);
539
540   a800_setup_mappers(image.device().machine(), a800_cart_type);
541
542   if (image.software_entry() == NULL)
543   {
544      size = image.length();
545      // if there is an header, skip it
546      if ((size % 0x1000) == 0x10)
547      {
548         size -= 0x10;
549         start = 0x10;
550      }
551      image.fread(image.device().machine().region("rslot")->base(), size - start);
552   }
553   else
554   {
555      size = image.get_software_region_length("rom");
556      memcpy(image.device().machine().region("rslot")->base(), image.get_software_region("rom"), size);
557   }
558
559   a800_cart_loaded |= (size > 0x0000) ? 2 : 0;
560
561   logerror("%s loaded right cartridge '%s' size 8K\n", image.device().machine().system().name, image.filename());
562   return IMAGE_INIT_PASS;
563}
564
565DEVICE_IMAGE_UNLOAD( a800_cart )
566{
567   a800_cart_loaded = a800_cart_loaded & ~LEFT_CARTSLOT_MOUNTED;
568   a800_cart_type = A800_UNKNOWN;
569   a800_setbank(image.device().machine(), a800_cart_loaded);
570}
571
572DEVICE_IMAGE_UNLOAD( a800_cart_right )
573{
574   a800_cart_loaded = a800_cart_loaded & ~RIGHT_CARTSLOT_MOUNTED;
575   a800_cart_type = A800_UNKNOWN;
576   a800_setbank(image.device().machine(), a800_cart_loaded);
577}
578
579
580/*************************************
581 *
582 *  Atari 800XL
583 *
584 *************************************/
585
586MACHINE_START( a800xl )
587{
588   atari_machine_start(machine);
589   ms_atari800xl_machine_start(machine, ATARI_800XL, TRUE);
590}
591
592/*************************************
593 *
594 *  Atari 5200 console
595 *
596 *************************************/
597
598MACHINE_START( a5200 )
599{
600   atari_machine_start(machine);
601   ms_atari_machine_start(machine, ATARI_800XL, TRUE);
602}
603
604
605DEVICE_IMAGE_LOAD( a5200_cart )
606{
607   UINT8 *mem = image.device().machine().region("maincpu")->base();
608   UINT32 size;
609
610   if (image.software_entry() == NULL)
611   {
612      /* load an optional (dual) cartidge */
613      size = image.fread(&mem[0x4000], 0x8000);
614   }
615   else
616   {
617      size = image.get_software_region_length("rom");
618      memcpy(mem + 0x4000, image.get_software_region("rom"), size);
619   }
620
621   if (size<0x8000) memmove(mem+0x4000+0x8000-size, mem+0x4000, size);
622   // mirroring of smaller cartridges
623   if (size <= 0x1000) memcpy(mem+0xa000, mem+0xb000, 0x1000);
624   if (size <= 0x2000) memcpy(mem+0x8000, mem+0xa000, 0x2000);
625   if (size <= 0x4000)
626   {
627      const char *info = hashfile_extrainfo(image);
628      memcpy(&mem[0x4000], &mem[0x8000], 0x4000);
629      if (info && !strcmp(info, "A13MIRRORING"))
630      {
631         memcpy(&mem[0x8000], &mem[0xa000], 0x2000);
632         memcpy(&mem[0x6000], &mem[0x4000], 0x2000);
633      }
634   }
635   logerror("A5200 loaded cartridge '%s' size %dK\n", image.filename() , size/1024);
636   return IMAGE_INIT_PASS;
637}
638
639DEVICE_IMAGE_UNLOAD( a5200_cart )
640{
641   UINT8 *mem = image.device().machine().region("maincpu")->base();
642   /* zap the cartridge memory (again) */
643   memset(&mem[0x4000], 0x00, 0x8000);
644}
645
646/*************************************
647 *
648 *  Atari XEGS
649 *
650 *************************************/
651
652static UINT8 xegs_banks = 0;
653static UINT8 xegs_cart = 0;
654
655static WRITE8_HANDLER( xegs_bankswitch )
656{
657   UINT8 *cart = space->machine().region("user1")->base();
658   data &= xegs_banks - 1;
659   memory_set_bankptr(space->machine(), "bank0", cart + data * 0x2000);
660}
661
662MACHINE_START( xegs )
663{
664   address_space *space = machine.device("maincpu")->memory().space(AS_PROGRAM);
665   UINT8 *cart = space->machine().region("user1")->base();
666   UINT8 *cpu  = space->machine().region("maincpu")->base();
667
668   atari_machine_start(machine);
669   space->install_legacy_write_handler(0xd500, 0xd5ff, FUNC(xegs_bankswitch));
670
671   if (xegs_cart)
672   {
673      memory_set_bankptr(machine, "bank0", cart);
674      memory_set_bankptr(machine, "bank1", cart + (xegs_banks - 1) * 0x2000);
675   }
676   else
677   {
678      // point to built-in Missile Command (this does not work well, though... FIXME!!)
679      memory_set_bankptr(machine, "bank0", cpu + 0x10000);
680      memory_set_bankptr(machine, "bank1", cpu + 0x10000);
681   }
682}
683
684DEVICE_IMAGE_LOAD( xegs_cart )
685{
686   UINT32 size;
687   UINT8 *ptr = image.device().machine().region("user1")->base();
688
689   if (image.software_entry() == NULL)
690   {
691      // skip the header
692      image.fseek(0x10, SEEK_SET);
693      size = image.length() - 0x10;
694      if (image.fread(ptr, size) != size)
695         return IMAGE_INIT_FAIL;
696   }
697   else
698   {
699      size = image.get_software_region_length("rom");
700      memcpy(ptr, image.get_software_region("rom"), size);
701   }
702
703   xegs_banks = size / 0x2000;
704   xegs_cart = 1;
705
706   return IMAGE_INIT_PASS;
707}
708
709DEVICE_IMAGE_UNLOAD( xegs_cart )
710{
711   xegs_cart = 0;
712   xegs_banks = 0;
713}
src/mess/machine/ataridev.h
r0r11532
1/*
2    ataridev.h
3
4*/
5
6#ifndef _ATARIDEV_H
7#define _ATARIDEV_H
8
9#define ATARI_5200   0
10#define ATARI_400   1
11#define ATARI_800   2
12#define ATARI_600XL 3
13#define ATARI_800XL 4
14
15/*----------- defined in machine/ataricrt.c -----------*/
16
17MACHINE_START( a400 );
18MACHINE_START( a800 );
19MACHINE_START( a800xl );
20MACHINE_START( a5200 );
21MACHINE_START( xegs );
22
23DEVICE_IMAGE_LOAD( a800_cart );
24DEVICE_IMAGE_UNLOAD( a800_cart );
25
26DEVICE_IMAGE_LOAD( a800_cart_right );
27DEVICE_IMAGE_UNLOAD( a800_cart_right );
28
29DEVICE_IMAGE_LOAD( a5200_cart );
30DEVICE_IMAGE_UNLOAD( a5200_cart );
31
32DEVICE_IMAGE_LOAD( xegs_cart );
33DEVICE_IMAGE_UNLOAD( xegs_cart );
34
35
36/*----------- defined in machine/atarifdc.c -----------*/
37/***************************************************************************
38    MACROS
39***************************************************************************/
40
41DECLARE_LEGACY_DEVICE(ATARI_FDC, atari_fdc);
42
43#define MCFG_ATARI_FDC_ADD(_tag)   \
44   MCFG_DEVICE_ADD((_tag),  ATARI_FDC, 0)
45
46
47/***************************************************************************
48    FUNCTION PROTOTYPES
49***************************************************************************/
50READ8_DEVICE_HANDLER( atari_serin_r );
51WRITE8_DEVICE_HANDLER( atari_serout_w );
52WRITE_LINE_DEVICE_HANDLER( atarifdc_pia_cb2_w );
53
54#endif /* _ATARIDEV_H */
55
src/mess/machine/amigafdc.c
r0r11532
1/****************************************************f***********************
2
3    Amiga floppy disk controller emulation
4
5    - The drive spins at 300 RPM = 1 Rev every 200ms
6    - At 2usec per bit, that's 12500 bytes per track, or 6250 words per track
7    - At 4usec per bit, that's 6250 bytes per track, or 3125 words per track
8    - Each standard amiga sector has 544 words per sector, and 11 sectors per track = 11968 bytes
9    - ( 12500(max) - 11968(actual) ) = 532 per track gap bytes
10
11***************************************************************************/
12
13
14#include "emu.h"
15#include "includes/amiga.h"
16#include "imagedev/flopdrv.h"
17#include "formats/ami_dsk.h"
18#include "amigafdc.h"
19#include "machine/6526cia.h"
20
21
22#define MAX_TRACK_BYTES         12500
23#define ACTUAL_TRACK_BYTES      11968
24#define GAP_TRACK_BYTES         ( MAX_TRACK_BYTES - ACTUAL_TRACK_BYTES )
25#define ONE_SECTOR_BYTES      (544*2)
26#define ONE_REV_TIME         200 /* ms */
27#define MAX_WORDS_PER_DMA_CYCLE   32 /* 64 bytes per dma cycle */
28#define DISK_DETECT_DELAY      1
29#define MAX_TRACKS            160
30#define MAX_MFM_TRACK_LEN      16384
31
32#define NUM_DRIVES 2
33
34/* required prototype */
35static void setup_fdc_buffer( device_t *device,int drive );
36
37/***************************************************************************
38    TYPE DEFINITIONS
39***************************************************************************/
40typedef struct {
41   int motor_on;
42   int side;
43   int dir;
44   int wprot;
45   int disk_changed;
46   device_image_interface *f;
47   UINT32 extinfo[MAX_TRACKS];
48   UINT32 extoffs[MAX_TRACKS];
49   int is_ext_image;
50   int cyl;
51   int tracklen;
52   UINT8 mfm[MAX_MFM_TRACK_LEN];
53   int   cached;
54   emu_timer *rev_timer;
55   emu_timer *sync_timer;
56   emu_timer *dma_timer;
57   int rev_timer_started;
58   int pos;
59   int len;
60   offs_t ptr;
61} fdc_def;
62
63typedef struct _amiga_fdc_t amiga_fdc_t;
64struct _amiga_fdc_t
65{
66   fdc_def fdc_status[NUM_DRIVES];
67
68   /* signals */
69   int fdc_sel;
70   int fdc_dir;
71   int fdc_side;
72   int fdc_step;
73   int fdc_rdy;
74};
75
76/*****************************************************************************
77    INLINE FUNCTIONS
78*****************************************************************************/
79INLINE amiga_fdc_t *get_safe_token(device_t *device)
80{
81   assert(device != NULL);
82   assert(device->type() == AMIGA_FDC);
83
84   return (amiga_fdc_t *)downcast<legacy_device_base *>(device)->token();
85}
86
87static TIMER_CALLBACK(fdc_rev_proc);
88static TIMER_CALLBACK(fdc_dma_proc);
89static TIMER_CALLBACK(fdc_sync_proc);
90static void check_extended_image( device_t *device, int id );
91
92static void amiga_load_proc(device_image_interface &image)
93{
94   amiga_fdc_t *fdc = get_safe_token(image.device().owner());
95   int id = floppy_get_drive(&image.device());
96   fdc->fdc_status[id].disk_changed = DISK_DETECT_DELAY;
97   fdc->fdc_status[id].f = &image;
98   fdc->fdc_status[id].cached = -1;
99   fdc->fdc_status[id].motor_on = 0;
100   fdc->fdc_status[id].rev_timer_started = 0;
101   fdc->fdc_status[id].rev_timer->reset(  );
102   fdc->fdc_status[id].sync_timer->reset(  );
103   fdc->fdc_status[id].dma_timer->reset(  );
104   fdc->fdc_rdy = 0;
105
106   check_extended_image( image.device().owner(), id );
107}
108
109static void amiga_unload_proc(device_image_interface &image)
110{
111   amiga_fdc_t *fdc = get_safe_token(image.device().owner());
112   int id = floppy_get_drive(&image.device());
113   fdc->fdc_status[id].disk_changed = DISK_DETECT_DELAY;
114   fdc->fdc_status[id].f = NULL;
115   fdc->fdc_status[id].cached = -1;
116   fdc->fdc_status[id].motor_on = 0;
117   fdc->fdc_status[id].rev_timer_started = 0;
118   fdc->fdc_status[id].rev_timer->reset(  );
119   fdc->fdc_status[id].sync_timer->reset(  );
120   fdc->fdc_status[id].dma_timer->reset(  );
121   fdc->fdc_rdy = 0;
122}
123
124/*-------------------------------------------------
125    DEVICE_START(amiga_fdc)
126-------------------------------------------------*/
127device_t *amiga_floppy_get_device_child(device_t *device,int drive)
128{
129   switch(drive) {
130      case 0 : return device->subdevice(FLOPPY_0);
131      case 1 : return device->subdevice(FLOPPY_1);
132   }
133   return NULL;
134}
135
136static DEVICE_START(amiga_fdc)
137{
138   amiga_fdc_t *fdc = get_safe_token(device);
139   int id;
140   for(id=0;id<2;id++)
141   {
142      fdc->fdc_status[id].rev_timer = device->machine().scheduler().timer_alloc(FUNC(fdc_rev_proc), (void*)device);
143      fdc->fdc_status[id].dma_timer = device->machine().scheduler().timer_alloc(FUNC(fdc_dma_proc), (void*)device);
144      fdc->fdc_status[id].sync_timer = device->machine().scheduler().timer_alloc(FUNC(fdc_sync_proc), (void*)device);
145      floppy_install_load_proc(amiga_floppy_get_device_child(device, id), amiga_load_proc);
146      floppy_install_unload_proc(amiga_floppy_get_device_child(device, id), amiga_unload_proc);
147      fdc->fdc_status[id].motor_on = 0;
148      fdc->fdc_status[id].side = 0;
149      fdc->fdc_status[id].dir = 0;
150      fdc->fdc_status[id].wprot = 1;
151      fdc->fdc_status[id].cyl = 0;
152      fdc->fdc_status[id].rev_timer_started = 0;
153      fdc->fdc_status[id].cached = -1;
154      fdc->fdc_status[id].pos = 0;
155      fdc->fdc_status[id].len = 0;
156      fdc->fdc_status[id].ptr = 0;
157      fdc->fdc_status[id].f = NULL;
158      fdc->fdc_status[id].is_ext_image = 0;
159      fdc->fdc_status[id].tracklen = MAX_TRACK_BYTES;
160      fdc->fdc_status[id].disk_changed = DISK_DETECT_DELAY;
161      fdc->fdc_status[id].rev_timer->reset(  );
162      fdc->fdc_status[id].sync_timer->reset(  );
163      fdc->fdc_status[id].dma_timer->reset(  );
164      memset( fdc->fdc_status[id].mfm, 0xaa, MAX_MFM_TRACK_LEN );
165   }
166   fdc->fdc_sel = 0x0f;
167   fdc->fdc_dir = 0;
168   fdc->fdc_side = 1;
169   fdc->fdc_step = 1;
170   fdc->fdc_rdy = 0;
171
172}
173
174
175/*-------------------------------------------------
176    DEVICE_RESET(amiga_fdc)
177-------------------------------------------------*/
178
179static DEVICE_RESET(amiga_fdc)
180{
181}
182
183static void check_extended_image( device_t *device, int id )
184{
185   UINT8   header[8], data[4];
186   amiga_fdc_t *fdc = get_safe_token(device);
187
188   fdc->fdc_status[id].is_ext_image = 0;
189
190   if ( fdc->fdc_status[id].f->fseek( 0, SEEK_SET ) )
191   {
192      logerror("FDC: image_fseek failed!\n" );
193      return;
194   }
195
196   fdc->fdc_status[id].f->fread( &header, sizeof( header ) );
197
198   if ( memcmp( header, "UAE--ADF", sizeof( header ) ) == 0 )
199   {
200      int      i;
201
202      for( i = 0; i < MAX_TRACKS; i++ )
203      {
204         fdc->fdc_status[id].f->fread( &data, sizeof( data ) );
205
206         /* data[0,1] = SYNC - data[2,3] = LEN */
207
208         fdc->fdc_status[id].extinfo[i] = data[0];
209         fdc->fdc_status[id].extinfo[i] <<= 8;
210         fdc->fdc_status[id].extinfo[i] |= data[1];
211         fdc->fdc_status[id].extinfo[i] <<= 8;
212         fdc->fdc_status[id].extinfo[i] |= data[2];
213         fdc->fdc_status[id].extinfo[i] <<= 8;
214         fdc->fdc_status[id].extinfo[i] |= data[3];
215
216         if ( i == 0 )
217            fdc->fdc_status[id].extoffs[i] = sizeof( header ) + ( MAX_TRACKS * sizeof( data ) );
218         else
219            fdc->fdc_status[id].extoffs[i] = fdc->fdc_status[id].extoffs[i-1] + ( fdc->fdc_status[id].extinfo[i-1] & 0xffff );
220      }
221
222      fdc->fdc_status[id].is_ext_image = 1;
223   }
224}
225
226static int fdc_get_curpos( device_t *device, int drive )
227{
228   amiga_state *state = device->machine().driver_data<amiga_state>();
229   double elapsed;
230   int speed;
231   int   bytes;
232   int pos;
233   amiga_fdc_t *fdc = get_safe_token(device);
234
235   if ( fdc->fdc_status[drive].rev_timer_started == 0 ) {
236      logerror("Rev timer not started on drive %d, cant get position!\n", drive );
237      return 0;
238   }
239
240   elapsed = fdc->fdc_status[drive].rev_timer ->elapsed( ).as_double();
241   speed = ( CUSTOM_REG(REG_ADKCON) & 0x100 ) ? 2 : 4;
242
243   bytes = elapsed /  attotime::from_usec( speed * 8 ).as_double();
244   pos = bytes % ( fdc->fdc_status[drive].tracklen );
245
246   return pos;
247}
248
249UINT16 amiga_fdc_get_byte (device_t *device)
250{
251   amiga_state *state = device->machine().driver_data<amiga_state>();
252   int pos;
253   int i, drive = -1;
254   UINT16 ret;
255   amiga_fdc_t *fdc = get_safe_token(device);
256
257   ret = ( ( CUSTOM_REG(REG_DSKLEN) >> 1 ) & 0x4000 ) & ( ( CUSTOM_REG(REG_DMACON) << 10 ) & 0x4000 );
258   ret |= ( CUSTOM_REG(REG_DSKLEN) >> 1 ) & 0x2000;
259
260   for ( i = 0; i < NUM_DRIVES; i++ ) {
261      if ( !( fdc->fdc_sel & ( 1 << i ) ) )
262         drive = i;
263   }
264
265   if ( drive == -1 )
266      return ret;
267
268   if ( fdc->fdc_status[drive].disk_changed )
269      return ret;
270
271   setup_fdc_buffer( device,drive );
272
273   pos = fdc_get_curpos( device, drive );
274
275   if ( fdc->fdc_status[drive].mfm[pos] == ( CUSTOM_REG(REG_DSRSYNC) >> 8 ) &&
276       fdc->fdc_status[drive].mfm[pos+1] == ( CUSTOM_REG(REG_DSRSYNC) & 0xff ) )
277         ret |= 0x1000;
278
279   if ( pos != fdc->fdc_status[drive].pos ) {
280      ret |= 0x8000;
281      fdc->fdc_status[drive].pos = pos;
282   }
283
284   ret |= fdc->fdc_status[drive].mfm[pos];
285
286   return ret;
287}
288
289static TIMER_CALLBACK(fdc_sync_proc)
290{
291   amiga_state *state = machine.driver_data<amiga_state>();
292   int drive = param;
293   UINT16         sync = CUSTOM_REG(REG_DSRSYNC);
294   int            cur_pos;
295   int            sector;
296   int            time;
297   amiga_fdc_t *fdc = get_safe_token((device_t*)ptr);
298
299   /* if floppy got ejected, stop */
300   if ( fdc->fdc_status[drive].disk_changed )
301      goto bail;
302
303   if ( fdc->fdc_status[drive].motor_on == 0 )
304      goto bail;
305
306   cur_pos = fdc_get_curpos( (device_t*)ptr, drive );
307
308   if ( cur_pos <= ( GAP_TRACK_BYTES + 6 ) )
309   {
310      sector = 0;
311   }
312   else
313   {
314      sector = ( cur_pos - ( GAP_TRACK_BYTES + 6 ) ) / ONE_SECTOR_BYTES;
315   }
316
317   setup_fdc_buffer( (device_t*)ptr, drive );
318
319   if ( cur_pos < 2 )
320      cur_pos = 2;
321
322   if ( fdc->fdc_status[drive].mfm[cur_pos-2] == ( ( sync >> 8 ) & 0xff ) &&
323       fdc->fdc_status[drive].mfm[cur_pos-1] == ( sync & 0xff ) )
324   {
325      address_space *space = machine.device("maincpu")->memory().space(AS_PROGRAM);
326
327      amiga_custom_w(space, REG_INTREQ, 0x8000 | INTENA_DSKSYN, 0xffff);
328   }
329
330   if ( sector < 10 )
331   {
332      /* start the sync timer */
333      time = ONE_SECTOR_BYTES;
334      time *= ( CUSTOM_REG(REG_ADKCON) & 0x0100 ) ? 2 : 4;
335      time *= 8;
336      fdc->fdc_status[drive].sync_timer->adjust(attotime::from_usec( time ), drive);
337      return;
338   }
339
340bail:
341   fdc->fdc_status[drive].sync_timer->reset(  );
342}
343
344static TIMER_CALLBACK(fdc_dma_proc)
345{
346   amiga_state *state = machine.driver_data<amiga_state>();
347   int drive = param;
348   amiga_fdc_t *fdc = get_safe_token((device_t*)ptr);
349
350   /* if DMA got disabled by the time we got here, stop operations */
351   if ( ( CUSTOM_REG(REG_DSKLEN) & 0x8000 ) == 0 )
352      goto bail;
353
354   if ( ( CUSTOM_REG(REG_DMACON) & 0x0210 ) == 0 )
355      goto bail;
356
357   /* if floppy got ejected, also stop */
358   if ( fdc->fdc_status[drive].disk_changed )
359      goto bail;
360
361   if ( fdc->fdc_status[drive].motor_on == 0 )
362      goto bail;
363
364   setup_fdc_buffer( (device_t*)ptr, drive );
365
366   if ( CUSTOM_REG(REG_DSKLEN) & 0x4000 ) /* disk write case, unsupported yet */
367   {
368      if ( fdc->fdc_status[drive].len > 0 )
369      {
370         address_space *space = machine.device("maincpu")->memory().space(AS_PROGRAM);
371
372         logerror("Write to disk unsupported yet\n" );
373
374         amiga_custom_w(space, REG_INTREQ, 0x8000 | INTENA_DSKBLK, 0xffff);
375      }
376   }
377   else
378   {
379      offs_t offset = fdc->fdc_status[drive].ptr;
380      int cur_pos = fdc->fdc_status[drive].pos;
381      int len = fdc->fdc_status[drive].len;
382
383      if ( len > MAX_WORDS_PER_DMA_CYCLE ) len = MAX_WORDS_PER_DMA_CYCLE;
384
385      fdc->fdc_status[drive].len -= len;
386
387      while ( len-- )
388      {
389         int dat = ( fdc->fdc_status[drive].mfm[cur_pos++] ) << 8;
390
391         cur_pos %= ( fdc->fdc_status[drive].tracklen );
392
393         dat |= fdc->fdc_status[drive].mfm[cur_pos++];
394
395         cur_pos %= ( fdc->fdc_status[drive].tracklen );
396
397         (*state->m_chip_ram_w)(state, offset, dat);
398
399         offset += 2;
400      }
401
402      fdc->fdc_status[drive].ptr = offset;
403      fdc->fdc_status[drive].pos = cur_pos;
404
405      if ( fdc->fdc_status[drive].len <= 0 )
406      {
407         address_space *space = machine.device("maincpu")->memory().space(AS_PROGRAM);
408
409         amiga_custom_w(space, REG_INTREQ, 0x8000 | INTENA_DSKBLK, 0xffff);
410      }
411      else
412      {
413         int time;
414         double   len_words = fdc->fdc_status[drive].len;
415         if ( len_words > MAX_WORDS_PER_DMA_CYCLE ) len_words = MAX_WORDS_PER_DMA_CYCLE;
416
417         time = len_words * 2;
418         time *= ( CUSTOM_REG(REG_ADKCON) & 0x0100 ) ? 2 : 4;
419         time *= 8;
420         fdc->fdc_status[drive].dma_timer->adjust(attotime::from_usec( time ), drive);
421         return;
422      }
423   }
424
425bail:
426   fdc->fdc_status[drive].dma_timer->reset(  );
427}
428
429void amiga_fdc_setup_dma( device_t *device ) {
430   amiga_state *state = device->machine().driver_data<amiga_state>();
431   int i, cur_pos, drive = -1, len_words = 0;
432   int time = 0;
433   amiga_fdc_t *fdc = get_safe_token(device);
434
435   for ( i = 0; i < NUM_DRIVES; i++ ) {
436      if ( !( fdc->fdc_sel & ( 1 << i ) ) )
437         drive = i;
438   }
439
440   if ( drive == -1 ) {
441      address_space *space = device->machine().device("maincpu")->memory().space(AS_PROGRAM);
442
443      logerror("Disk DMA started with no drive selected!\n" );
444      amiga_custom_w(space, REG_INTREQ, 0x8000 | INTENA_DSKBLK, 0xffff);
445      return;
446   }
447
448   if ( ( CUSTOM_REG(REG_DSKLEN) & 0x8000 ) == 0 )
449      goto bail;
450
451   if ( ( CUSTOM_REG(REG_DMACON) & 0x0210 ) == 0 )
452      goto bail;
453
454   if ( fdc->fdc_status[drive].disk_changed )
455      goto bail;
456
457   setup_fdc_buffer( device,drive );
458
459   fdc->fdc_status[drive].len = CUSTOM_REG(REG_DSKLEN) & 0x3fff;
460   fdc->fdc_status[drive].ptr = CUSTOM_REG_LONG(REG_DSKPTH);
461   fdc->fdc_status[drive].pos = cur_pos = fdc_get_curpos( device, drive );
462
463   /* we'll do a set amount at a time */
464   len_words = fdc->fdc_status[drive].len;
465   if ( len_words > MAX_WORDS_PER_DMA_CYCLE ) len_words = MAX_WORDS_PER_DMA_CYCLE;
466
467   if ( CUSTOM_REG(REG_ADKCON) & 0x0400 ) { /* Wait for sync */
468      if ( CUSTOM_REG(REG_DSRSYNC) != 0x4489 ) {
469         logerror("Attempting to read a non-standard SYNC\n" );
470      }
471
472      i = cur_pos;
473      do {
474         if ( fdc->fdc_status[drive].mfm[i] == ( CUSTOM_REG(REG_DSRSYNC) >> 8 ) &&
475             fdc->fdc_status[drive].mfm[i+1] == ( CUSTOM_REG(REG_DSRSYNC) & 0xff ) )
476               break;
477
478         i++;
479         i %= ( fdc->fdc_status[drive].tracklen );
480         time++;
481      } while( i != cur_pos );
482
483      if ( i == cur_pos && time != 0 ) {
484         logerror("SYNC not found on track!\n" );
485         return;
486      } else {
487         fdc->fdc_status[drive].pos = i + 2;
488         time += 2;
489      }
490   }
491
492   time += len_words * 2;
493   time *= ( CUSTOM_REG(REG_ADKCON) & 0x0100 ) ? 2 : 4;
494   time *= 8;
495   fdc->fdc_status[drive].dma_timer->adjust(attotime::from_usec( time ), drive);
496
497   return;
498
499bail:
500   fdc->fdc_status[drive].dma_timer->reset(  );
501}
502
503static void setup_fdc_buffer( device_t *device,int drive )
504{
505   int      sector, offset, len;
506   UINT8   temp_cyl[512*11];
507   amiga_fdc_t *fdc = get_safe_token(device);
508
509   /* no disk in drive */
510   if ( fdc->fdc_status[drive].f == NULL ) {
511      memset( &fdc->fdc_status[drive].mfm[0], 0xaa, 32 );
512      fdc->fdc_status[drive].disk_changed = DISK_DETECT_DELAY;
513      return;
514   }
515
516   len = 512*11;
517
518   offset = ( fdc->fdc_status[drive].cyl << 1 ) | fdc->fdc_side;
519
520   if ( fdc->fdc_status[drive].cached == offset )
521      return;
522
523#if 0
524   popmessage("T:%d S:%d", fdc->fdc_status[drive].cyl, fdc_side );
525#endif
526
527   if ( fdc->fdc_status[drive].is_ext_image )
528   {
529      len = fdc->fdc_status[drive].extinfo[offset] & 0xffff;
530
531      if ( len > ( MAX_MFM_TRACK_LEN - 2 ) )
532         len = MAX_MFM_TRACK_LEN - 2;
533
534      if ( fdc->fdc_status[drive].f->fseek( fdc->fdc_status[drive].extoffs[offset], SEEK_SET ) )
535      {
536         logerror("FDC: image_fseek failed!\n" );
537         fdc->fdc_status[drive].f = NULL;
538         fdc->fdc_status[drive].disk_changed = DISK_DETECT_DELAY;
539         return;
540      }
541
542      /* if SYNC is 0000, then its a regular amiga dos track image */
543      if ( ( fdc->fdc_status[drive].extinfo[offset] >> 16 ) == 0x0000 )
544      {
545         fdc->fdc_status[drive].f->fread( temp_cyl, len );
546         /* fall through to regular load */
547      }
548      else /* otherwise, it's a raw track */
549      {
550         fdc->fdc_status[drive].mfm[0] = ( fdc->fdc_status[drive].extinfo[offset] >> 24 ) & 0xff;
551         fdc->fdc_status[drive].mfm[1] = ( fdc->fdc_status[drive].extinfo[offset] >> 16 ) & 0xff;
552         fdc->fdc_status[drive].f->fread( &fdc->fdc_status[drive].mfm[2], len );
553         fdc->fdc_status[drive].tracklen = len + 2;
554         fdc->fdc_status[drive].cached = offset;
555         return;
556      }
557   }
558   else
559   {
560      if ( fdc->fdc_status[drive].f->fseek( offset * len, SEEK_SET ) )
561      {
562         logerror("FDC: image_fseek failed!\n" );
563         fdc->fdc_status[drive].f = NULL;
564         fdc->fdc_status[drive].disk_changed = DISK_DETECT_DELAY;
565         return;
566      }
567
568      fdc->fdc_status[drive].f->fread( temp_cyl, len );
569   }
570
571   fdc->fdc_status[drive].tracklen = MAX_TRACK_BYTES;
572
573   memset( &fdc->fdc_status[drive].mfm[ONE_SECTOR_BYTES*11], 0xaa, GAP_TRACK_BYTES );
574
575   for ( sector = 0; sector < 11; sector++ ) {
576      int x;
577       UINT8 *dest = ( &fdc->fdc_status[drive].mfm[(ONE_SECTOR_BYTES*sector)] );
578       UINT8 *src = &temp_cyl[sector*512];
579      UINT32 tmp;
580      UINT32 even, odd;
581      UINT32 hck = 0, dck = 0;
582
583      /* Preamble and sync */
584      *(dest + 0) = 0xaa;
585      *(dest + 1) = 0xaa;
586      *(dest + 2) = 0xaa;
587      *(dest + 3) = 0xaa;
588      *(dest + 4) = 0x44;
589      *(dest + 5) = 0x89;
590      *(dest + 6) = 0x44;
591      *(dest + 7) = 0x89;
592
593      /* Track and sector info */
594
595      tmp = 0xff000000 | (offset<<16) | (sector<<8) | (11 - sector);
596      odd = (tmp & 0x55555555) | 0xaaaaaaaa;
597      even = ( ( tmp >> 1 ) & 0x55555555 ) | 0xaaaaaaaa;
598      *(dest +  8) = (UINT8) ((even & 0xff000000)>>24);
599      *(dest +  9) = (UINT8) ((even & 0xff0000)>>16);
600      *(dest + 10) = (UINT8) ((even & 0xff00)>>8);
601      *(dest + 11) = (UINT8) ((even & 0xff));
602      *(dest + 12) = (UINT8) ((odd & 0xff000000)>>24);
603      *(dest + 13) = (UINT8) ((odd & 0xff0000)>>16);
604      *(dest + 14) = (UINT8) ((odd & 0xff00)>>8);
605      *(dest + 15) = (UINT8) ((odd & 0xff));
606
607      /* Fill unused space */
608
609      for (x = 16 ; x < 48; x++)
610         *(dest + x) = 0xaa;
611
612      /* Encode data section of sector */
613
614      for (x = 64 ; x < 576; x++)
615      {
616         tmp = *(src + x - 64);
617         odd = (tmp & 0x55);
618         even = (tmp>>1) & 0x55;
619         *(dest + x) = (UINT8) (even | 0xaa);
620         *(dest + x + 512) = (UINT8) (odd | 0xaa);
621      }
622
623      /* Calculate checksum for unused space */
624
625      for(x = 8; x < 48; x += 4)
626          hck ^= (((UINT32) *(dest + x))<<24) | (((UINT32) *(dest + x + 1))<<16) |
627                (((UINT32) *(dest + x + 2))<<8) | ((UINT32) *(dest + x + 3));
628
629      even = odd = hck;
630      odd >>= 1;
631      even |= 0xaaaaaaaa;
632      odd |= 0xaaaaaaaa;
633
634      *(dest + 48) = (UINT8) ((odd & 0xff000000)>>24);
635      *(dest + 49) = (UINT8) ((odd & 0xff0000)>>16);
636      *(dest + 50) = (UINT8) ((odd & 0xff00)>>8);
637      *(dest + 51) = (UINT8) (odd & 0xff);
638      *(dest + 52) = (UINT8) ((even & 0xff000000)>>24);
639      *(dest + 53) = (UINT8) ((even & 0xff0000)>>16);
640      *(dest + 54) = (UINT8) ((even & 0xff00)>>8);
641      *(dest + 55) = (UINT8) (even & 0xff);
642
643      /* Calculate checksum for data section */
644
645      for(x = 64; x < 1088; x += 4)
646         dck ^= (((UINT32) *(dest + x))<<24) | (((UINT32) *(dest + x + 1))<<16) |
647               (((UINT32) *(dest + x + 2))<< 8) |  ((UINT32) *(dest + x + 3));
648      even = odd = dck;
649      odd >>= 1;
650      even |= 0xaaaaaaaa;
651      odd |= 0xaaaaaaaa;
652      *(dest + 56) = (UINT8) ((odd & 0xff000000)>>24);
653      *(dest + 57) = (UINT8) ((odd & 0xff0000)>>16);
654      *(dest + 58) = (UINT8) ((odd & 0xff00)>>8);
655      *(dest + 59) = (UINT8) (odd & 0xff);
656      *(dest + 60) = (UINT8) ((even & 0xff000000)>>24);
657      *(dest + 61) = (UINT8) ((even & 0xff0000)>>16);
658      *(dest + 62) = (UINT8) ((even & 0xff00)>>8);
659      *(dest + 63) = (UINT8) (even & 0xff);
660   }
661
662   // update MFM data with proper CLK signal
663   int lastbit= 0;
664   for(int i=0;i<MAX_TRACK_BYTES ;i++)
665   {
666      UINT8 c=fdc->fdc_status[drive].mfm[i];
667      UINT8 dat = 0;
668      for(int j=0;j<8;j=j+2)
669      {
670         UINT8 c1=(c>>(6-j))&0x3;
671         if(c1&0x1)
672         {
673            dat |= (0x01<<(6-j));
674            lastbit=1;
675         }
676         else
677         {
678            if(lastbit==0 && (c1&0x2))
679            {
680               dat |= (0x02<<(6-j));
681            }
682            else
683            {
684               dat |= (0x00<<(6-j));
685            }
686            lastbit=0;
687         }
688      }
689      fdc->fdc_status[drive].mfm[i] = dat;
690   }
691   fdc->fdc_status[drive].cached = offset;
692}
693
694static TIMER_CALLBACK(fdc_rev_proc)
695{
696   amiga_state *state = machine.driver_data<amiga_state>();
697   int drive = param;
698   int time;
699   device_t *cia;
700   amiga_fdc_t *fdc = get_safe_token((device_t*)ptr);
701
702   /* Issue a index pulse when a disk revolution completes */
703   cia = machine.device("cia_1");
704   mos6526_flag_w(cia, 0);
705   mos6526_flag_w(cia, 1);
706
707   fdc->fdc_status[drive].rev_timer->adjust(attotime::from_msec( ONE_REV_TIME ), drive);
708   fdc->fdc_status[drive].rev_timer_started = 1;
709
710   if ( fdc->fdc_status[drive].is_ext_image == 0 )
711   {
712      /* also start the sync timer */
713      time = GAP_TRACK_BYTES + 6;
714      time *= ( CUSTOM_REG(REG_ADKCON) & 0x0100 ) ? 2 : 4;
715      time *= 8;
716      fdc->fdc_status[drive].sync_timer->adjust(attotime::from_usec( time ), drive);
717   }
718}
719
720static void start_rev_timer( device_t *device,int drive ) {
721//  double time;
722   amiga_fdc_t *fdc = get_safe_token(device);
723
724   if ( fdc->fdc_status[drive].rev_timer_started ) {
725      logerror("Revolution timer started twice?!\n" );
726      return;
727   }
728
729   fdc->fdc_status[drive].rev_timer->adjust(attotime::from_msec( ONE_REV_TIME ), drive);
730   fdc->fdc_status[drive].rev_timer_started = 1;
731}
732
733static void stop_rev_timer( device_t *device,int drive ) {
734   amiga_fdc_t *fdc = get_safe_token(device);
735
736   if ( fdc->fdc_status[drive].rev_timer_started == 0 ) {
737      logerror("Revolution timer never started?!\n" );
738      return;
739   }
740
741   fdc->fdc_status[drive].rev_timer->reset(  );
742   fdc->fdc_status[drive].rev_timer_started = 0;
743   fdc->fdc_status[drive].dma_timer->reset(  );
744   fdc->fdc_status[drive].sync_timer->reset(  );
745}
746
747static void fdc_setup_leds(device_t *device, int drive ) {
748
749   char portname[12];
750   amiga_fdc_t *fdc = get_safe_token(device);
751   sprintf(portname, "drive_%d_led", drive);
752   output_set_value(portname, fdc->fdc_status[drive].motor_on == 0 ? 0 : 1);
753
754   if ( drive == 0 )
755      set_led_status(device->machine(), 1, fdc->fdc_status[drive].motor_on ); /* update internal drive led */
756
757   if ( drive == 1 )
758      set_led_status(device->machine(), 2, fdc->fdc_status[drive].motor_on ); /* update external drive led */
759}
760
761static void fdc_stepdrive( device_t *device,int drive ) {
762   amiga_fdc_t *fdc = get_safe_token(device);
763
764   if ( fdc->fdc_dir ) {
765      if ( fdc->fdc_status[drive].cyl )
766         fdc->fdc_status[drive].cyl--;
767   } else {
768      if ( fdc->fdc_status[drive].cyl < 79 )
769         fdc->fdc_status[drive].cyl++;
770   }
771
772   /* Update disk detection if applicable */
773   if ( fdc->fdc_status[drive].f != NULL )
774   {
775      if ( fdc->fdc_status[drive].disk_changed > 0 )
776         fdc->fdc_status[drive].disk_changed--;
777   }
778}
779
780static void fdc_motor( device_t *device,int drive, int off ) {
781   amiga_fdc_t *fdc = get_safe_token(device);
782   int on = !off;
783
784   if ( ( fdc->fdc_status[drive].motor_on == 0 ) && on ) {
785      fdc->fdc_status[drive].pos = 0;
786
787      start_rev_timer( device,drive );
788
789   } else {
790      if ( fdc->fdc_status[drive].motor_on && off )
791         stop_rev_timer(device, drive );
792   }
793
794   fdc->fdc_status[drive].motor_on = on;
795}
796
797WRITE8_DEVICE_HANDLER( amiga_fdc_control_w )
798{
799   int step_pulse;
800   int drive;
801
802   amiga_fdc_t *fdc = get_safe_token(device);
803
804   if ( fdc->fdc_sel != ( ( data >> 3 ) & 15 ) )
805      fdc->fdc_rdy = 0;
806
807   fdc->fdc_sel = ( data >> 3 ) & 15;
808    fdc->fdc_side = 1 - ( ( data >> 2 ) & 1 );
809   fdc->fdc_dir = ( data >> 1 ) & 1;
810
811   step_pulse = data & 1;
812
813    if ( fdc->fdc_step != step_pulse ) {
814      fdc->fdc_step = step_pulse;
815
816       if ( fdc->fdc_step == 0 ) {
817          for ( drive = 0; drive < NUM_DRIVES; drive++ ) {
818            if ( !( fdc->fdc_sel & ( 1 << drive ) ) )
819                fdc_stepdrive( device, drive );
820         }
821      }
822   }
823
824   for ( drive = 0; drive < NUM_DRIVES; drive++ ) {
825      if ( !( fdc->fdc_sel & ( 1 << drive ) ) ) {
826         fdc_motor( device, drive, ( data >> 7 ) & 1 );
827         fdc_setup_leds( device,drive );
828      }
829    }
830}
831
832UINT8  amiga_fdc_status_r (device_t *device)
833{
834   int drive = -1, ret = 0x3c;
835   amiga_fdc_t *fdc = get_safe_token(device);
836   for ( drive = 0; drive < NUM_DRIVES; drive++ ) {
837      if ( !( fdc->fdc_sel & ( 1 << drive ) ) ) {
838
839         if ( fdc->fdc_status[drive].motor_on ) {
840            if ( fdc->fdc_rdy ) ret &= ~0x20;
841            fdc->fdc_rdy = 1;
842         } else {
843            /* return drive id */
844            ret &= ~0x20;
845         }
846
847         if ( fdc->fdc_status[drive].cyl == 0 )
848            ret &= ~0x10;
849
850         if ( fdc->fdc_status[drive].wprot )
851            ret &= ~0x08;
852
853         if ( fdc->fdc_status[drive].disk_changed )
854            ret &= ~0x04;
855
856         return ret;
857      }
858   }
859
860   return ret;
861}
862
863static const floppy_config amiga_floppy_config =
864{
865   DEVCB_NULL,
866   DEVCB_NULL,
867   DEVCB_NULL,
868   DEVCB_NULL,
869   DEVCB_NULL,
870   FLOPPY_STANDARD_3_5_DSHD,
871   FLOPPY_OPTIONS_NAME(amiga_only),
872   NULL
873};
874
875static MACHINE_CONFIG_FRAGMENT( amiga_fdc )
876   MCFG_FLOPPY_2_DRIVES_ADD(amiga_floppy_config)
877MACHINE_CONFIG_END
878
879
880DEVICE_GET_INFO( amiga_fdc )
881{
882   switch (state)
883   {
884      /* --- the following bits of info are returned as 64-bit signed integers --- */
885      case DEVINFO_INT_INLINE_CONFIG_BYTES:         info->i = 0;                                    break;
886      case DEVINFO_INT_TOKEN_BYTES:               info->i = sizeof(amiga_fdc_t);                        break;
887
888      /* --- the following bits of info are returned as pointers --- */
889      case DEVINFO_PTR_MACHINE_CONFIG:            info->machine_config = MACHINE_CONFIG_NAME(amiga_fdc);      break;
890
891      /* --- the following bits of info are returned as pointers to data or functions --- */
892      case DEVINFO_FCT_START:                     info->start = DEVICE_START_NAME(amiga_fdc);               break;
893      case DEVINFO_FCT_STOP:                     /* Nothing */                                    break;
894      case DEVINFO_FCT_RESET:                     info->reset = DEVICE_RESET_NAME(amiga_fdc);               break;
895
896      /* --- the following bits of info are returned as NULL-terminated strings --- */
897      case DEVINFO_STR_NAME:                     strcpy(info->s, "Amiga FDC");                        break;
898      case DEVINFO_STR_FAMILY:                  strcpy(info->s, "Amiga FDC");                        break;
899      case DEVINFO_STR_VERSION:                  strcpy(info->s, "1.0");                              break;
900      case DEVINFO_STR_SOURCE_FILE:               strcpy(info->s, __FILE__);                           break;
901      case DEVINFO_STR_CREDITS:                  strcpy(info->s, "Copyright the MESS Team");             break;
902   }
903}
904
905DEFINE_LEGACY_DEVICE(AMIGA_FDC, amiga_fdc);
src/mess/machine/amigakbd.c
r0r11532
1/***************************************************************************
2
3    Amiga keyboard controller emulation
4
5***************************************************************************/
6
7
8#include "emu.h"
9#include "includes/amiga.h"
10#include "amigakbd.h"
11#include "machine/6526cia.h"
12
13
14#define KEYBOARD_BUFFER_SIZE   256
15
16typedef struct
17{
18   UINT8 *buf;
19   int buf_pos;
20   int cur_pos;
21   emu_timer *timer;
22} amigakbd_t;
23static amigakbd_t kbd;
24
25static void kbd_sendscancode( running_machine &machine, UINT8 scancode )
26{
27   int j;
28   device_t *cia = machine.device("cia_0");
29
30   /* send over to the cia A */
31   for( j = 0; j < 8; j++ )
32   {
33      mos6526_cnt_w( cia, 0 );   /* lower cnt */
34      mos6526_sp_w( cia, BIT(scancode << j, 7) ); /* set the serial data */
35      mos6526_cnt_w( cia, 1 );   /* raise cnt */
36   }
37}
38
39static TIMER_CALLBACK( kbd_update_callback )
40{
41   UINT8   scancode;
42
43   (void)param;
44
45   /* if we don't have pending data, bail */
46
47   if ( kbd.buf_pos == kbd.cur_pos )
48      return;
49
50   /* fetch the next scan code and send it to the Amiga */
51   scancode = kbd.buf[kbd.cur_pos++];
52   kbd.cur_pos %= KEYBOARD_BUFFER_SIZE;
53   kbd_sendscancode( machine, scancode );
54
55   /* if we still have more data, schedule another update */
56   if ( kbd.buf_pos != kbd.cur_pos )
57   {
58      kbd.timer->adjust(machine.primary_screen->frame_period() / 4);
59   }
60}
61
62static INPUT_CHANGED( kbd_update )
63{
64   int   index = (int)(FPTR)param, i;
65   UINT32   oldvalue = oldval * field.mask, newvalue = newval * field.mask;
66   UINT32   delta = oldvalue ^ newvalue;
67
68   /* Special case Page UP, which we will use as Action Replay button */
69   if ( (index == 3) && ( delta & 0x80000000 ) && ( newvalue & 0x80000000 ) )
70   {
71      const amiga_machine_interface *amiga_intf = amiga_get_interface(field.machine());
72
73      if ( amiga_intf != NULL && amiga_intf->nmi_callback )
74      {
75         (*amiga_intf->nmi_callback)(field.machine());
76      }
77   }
78   else
79   {
80      int key_buf_was_empty = ( kbd.buf_pos == kbd.cur_pos ) ? 1 : 0;
81
82      for( i = 0; i < 32; i++ )
83      {
84         if ( delta & ( 1 << i ) )
85         {
86            int down = ( newvalue & ( 1 << i ) ) ? 0 : 1;
87            int scancode = ( ( (index*32)+i ) << 1 ) | down;
88            int amigacode = ~scancode;
89
90            /* add the keycode to the buffer */
91            kbd.buf[kbd.buf_pos++] = amigacode & 0xff;
92            kbd.buf_pos %= KEYBOARD_BUFFER_SIZE;
93         }
94      }
95
96      /* if the buffer was empty and we have new data, start a timer to send the keystrokes */
97      if ( key_buf_was_empty && ( kbd.buf_pos != kbd.cur_pos ) )
98      {
99         kbd.timer->adjust(field.machine().primary_screen->frame_period() / 4);
100      }
101   }
102}
103
104void amigakbd_init( running_machine &machine )
105{
106   /* allocate a keyboard buffer */
107   kbd.buf = auto_alloc_array(machine, UINT8, KEYBOARD_BUFFER_SIZE);
108   kbd.buf_pos = 0;
109   kbd.cur_pos = 0;
110   kbd.timer = machine.scheduler().timer_alloc(FUNC(kbd_update_callback));
111   kbd.timer->reset();
112}
113
114/*********************************************************************************************/
115
116/* Layout is for the US A500 keyboard */
117
118INPUT_PORTS_START( amiga_us_keyboard )
119   PORT_START("amiga_keyboard_0")
120   PORT_BIT( 0x00000001, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CHANGED(kbd_update, 0) PORT_CODE(KEYCODE_TILDE) PORT_CHAR('`') PORT_CHAR('~')      // 00
121   PORT_BIT( 0x00000002, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CHANGED(kbd_update, 0) PORT_CODE(KEYCODE_1) PORT_CHAR('1') PORT_CHAR('!')         // 01
122   PORT_BIT( 0x00000004, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CHANGED(kbd_update, 0) PORT_CODE(KEYCODE_2) PORT_CHAR('2') PORT_CHAR('@')         // 02
123   PORT_BIT( 0x00000008, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CHANGED(kbd_update, 0) PORT_CODE(KEYCODE_3) PORT_CHAR('3') PORT_CHAR('#')         // 03
124   PORT_BIT( 0x00000010, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CHANGED(kbd_update, 0) PORT_CODE(KEYCODE_4) PORT_CHAR('4') PORT_CHAR('$')         // 04
125   PORT_BIT( 0x00000020, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CHANGED(kbd_update, 0) PORT_CODE(KEYCODE_5) PORT_CHAR('5') PORT_CHAR('%')         // 05
126   PORT_BIT( 0x00000040, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CHANGED(kbd_update, 0) PORT_CODE(KEYCODE_6) PORT_CHAR('6') PORT_CHAR('^')         // 06
127   PORT_BIT( 0x00000080, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CHANGED(kbd_update, 0) PORT_CODE(KEYCODE_7) PORT_CHAR('7') PORT_CHAR('&')         // 07
128   PORT_BIT( 0x00000100, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CHANGED(kbd_update, 0) PORT_CODE(KEYCODE_8) PORT_CHAR('8') PORT_CHAR('*')         // 08
129   PORT_BIT( 0x00000200, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CHANGED(kbd_update, 0) PORT_CODE(KEYCODE_9) PORT_CHAR('9') PORT_CHAR('(')         // 09
130   PORT_BIT( 0x00000400, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CHANGED(kbd_update, 0) PORT_CODE(KEYCODE_0) PORT_CHAR('0') PORT_CHAR(')')         // 0A
131   PORT_BIT( 0x00000800, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CHANGED(kbd_update, 0) PORT_CODE(KEYCODE_MINUS) PORT_CHAR('-') PORT_CHAR('_')      // 0B
132   PORT_BIT( 0x00001000, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CHANGED(kbd_update, 0) PORT_CODE(KEYCODE_EQUALS) PORT_CHAR('=') PORT_CHAR('+')      // 0C
133   PORT_BIT( 0x00002000, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CHANGED(kbd_update, 0) PORT_CODE(KEYCODE_BACKSLASH2) PORT_CHAR('\\') PORT_CHAR('\xA6')   // 0D
134   PORT_BIT( 0x00004000, IP_ACTIVE_HIGH, IPT_UNUSED) PORT_CHANGED(kbd_update, 0)                           // 0E
135   PORT_BIT( 0x00008000, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CHANGED(kbd_update, 0) PORT_CODE(KEYCODE_0_PAD) PORT_CHAR(UCHAR_MAMEKEY(0_PAD))   // 0F
136   PORT_BIT( 0x00010000, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CHANGED(kbd_update, 0) PORT_CODE(KEYCODE_Q) PORT_CHAR('q') PORT_CHAR('Q')         // 10
137   PORT_BIT( 0x00020000, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CHANGED(kbd_update, 0) PORT_CODE(KEYCODE_W) PORT_CHAR('w') PORT_CHAR('W')         // 11
138   PORT_BIT( 0x00040000, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CHANGED(kbd_update, 0) PORT_CODE(KEYCODE_E) PORT_CHAR('e') PORT_CHAR('E')         // 12
139   PORT_BIT( 0x00080000, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CHANGED(kbd_update, 0) PORT_CODE(KEYCODE_R) PORT_CHAR('r') PORT_CHAR('R')         // 13
140   PORT_BIT( 0x00100000, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CHANGED(kbd_update, 0) PORT_CODE(KEYCODE_T) PORT_CHAR('t') PORT_CHAR('T')         // 14
141   PORT_BIT( 0x00200000, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CHANGED(kbd_update, 0) PORT_CODE(KEYCODE_Y) PORT_CHAR('y') PORT_CHAR('Y')         // 15
142   PORT_BIT( 0x00400000, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CHANGED(kbd_update, 0) PORT_CODE(KEYCODE_U) PORT_CHAR('u') PORT_CHAR('U')         // 16
143   PORT_BIT( 0x00800000, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CHANGED(kbd_update, 0) PORT_CODE(KEYCODE_I) PORT_CHAR('i') PORT_CHAR('I')         // 17
144   PORT_BIT( 0x01000000, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CHANGED(kbd_update, 0) PORT_CODE(KEYCODE_O) PORT_CHAR('o') PORT_CHAR('O')         // 18
145   PORT_BIT( 0x02000000, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CHANGED(kbd_update, 0) PORT_CODE(KEYCODE_P) PORT_CHAR('p') PORT_CHAR('P')         // 19
146   PORT_BIT( 0x04000000, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CHANGED(kbd_update, 0) PORT_CODE(KEYCODE_OPENBRACE) PORT_CHAR('[') PORT_CHAR('{')   // 1A
147   PORT_BIT( 0x08000000, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CHANGED(kbd_update, 0) PORT_CODE(KEYCODE_CLOSEBRACE) PORT_CHAR(']') PORT_CHAR('}')   // 1B
148   PORT_BIT( 0x10000000, IP_ACTIVE_HIGH, IPT_UNUSED) PORT_CHANGED(kbd_update, 0)                           // 1C
149   PORT_BIT( 0x20000000, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CHANGED(kbd_update, 0) PORT_CODE(KEYCODE_1_PAD) PORT_CHAR(UCHAR_MAMEKEY(1_PAD))   // 1D
150   PORT_BIT( 0x40000000, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CHANGED(kbd_update, 0) PORT_CODE(KEYCODE_2_PAD) PORT_CHAR(UCHAR_MAMEKEY(2_PAD))   // 1E
151   PORT_BIT( 0x80000000, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CHANGED(kbd_update, 0) PORT_CODE(KEYCODE_3_PAD) PORT_CHAR(UCHAR_MAMEKEY(3_PAD))   // 1F
152
153   PORT_START("amiga_keyboard_1")
154   PORT_BIT( 0x00000001, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CHANGED(kbd_update, 1) PORT_CODE(KEYCODE_A) PORT_CHAR('a') PORT_CHAR('A')         // 20
155   PORT_BIT( 0x00000002, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CHANGED(kbd_update, 1) PORT_CODE(KEYCODE_S) PORT_CHAR('s') PORT_CHAR('S')         // 21
156   PORT_BIT( 0x00000004, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CHANGED(kbd_update, 1) PORT_CODE(KEYCODE_D) PORT_CHAR('d') PORT_CHAR('D')         // 22
157   PORT_BIT( 0x00000008, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CHANGED(kbd_update, 1) PORT_CODE(KEYCODE_F) PORT_CHAR('f') PORT_CHAR('F')         // 23
158   PORT_BIT( 0x00000010, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CHANGED(kbd_update, 1) PORT_CODE(KEYCODE_G) PORT_CHAR('g') PORT_CHAR('G')         // 24
159   PORT_BIT( 0x00000020, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CHANGED(kbd_update, 1) PORT_CODE(KEYCODE_H) PORT_CHAR('h') PORT_CHAR('H')         // 25
160   PORT_BIT( 0x00000040, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CHANGED(kbd_update, 1) PORT_CODE(KEYCODE_J) PORT_CHAR('j') PORT_CHAR('J')         // 26
161   PORT_BIT( 0x00000080, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CHANGED(kbd_update, 1) PORT_CODE(KEYCODE_K) PORT_CHAR('k') PORT_CHAR('K')         // 27
162   PORT_BIT( 0x00000100, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CHANGED(kbd_update, 1) PORT_CODE(KEYCODE_L) PORT_CHAR('l') PORT_CHAR('L')         // 28
163   PORT_BIT( 0x00000200, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CHANGED(kbd_update, 1) PORT_CODE(KEYCODE_COLON) PORT_CHAR(';') PORT_CHAR(':')      // 29
164   PORT_BIT( 0x00000400, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CHANGED(kbd_update, 1) PORT_CODE(KEYCODE_QUOTE) PORT_CHAR('\'') PORT_CHAR('"')      // 2A
165   PORT_BIT( 0x00000800, IP_ACTIVE_HIGH, IPT_UNUSED) PORT_CHANGED(kbd_update, 1)                           // 2B
166   PORT_BIT( 0x00001000, IP_ACTIVE_HIGH, IPT_UNUSED) PORT_CHANGED(kbd_update, 1)                           // 2C
167   PORT_BIT( 0x00002000, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CHANGED(kbd_update, 1) PORT_CODE(KEYCODE_4_PAD) PORT_CHAR(UCHAR_MAMEKEY(4_PAD))   // 2D
168   PORT_BIT( 0x00004000, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CHANGED(kbd_update, 1) PORT_CODE(KEYCODE_5_PAD) PORT_CHAR(UCHAR_MAMEKEY(5_PAD))   // 2E
169   PORT_BIT( 0x00008000, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CHANGED(kbd_update, 1) PORT_CODE(KEYCODE_6_PAD) PORT_CHAR(UCHAR_MAMEKEY(6_PAD))   // 2F
170   PORT_BIT( 0x00010000, IP_ACTIVE_HIGH, IPT_UNUSED) PORT_CHANGED(kbd_update, 1)                           // 30
171   PORT_BIT( 0x00020000, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CHANGED(kbd_update, 1) PORT_CODE(KEYCODE_Z) PORT_CHAR('z') PORT_CHAR('Z')         // 31
172   PORT_BIT( 0x00040000, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CHANGED(kbd_update, 1) PORT_CODE(KEYCODE_X) PORT_CHAR('x') PORT_CHAR('X')         // 32
173   PORT_BIT( 0x00080000, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CHANGED(kbd_update, 1) PORT_CODE(KEYCODE_C) PORT_CHAR('c') PORT_CHAR('C')         // 33
174   PORT_BIT( 0x00100000, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CHANGED(kbd_update, 1) PORT_CODE(KEYCODE_V) PORT_CHAR('v') PORT_CHAR('V')         // 34
175   PORT_BIT( 0x00200000, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CHANGED(kbd_update, 1) PORT_CODE(KEYCODE_B) PORT_CHAR('b') PORT_CHAR('B')         // 35
176   PORT_BIT( 0x00400000, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CHANGED(kbd_update, 1) PORT_CODE(KEYCODE_N) PORT_CHAR('n') PORT_CHAR('N')         // 36
177   PORT_BIT( 0x00800000, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CHANGED(kbd_update, 1) PORT_CODE(KEYCODE_M) PORT_CHAR('m') PORT_CHAR('M')         // 37
178   PORT_BIT( 0x01000000, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CHANGED(kbd_update, 1) PORT_CODE(KEYCODE_COMMA) PORT_CHAR(',') PORT_CHAR('<')      // 38
179   PORT_BIT( 0x02000000, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CHANGED(kbd_update, 1) PORT_CODE(KEYCODE_STOP)    PORT_CHAR('.') PORT_CHAR('>')      // 39
180   PORT_BIT( 0x04000000, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CHANGED(kbd_update, 1) PORT_CODE(KEYCODE_SLASH) PORT_CHAR('/') PORT_CHAR('?')      // 3A
181   PORT_BIT( 0x08000000, IP_ACTIVE_HIGH, IPT_UNUSED) PORT_CHANGED(kbd_update, 1)                           // 3B
182   PORT_BIT( 0x10000000, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CHANGED(kbd_update, 1) PORT_CODE(KEYCODE_DEL_PAD) PORT_CHAR(UCHAR_MAMEKEY(DEL_PAD))// 3C
183   PORT_BIT( 0x20000000, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CHANGED(kbd_update, 1) PORT_CODE(KEYCODE_7_PAD) PORT_CHAR(UCHAR_MAMEKEY(7_PAD))   // 3D
184   PORT_BIT( 0x40000000, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CHANGED(kbd_update, 1) PORT_CODE(KEYCODE_8_PAD) PORT_CHAR(UCHAR_MAMEKEY(8_PAD))   // 3E
185   PORT_BIT( 0x80000000, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CHANGED(kbd_update, 1) PORT_CODE(KEYCODE_9_PAD) PORT_CHAR(UCHAR_MAMEKEY(9_PAD))   // 3F
186
187   PORT_START("amiga_keyboard_2")
188   PORT_BIT( 0x00000001, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CHANGED(kbd_update, 2) PORT_CODE(KEYCODE_SPACE) PORT_CHAR(' ')                  // 40
189   PORT_BIT( 0x00000002, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CHANGED(kbd_update, 2) PORT_CODE(KEYCODE_BACKSPACE) PORT_CHAR(8)               // 41
190   PORT_BIT( 0x00000004, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CHANGED(kbd_update, 2) PORT_CODE(KEYCODE_TAB) PORT_CHAR('\t')                  // 42
191   PORT_BIT( 0x00000008, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CHANGED(kbd_update, 2) PORT_CODE(KEYCODE_ENTER_PAD) PORT_CHAR(UCHAR_MAMEKEY(ENTER_PAD))   // 43
192   PORT_BIT( 0x00000010, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CHANGED(kbd_update, 2) PORT_CODE(KEYCODE_ENTER) PORT_CHAR(13)                  // 44
193   PORT_BIT( 0x00000020, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CHANGED(kbd_update, 2) PORT_CODE(KEYCODE_ESC) PORT_CHAR(UCHAR_MAMEKEY(ESC))      // 45
194   PORT_BIT( 0x00000040, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CHANGED(kbd_update, 2) PORT_CODE(KEYCODE_DEL) PORT_CHAR(UCHAR_MAMEKEY(DEL))      // 46
195   PORT_BIT( 0x00000080, IP_ACTIVE_HIGH, IPT_UNUSED) PORT_CHANGED(kbd_update, 2)                           // 47
196   PORT_BIT( 0x00000100, IP_ACTIVE_HIGH, IPT_UNUSED) PORT_CHANGED(kbd_update, 2)                           // 48
197   PORT_BIT( 0x00000200, IP_ACTIVE_HIGH, IPT_UNUSED) PORT_CHANGED(kbd_update, 2)                           // 49
198   PORT_BIT( 0x00000400, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CHANGED(kbd_update, 2) PORT_CODE(KEYCODE_MINUS_PAD) PORT_CHAR(UCHAR_MAMEKEY(MINUS_PAD))   // 4A
199   PORT_BIT( 0x00000800, IP_ACTIVE_HIGH, IPT_UNUSED) PORT_CHANGED(kbd_update, 2)                           // 4B
200   PORT_BIT( 0x00001000, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CHANGED(kbd_update, 2) PORT_CODE(KEYCODE_UP) PORT_CHAR(UCHAR_MAMEKEY(UP))         // 4C
201   PORT_BIT( 0x00002000, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CHANGED(kbd_update, 2) PORT_CODE(KEYCODE_DOWN) PORT_CHAR(UCHAR_MAMEKEY(DOWN))      // 4D
202   PORT_BIT( 0x00004000, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CHANGED(kbd_update, 2) PORT_CODE(KEYCODE_RIGHT) PORT_CHAR(UCHAR_MAMEKEY(RIGHT))   // 4E
203   PORT_BIT( 0x00008000, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CHANGED(kbd_update, 2) PORT_CODE(KEYCODE_LEFT) PORT_CHAR(UCHAR_MAMEKEY(LEFT))      // 4F
204   PORT_BIT( 0x00010000, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CHANGED(kbd_update, 2) PORT_CODE(KEYCODE_F1) PORT_CHAR(UCHAR_MAMEKEY(F1))         // 50
205   PORT_BIT( 0x00020000, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CHANGED(kbd_update, 2) PORT_CODE(KEYCODE_F2) PORT_CHAR(UCHAR_MAMEKEY(F2))         // 51
206   PORT_BIT( 0x00040000, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CHANGED(kbd_update, 2) PORT_CODE(KEYCODE_F3) PORT_CHAR(UCHAR_MAMEKEY(F3))         // 52
207   PORT_BIT( 0x00080000, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CHANGED(kbd_update, 2) PORT_CODE(KEYCODE_F4) PORT_CHAR(UCHAR_MAMEKEY(F4))         // 53
208   PORT_BIT( 0x00100000, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CHANGED(kbd_update, 2) PORT_CODE(KEYCODE_F5) PORT_CHAR(UCHAR_MAMEKEY(F5))         // 54
209   PORT_BIT( 0x00200000, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CHANGED(kbd_update, 2) PORT_CODE(KEYCODE_F6) PORT_CHAR(UCHAR_MAMEKEY(F6))         // 55
210   PORT_BIT( 0x00400000, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CHANGED(kbd_update, 2) PORT_CODE(KEYCODE_F7) PORT_CHAR(UCHAR_MAMEKEY(F7))         // 56
211   PORT_BIT( 0x00800000, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CHANGED(kbd_update, 2) PORT_CODE(KEYCODE_F8) PORT_CHAR(UCHAR_MAMEKEY(F8))         // 57
212   PORT_BIT( 0x01000000, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CHANGED(kbd_update, 2) PORT_CODE(KEYCODE_F9) PORT_CHAR(UCHAR_MAMEKEY(F9))         // 58
213   PORT_BIT( 0x02000000, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CHANGED(kbd_update, 2) PORT_CODE(KEYCODE_F10) PORT_CHAR(UCHAR_MAMEKEY(F10))      // 59
214   PORT_BIT( 0x04000000, IP_ACTIVE_HIGH, IPT_UNUSED) PORT_CHANGED(kbd_update, 2)                           // 5A
215   PORT_BIT( 0x08000000, IP_ACTIVE_HIGH, IPT_UNUSED) PORT_CHANGED(kbd_update, 2)                           // 5B
216   PORT_BIT( 0x10000000, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CHANGED(kbd_update, 2) PORT_CODE(KEYCODE_SLASH_PAD) PORT_CHAR(UCHAR_MAMEKEY(SLASH_PAD))   // 5C
217   PORT_BIT( 0x20000000, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CHANGED(kbd_update, 2) PORT_CODE(KEYCODE_ASTERISK) PORT_CHAR(UCHAR_MAMEKEY(ASTERISK))   // 5D
218   PORT_BIT( 0x40000000, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CHANGED(kbd_update, 2) PORT_CODE(KEYCODE_PLUS_PAD) PORT_CHAR(UCHAR_MAMEKEY(PLUS_PAD))   // 5E
219   PORT_BIT( 0x80000000, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CHANGED(kbd_update, 2) PORT_CODE(KEYCODE_INSERT) PORT_CHAR(UCHAR_MAMEKEY(INSERT))   // 5F
220
221   PORT_START("amiga_keyboard_3")
222   PORT_BIT( 0x00000001, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CHANGED(kbd_update, 3) PORT_NAME("Shift (Left)") PORT_CODE(KEYCODE_LSHIFT) PORT_CHAR(UCHAR_SHIFT_1)   // 60
223   PORT_BIT( 0x00000002, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CHANGED(kbd_update, 3) PORT_NAME("Shift (Right)") PORT_CODE(KEYCODE_RSHIFT) PORT_CHAR(UCHAR_SHIFT_1)   // 61
224   PORT_BIT( 0x00000004, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CHANGED(kbd_update, 3) PORT_NAME("Caps Lock") PORT_CODE(KEYCODE_CAPSLOCK)         // 62
225   PORT_BIT( 0x00000008, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CHANGED(kbd_update, 3) PORT_NAME("Ctrl") PORT_CODE(KEYCODE_LCONTROL) PORT_CHAR(UCHAR_MAMEKEY(LCONTROL))// 63
226   PORT_BIT( 0x00000010, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CHANGED(kbd_update, 3) PORT_NAME("Alt (Left)") PORT_CODE(KEYCODE_LALT) PORT_CHAR(UCHAR_MAMEKEY(LALT))   // 64
227   PORT_BIT( 0x00000020, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CHANGED(kbd_update, 3) PORT_NAME("Alt (Right)") PORT_CODE(KEYCODE_RALT) PORT_CHAR(UCHAR_MAMEKEY(RALT))   // 65
228   PORT_BIT( 0x00000040, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CHANGED(kbd_update, 3) PORT_NAME("Amiga A (Left)") PORT_CODE(KEYCODE_LWIN)            // 66
229   PORT_BIT( 0x00000080, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CHANGED(kbd_update, 3) PORT_NAME("Amiga A (Right)")  PORT_CODE(KEYCODE_RWIN)         // 67
230   PORT_BIT( 0x00000100, IP_ACTIVE_HIGH, IPT_UNUSED) PORT_CHANGED(kbd_update, 3)                           // 68
231   PORT_BIT( 0x00000200, IP_ACTIVE_HIGH, IPT_UNUSED) PORT_CHANGED(kbd_update, 3)                           // 69
232   PORT_BIT( 0x00000400, IP_ACTIVE_HIGH, IPT_UNUSED) PORT_CHANGED(kbd_update, 3)                           // 6A
233   PORT_BIT( 0x00000800, IP_ACTIVE_HIGH, IPT_UNUSED) PORT_CHANGED(kbd_update, 3)                           // 6B
234   PORT_BIT( 0x00001000, IP_ACTIVE_HIGH, IPT_UNUSED) PORT_CHANGED(kbd_update, 3)                           // 6C
235   PORT_BIT( 0x00002000, IP_ACTIVE_HIGH, IPT_UNUSED) PORT_CHANGED(kbd_update, 3)                           // 6D
236   PORT_BIT( 0x00004000, IP_ACTIVE_HIGH, IPT_UNUSED) PORT_CHANGED(kbd_update, 3)                           // 6E
237   PORT_BIT( 0x00008000, IP_ACTIVE_HIGH, IPT_UNUSED) PORT_CHANGED(kbd_update, 3)                           // 6F
238   PORT_BIT( 0x00010000, IP_ACTIVE_HIGH, IPT_UNUSED) PORT_CHANGED(kbd_update, 3)                           // 70
239   PORT_BIT( 0x00020000, IP_ACTIVE_HIGH, IPT_UNUSED) PORT_CHANGED(kbd_update, 3)                           // 71
240   PORT_BIT( 0x00040000, IP_ACTIVE_HIGH, IPT_UNUSED) PORT_CHANGED(kbd_update, 3)                           // 72
241   PORT_BIT( 0x00080000, IP_ACTIVE_HIGH, IPT_UNUSED) PORT_CHANGED(kbd_update, 3)                           // 73
242   PORT_BIT( 0x00100000, IP_ACTIVE_HIGH, IPT_UNUSED) PORT_CHANGED(kbd_update, 3)                           // 74
243   PORT_BIT( 0x00200000, IP_ACTIVE_HIGH, IPT_UNUSED) PORT_CHANGED(kbd_update, 3)                           // 75
244   PORT_BIT( 0x00400000, IP_ACTIVE_HIGH, IPT_UNUSED) PORT_CHANGED(kbd_update, 3)                           // 76
245   PORT_BIT( 0x00800000, IP_ACTIVE_HIGH, IPT_UNUSED) PORT_CHANGED(kbd_update, 3)                           // 77
246   PORT_BIT( 0x01000000, IP_ACTIVE_HIGH, IPT_UNUSED) PORT_CHANGED(kbd_update, 3)                           // 78
247   PORT_BIT( 0x02000000, IP_ACTIVE_HIGH, IPT_UNUSED) PORT_CHANGED(kbd_update, 3)                           // 79
248   PORT_BIT( 0x04000000, IP_ACTIVE_HIGH, IPT_UNUSED) PORT_CHANGED(kbd_update, 3)                           // 7A
249   PORT_BIT( 0x08000000, IP_ACTIVE_HIGH, IPT_UNUSED) PORT_CHANGED(kbd_update, 3)                           // 7B
250   PORT_BIT( 0x10000000, IP_ACTIVE_HIGH, IPT_UNUSED) PORT_CHANGED(kbd_update, 3)                           // 7C
251   PORT_BIT( 0x20000000, IP_ACTIVE_HIGH, IPT_UNUSED) PORT_CHANGED(kbd_update, 3)                           // 7D
252   PORT_BIT( 0x40000000, IP_ACTIVE_HIGH, IPT_UNUSED) PORT_CHANGED(kbd_update, 3)                           // 7E
253   PORT_BIT( 0x80000000, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CHANGED(kbd_update, 3)   PORT_CODE(KEYCODE_PGUP)         // 7F NMI button
254INPUT_PORTS_END
src/mess/machine/amigafdc.h
r0r11532
1#ifndef AMIGAFDC_H
2#define AMIGAFDC_H
3
4WRITE8_DEVICE_HANDLER( amiga_fdc_control_w );
5UINT8  amiga_fdc_status_r (device_t *device);
6UINT16 amiga_fdc_get_byte (device_t *device);
7void amiga_fdc_setup_dma( device_t *device );
8
9/***************************************************************************
10    MACROS
11***************************************************************************/
12
13DECLARE_LEGACY_DEVICE(AMIGA_FDC, amiga_fdc);
14
15#define MCFG_AMIGA_FDC_ADD(_tag)   \
16   MCFG_DEVICE_ADD((_tag),  AMIGA_FDC, 0)
17
18#endif /* AMIGAFDC_H */
src/mess/machine/amigakbd.h
r0r11532
1#ifndef AMIGAKBD_H
2#define AMIGAKBD_H
3
4void amigakbd_init( running_machine &machine );
5
6INPUT_PORTS_EXTERN( amiga_us_keyboard );
7
8#endif /* AMIGAKBD_H */
src/mess/machine/amigacrt.c
r0r11532
1/***************************************************************************
2
3    Amiga cartridge emulation
4
5TODO:
6- Investigate why the AR2/3 sometimes garble the video on exit from the cart
7- Add Nordic Power and similar carts
8- Add HRTMon A1200 cart
9
10***************************************************************************/
11
12
13#include "emu.h"
14#include "includes/amiga.h"
15#include "cpu/m68000/m68000.h"
16#include "machine/6526cia.h"
17#include "machine/amigacrt.h"
18
19enum
20{
21   /* supported cartridges */
22   ACTION_REPLAY            =   0,
23   ACTION_REPLAY_MKII,
24   ACTION_REPLAY_MKIII
25};
26
27typedef struct
28{
29   int cart_type;
30   int ar1_spurious;
31   UINT16 ar23_mode;
32} amigacrt_t;
33static amigacrt_t amigacrt;
34
35/***************************************************************************
36
37  Utilities
38
39***************************************************************************/
40
41static int check_kickstart_12_13( running_machine &machine, const char *cart_name )
42{
43   UINT16 * ksmem = (UINT16 *)machine.region( "user1" )->base();
44
45   if ( ksmem[2] == 0x00FC )
46      return 1;
47
48   logerror( "%s requires Kickstart version 1.2 or 1.3 - Cart not installed\n", cart_name );
49
50   return 0;
51}
52
53/***************************************************************************
54
55  Amiga Action Replay 1
56
57  Whenever you push the button, an NMI interrupt is generated.
58
59  The cartridge protects itself from being removed from memory by
60  generating an interrupt whenever either the spurious interrupt
61  vector is written at $60, or the nmi interrupt vector is written at
62  $7c. If the spurious interrupt vector at $60 is written, then
63  a NMI is generated, and the spurious irq vector is restored. If the
64  NMI vector at $7c is written, then a spurious interrupt is generated,
65  and the NMI vector is restored.
66
67  When breakpoints are set, the target address is replaced by a trap
68  instruction, and the original contents of the address are kept in
69  the cartridge's RAM. A trap handler is installed pointing to $40
70  in RAM, where code that clears memory address $60 followed by two
71  nops are written. There seems to be a small delay between the write
72  to $60 and until the actual NMI is generated, since the cart expects
73  the PC to be at $46 (at the second nop).
74
75***************************************************************************/
76
77static IRQ_CALLBACK(amiga_ar1_irqack)
78{
79   if ( irqline == 7 && amigacrt.ar1_spurious )
80   {
81      return M68K_INT_ACK_SPURIOUS;
82   }
83
84   return (24+irqline);
85}
86
87static TIMER_CALLBACK( amiga_ar1_delayed_nmi )
88{
89   (void)param;
90   cputag_set_input_line(machine, "maincpu", 7, PULSE_LINE);
91}
92
93static void amiga_ar1_nmi( running_machine &machine )
94{
95   amiga_state *state = machine.driver_data<amiga_state>();
96   /* get the cart's built-in ram */
97   UINT16 *ar_ram = (UINT16 *)machine.device("maincpu")->memory().space(AS_PROGRAM)->get_write_ptr(0x9fc000);
98
99   if ( ar_ram != NULL )
100   {
101      int i;
102
103      /* copy custom register values */
104      for( i = 0; i < 256; i++ )
105         ar_ram[0x1800+i] = CUSTOM_REG(i);
106
107      /* trigger NMI irq */
108      amigacrt.ar1_spurious = 0;
109      machine.scheduler().timer_set(machine.device<cpu_device>("maincpu")->cycles_to_attotime(28), FUNC(amiga_ar1_delayed_nmi));
110   }
111}
112
113static WRITE16_HANDLER( amiga_ar1_chipmem_w )
114{
115   amiga_state *state = space->machine().driver_data<amiga_state>();
116   int pc = cpu_get_pc(&space->device());
117
118   /* see if we're inside the AR1 rom */
119   if ( ((pc >> 16) & 0xff ) != 0xf0 )
120   {
121      /* if we're not, see if either the Spurious IRQ vector
122           or the NMI vector are being overwritten */
123      if ( offset == (0x60/2) || offset == (0x7c/2) )
124      {
125         /* trigger an NMI or spurious irq */
126         amigacrt.ar1_spurious = (offset == 0x60/2) ? 0 : 1;
127         space->machine().scheduler().timer_set(space->machine().device<cpu_device>("maincpu")->cycles_to_attotime(28), FUNC(amiga_ar1_delayed_nmi));
128      }
129   }
130
131   (*state->m_chip_ram_w)(state,  offset * 2, data );
132}
133
134static void amiga_ar1_check_overlay( running_machine &machine )
135{
136   machine.device("maincpu")->memory().space(AS_PROGRAM)->install_legacy_write_handler(0x000000, 0x00007f, FUNC(amiga_ar1_chipmem_w));
137}
138
139static void amiga_ar1_init( running_machine &machine )
140{
141   void *ar_ram;
142
143   /* check kickstart version */
144   if ( !check_kickstart_12_13( machine, "Amiga Action Replay" ) )
145   {
146      amigacrt.cart_type = -1;
147      return;
148   }
149
150   /* setup the cart ram */
151   ar_ram = auto_alloc_array(machine, UINT8, 0x4000);
152   memset(ar_ram, 0, 0x4000);
153
154   /* Install ROM */
155   machine.device("maincpu")->memory().space(AS_PROGRAM)->install_read_bank(0xf00000, 0xf7ffff, "bank2");
156   machine.device("maincpu")->memory().space(AS_PROGRAM)->unmap_write(0xf00000, 0xf7ffff);
157
158   /* Install RAM */
159   machine.device("maincpu")->memory().space(AS_PROGRAM)->install_readwrite_bank(0x9fc000, 0x9fffff, "bank3");
160
161   /* Configure Banks */
162   memory_set_bankptr(machine, "bank2", machine.region("user2")->base());
163   memory_set_bankptr(machine, "bank3", ar_ram);
164
165   amigacrt.ar1_spurious = 0;
166
167   /* Install IRQ ACK callback */
168   device_set_irq_callback(machine.device("maincpu"), amiga_ar1_irqack);
169}
170
171/***************************************************************************
172
173  Amiga Action Replay MKII/MKIII
174
175  Whenever you push the button, an overlay of the cartridge appears
176  in RAM and an NMI interrupt is generated. Only reads are overlayed.
177  Writes go directly to chipmem (so that the CPU can write the stack
178  information for the NMI). Once the interrupt is taken, the cart
179  disables the ROM overlay and checks it's internal mode register
180  to see why it was invoked.
181
182  When a breakpoint is set the cart replaces the target instruction
183  with a trap, and adds a trap handler that it locates in the $100-$120
184  area. The handler simply has one instruction: TST.B $BFE001. This cia
185  access is monitored, and the conditions match (PC < 120 and a previous
186  command requested the monitoring of the cia) then the cart is invoked.
187
188***************************************************************************/
189
190static void amiga_ar23_freeze( running_machine &machine );
191
192static READ16_HANDLER( amiga_ar23_cia_r )
193{
194   int pc = cpu_get_pc(&space->device());
195
196   if ( ACCESSING_BITS_0_7 && offset == 2048 && pc >= 0x40 && pc < 0x120 )
197   {
198      amiga_ar23_freeze(space->machine());
199   }
200
201   return amiga_cia_r( space, offset, mem_mask );
202}
203
204static WRITE16_HANDLER( amiga_ar23_mode_w )
205{
206   if ( data & 2 )
207   {
208      space->install_legacy_read_handler(0xbfd000, 0xbfefff, FUNC(amiga_ar23_cia_r));
209   }
210   else
211   {
212      space->install_legacy_read_handler(0xbfd000, 0xbfefff, FUNC(amiga_cia_r));
213   }
214
215   amigacrt.ar23_mode = (data&0x3);
216   if ( amigacrt.ar23_mode == 0 )
217      amigacrt.ar23_mode = 1;
218
219}
220
221static READ16_HANDLER( amiga_ar23_mode_r )
222{
223   amiga_state *state = space->machine().driver_data<amiga_state>();
224   UINT16 *mem = (UINT16 *)space->machine().region( "user2" )->base();
225
226   if ( ACCESSING_BITS_0_7 )
227   {
228      if ( offset < 2 )
229         return (mem[offset] | (amigacrt.ar23_mode&3));
230
231      if ( offset == 0x03 ) /* disable cart oberlay on chip mem */
232      {
233         UINT32 mirror_mask = state->m_chip_ram_size;
234
235         memory_set_bank(space->machine(), "bank1", 0);
236
237         while( (mirror_mask<<1) < 0x100000 )
238         {
239            mirror_mask |= ( mirror_mask << 1 );
240         }
241
242         /* overlay disabled, map RAM on 0x000000 */
243         space->install_write_bank(0x000000, state->m_chip_ram_size - 1, 0, mirror_mask, "bank1");
244      }
245   }
246
247   return mem[offset];
248}
249
250static WRITE16_HANDLER( amiga_ar23_chipmem_w )
251{
252   amiga_state *state = space->machine().driver_data<amiga_state>();
253   if ( offset == (0x08/2) )
254   {
255      if ( amigacrt.ar23_mode & 1 )
256         amiga_ar23_freeze(space->machine());
257   }
258
259   (*state->m_chip_ram_w)(state,  offset * 2, data );
260}
261
262static void amiga_ar23_freeze( running_machine &machine )
263{
264   amiga_state *state = machine.driver_data<amiga_state>();
265   int pc = cpu_get_pc(machine.device("maincpu"));
266
267   /* only freeze if we're not inside the cart's ROM */
268   if ( ((pc >> 16) & 0xfe ) != 0x40 )
269   {
270      /* get the cart's built-in ram */
271      UINT16 *ar_ram = (UINT16 *)machine.device("maincpu")->memory().space(AS_PROGRAM)->get_write_ptr(0x440000);
272
273      if ( ar_ram != NULL )
274      {
275         int      i;
276
277         for( i = 0; i < 0x100; i++ )
278            ar_ram[0x7800+i] = CUSTOM_REG(i);
279      }
280
281      /* overlay the cart rom's in chipram */
282      memory_set_bank(machine, "bank1", 2);
283
284      /* writes go to chipram */
285      machine.device("maincpu")->memory().space(AS_PROGRAM)->install_legacy_write_handler(0x000000, state->m_chip_ram_size - 1, FUNC(amiga_ar23_chipmem_w));
286
287      /* trigger NMI irq */
288      cputag_set_input_line(machine, "maincpu", 7, PULSE_LINE);
289   }
290}
291
292static void amiga_ar23_nmi( running_machine &machine )
293{
294   amigacrt.ar23_mode = 0;
295   amiga_ar23_freeze(machine);
296}
297
298#if 0
299static WRITE16_HANDLER( amiga_ar23_custom_w )
300{
301   int pc = cpu_get_pc(&space->device());
302
303   /* see if we're inside the AR2 rom */
304   if ( ((pc >> 16) & 0xfe ) != 0x40 )
305   {
306      /* get the cart's built-in ram */
307      UINT16 *ar_ram = (UINT16 *)memory_get_write_ptr(0, AS_PROGRAM, 0x440000);
308
309      if ( ar_ram != NULL )
310      {
311         ar_ram[0x7800+offset] = data;
312      }
313   }
314
315   amiga_custom_w( offset, data, mem_mask );
316}
317
318static READ16_HANDLER( amiga_ar23_custom_r )
319{
320   UINT16 data = amiga_custom_r( offset, mem_mask );
321
322   int pc = cpu_get_pc(&space->device());
323
324   /* see if we're inside the AR2 rom */
325   if ( ((pc >> 16) & 0xfe ) != 0x40 )
326   {
327      /* get the cart's built-in ram */
328      UINT16 *ar_ram = (UINT16 *)memory_get_write_ptr(0, AS_PROGRAM, 0x440000);
329
330      if ( ar_ram != NULL )
331      {
332         ar_ram[0x7800+offset] = data;
333      }
334   }
335
336   return data;
337}
338#endif
339
340static void amiga_ar23_check_overlay( running_machine &machine )
341{
342   amigacrt.ar23_mode = 3;
343   machine.device("maincpu")->memory().space(AS_PROGRAM)->install_legacy_write_handler(0x000000, 0x00000f, FUNC(amiga_ar23_chipmem_w));
344}
345
346static void amiga_ar23_init( running_machine &machine, int ar3 )
347{
348   amiga_state *state = machine.driver_data<amiga_state>();
349   UINT32 mirror = 0x20000, size = 0x1ffff;
350   void *ar_ram;
351
352   /* check kickstart version */
353   if ( !check_kickstart_12_13( machine, "Action Replay MKII or MKIII" ) )
354   {
355      amigacrt.cart_type = -1;
356      return;
357   }
358
359   /* setup the cart ram */
360   ar_ram = auto_alloc_array_clear(machine, UINT8,0x10000);
361
362   if ( ar3 )
363   {
364      mirror = 0;
365      size = 0x3ffff;
366   }
367
368   /* Install ROM */
369   machine.device("maincpu")->memory().space(AS_PROGRAM)->install_read_bank(0x400000, 0x400000+size, 0, mirror, "bank2");
370   machine.device("maincpu")->memory().space(AS_PROGRAM)->unmap_write(0x400000, 0x400000+size, 0, mirror);
371
372   /* Install RAM */
373   machine.device("maincpu")->memory().space(AS_PROGRAM)->install_read_bank(0x440000, 0x44ffff, "bank3");
374   machine.device("maincpu")->memory().space(AS_PROGRAM)->install_write_bank(0x440000, 0x44ffff, "bank3");
375
376   /* Install Custom chip monitor */
377//  machine.device("maincpu")->memory().space(AS_PROGRAM)->install_legacy_read_handler(0xdff000, 0xdff1ff, FUNC(amiga_ar23_custom_r));
378//  machine.device("maincpu")->memory().space(AS_PROGRAM)->install_legacy_write_handler(0xdff000, 0xdff1ff, FUNC(amiga_ar23_custom_w));
379
380   /* Install status/mode handlers */
381   machine.device("maincpu")->memory().space(AS_PROGRAM)->install_legacy_read_handler(0x400000, 0x400007, 0, mirror, FUNC(amiga_ar23_mode_r));
382   machine.device("maincpu")->memory().space(AS_PROGRAM)->install_legacy_write_handler(0x400000, 0x400003, 0, mirror, FUNC(amiga_ar23_mode_w));
383
384   /* Configure Banks */
385   memory_set_bankptr(machine, "bank2", machine.region("user2")->base());
386   memory_set_bankptr(machine, "bank3", ar_ram);
387
388   memory_configure_bank(machine, "bank1", 0, 2, state->m_chip_ram, 0);
389   memory_configure_bank(machine, "bank1", 1, 2, machine.region("user1")->base(), 0);
390   memory_configure_bank(machine, "bank1", 2, 2, machine.region("user2")->base(), 0);
391
392   amigacrt.ar23_mode = 3;
393}
394
395/***************************************************************************
396
397    MAME/MESS hooks
398
399***************************************************************************/
400
401void amiga_cart_init( running_machine &machine )
402{
403   /* see what is there */
404   UINT16 *mem = (UINT16 *)machine.region( "user2" )->base();
405
406   amigacrt.cart_type = -1;
407
408   if ( mem != NULL )
409   {
410      if ( mem[0x00] == 0x1111 )
411      {
412         amigacrt.cart_type = ACTION_REPLAY;
413         amiga_ar1_init(machine);
414      }
415      else if ( mem[0x0C] == 0x4D6B )
416      {
417         amigacrt.cart_type = ACTION_REPLAY_MKII;
418         amiga_ar23_init(machine, 0);
419      }
420      else if ( mem[0x0C] == 0x4D4B )
421      {
422         amigacrt.cart_type = ACTION_REPLAY_MKIII;
423         amiga_ar23_init(machine, 1);
424      }
425   }
426}
427
428void amiga_cart_check_overlay( running_machine &machine )
429{
430   if ( amigacrt.cart_type < 0 )
431      return;
432
433   switch( amigacrt.cart_type )
434   {
435      case ACTION_REPLAY:
436         amiga_ar1_check_overlay(machine);
437      break;
438
439      case ACTION_REPLAY_MKII:
440      case ACTION_REPLAY_MKIII:
441         amiga_ar23_check_overlay(machine);
442      break;
443   }
444}
445
446void amiga_cart_nmi( running_machine &machine )
447{
448   if ( amigacrt.cart_type < 0 )
449      return;
450
451   switch( amigacrt.cart_type )
452   {
453      case ACTION_REPLAY:
454         amiga_ar1_nmi(machine);
455      break;
456
457      case ACTION_REPLAY_MKII:
458      case ACTION_REPLAY_MKIII:
459         amiga_ar23_nmi(machine);
460      break;
461   }
462}
src/mess/machine/amigacrt.h
r0r11532
1#ifndef AMIGACRT_H
2#define AMIGACRT_H
3
4void amiga_cart_init( running_machine &machine );
5void amiga_cart_check_overlay( running_machine &machine );
6void amiga_cart_nmi( running_machine &machine );
7
8#endif /* AMIGACRT_H */
src/mess/machine/nes_pcb.c
r0r11532
1/*****************************************************************************************
2
3    NES Cart PCBs Emulation
4
5****************************************************************************************/
6
7typedef struct _nes_pcb  nes_pcb;
8struct _nes_pcb
9{
10   const char              *pcb_name;
11   int                     pcb_id;
12};
13
14// Here, we take the feature attribute from .xml (i.e. the PCB name) and we assign a unique ID to it
15static const nes_pcb pcb_list[] =
16{
17   /* Nintendo HROM, NROM, RROM, SROM & STROM */
18   { "HVC-HROM",         STD_NROM },
19   { "HVC-NROM",         STD_NROM },
20   { "HVC-NROM-128",     STD_NROM },
21   { "HVC-NROM-256",     STD_NROM },
22   { "HVC-RROM",         STD_NROM },
23   { "HVC-RROM-128",     STD_NROM },
24   { "HVC-RTROM",        STD_NROM },
25   { "HVC-SROM",         STD_NROM },
26   { "HVC-STROM",        STD_NROM },
27   { "NES-HROM",         STD_NROM },
28   { "NES-NROM",         STD_NROM },
29   { "NES-NROM-128",     STD_NROM },
30   { "NES-NROM-256",     STD_NROM },
31   { "NES-RROM",         STD_NROM },
32   { "NES-RROM-128",     STD_NROM },
33   { "NES-SROM",         STD_NROM },
34   { "NES-STROM",        STD_NROM },
35   /* "No mapper" boards by other manufacturer */
36   { "IREM-NROM-128",    STD_NROM },
37   { "IREM-NROM-256",    STD_NROM },
38   { "BANDAI-NROM-128",  STD_NROM },
39   { "BANDAI-NROM-256",  STD_NROM },
40   { "KONAMI-NROM-128",  STD_NROM },
41   { "SETA-NROM-128",    STD_NROM },
42   { "SUNSOFT-NROM-128", STD_NROM },
43   { "SUNSOFT-NROM-256", STD_NROM },
44   { "TAITO-NROM-128",   STD_NROM },
45   { "TAITO-NROM-256",   STD_NROM },
46   { "NAMCOT-3301",      STD_NROM },
47   { "NAMCOT-3302",      STD_NROM },
48   { "NAMCOT-3303",      STD_NROM },
49   { "NAMCOT-3304",      STD_NROM },
50   { "NAMCOT-3305",      STD_NROM },
51   { "NAMCOT-3311",      STD_NROM },
52   { "NAMCOT-3312",      STD_NROM },
53   { "NAMCOT-3411",      STD_NROM },
54   { "JALECO-JF-01",     STD_NROM },
55   { "JALECO-JF-02",     STD_NROM },
56   { "JALECO-JF-03",     STD_NROM },
57   { "JALECO-JF-04",     STD_NROM },
58   { "TENGEN-800003",    STD_NROM },
59   { "SACHEN-NROM",      STD_NROM },
60   /* Nintendo Family BASIC pcb (NROM + 2K or 4K WRAM) */
61   { "HVC-FAMILYBASIC",  HVC_FAMBASIC },
62   /* Game Genie */
63   { "CAMERICA-GAMEGENIE", GG_NROM },
64//
65   /* Nintendo UNROM/UOROM */
66   { "HVC-UNROM",        STD_UXROM },
67   { "HVC-UNEPROM",      STD_UXROM },
68   { "HVC-UOROM",        STD_UXROM },
69   { "NES-UNROM",        STD_UXROM },
70   { "NES-UNEPROM",      STD_UXROM },
71   { "NES-UOROM",        STD_UXROM },
72   { "HVC-UNROM+74HC08", UXROM_CC },
73   /* UxROM boards by other manufacturer */
74   { "IREM-UNROM",       STD_UXROM },
75   { "KONAMI-UNROM",     STD_UXROM },
76   { "TAITO-UNROM",      STD_UXROM },
77   { "JALECO-JF-15",     STD_UXROM },
78   { "JALECO-JF-18",     STD_UXROM },
79   { "JALECO-JF-39",     STD_UXROM },
80//
81   /* Nintendo CNROM */
82   { "HVC-CNROM",        STD_CNROM },
83   { "NES-CNROM",        STD_CNROM },
84   /* CxROM boards by other manufacturer */
85   { "BANDAI-CNROM",     STD_CNROM },
86   { "BANDAI-74*161/32", STD_CNROM },
87   { "KONAMI-CNROM",     STD_CNROM },
88   { "NAMCOT-CNROM+WRAM", STD_CNROM },
89   { "TAITO-CNROM",      STD_CNROM },
90   { "AVE-74*161",       STD_CNROM },
91   { "NTDEC-N715061",    STD_CNROM },
92   { "NTDEC-N715062",    STD_CNROM },
93   { "SACHEN-CNROM",     STD_CNROM },
94   /* Bandai Aerobics Studio (CNROM boards + special audio chip) */
95   { "BANDAI-PT-554",    BANDAI_PT554 },
96   /* FIXME: Is this the same as mapper 3? */
97   { "TENGEN-800008",    TENGEN_800008 },
98//
99   /* Nintendo AxROM */
100   { "HVC-AMROM",        STD_AXROM },
101   { "HVC-AN1ROM",       STD_AXROM },
102   { "HVC-ANROM",        STD_AXROM },
103   { "HVC-AOROM",        STD_AXROM },
104   { "NES-AMROM",        STD_AXROM },
105   { "NES-AN1ROM",       STD_AXROM },
106   { "NES-ANROM",        STD_AXROM },
107   { "NES-AOROM",        STD_AXROM },
108   /* AxROM boards by other manufacturer */
109   { "ACCLAIM-AOROM",    STD_AXROM },
110//
111   /* Nintendo PxROM */
112   { "HVC-PEEOROM",      STD_PXROM },
113   { "HVC-PNROM",        STD_PXROM },
114   { "NES-PEEOROM",      STD_PXROM },
115   { "NES-PNROM",        STD_PXROM },
116//
117   /* Nintendo FxROM */
118   { "HVC-FJROM",        STD_FXROM },
119   { "HVC-FKROM",        STD_FXROM },
120   { "NES-FJROM",        STD_FXROM },
121   { "NES-FKROM",        STD_FXROM },
122//
123   /* Nintendo BXROM */
124   { "HVC-BNROM",        STD_BXROM },
125   { "NES-BNROM",        STD_BXROM },
126   /* BxROM boards by other manufacturer */
127   { "IREM-BNROM",       STD_BXROM },
128//
129   /* Nintendo CPROM */
130   { "HVC-CPROM",        STD_CPROM },
131   { "NES-CPROM",        STD_CPROM },
132//
133   /* Nintendo GNROM & MHROM */
134   { "HVC-GNROM",        STD_GXROM },
135   { "NES-GNROM",        STD_GXROM },
136   { "HVC-MHROM",        STD_MXROM },
137   { "NES-MHROM",        STD_MXROM },
138   { "PAL-MH",           STD_MXROM },
139   /* GxROM boards by other manufacturer */
140   { "BANDAI-GNROM",     STD_GXROM },
141//
142   /* Nintendo NxROM */
143   { "HVC-NTBROM",       STD_NXROM },
144   { "NES-NTBROM",       STD_NXROM },
145   /* NxROM boards by other manufacturer (this board was mainly used by Sunsoft?) */
146   { "SUNSOFT-4",        STD_NXROM },
147   { "SUNSOFT-DCS",      SUNSOFT_DCS },
148   { "TENGEN-800042",    STD_NXROM },
149//
150   /* Nintendo JxROM */
151   { "HVC-JLROM",        STD_JXROM },
152   { "HVC-JSROM",        STD_JXROM },
153   { "NES-JLROM",        STD_JXROM },
154   { "NES-JSROM",        STD_JXROM },
155   { "NES-BTR",          STD_JXROM },
156   /* JxROM boards by other manufacturer (this board was mainly used by Sunsoft?) */
157   { "SUNSOFT-5A",       STD_JXROM },
158   { "SUNSOFT-5B",       STD_JXROM },
159   { "SUNSOFT-FME-7",    STD_JXROM },
160//
161   /* Nintendo UN1ROM */
162   { "HVC-UN1ROM",       STD_UN1ROM },
163   { "NES-UN1ROM",       STD_UN1ROM },
164//
165   /* Nintendo SxROM */
166   { "HVC-SAROM",        STD_SXROM },
167   { "HVC-SBROM",        STD_SXROM },
168   { "HVC-SC1ROM",       STD_SXROM },
169   { "HVC-SCROM",        STD_SXROM },
170   { "HVC-SEROM",        STD_SXROM },
171   { "HVC-SF1ROM",       STD_SXROM },
172   { "HVC-SFROM",        STD_SXROM },
173   { "HVC-SGROM",        STD_SXROM },
174   { "HVC-SH1ROM",       STD_SXROM },
175   { "HVC-SHROM",        STD_SXROM },
176   { "HVC-SIROM",        STD_SXROM },
177   { "HVC-SJROM",        STD_SXROM },
178   { "HVC-SKROM",        STD_SXROM },
179   { "HVC-SKEPROM",      STD_SXROM },
180   { "HVC-SL1ROM",       STD_SXROM },
181   { "HVC-SL2ROM",       STD_SXROM },
182   { "HVC-SL3ROM",       STD_SXROM },
183   { "HVC-SLROM",        STD_SXROM },
184   { "HVC-SLRROM",       STD_SXROM },
185   { "HVC-SMROM",        STD_SXROM },
186   { "HVC-SNROM",        STD_SXROM },
187   { "HVC-SUROM",        STD_SXROM },
188   { "HVC-SXROM",        STD_SXROM },
189   { "NES-SAROM",        STD_SXROM },
190   { "NES-SBROM",        STD_SXROM },
191   { "NES-SC1ROM",       STD_SXROM },
192   { "NES-SCROM",        STD_SXROM },
193   { "NES-SEROM",        STD_SXROM },
194   { "NES-SF1ROM",       STD_SXROM },
195   { "NES-SFROM",        STD_SXROM },
196   { "NES-SGROM",        STD_SXROM },
197   { "NES-SH1ROM",       STD_SXROM },
198   { "NES-SHROM",        STD_SXROM },
199   { "NES-SIROM",        STD_SXROM },
200   { "NES-SJROM",        STD_SXROM },
201   { "NES-SKROM",        STD_SXROM },
202   { "NES-SKEPROM",      STD_SXROM },
203   { "NES-SL1ROM",       STD_SXROM },
204   { "NES-SL2ROM",       STD_SXROM },
205   { "NES-SL3ROM",       STD_SXROM },
206   { "NES-SLROM",        STD_SXROM },
207   { "NES-SLRROM",       STD_SXROM },
208   { "NES-SMROM",        STD_SXROM },
209   { "NES-SNROM",        STD_SXROM },
210   { "NES-SUROM",        STD_SXROM },
211   { "NES-SXROM",        STD_SXROM },
212   { "NES-WH",           STD_SXROM },
213   { "NES-SOROM",        STD_SOROM },
214   { "HVC-SOROM",        STD_SOROM },
215   /* SxROM boards by other manufacturer */
216   { "KONAMI-SLROM",     STD_SXROM },
217   { "VIRGIN-SNROM",     STD_SXROM },
218//
219   /* Nintendo TxROM */
220   { "HVC-TBROM",        STD_TXROM },
221   { "HVC-TEROM",        STD_TXROM },
222   { "HVC-TFROM",        STD_TXROM },
223   { "HVC-TGROM",        STD_TXROM },
224   { "HVC-TKROM",        STD_TXROM },
225   { "HVC-TL1ROM",       STD_TXROM },
226   { "HVC-TL2ROM",       STD_TXROM },
227   { "HVC-TLROM",        STD_TXROM },
228   { "HVC-TNROM",        STD_TXROM },
229   { "HVC-TR1ROM",       STD_TVROM },
230   { "HVC-TSROM",        STD_TXROM },
231   { "HVC-TVROM",        STD_TVROM },
232   { "NES-B4",           STD_TXROM },
233   { "NES-TBROM",        STD_TXROM },
234   { "NES-TEROM",        STD_TXROM },
235   { "NES-TFROM",        STD_TXROM },
236   { "NES-TGROM",        STD_TXROM },
237   { "NES-TKROM",        STD_TXROM },
238   { "NES-TL1ROM",       STD_TXROM },
239   { "NES-TL2ROM",       STD_TXROM },
240   { "NES-TLROM",        STD_TXROM },
241   { "NES-TNROM",        STD_TXROM },
242   { "NES-TR1ROM",       STD_TVROM },
243   { "NES-TSROM",        STD_TXROM },
244   { "NES-TVROM",        STD_TVROM },
245   /* TxROM boards by other manufacturer */
246   { "ACCLAIM-MC-ACC",   STD_TXROM },
247   { "ACCLAIM-TLROM",    STD_TXROM },
248   { "KONAMI-TLROM",     STD_TXROM },
249//
250   /* Nintendo DxROM */
251   { "HVC-DE1ROM",       STD_DXROM },
252   { "HVC-DEROM",        STD_DXROM },
253   { "HVC-DRROM",        STD_DRROM },
254   { "NES-DE1ROM",       STD_DXROM },
255   { "NES-DEROM",        STD_DXROM },
256   { "NES-DRROM",        STD_DRROM },
257   /* DxROM boards by other manufacturer */
258   { "NAMCOT-3401",      STD_DXROM },
259   { "NAMCOT-3405",      STD_DXROM },
260   { "NAMCOT-3406",      STD_DXROM },
261   { "NAMCOT-3407",      STD_DXROM },
262   { "NAMCOT-3413",      STD_DXROM },
263   { "NAMCOT-3414",      STD_DXROM },
264   { "NAMCOT-3415",      STD_DXROM },
265   { "NAMCOT-3416",      STD_DXROM },
266   { "NAMCOT-3417",      STD_DXROM },
267   { "NAMCOT-3451",      STD_DXROM },
268   { "TENGEN-800002",    STD_DXROM },
269   { "TENGEN-800004",    STD_DRROM },
270   { "TENGEN-800030",    STD_DXROM },
271//
272   /* Nintendo HKROM */
273   { "HVC-HKROM",        STD_HKROM },
274   { "NES-HKROM",        STD_HKROM },
275//
276   /* Nintendo BNROM */
277   { "HVC-TQROM",        STD_TQROM },
278   { "NES-TQROM",        STD_TQROM },
279//
280   /* Nintendo TxSROM */
281   { "HVC-TKSROM",       STD_TXSROM },
282   { "HVC-TLSROM",       STD_TXSROM },
283   { "NES-TKSROM",       STD_TXSROM },
284   { "NES-TLSROM",       STD_TXSROM },
285//
286   /* Nintendo ExROM */
287   { "HVC-EKROM",        STD_EXROM },
288   { "HVC-ELROM",        STD_EXROM },
289   { "HVC-ETROM",        STD_EXROM },
290   { "HVC-EWROM",        STD_EXROM },
291   { "NES-EKROM",        STD_EXROM },
292   { "NES-ELROM",        STD_EXROM },
293   { "NES-ETROM",        STD_EXROM },
294   { "NES-EWROM",        STD_EXROM },
295//
296   /* Nintendo Custom boards */
297   { "PAL-ZZ",           PAL_ZZ },
298   { "NES-QJ",           NES_QJ },
299   { "NES-EVENT",        UNSUPPORTED_BOARD },
300//
301   /* Discrete board IC_74x139x74 */
302   { "JALECO-JF-05",     DIS_74X139X74 },
303   { "JALECO-JF-06",     DIS_74X139X74 },
304   { "JALECO-JF-07",     DIS_74X139X74 },
305   { "JALECO-JF-08",     DIS_74X139X74 },
306   { "JALECO-JF-09",     DIS_74X139X74 },
307   { "JALECO-JF-10",     DIS_74X139X74 },
308   { "KONAMI-74*139/74", DIS_74X139X74 },
309   { "TAITO-74*139/74",  DIS_74X139X74 },
310   /* Discrete board IC_74x377 */
311   { "AGCI-47516",       DIS_74X377 },
312   { "AVE-NINA-07",      DIS_74X377 },
313   { "COLORDREAMS-74*377", DIS_74X377 },
314   /* Discrete board IC_74x161x161x32 */
315   { "BANDAI-74*161/161/32", DIS_74X161X161X32 },
316   { "TAITO-74*161/161/32", DIS_74X161X161X32 },
317   /* Discrete board IC_74x161x138 */
318   { "BIT-CORP-74*161/138", DIS_74X161X138 },
319//
320   { "BANDAI-LZ93D50",   BANDAI_LZ93 },
321   { "BANDAI-LZ93D50+24C01", BANDAI_LZ93EX },
322   { "BANDAI-LZ93D50+24C02", BANDAI_LZ93EX },
323   { "BANDAI-FCG-1",     BANDAI_FCG },
324   { "BANDAI-FCG-2",     BANDAI_FCG },
325   { "BANDAI-JUMP2",     BANDAI_JUMP2 },
326   { "BANDAI-DATACH",    BANDAI_DATACH },
327   { "BANDAI-KARAOKE",   BANDAI_KARAOKE },
328   { "BANDAI-OEKAKIDS",  BANDAI_OEKAKIDS },
329   { "IREM-FCG-1",       BANDAI_FCG },
330//
331   { "IREM-G101",        IREM_G101 },
332   { "IREM-74*161/161/21/138", IREM_LROG017 },
333   { "IREM-H-3001",      IREM_H3001 },
334   { "IREM-H3001",       IREM_H3001 },
335   { "IREM-HOLYDIVER",   IREM_HOLYDIV },
336   { "IREM-TAM-S1",      IREM_TAM_S1 },
337//
338   { "JALECO-JF-23",     JALECO_SS88006 },
339   { "JALECO-JF-24",     JALECO_SS88006 },
340   { "JALECO-JF-25",     JALECO_SS88006 },
341   { "JALECO-JF-27",     JALECO_SS88006 },
342   { "JALECO-JF-29",     JALECO_SS88006 },
343   { "JALECO-JF-30",     JALECO_SS88006 },
344   { "JALECO-JF-31",     JALECO_SS88006 },
345   { "JALECO-JF-32",     JALECO_SS88006 },
346   { "JALECO-JF-33",     JALECO_SS88006 },
347   { "JALECO-JF-34",     JALECO_SS88006 },
348   { "JALECO-JF-35",     JALECO_SS88006 },
349   { "JALECO-JF-36",     JALECO_SS88006 },
350   { "JALECO-JF-37",     JALECO_SS88006 },
351   { "JALECO-JF-38",     JALECO_SS88006 },
352   { "JALECO-JF-40",     JALECO_SS88006 },
353   { "JALECO-JF-41",     JALECO_SS88006 },
354   { "JALECO-JF-11",     JALECO_JF11 },
355   { "JALECO-JF-12",     JALECO_JF11 },
356   { "JALECO-JF-14",     JALECO_JF11 },
357   { "JALECO-JF-13",     JALECO_JF13 },
358   { "JALECO-JF-16",     JALECO_JF16 },
359   { "JALECO-JF-17",     JALECO_JF17 },
360   { "JALECO-JF-26",     JALECO_JF17 },
361   { "JALECO-JF-28",     JALECO_JF17 },
362   { "JALECO-JF-19",     JALECO_JF19 },
363   { "JALECO-JF-21",     JALECO_JF19 },
364//
365   { "KONAMI-VRC-1",     KONAMI_VRC1 },
366   { "JALECO-JF-20",     KONAMI_VRC1 },
367   { "JALECO-JF-22",     KONAMI_VRC1 },
368   { "KONAMI-VRC-2",     KONAMI_VRC2 },
369   { "KONAMI-VRC-3",     KONAMI_VRC3 },
370   { "KONAMI-VRC-4",     KONAMI_VRC4 },
371   { "KONAMI-VRC-6",     KONAMI_VRC6 },
372   { "KONAMI-VRC-7",     KONAMI_VRC7 },
373   { "UNL-VRC7",         KONAMI_VRC7 },
374//
375   { "NAMCOT-163",       NAMCOT_163 },
376   { "NAMCOT-175",       NAMCOT_163 },
377   { "NAMCOT-340",       NAMCOT_163 },
378   { "NAMCOT-3425",      NAMCOT_3425 },
379   { "NAMCOT-3433",      NAMCOT_34X3 },
380   { "NAMCOT-3443",      NAMCOT_34X3 },
381   { "NAMCOT-3446",      NAMCOT_3446 },
382   { "NAMCOT-3453",      NAMCOT_3453 },
383//
384   { "SUNSOFT-1",        SUNSOFT_1 },
385   { "SUNSOFT-2",        SUNSOFT_2 },
386   { "SUNSOFT-3",        SUNSOFT_3 },
387   //
388   { "TAITO-TC0190FMC",  TAITO_TC0190FMC },
389   { "TAITO-TC0190FMC+PAL16R4", TAITO_TC0190FMCP },
390   { "TAITO-TC0350FMR",  TAITO_TC0190FMC },
391   { "TAITO-X1-005",     TAITO_X1_005 },   // two variants exist, depending on pin17 & pin31 connections
392   { "TAITO-X1-017",     TAITO_X1_017 },
393//
394   { "AGCI-50282",       AGCI_50282 },
395   { "AVE-NINA-01",      AVE_NINA01 },
396   { "AVE-NINA-02",      AVE_NINA01 },
397   { "AVE-NINA-03",      AVE_NINA06 },
398   { "AVE-NINA-06",      AVE_NINA06 },
399   { "AVE-MB-91",        AVE_NINA06 },
400   { "TXC-74*138/175",   AVE_NINA06 },
401   { "UNL-SA-016-1M",    AVE_NINA06 },
402   { "CAMERICA-ALGN",    CAMERICA_BF9093 },
403   { "CAMERICA-BF9093",  CAMERICA_BF9093 },
404   { "CAMERICA-BF9097",  CAMERICA_BF9097 },
405   { "CAMERICA-ALGQ",    CAMERICA_BF9096 },
406   { "CAMERICA-BF9096",  CAMERICA_BF9096 },
407   { "CAMERICA-GOLDENFIVE", CAMERICA_GOLDENFIVE },
408   { "CNE-DECATHLON",    CNE_DECATHLON },
409   { "CNE-PSB",          CNE_FSB },
410   { "CNE-SHLZ",         CNE_SHLZ },
411   { "JYCOMPANY-A",      UNSUPPORTED_BOARD },   // mapper 90
412   { "JYCOMPANY-B",      UNSUPPORTED_BOARD },   // mapper 209
413   { "JYCOMPANY-C",      UNSUPPORTED_BOARD },   // mapper 211
414   { "NTDEC-112",        NTDEC_ASDER },   // mapper 112 (better rename this board tag, to avoid confusion with TC-112!!
415   { "NTDEC-TC-112",     NTDEC_FIGHTINGHERO },
416   { "NTDEC-193",        NTDEC_FIGHTINGHERO },   // mapper 193
417   { "UNL-TEK90",        UNSUPPORTED_BOARD },   // related to JY Company? (i.e. mappers 90, 209, 211?)
418   { "UNL-SA-002",       SACHEN_TCU02 },
419   { "UNL-SA-009",       SACHEN_SA009 },
420   { "UNL-SA-0036",      SACHEN_SA0036 },
421   { "UNL-SA-0037",      SACHEN_SA0037 },
422   { "UNL-SA-72007",     SACHEN_SA72007 },
423   { "UNL-SA-72008",     SACHEN_SA72008 },
424   { "UNL-SA-NROM",      SACHEN_TCA01 },
425   { "UNL-SACHEN-TCA01", SACHEN_TCA01 },
426   { "SACHEN-8259A",     SACHEN_8259A },
427   { "UNL-SACHEN-8259A", SACHEN_8259A },
428   { "SACHEN-8259B",     SACHEN_8259B },
429   { "UNL-SACHEN-8259B", SACHEN_8259B },
430   { "SACHEN-8259C",     SACHEN_8259C },
431   { "UNL-SACHEN-8259C", SACHEN_8259C },
432   { "SACHEN-8259D",     SACHEN_8259D },
433   { "UNL-SACHEN-8259D", SACHEN_8259D },
434   { "UNL-SACHEN-74LS374N", SACHEN_74LS374 },
435   { "UNL-SACHEN-74LS374N-A", SACHEN_74LS374_A },   /* FIXME: Made up boards the different mirroring handling */
436   { "UNL-TC-U01-1.5M",  SACHEN_TCU01 },
437   { "TENGEN-800032",    TENGEN_800032 },
438   { "TENGEN-800037",    TENGEN_800037 },
439   { "WAIXING-A",        WAIXING_TYPE_A },
440   { "WAIXING-A-1",      WAIXING_TYPE_A_1 },   /* FIXME: Made up boards the different CHRRAM banks (see Ji Jia Zhan Shi) */
441   { "WAIXING-B",        WAIXING_TYPE_B },
442   { "WAIXING-C",        WAIXING_TYPE_C },
443   { "WAIXING-D",        WAIXING_TYPE_D },
444   { "WAIXING-E",        WAIXING_TYPE_E },
445   { "WAIXING-F",        WAIXING_TYPE_F },
446   { "WAIXING-G",        WAIXING_TYPE_G },
447   { "WAIXING-H",        WAIXING_TYPE_H },
448   { "WAIXING-I",        WAIXING_TYPE_I },
449   { "WAIXING-J",        WAIXING_TYPE_J },
450   { "WAIXING-SGZLZ",    WAIXING_SGZLZ },
451   { "WAIXING-SEC",      WAIXING_SECURITY },
452   { "WAIXING-SGZ",      WAIXING_SGZ },
453   { "WAIXING-PS2",      WAIXING_PS2 },
454   { "WAIXING-FFV",      WAIXING_FFV },
455   { "WAIXING-ZS",       WAIXING_ZS },
456   { "WAIXING-DQ8",      WAIXING_DQ8 },
457   { "WAIXING-SH2",      WAIXING_SH2 },
458//
459   { "TXC-TW",           TXC_TW },
460   { "TXC-STRIKEWOLF",   TXC_STRIKEWOLF },
461   { "TXC-MXMDHTWO",     TXC_MXMDHTWO },
462   { "UNL-22211",        TXC_22211A },
463   /* FIXME: Made up boards the different mirroring handling */
464   { "UNL-22211-A",      TXC_22211A },
465   { "UNL-22211-B",      TXC_22211B },
466   { "UNL-22211-C",      TXC_22211C },
467   { "UNL-REXSOFT-DBZ5", REXSOFT_DBZ5 },
468   { "UNL-SL1632",       REXSOFT_SL1632 },
469   { "SUBOR-BOARD-0",    SUBOR_TYPE0 },
470   { "SUBOR-BOARD-1",    SUBOR_TYPE1 },
471   { "SOMERITEAM-SL-12", SOMERI_SL12 }, // mapper 116
472   { "UNL-CONY",         CONY_BOARD },
473   { "UNL-GOUDER",       GOUDER_37017 },
474   { "UNL-NITRA",        NITRA_TDA },
475   { "UNL-HOSENKAN",     HOSENKAN_BOARD },
476   { "UNL-SUPERGAME",    SUPERGAME_LIONKING },
477   { "UNL-PANDAPRINCE",  KAY_PANDAPRINCE },
478   { "DREAMTECH01",      DREAMTECH_BOARD },
479   { "DAOU-306",         OPENCORP_DAOU306 },
480   { "HES",              HES_BOARD },
481   /* FIXME: Made up boards the different mirroring handling? */
482   { "HES-6IN1",         HES6IN1_BOARD },
483   { "SUPERGAME-BOOGERMAN", SUPERGAME_BOOGERMAN },
484   { "FUTUREMEDIA",      FUTUREMEDIA_BOARD },
485   { "FUKUTAKE",         FUKUTAKE_BOARD },
486   { "MAGICSERIES",      MAGICSERIES_MD },
487   { "KASING",           KASING_BOARD },
488   { "HENGGEDIANZI",     HENGEDIANZI_BOARD },
489   { "HENGGEDIANZI-XJZB", HENGEDIANZI_XJZB },
490   { "KAISER-KS7058",    KAISER_KS7058 },
491   { "KAISER-KS202",     KAISER_KS202 },// mapper 56
492   { "KAISER-KS7022",    KAISER_KS7022 },// mapper 175
493   { "UNL-KS7017",       KAISER_KS7017 },
494   { "UNL-KS7032",       KAISER_KS7032 }, //  mapper 142
495   { "RCM-GS2015",       RCM_GS2015 },
496   { "RCM-TETRISFAMILY", RCM_TETRISFAMILY },
497   { "UNL-NINJARYU",     UNSUPPORTED_BOARD },// mapper 111
498   { "UNL-NANJING",      NANJING_BOARD },// mapper 163
499   { "WHIRLWIND-2706",   WHIRLWIND_2706 },
500   { "UNL-H2288",        UNL_H2288 },
501   { "UNL-DANCE",        UNSUPPORTED_BOARD },
502   { "UNL-EDU2000",      UNL_EDU2K },
503   { "UNL-SHERO",        UNSUPPORTED_BOARD /*SACHEN_SHERO*/ },
504   { "UNL-TF1201",       UNSUPPORTED_BOARD /*UNL_TF1201*/ },
505   { "RUMBLESTATION",    RUMBLESTATION_BOARD },   // mapper 46
506   { "UNL-WORLDHERO",    UNSUPPORTED_BOARD },// mapper 27
507   { "UNL-A9746",        UNSUPPORTED_BOARD },// mapper 219
508   { "UNL-603-5052",     UNL_603_5052 },// mapper 238?
509   { "UNL-SHJY3",        UNL_SHJY3 },// mapper 253
510   { "UNL-RACERMATE",    UNL_RACERMATE },// mapper 168
511   { "UNL-N625092",      UNL_N625092 },
512   { "BMC-N625092",      UNL_N625092 },
513   { "UNL-SC-127",       UNL_SC127 },
514   { "UNL-SMB2J",        UNL_SMB2J },
515   { "BTL-SMB2C",        UNL_SMB2J },
516   { "UNL-MK2",          UNL_MK2 },
517   { "UNL-XZY",          UNL_XZY },
518   { "UNL-KOF96",        UNL_KOF96 },
519   { "UNL-SUPERFIGHTER3", UNL_SUPERFIGHTER3 },
520   { "UNL-8237",         UNL_8237 },
521   { "UNL-AX5705",       UNL_AX5705 },
522   { "UNL-CC-21",        UNL_CC21 },
523   { "UNL-KOF97",        UNL_KOF97 },
524   { "UNL-T-230",        UNL_T230 },
525   { "UNL-STUDYNGAME",   UNL_STUDYNGAME },   // mapper 39
526   { "UNL-OneBus",       UNSUPPORTED_BOARD },
527//
528   { "BTL-SMB2A",         BTL_SMB2A },
529   { "BTL-MARIOBABY",     BTL_MARIOBABY },
530   { "BTL-AISENSHINICOL", BTL_AISENSHINICOL },
531   { "BTL-SMB2B",         BTL_SMB2B },
532   { "BTL-SMB3",          BTL_SMB3 },
533   { "BTL-SUPERBROS11",   BTL_SUPERBROS11 },
534   { "BTL-DRAGONNINJA",   BTL_DRAGONNINJA },
535   { "BTL-MARIO1-MALEE2", UNSUPPORTED_BOARD },   // mapper 55?
536   { "BTL-2708",          UNSUPPORTED_BOARD },// mapper 103
537   { "BTL-TOBIDASEDAISAKUSEN", BTL_TOBIDASE },// mapper 120
538   { "BTL-SHUIGUANPIPE",  UNSUPPORTED_BOARD },// mapper 183
539   { "BTL-PIKACHUY2K",    BTL_PIKACHUY2K },// mapper 254
540//
541   { "BMC-190IN1",          BMC_190IN1 },
542   { "BMC-64IN1NOREPEAT",   BMC_64IN1NR },
543   { "BMC-A65AS",           BMC_A65AS },
544   { "BMC-GS-2004",         BMC_GS2004 },
545   { "BMC-GS-2013",         BMC_GS2013 },
546   { "BMC-NOVELDIAMOND9999999IN1", BMC_NOVELDIAMOND },
547   { "BMC-9999999IN1",      BMC_9999999IN1 }, // mapper 213... same as BMC-NOVELDIAMOND9999999IN1 ??
548   { "BMC-SUPER24IN1SC03",  BMC_S24IN1SC03 },
549   { "BMC-SUPERHIK8IN1",    BMC_HIK8IN1 },
550   { "BMC-T-262",           BMC_T262 },
551   { "BMC-WS",              BMC_WS },
552   { "MLT-ACTION52",        ACTENT_ACT52 },
553   { "MLT-CALTRON6IN1",     CALTRON_6IN1 },
554   { "MLT-MAXI15",          UNSUPPORTED_BOARD}, //  mapper 234
555   { "BMC-SUPERBIG-7IN1",   BMC_SUPERBIG_7IN1 },
556   { "BMC-SUPERHIK-4IN1",   BMC_SUPERHIK_4IN1 },
557   { "BMC-BALLGAMES-11IN1", BMC_BALLGAMES_11IN1 },
558   { "BMC-MARIOPARTY-7IN1", BMC_MARIOPARTY_7IN1 },
559   { "BMC-GKA",             BMC_GKA },
560   { "BMC-GKB",             BMC_GKB },
561   { "BMC-SUPER700IN1",     BMC_SUPER_700IN1 },
562   { "BMC-FAMILY-4646B",    BMC_FAMILY_4646B },
563   { "BMC-36IN1",           BMC_36IN1 },
564   { "BMC-21IN1",           BMC_21IN1 },
565   { "BMC-150IN1",          BMC_150IN1 },
566   { "BMC-35IN1",           BMC_35IN1 },
567   { "BMC-64IN1",           BMC_64IN1 },
568   { "BMC-15IN1",           BMC_15IN1 },
569   { "BMC-SUPERHIK-300IN1", BMC_SUPERHIK_300IN1 },
570   { "BMC-SUPERGUN-20IN1",  BMC_SUPERGUN_20IN1 },
571   { "BMC-GOLDENCARD-6IN1", BMC_GOLDENCARD_6IN1 },
572   { "BMC-72IN1",           BMC_72IN1 },
573   { "BMC-76IN1",           BMC_76IN1 },
574   { "BMC-SUPER42IN1",      BMC_SUPER_42IN1 },
575   { "BMC-1200IN1",         BMC_1200IN1 },
576   { "BMC-31IN1",           BMC_31IN1 },
577   { "BMC-22GAMES",         BMC_22GAMES },
578   { "BMC-20IN1",           BMC_20IN1 },
579   { "BMC-110IN1",          BMC_110IN1 },
580   { "BMC-810544-C-A1",     BMC_810544 },
581   { "BMC-411120-C",        UNSUPPORTED_BOARD },
582   { "BMC-830118C",         UNSUPPORTED_BOARD },
583   { "BMC-12-IN-1",         UNSUPPORTED_BOARD },
584   { "BMC-NTD-03",          BMC_NTD_03 },
585   { "BMC-8157",            UNSUPPORTED_BOARD /*BMC_8157*/ },
586   { "BMC-BS-5",            BMC_BENSHENG_BS5 },
587   { "BMC-FK23C",           BMC_FK23C },
588   { "BMC-FK23CA",          BMC_FK23CA },
589   { "BMC-GHOSTBUSTERS63IN1", BMC_G63IN1 },
590   { "BMC-SUPERVISION16IN1", UNSUPPORTED_BOARD },   // mapper 53
591   { "BMC-RESETBASED-4IN1", UNSUPPORTED_BOARD },// mapper 60 with 64k prg and 32k chr
592   { "BMC-VT5201",          BMC_VT5201 },// mapper 60 otherwise
593   { "BMC-D1038",           BMC_VT5201 }, // mapper 60?
594   { "BMC-42IN1RESETSWITCH", UNSUPPORTED_BOARD },   // mapper 60?
595   { "BMC-SUPER22GAMES",    UNSUPPORTED_BOARD },// mapper 233
596   { "BMC-GOLDENGAME-150IN1", UNSUPPORTED_BOARD },// mapper 235 with 2M PRG
597   { "BMC-GOLDENGAME-260IN1", UNSUPPORTED_BOARD },// mapper 235 with 4M PRG
598   { "BMC-70IN1",           UNSUPPORTED_BOARD },   // mapper 236?
599   { "BMC-70IN1B",          UNSUPPORTED_BOARD },   // mapper 236?
600   { "BMC-SUPERHIK-KOF",    UNSUPPORTED_BOARD },// mapper 251
601   { "BMC-POWERJOY",        BMC_PJOY84 },
602// are there dumps of games with these boards?
603   { "BMC-13IN1JY110",   UNSUPPORTED_BOARD }, //  [mentioned in FCEUMM source - we need more info]
604   { "BMC-GK-192",       UNSUPPORTED_BOARD }, //  [mentioned in FCEUMM source - we need more info]
605   { "KONAMI-QTAI",      UNSUPPORTED_BOARD }, //  [mentioned in FCEUMM source - we need more info]
606   { "UNL-3D-BLOCK",     UNSUPPORTED_BOARD }, //  [mentioned in FCEUMM source - we need more info]
607   { "UNL-C-N22M",       UNSUPPORTED_BOARD }, //  [mentioned in FCEUMM source - we need more info]
608   { "UNL-PEC-586",      UNSUPPORTED_BOARD }, //  [mentioned in FCEUMM source - we need more info]
609//
610   { "UNKNOWN",          UNKNOWN_BOARD }  //  a few pirate dumps uses the wrong mapper...
611};
612
613const nes_pcb *nes_pcb_lookup( const char *board )
614{
615   int i;
616   for (i = 0; i < ARRAY_LENGTH(pcb_list); i++)
617   {
618      if (!mame_stricmp(pcb_list[i].pcb_name, board))
619         return &pcb_list[i];
620   }
621   return NULL;
622}
623
624int nes_get_pcb_id( running_machine &machine, const char *feature )
625{
626   const nes_pcb *pcb = nes_pcb_lookup(feature);
627
628   if (pcb == NULL)
629      fatalerror("Unimplemented PCB type %s\n", feature);
630
631   return pcb->pcb_id;
632}
633
634/************************************************
635
636   PCB Emulation (to be moved to MAME later)
637
638   In the end, iNES, UNIF and xml should be
639   simply handled through a look-up table
640   which associates the mapper/board/feature
641   to the correct pcb_id and then the core
642   function pcb_handlers_setup should be called
643   to set-up the expected handlers and callbacks
644
645   Similarly, PC-10, VSNES and NES-based
646   multigame boards, should simply call
647   pcb_handlers_setup with the proper pcb_id
648   at the beginning, rather than use ad hoc
649   implementations.
650
651************************************************/
652
653// helper function for the few mappers reading from 0x8000-0xffff for protection
654INLINE UINT8 mmc_hi_access_rom( running_machine &machine, UINT32 offset )
655{
656   nes_state *state = machine.driver_data<nes_state>();
657
658   // usual ROM access
659   switch (offset & 0x6000)
660   {
661      case 0x0000:
662         return state->m_rom[0x10000 + state->m_prg_bank[0] * 0x2000 + (offset & 0x1fff)];
663      case 0x2000:
664         return state->m_rom[0x10000 + state->m_prg_bank[1] * 0x2000 + (offset & 0x1fff)];
665      case 0x4000:
666         return state->m_rom[0x10000 + state->m_prg_bank[2] * 0x2000 + (offset & 0x1fff)];
667      case 0x6000:
668         return state->m_rom[0x10000 + state->m_prg_bank[3] * 0x2000 + (offset & 0x1fff)];
669   }
670   return 0;
671}
672
673/*************************************************************
674
675 NROM board emulation
676
677 Games: Mario Bros., Super Mario Bros., Tennis and most of
678 the first generation games
679
680 iNES: mapper 0
681
682 In MESS: Supported, no need of specific handlers or IRQ
683
684 *************************************************************/
685
686/*************************************************************
687
688 UxROM board emulation
689
690 Games: Castlevania, Dragon Quest II, Duck Tales, MegaMan,
691 Metal Gear
692
693 writes to 0x8000-0xffff change PRG 16K lower banks
694
695 missing BC?
696
697 iNES: mapper 2
698
699 In MESS: Supported.
700
701 *************************************************************/
702
703static WRITE8_HANDLER( uxrom_w )
704{
705   LOG_MMC(("uxrom_w, offset: %04x, data: %02x\n", offset, data));
706
707   prg16_89ab(space->machine(), data);
708}
709
710/*************************************************************
711
712 Nihon Bussan UNROM M5
713
714 Games: Crazy Climber Jpn
715
716 Very simple mapper: prg16_89ab is always set to bank 0,
717 while prg16_cdef is set by writes to 0x8000-0xffff. The game
718 uses a custom controller.
719
720 iNES: mapper 180
721
722 In MESS: Supported.
723
724 *************************************************************/
725
726static WRITE8_HANDLER( uxrom_cc_w )
727{
728   LOG_MMC(("uxrom_cc_w, offset: %04x, data: %02x\n", offset, data));
729
730   prg16_cdef(space->machine(), data);
731}
732
733/*************************************************************
734
735 UN1ROM board emulation
736
737 Games: Senjou no Okami
738
739 writes to 0x8000-0xffff change PRG 16K lower banks
740
741 missing BC?
742
743 iNES: mapper 94
744
745 In MESS: Supported.
746
747 *************************************************************/
748
749static WRITE8_HANDLER( un1rom_w )
750{
751   LOG_MMC(("un1rom_w, offset: %04x, data: %02x\n", offset, data));
752
753   prg16_89ab(space->machine(), data >> 2);
754}
755
756/*************************************************************
757
758 CNROM board emulation
759
760 Games: B-Wings, Mighty Bomb Jack, Seicross, Spy vs. Spy,
761 Adventure Island, Flipull, Friday 13th, GeGeGe no
762 Kitarou, Ghostbusters, Gradius, Hokuto no Ken, Milon's
763 Secret Castle
764
765 writes to 0x8000-0xffff change CHR 8K banks
766
767 missing BC?
768
769 iNES: mappers 3 & 185 (the latter for games using Pins as
770 protection)
771
772 Notice that BANDAI_PT554 board (Aerobics Studio) uses very
773 similar hardware but with an additional sound chip which
774 gets writes to 0x6000 (currently unemulated in MESS)
775
776 In MESS: Supported
777
778 *************************************************************/
779
780static WRITE8_HANDLER( cnrom_w )
781{
782   nes_state *state = space->machine().driver_data<nes_state>();
783   LOG_MMC(("cnrom_w, offset: %04x, data: %02x\n", offset, data));
784
785   if (state->m_ce_mask)
786   {
787      chr8(space->machine(), data & ~state->m_ce_mask, CHRROM);
788
789      if ((data & state->m_ce_mask) == state->m_ce_state)
790         state->m_chr_open_bus = 0;
791      else
792         state->m_chr_open_bus = 1;
793   }
794   else
795      chr8(space->machine(), data, CHRROM);
796}
797
798/*************************************************************
799
800 Bandai PT-554 board emulation
801
802 This is used by Aerobics Studio. It is basically a CNROM board
803 with an additional sound chip which is not currently emulated by
804 MESS
805
806 iNES: mapper 3?
807
808 *************************************************************/
809
810static WRITE8_HANDLER( bandai_pt554_m_w )
811{
812   LOG_MMC(("Bandai PT-554 Sound write, data: %02x\n", data));
813
814   // according to NEStopia, this is the effect
815   if (!BIT(data, 6))
816   {
817      // send command (data & 0x07) to sound chip
818   }
819}
820
821/*************************************************************
822
823 CPROM board emulation
824
825 Games: Videomation
826
827 writes to 0x8000-0xffff change CHR 4K lower banks
828
829 iNES: mapper 13
830
831 In MESS: Supported
832
833 *************************************************************/
834
835static WRITE8_HANDLER( cprom_w )
836{
837   LOG_MMC(("cprom_w, offset: %04x, data: %02x\n", offset, data));
838   chr4_4(space->machine(), data, CHRRAM);
839}
840
841/*************************************************************
842
843 AxROM board emulation
844
845 Games: Arch Rivals, Battletoads, Cabal, Commando, Solstice
846
847 writes to 0x8000-0xffff change PRG banks + sets mirroring
848
849 missing BC for AMROM?
850
851 iNES: mapper 7
852
853 In MESS: Supported
854
855 *************************************************************/
856
857static WRITE8_HANDLER( axrom_w )
858{
859   LOG_MMC(("axrom_w, offset: %04x, data: %02x\n", offset, data));
860
861   set_nt_mirroring(space->machine(), BIT(data, 4) ? PPU_MIRROR_HIGH : PPU_MIRROR_LOW);
862   prg32(space->machine(), data);
863}
864
865/*************************************************************
866
867 BxROM board emulation
868
869 writes to 0x8000-0xffff change PRG banks
870
871 missing BC?
872
873 iNES: mapper 34
874
875 *************************************************************/
876
877static WRITE8_HANDLER( bxrom_w )
878{
879   /* This portion of the mapper is nearly identical to Mapper 7, except no one-screen mirroring */
880   /* Deadly Towers is really a BxROM game - the demo screens look wrong using mapper 7. */
881   LOG_MMC(("bxrom_w, offset: %04x, data: %02x\n", offset, data));
882
883   prg32(space->machine(), data);
884}
885
886/*************************************************************
887
888 GxROM/MxROM board emulation
889
890 writes to 0x8000-0xffff change PRG and CHR banks
891
892 missing BC?
893
894 iNES: mapper 66
895
896 *************************************************************/
897
898static WRITE8_HANDLER( gxrom_w )
899{
900   LOG_MMC(("gxrom_w, offset %04x, data: %02x\n", offset, data));
901
902   prg32(space->machine(), (data & 0xf0) >> 4);
903   chr8(space->machine(), data & 0x0f, CHRROM);
904}
905
906/*************************************************************
907
908 SxROM (MMC1 based) board emulation
909
910 iNES: mapper 1 (and 155 for the MMC1A variant which does not
911 have WRAM disable bit)
912
913 *************************************************************/
914
915static TIMER_CALLBACK( mmc1_resync_callback )
916{
917   nes_state *state = machine.driver_data<nes_state>();
918   state->m_mmc1_reg_write_enable = 1;
919}
920
921
922static void mmc1_set_wram( address_space *space, int board )
923{
924   running_machine &machine = space->machine();
925   nes_state *state = machine.driver_data<nes_state>();
926   UINT8 bank = BIT(state->m_mmc_reg[0], 4) ? BIT(state->m_mmc_reg[1], 4) : BIT(state->m_mmc_reg[1], 3);
927
928   switch (board)
929   {
930      case STD_SXROM:      // here also reads are disabled!
931         if (!BIT(state->m_mmc_reg[3], 4))
932            space->install_readwrite_bank(0x6000, 0x7fff, "bank5");
933         else
934         {
935            space->unmap_readwrite(0x6000, 0x7fff);
936            break;
937         }
938      case STD_SXROM_A:   // ignore WRAM enable bit
939         if (state->m_battery_size > 0x2000)
940            wram_bank(machine, ((state->m_mmc_reg[1] & 3) >> 2), NES_BATTERY);
941         else if (state->m_battery_size)
942            wram_bank(machine, 0, NES_BATTERY);
943         break;
944      case STD_SOROM:      // there are 2 WRAM banks only and battery is bank 2 for the cart (hence, we invert bank, because we have battery first)
945         if (!BIT(state->m_mmc_reg[3], 4))
946            space->install_readwrite_bank(0x6000, 0x7fff, "bank5");
947         else
948         {
949            space->unmap_readwrite(0x6000, 0x7fff);
950            break;
951         }
952      case STD_SOROM_A:   // ignore WRAM enable bit
953         wram_bank(machine, 0, bank ? NES_BATTERY : NES_WRAM);
954         break;
955   }
956}
957
958static void mmc1_set_prg( running_machine &machine )
959{
960   nes_state *state = machine.driver_data<nes_state>();
961   UINT8 prg_mode, prg_offset;
962
963   prg_mode = state->m_mmc_reg[0] & 0x0c;
964   /* prg_mode&0x8 determines bank size: 32k (if 0) or 16k (if 1)? when in 16k mode,
965     prg_mode&0x4 determines which half of the PRG space we can swap: if it is 4,
966     mmc_reg[3] sets banks at 0x8000; if it is 0, mmc_reg[3] sets banks at 0xc000. */
967
968   prg_offset = state->m_mmc_reg[1] & 0x10;
969   /* In principle, mmc_reg[2]&0x10 might affect "extended" banks as well, when chr_mode=1.
970     However, quoting Disch's docs: When in 4k CHR mode, 0x10 in both $A000 and $C000 *must* be
971     set to the same value, or else pages will constantly be swapped as graphics render!
972     Hence, we use only mmc_reg[1]&0x10 for prg_offset */
973
974   switch (prg_mode)
975   {
976      case 0x00:
977      case 0x04:
978//          printf("PRG 32 bank %d \n", (prg_offset + state->m_mmc_reg[3]) >> 1);
979         prg32(machine, (prg_offset + state->m_mmc_reg[3]) >> 1);
980         break;
981      case 0x08:
982//          printf("PRG 16 bank %d (high) \n", prg_offset + state->m_mmc_reg[3]);
983         prg16_89ab(machine, prg_offset + 0);
984         prg16_cdef(machine, prg_offset + state->m_mmc_reg[3]);
985         break;
986      case 0x0c:
987//          printf("PRG 16 bank %d (low) \n", prg_offset + state->m_mmc_reg[3]);
988         prg16_89ab(machine, prg_offset + state->m_mmc_reg[3]);
989         prg16_cdef(machine, prg_offset + 0x0f);
990         break;
991   }
992}
993
994static void mmc1_set_prg_wram( address_space *space, int board )
995{
996   mmc1_set_prg(space->machine());
997   mmc1_set_wram(space, board);
998}
999
1000static void mmc1_set_chr( running_machine &machine )
1001{
1002   nes_state *state = machine.driver_data<nes_state>();
1003   UINT8 chr_mode = BIT(state->m_mmc_reg[0], 4);
1004
1005   if (chr_mode)
1006   {
1007      chr4_0(machine, state->m_mmc_reg[1] & 0x1f, state->m_mmc_chr_source);
1008      chr4_4(machine, state->m_mmc_reg[2] & 0x1f, state->m_mmc_chr_source);
1009   }
1010   else
1011      chr8(machine, (state->m_mmc_reg[1] & 0x1f) >> 1, state->m_mmc_chr_source);
1012}
1013
1014static void common_sxrom_write_handler( address_space *space, offs_t offset, UINT8 data, int board )
1015{
1016   running_machine &machine = space->machine();
1017   nes_state *state = machine.driver_data<nes_state>();
1018   /* Note that there is only one latch and shift counter, shared amongst the 4 regs */
1019   /* Space Shuttle will not work if they have independent variables. */
1020
1021   /* here we would need to add an if(cpu_cycles_passed>1) test, and
1022     if requirement is not met simply return without writing anything.
1023     Some games (AD&D Hillsfar, Bill & Ted Excellent Adventure, Cosmic
1024     Wars, Rocket Ranger, Sesame Street 123 and Snow Brothers) rely on
1025     this behavior!! */
1026   if (state->m_mmc1_reg_write_enable == 0)
1027   {
1028      return;
1029   }
1030   else
1031   {
1032      state->m_mmc1_reg_write_enable = 0;
1033      space->machine().scheduler().synchronize(FUNC(mmc1_resync_callback));
1034   }
1035
1036   if (data & 0x80)
1037   {
1038      state->m_mmc1_count = 0;
1039      state->m_mmc1_latch = 0;
1040
1041      /* Set reg at 0x8000 to size 16k and lower half swap - needed for Robocop 3, Dynowars */
1042      state->m_mmc_reg[0] |= 0x0c;
1043      mmc1_set_prg_wram(space, board);
1044      return;
1045   }
1046
1047   if (state->m_mmc1_count < 5)
1048   {
1049      if (state->m_mmc1_count == 0) state->m_mmc1_latch = 0;
1050      state->m_mmc1_latch >>= 1;
1051      state->m_mmc1_latch |= (data & 0x01) ? 0x10 : 0x00;
1052      state->m_mmc1_count++;
1053   }
1054
1055   if (state->m_mmc1_count == 5)
1056   {
1057      switch (offset & 0x6000)   /* Which reg shall we write to? */
1058      {
1059         case 0x0000:
1060            state->m_mmc_reg[0] = state->m_mmc1_latch;
1061
1062            switch (state->m_mmc_reg[0] & 0x03)
1063            {
1064            case 0: set_nt_mirroring(machine, PPU_MIRROR_LOW); break;
1065            case 1: set_nt_mirroring(machine, PPU_MIRROR_HIGH); break;
1066            case 2: set_nt_mirroring(machine, PPU_MIRROR_VERT); break;
1067            case 3: set_nt_mirroring(machine, PPU_MIRROR_HORZ); break;
1068            }
1069            mmc1_set_chr(machine);
1070            mmc1_set_prg_wram(space, board);
1071            break;
1072         case 0x2000:
1073            state->m_mmc_reg[1] = state->m_mmc1_latch;
1074            mmc1_set_chr(machine);
1075            mmc1_set_prg_wram(space, board);
1076            break;
1077         case 0x4000:
1078            state->m_mmc_reg[2] = state->m_mmc1_latch;
1079            mmc1_set_chr(machine);
1080            break;
1081         case 0x6000:
1082            state->m_mmc_reg[3] = state->m_mmc1_latch;
1083            mmc1_set_prg_wram(space, board);
1084            break;
1085      }
1086      state->m_mmc1_count = 0;
1087   }
1088}
1089
1090static WRITE8_HANDLER( sxrom_w )
1091{
1092   nes_state *state = space->machine().driver_data<nes_state>();
1093
1094   LOG_MMC(("sxrom_w, offset: %04x, data: %02x\n", offset, data));
1095   common_sxrom_write_handler(space, offset, data, state->m_pcb_id);
1096}
1097
1098/*************************************************************
1099
1100 PxROM (MMC2 based) board emulation
1101
1102 Games: Punch Out!!, Mike Tyson's Punch Out!!
1103
1104 iNES: mapper 9
1105
1106 In MESS: Supported
1107
1108 *************************************************************/
1109
1110static void mmc2_latch( device_t *device, offs_t offset )
1111{
1112   nes_state *state = device->machine().driver_data<nes_state>();
1113   if ((offset & 0x3ff0) == 0x0fd0)
1114   {
1115      LOG_MMC(("mmc2 vrom latch switch (bank 0 low): %02x\n", state->m_mmc_reg[0]));
1116      state->m_mmc_latch1 = 0xfd;
1117      chr4_0(device->machine(), state->m_mmc_reg[0], CHRROM);
1118   }
1119   else if ((offset & 0x3ff0) == 0x0fe0)
1120   {
1121      LOG_MMC(("mmc2 vrom latch switch (bank 0 high): %02x\n", state->m_mmc_reg[1]));
1122      state->m_mmc_latch1 = 0xfe;
1123      chr4_0(device->machine(), state->m_mmc_reg[1], CHRROM);
1124   }
1125   else if ((offset & 0x3ff0) == 0x1fd0)
1126   {
1127      LOG_MMC(("mmc2 vrom latch switch (bank 1 low): %02x\n", state->m_mmc_reg[2]));
1128      state->m_mmc_latch2 = 0xfd;
1129      chr4_4(device->machine(), state->m_mmc_reg[2], CHRROM);
1130   }
1131   else if ((offset & 0x3ff0) == 0x1fe0)
1132   {
1133      LOG_MMC(("mmc2 vrom latch switch (bank 0 high): %02x\n", state->m_mmc_reg[3]));
1134      state->m_mmc_latch2 = 0xfe;
1135      chr4_4(device->machine(), state->m_mmc_reg[3], CHRROM);
1136   }
1137}
1138
1139static WRITE8_HANDLER( pxrom_w )
1140{
1141   nes_state *state = space->machine().driver_data<nes_state>();
1142   LOG_MMC(("pxrom_w, offset: %04x, data: %02x\n", offset, data));
1143   switch (offset & 0x7000)
1144   {
1145      case 0x2000:
1146         prg8_89(space->machine(), data);
1147         break;
1148      case 0x3000:
1149         state->m_mmc_reg[0] = data;
1150         if (state->m_mmc_latch1 == 0xfd)
1151            chr4_0(space->machine(), state->m_mmc_reg[0], CHRROM);
1152         break;
1153      case 0x4000:
1154         state->m_mmc_reg[1] = data;
1155         if (state->m_mmc_latch1 == 0xfe)
1156            chr4_0(space->machine(), state->m_mmc_reg[1], CHRROM);
1157         break;
1158      case 0x5000:
1159         state->m_mmc_reg[2] = data;
1160         if (state->m_mmc_latch2 == 0xfd)
1161            chr4_4(space->machine(), state->m_mmc_reg[2], CHRROM);
1162         break;
1163      case 0x6000:
1164         state->m_mmc_reg[3] = data;
1165         if (state->m_mmc_latch2 == 0xfe)
1166            chr4_4(space->machine(), state->m_mmc_reg[3], CHRROM);
1167         break;
1168      case 0x7000:
1169         set_nt_mirroring(space->machine(), BIT(data, 0) ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT);
1170         break;
1171      default:
1172         LOG_MMC(("MMC2 uncaught w: %04x:%02x\n", offset, data));
1173         break;
1174   }
1175}
1176
1177/*************************************************************
1178
1179 FxROM (MMC4 based) board emulation
1180
1181 Games: Famicom Wars, Fire Emblem, Fire Emblem Gaiden
1182
1183 iNES: mapper 10
1184
1185 In MESS: Supported
1186
1187*************************************************************/
1188
1189static WRITE8_HANDLER( fxrom_w )
1190{
1191   LOG_MMC(("fxrom_w, offset: %04x, data: %02x\n", offset, data));
1192   switch (offset & 0x7000)
1193   {
1194      case 0x2000:
1195         prg16_89ab(space->machine(), data);
1196         break;
1197      default:
1198         pxrom_w(space, offset, data);
1199         break;
1200   }
1201}
1202
1203/*************************************************************
1204
1205 TxROM (MMC3 based) board emulation
1206
1207 iNES: mapper 4
1208
1209 *************************************************************/
1210
1211static void mmc3_set_wram( address_space *space )
1212{
1213   running_machine &machine = space->machine();
1214   nes_state *state = machine.driver_data<nes_state>();
1215
1216   // skip this function if we are emulating a MMC3 clone with mid writes
1217   if (state->m_mmc_write_mid != NULL)
1218      return;
1219
1220   if (BIT(state->m_mmc3_wram_protect, 7))
1221      space->install_readwrite_bank(0x6000, 0x7fff, "bank5");
1222   else
1223   {
1224      space->unmap_readwrite(0x6000, 0x7fff);
1225      return;
1226   }
1227
1228   if (!BIT(state->m_mmc3_wram_protect, 6))
1229      space->install_write_bank(0x6000, 0x7fff, "bank5");
1230   else
1231   {
1232      space->unmap_write(0x6000, 0x7fff);
1233      return;
1234   }
1235}
1236
1237static void mmc3_set_prg( running_machine &machine, int prg_base, int prg_mask )
1238{
1239   nes_state *state = machine.driver_data<nes_state>();
1240   UINT8 prg_flip = (state->m_mmc3_latch & 0x40) ? 2 : 0;
1241
1242   state->m_mmc3_prg_cb(machine, 0, prg_base | (state->m_mmc_prg_bank[0 ^ prg_flip] & prg_mask));
1243   state->m_mmc3_prg_cb(machine, 1, prg_base | (state->m_mmc_prg_bank[1] & prg_mask));
1244   state->m_mmc3_prg_cb(machine, 2, prg_base | (state->m_mmc_prg_bank[2 ^ prg_flip] & prg_mask));
1245   state->m_mmc3_prg_cb(machine, 3, prg_base | (state->m_mmc_prg_bank[3] & prg_mask));
1246}
1247
1248static void mmc3_set_chr( running_machine &machine, UINT8 chr, int chr_base, int chr_mask )
1249{
1250   nes_state *state = machine.driver_data<nes_state>();
1251   UINT8 chr_page = (state->m_mmc3_latch & 0x80) >> 5;
1252
1253   state->m_mmc3_chr_cb(machine, chr_page ^ 0, chr_base | ((state->m_mmc_vrom_bank[0] & ~0x01) & chr_mask), chr);
1254   state->m_mmc3_chr_cb(machine, chr_page ^ 1, chr_base | ((state->m_mmc_vrom_bank[0] |  0x01) & chr_mask), chr);
1255   state->m_mmc3_chr_cb(machine, chr_page ^ 2, chr_base | ((state->m_mmc_vrom_bank[1] & ~0x01) & chr_mask), chr);
1256   state->m_mmc3_chr_cb(machine, chr_page ^ 3, chr_base | ((state->m_mmc_vrom_bank[1] |  0x01) & chr_mask), chr);
1257   state->m_mmc3_chr_cb(machine, chr_page ^ 4, chr_base | (state->m_mmc_vrom_bank[2] & chr_mask), chr);
1258   state->m_mmc3_chr_cb(machine, chr_page ^ 5, chr_base | (state->m_mmc_vrom_bank[3] & chr_mask), chr);
1259   state->m_mmc3_chr_cb(machine, chr_page ^ 6, chr_base | (state->m_mmc_vrom_bank[4] & chr_mask), chr);
1260   state->m_mmc3_chr_cb(machine, chr_page ^ 7, chr_base | (state->m_mmc_vrom_bank[5] & chr_mask), chr);
1261}
1262
1263/* Here, IRQ counter decrements every scanline. */
1264static void mmc3_irq( device_t *device, int scanline, int vblank, int blanked )
1265{
1266   nes_state *state = device->machine().driver_data<nes_state>();
1267
1268   if (scanline < PPU_BOTTOM_VISIBLE_SCANLINE)
1269   {
1270      int priorCount = state->m_IRQ_count;
1271      if ((state->m_IRQ_count == 0) || state->m_IRQ_clear)
1272         state->m_IRQ_count = state->m_IRQ_count_latch;
1273      else
1274         state->m_IRQ_count--;
1275
1276      if (state->m_IRQ_enable && !blanked && (state->m_IRQ_count == 0) && (priorCount || state->m_IRQ_clear /*|| !state->m_mmc3_alt_irq*/)) // according to blargg the latter should be present as well, but it breaks Rampart and Joe & Mac US: they probably use the alt irq!
1277      {
1278         LOG_MMC(("irq fired, scanline: %d (MAME %d, beam pos: %d)\n", scanline,
1279                device->machine().primary_screen->vpos(), device->machine().primary_screen->hpos()));
1280         device_set_input_line(state->m_maincpu, M6502_IRQ_LINE, HOLD_LINE);
1281      }
1282   }
1283   state->m_IRQ_clear = 0;
1284}
1285
1286static WRITE8_HANDLER( txrom_w )
1287{
1288   nes_state *state = space->machine().driver_data<nes_state>();
1289   UINT8 mmc_helper, cmd;
1290
1291   LOG_MMC(("txrom_w, offset: %04x, data: %02x\n", offset, data));
1292
1293   switch (offset & 0x6001)
1294   {
1295      case 0x0000:
1296         mmc_helper = state->m_mmc3_latch ^ data;
1297         state->m_mmc3_latch = data;
1298
1299         /* Has PRG Mode changed? */
1300         if (mmc_helper & 0x40)
1301            mmc3_set_prg(space->machine(), state->m_mmc_prg_base, state->m_mmc_prg_mask);
1302
1303         /* Has CHR Mode changed? */
1304         if (mmc_helper & 0x80)
1305            mmc3_set_chr(space->machine(), state->m_mmc_chr_source, state->m_mmc_chr_base, state->m_mmc_chr_mask);
1306         break;
1307
1308      case 0x0001:
1309         cmd = state->m_mmc3_latch & 0x07;
1310         switch (cmd)
1311         {
1312         case 0: case 1:   // these do not need to be separated: we take care of them in set_chr!
1313         case 2: case 3: case 4: case 5:
1314            state->m_mmc_vrom_bank[cmd] = data;
1315            mmc3_set_chr(space->machine(), state->m_mmc_chr_source, state->m_mmc_chr_base, state->m_mmc_chr_mask);
1316            break;
1317         case 6:
1318         case 7:
1319            state->m_mmc_prg_bank[cmd - 6] = data;
1320            mmc3_set_prg(space->machine(), state->m_mmc_prg_base, state->m_mmc_prg_mask);
1321            break;
1322         }
1323         break;
1324
1325      case 0x2000:
1326         set_nt_mirroring(space->machine(), BIT(data, 0) ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT);
1327         break;
1328
1329      case 0x2001:
1330         state->m_mmc3_wram_protect = data;
1331         mmc3_set_wram(space);
1332         break;
1333
1334      case 0x4000:
1335         state->m_IRQ_count_latch = data;
1336         break;
1337
1338      case 0x4001:
1339         state->m_IRQ_count = 0;
1340         break;
1341
1342      case 0x6000:
1343         state->m_IRQ_enable = 0;
1344         break;
1345
1346      case 0x6001:
1347         state->m_IRQ_enable = 1;
1348         break;
1349
1350      default:
1351         logerror("txrom_w uncaught: %04x value: %02x\n", offset + 0x8000, data);
1352         break;
1353   }
1354}
1355
1356/*************************************************************
1357
1358 HKROM (MMC6 based) board emulation
1359
1360 iNES: mapper 4
1361
1362 *************************************************************/
1363
1364static WRITE8_HANDLER( hkrom_m_w )
1365{
1366   nes_state *state = space->machine().driver_data<nes_state>();
1367   UINT8 write_hi, write_lo;
1368   LOG_MMC(("hkrom_m_w, offset: %04x, data: %02x\n", offset, data));
1369
1370   if (offset < 0x1000)
1371      return;
1372
1373   // banks can be written only if both read & write is enabled!
1374   write_hi = ((state->m_mmc6_reg & 0xc0) == 0xc0);
1375   write_lo = ((state->m_mmc6_reg & 0x30) == 0x30);
1376
1377   if (BIT(offset, 9) && write_hi)   // access to upper 1k
1378      state->m_mapper_bram[offset & (state->m_mapper_bram_size - 1)] = data;
1379
1380   if (!BIT(offset, 9) && write_lo)   // access to lower 1k
1381      state->m_mapper_bram[offset & (state->m_mapper_bram_size - 1)] = data;
1382}
1383
1384static READ8_HANDLER( hkrom_m_r )
1385{
1386   nes_state *state = space->machine().driver_data<nes_state>();
1387   LOG_MMC(("hkrom_m_r, offset: %04x\n", offset));
1388
1389   if (offset < 0x1000)
1390      return 0xff;   // here it should be open bus
1391
1392   if (!(state->m_mmc6_reg & 0xa0))
1393      return 0xff;   // here it should be open bus
1394
1395   if (BIT(offset, 9) && BIT(state->m_mmc6_reg, 7))   // access to upper 1k when upper read is enabled
1396      return state->m_mapper_bram[offset & (state->m_mapper_bram_size - 1)];
1397
1398   if (!BIT(offset, 9) && BIT(state->m_mmc6_reg, 5))   // access to lower 1k when lower read is enabled
1399      return state->m_mapper_bram[offset & (state->m_mapper_bram_size - 1)];
1400
1401   // If only one bank is enabled for reading, the other reads back as zero
1402   return 0x00;
1403}
1404
1405static WRITE8_HANDLER( hkrom_w )
1406{
1407   nes_state *state = space->machine().driver_data<nes_state>();
1408   UINT8 mmc6_helper;
1409   LOG_MMC(("hkrom_w, offset: %04x, data: %02x\n", offset, data));
1410
1411   switch (offset & 0x6001)
1412   {
1413      case 0x0000:
1414         mmc6_helper = state->m_mmc3_latch ^ data;
1415         state->m_mmc3_latch = data;
1416
1417         if (!state->m_mmc_latch2 && BIT(data, 5))   // if WRAM is disabled and has to be enabled, write
1418            state->m_mmc_latch2 = BIT(data, 5);   // (once WRAM has been enabled, it cannot be disabled without resetting the game)
1419
1420         /* Has PRG Mode changed? */
1421         if (BIT(mmc6_helper, 6))
1422            mmc3_set_prg(space->machine(), state->m_mmc_prg_base, state->m_mmc_prg_mask);
1423
1424         /* Has CHR Mode changed? */
1425         if (BIT(mmc6_helper, 7))
1426            mmc3_set_chr(space->machine(), state->m_mmc_chr_source, state->m_mmc_chr_base, state->m_mmc_chr_mask);
1427         break;
1428
1429      case 0x2001:
1430         if (state->m_mmc_latch2)
1431            state->m_mmc6_reg = data;
1432         break;
1433
1434      case 0x4001:
1435         state->m_IRQ_count = 0;
1436         state->m_IRQ_clear = 1;
1437         break;
1438
1439      default:
1440         txrom_w(space, offset, data);
1441         break;
1442   }
1443}
1444
1445/*************************************************************
1446
1447 TxSROM (MMC3 based) board emulation
1448
1449 Games: Armadillo, Play Action Football, Pro Hockey, RPG
1450 Jinsei Game, Y's 3
1451
1452 iNES: mapper 118
1453
1454 In MESS: Supported. It also uses mmc3_irq.
1455
1456 *************************************************************/
1457
1458static void txsrom_set_mirror( running_machine &machine )
1459{
1460   nes_state *state = machine.driver_data<nes_state>();
1461   if (state->m_mmc3_latch & 0x80)
1462   {
1463      set_nt_page(machine, 0, CIRAM, (state->m_mmc_vrom_bank[2] & 0x80) >> 7, 1);
1464      set_nt_page(machine, 1, CIRAM, (state->m_mmc_vrom_bank[3] & 0x80) >> 7, 1);
1465      set_nt_page(machine, 2, CIRAM, (state->m_mmc_vrom_bank[4] & 0x80) >> 7, 1);
1466      set_nt_page(machine, 3, CIRAM, (state->m_mmc_vrom_bank[5] & 0x80) >> 7, 1);
1467   }
1468   else
1469   {
1470      set_nt_page(machine, 0, CIRAM, (state->m_mmc_vrom_bank[0] & 0x80) >> 7, 1);
1471      set_nt_page(machine, 1, CIRAM, (state->m_mmc_vrom_bank[0] & 0x80) >> 7, 1);
1472      set_nt_page(machine, 2, CIRAM, (state->m_mmc_vrom_bank[1] & 0x80) >> 7, 1);
1473      set_nt_page(machine, 3, CIRAM, (state->m_mmc_vrom_bank[1] & 0x80) >> 7, 1);
1474   }
1475}
1476
1477static void txsrom_chr_cb( running_machine &machine, int start, int bank, int source )
1478{
1479   txsrom_set_mirror(machine);   // we could probably update only for one (e.g. the first) call, to slightly optimize the code
1480   chr1_x(machine, start, bank, source);
1481}
1482
1483static WRITE8_HANDLER( txsrom_w )
1484{
1485   LOG_MMC(("txsrom_w, offset: %04x, data: %02x\n", offset, data));
1486
1487   switch (offset & 0x6001)
1488   {
1489      case 0x2000:
1490         break;
1491
1492      default:
1493         txrom_w(space, offset, data);
1494         break;
1495   }
1496}
1497
1498/*************************************************************
1499
1500 TQROM (MMC3 based) board emulation
1501
1502 Games: Pin Bot, High Speed
1503
1504 iNES: mapper 119
1505
1506 In MESS: Supported. It also uses mmc3_irq.
1507
1508 *************************************************************/
1509
1510static void tqrom_set_chr( running_machine &machine )
1511{
1512   nes_state *state = machine.driver_data<nes_state>();
1513   UINT8 chr_page = (state->m_mmc3_latch & 0x80) >> 5;
1514   UINT8 chr_src[6], chr_mask[6];
1515   int i;
1516
1517   for (i = 0; i < 6; i++)
1518   {
1519      chr_src[i] = (state->m_mmc_vrom_bank[i] & 0x40) ? CHRRAM : CHRROM;
1520      chr_mask[i] =  (state->m_mmc_vrom_bank[i] & 0x40) ? 0x07 : 0x3f;
1521   }
1522
1523   chr1_x(machine, chr_page ^ 0, ((state->m_mmc_vrom_bank[0] & ~0x01) & chr_mask[0]), chr_src[0]);
1524   chr1_x(machine, chr_page ^ 1, ((state->m_mmc_vrom_bank[0] |  0x01) & chr_mask[0]), chr_src[0]);
1525   chr1_x(machine, chr_page ^ 2, ((state->m_mmc_vrom_bank[1] & ~0x01) & chr_mask[1]), chr_src[1]);
1526   chr1_x(machine, chr_page ^ 3, ((state->m_mmc_vrom_bank[1] |  0x01) & chr_mask[1]), chr_src[1]);
1527   chr1_x(machine, chr_page ^ 4, (state->m_mmc_vrom_bank[2] & chr_mask[2]), chr_src[2]);
1528   chr1_x(machine, chr_page ^ 5, (state->m_mmc_vrom_bank[3] & chr_mask[3]), chr_src[3]);
1529   chr1_x(machine, chr_page ^ 6, (state->m_mmc_vrom_bank[4] & chr_mask[4]), chr_src[4]);
1530   chr1_x(machine, chr_page ^ 7, (state->m_mmc_vrom_bank[5] & chr_mask[5]), chr_src[5]);
1531}
1532
1533static WRITE8_HANDLER( tqrom_w )
1534{
1535   nes_state *state = space->machine().driver_data<nes_state>();
1536   UINT8 mmc_helper, cmd;
1537   LOG_MMC(("tqrom_w, offset: %04x, data: %02x\n", offset, data));
1538
1539   switch (offset & 0x6001)
1540   {
1541      case 0x0000:
1542         mmc_helper = state->m_mmc3_latch ^ data;
1543         state->m_mmc3_latch = data;
1544
1545         /* Has PRG Mode changed? */
1546         if (mmc_helper & 0x40)
1547            mmc3_set_prg(space->machine(), state->m_mmc_prg_base, state->m_mmc_prg_mask);
1548
1549         /* Has CHR Mode changed? */
1550         if (mmc_helper & 0x80)
1551            tqrom_set_chr(space->machine());
1552         break;
1553      case 0x0001: /* $8001 */
1554         cmd = state->m_mmc3_latch & 0x07;
1555         switch (cmd)
1556         {
1557         case 0: case 1:   // these do not need to be separated: we take care of them in set_chr!
1558         case 2: case 3: case 4: case 5:
1559            state->m_mmc_vrom_bank[cmd] = data;
1560            tqrom_set_chr(space->machine());
1561            break;
1562         case 6:
1563         case 7:
1564            state->m_mmc_prg_bank[cmd - 6] = data;
1565            mmc3_set_prg(space->machine(), state->m_mmc_prg_base, state->m_mmc_prg_mask);
1566            break;
1567         }
1568         break;
1569
1570      default:
1571         txrom_w(space, offset, data);
1572         break;
1573   }
1574}
1575
1576/*************************************************************
1577
1578 PAL-ZZ board (MMC3 variant for European 3-in-1 Nintendo cart
1579 Super Mario Bros. + Tetris + Nintendo World Cup)
1580
1581 iNES: mapper 37
1582
1583 *************************************************************/
1584
1585static WRITE8_HANDLER( zz_m_w )
1586{
1587   nes_state *state = space->machine().driver_data<nes_state>();
1588   UINT8 mmc_helper = data & 0x07;
1589   LOG_MMC(("zz_m_w, offset: %04x, data: %02x\n", offset, data));
1590
1591   state->m_mmc_prg_base = (BIT(mmc_helper, 2) << 4) | (((mmc_helper & 0x03) == 0x03) ? 0x08 : 0);
1592   state->m_mmc_prg_mask = (mmc_helper << 1) | 0x07;
1593   state->m_mmc_chr_base = BIT(mmc_helper, 2) << 7;
1594   state->m_mmc_chr_mask = 0x7f;
1595   mmc3_set_prg(space->machine(), state->m_mmc_prg_base, state->m_mmc_prg_mask);
1596   mmc3_set_chr(space->machine(), state->m_mmc_chr_source, state->m_mmc_chr_base, state->m_mmc_chr_mask);
1597}
1598
1599/*************************************************************
1600
1601 NES-QJ board (MMC3 variant for US 2-in-1 Nintendo cart
1602 Super Spike V'Ball + Nintendo World Cup)
1603
1604 iNES: mapper 47
1605
1606 *************************************************************/
1607
1608static WRITE8_HANDLER( qj_m_w )
1609{
1610   nes_state *state = space->machine().driver_data<nes_state>();
1611   LOG_MMC(("qj_m_w, offset: %04x, data: %02x\n", offset, data));
1612
1613   state->m_mmc_prg_base = BIT(data, 0) << 4;
1614   state->m_mmc_prg_mask = 0x0f;
1615   state->m_mmc_chr_base = BIT(data, 0) << 7;
1616   state->m_mmc_chr_mask = 0x7f;
1617   mmc3_set_prg(space->machine(), state->m_mmc_prg_base, state->m_mmc_prg_mask);
1618   mmc3_set_chr(space->machine(), state->m_mmc_chr_source, state->m_mmc_chr_base, state->m_mmc_chr_mask);
1619}
1620
1621/*************************************************************
1622
1623 ExROM (MMC5 based) board emulation
1624
1625 Games: Castlevania III, Just Breed, many Koei titles
1626
1627 iNES: mapper 5
1628
1629 MESS status: Mostly Unsupported
1630
1631 *************************************************************/
1632
1633#if 0
1634static void mmc5_update_chr_a( running_machine &machine )
1635{
1636   nes_state *state = machine.driver_data<nes_state>();
1637   switch (state->m_mmc5_chr_mode)
1638   {
1639      case 0:   // 8k banks
1640         chr8(machine, state->m_mmc5_vrom_regA[7] & 0xff, CHRROM);
1641         break;
1642
1643      case 1:   // 4k banks
1644         chr4_0(machine, state->m_mmc5_vrom_regA[3] & 0xff, CHRROM);
1645         chr4_4(machine, state->m_mmc5_vrom_regA[7] & 0xff, CHRROM);
1646         break;
1647
1648      case 2:   // 2k banks
1649         chr2_0(machine, state->m_mmc5_vrom_regA[1], CHRROM);
1650         chr2_2(machine, state->m_mmc5_vrom_regA[3], CHRROM);
1651         chr2_4(machine, state->m_mmc5_vrom_regA[5], CHRROM);
1652         chr2_6(machine, state->m_mmc5_vrom_regA[7], CHRROM);
1653         break;
1654
1655      case 3:   // 1k banks
1656         chr1_0(machine, state->m_mmc5_vrom_regA[0], CHRROM);
1657         chr1_1(machine, state->m_mmc5_vrom_regA[1], CHRROM);
1658         chr1_2(machine, state->m_mmc5_vrom_regA[2], CHRROM);
1659         chr1_3(machine, state->m_mmc5_vrom_regA[3], CHRROM);
1660         chr1_4(machine, state->m_mmc5_vrom_regA[4], CHRROM);
1661         chr1_5(machine, state->m_mmc5_vrom_regA[5], CHRROM);
1662         chr1_6(machine, state->m_mmc5_vrom_regA[6], CHRROM);
1663         chr1_7(machine, state->m_mmc5_vrom_regA[7], CHRROM);
1664         break;
1665   }
1666}
1667
1668static void mmc5_update_chr_b( running_machine &machine )
1669{
1670   nes_state *state = machine.driver_data<nes_state>();
1671   switch (state->m_mmc5_chr_mode)
1672   {
1673      case 0:   // 8k banks
1674         chr8(machine, state->m_mmc5_vrom_regB[3] & 0xff, CHRROM);
1675         break;
1676
1677      case 1:   // 4k banks
1678         chr4_0(machine, state->m_mmc5_vrom_regB[3] & 0xff, CHRROM);
1679         chr4_4(machine, state->m_mmc5_vrom_regB[3] & 0xff, CHRROM);
1680         break;
1681
1682      case 2:   // 2k banks
1683         chr2_0(machine, state->m_mmc5_vrom_regB[1], CHRROM);
1684         chr2_2(machine, state->m_mmc5_vrom_regB[3], CHRROM);
1685         chr2_4(machine, state->m_mmc5_vrom_regB[1], CHRROM);
1686         chr2_6(machine, state->m_mmc5_vrom_regB[3], CHRROM);
1687         break;
1688
1689      case 3:   // 1k banks
1690         chr1_0(machine, state->m_mmc5_vrom_regB[0], CHRROM);
1691         chr1_1(machine, state->m_mmc5_vrom_regB[1], CHRROM);
1692         chr1_2(machine, state->m_mmc5_vrom_regB[2], CHRROM);
1693         chr1_3(machine, state->m_mmc5_vrom_regB[3], CHRROM);
1694         chr1_4(machine, state->m_mmc5_vrom_regB[0], CHRROM);
1695         chr1_5(machine, state->m_mmc5_vrom_regB[1], CHRROM);
1696         chr1_6(machine, state->m_mmc5_vrom_regB[2], CHRROM);
1697         chr1_7(machine, state->m_mmc5_vrom_regB[3], CHRROM);
1698         break;
1699   }
1700}
1701#endif
1702
1703static void mmc5_update_prg( running_machine &machine )
1704{
1705   nes_state *state = machine.driver_data<nes_state>();
1706   int bank1, bank2, bank3;
1707
1708   switch (state->m_mmc5_prg_mode)
1709   {
1710      case 0:   // 32k banks
1711         prg32(machine, state->m_mmc5_prg_regs[3] >> 2);
1712         break;
1713
1714      case 1:   // 16k banks
1715         //          printf("problema 1: %x\n", state->m_mmc5_prg_regs[1]);
1716         bank1 = state->m_mmc5_prg_regs[1];
1717
1718         if (!BIT(bank1, 7))
1719         {
1720            state->m_prg_bank[0] = state->m_prg_chunks + (bank1 & 0x06);
1721            state->m_prg_bank[1] = state->m_prg_chunks + (bank1 & 0x06) + 1;
1722            memory_set_bank(machine, "bank1", state->m_prg_bank[0]);
1723            memory_set_bank(machine, "bank2", state->m_prg_bank[1]);
1724         }
1725         else
1726            prg16_89ab(machine, bank1 >> 1);
1727
1728         prg16_cdef(machine, state->m_mmc5_prg_regs[3] >> 1);
1729         break;
1730
1731      case 2:   // 16k-8k banks
1732         //          printf("problema 2: %x %x\n", state->m_mmc5_prg_regs[1], state->m_mmc5_prg_regs[2]);
1733         bank1 = state->m_mmc5_prg_regs[1];
1734         bank3 = state->m_mmc5_prg_regs[2];
1735
1736         if (!BIT(bank1, 7))
1737         {
1738            state->m_prg_bank[0] = state->m_prg_chunks + (bank1 & 0x06);
1739            state->m_prg_bank[1] = state->m_prg_chunks + (bank1 & 0x06) + 1;
1740            memory_set_bank(machine, "bank1", state->m_prg_bank[0]);
1741            memory_set_bank(machine, "bank2", state->m_prg_bank[1]);
1742         }
1743         else
1744            prg16_89ab(machine, (bank1 & 0x7f) >> 1);
1745
1746         if (!BIT(bank3, 7))
1747         {
1748            state->m_prg_bank[2] = state->m_prg_chunks + (bank3 & 0x07);
1749            memory_set_bank(machine, "bank3", state->m_prg_bank[2]);
1750         }
1751         else
1752            prg8_cd(machine, bank3 & 0x7f);
1753
1754         prg8_ef(machine, state->m_mmc5_prg_regs[3]);
1755         break;
1756
1757      case 3:   // 8k banks
1758         //          printf("problema 3: %x %x %x\n", state->m_mmc5_prg_regs[0], state->m_mmc5_prg_regs[1], state->m_mmc5_prg_regs[2]);
1759         bank1 = state->m_mmc5_prg_regs[0];
1760         bank2 = state->m_mmc5_prg_regs[1];
1761         bank3 = state->m_mmc5_prg_regs[2];
1762
1763         if (!BIT(bank1, 7))
1764         {
1765            state->m_prg_bank[0] = state->m_prg_chunks + (bank1 & 0x07);
1766            memory_set_bank(machine, "bank1", state->m_prg_bank[0]);
1767         }
1768         else
1769            prg8_89(machine, bank1 & 0x7f);
1770
1771         if (!BIT(bank2, 7))
1772         {
1773            state->m_prg_bank[1] = state->m_prg_chunks + (bank2 & 0x07);
1774            memory_set_bank(machine, "bank2", state->m_prg_bank[1]);
1775         }
1776         else
1777            prg8_ab(machine, bank2 & 0x7f);
1778
1779         if (!BIT(bank3, 7))
1780         {
1781            state->m_prg_bank[2] = state->m_prg_chunks + (bank3 & 0x07);
1782            memory_set_bank(machine, "bank3", state->m_prg_bank[2]);
1783         }
1784         else
1785            prg8_cd(machine, bank3 & 0x7f);
1786
1787         prg8_ef(machine, state->m_mmc5_prg_regs[3]);
1788         break;
1789   }
1790}
1791
1792static void mmc5_update_render_mode( running_machine &machine )
1793{
1794}
1795
1796static void mmc5_irq( device_t *device, int scanline, int vblank, int blanked )
1797{
1798   nes_state *state = device->machine().driver_data<nes_state>();
1799
1800#if 1
1801   if (scanline == 0)
1802      state->m_IRQ_status |= 0x40;
1803   else if (scanline > PPU_BOTTOM_VISIBLE_SCANLINE)
1804      state->m_IRQ_status &= ~0x40;
1805#endif
1806
1807   if (scanline == state->m_IRQ_count)
1808   {
1809      if (state->m_IRQ_enable)
1810         device_set_input_line(state->m_maincpu, M6502_IRQ_LINE, HOLD_LINE);
1811
1812      state->m_IRQ_status = 0xff;
1813   }
1814
1815   /* FIXME: this is ok, but then we would need to update them again when we have the BG Hblank
1816     I leave it commented out until the PPU is updated for this */
1817   //  if (ppu2c0x_is_sprite_8x16(state->m_ppu) || state->m_mmc5_last_chr_a)
1818   //      mmc5_update_chr_a(device->machine());
1819   //  else
1820   //      mmc5_update_chr_b(device->machine());
1821}
1822
1823static void mmc5_ppu_mirror( running_machine &machine, int page, int src )
1824{
1825   switch (src)
1826   {
1827      case 0:   /* CIRAM0 */
1828         set_nt_page(machine, page, CIRAM, 0, 1);
1829         break;
1830      case 1:   /* CIRAM1 */
1831         set_nt_page(machine, page, CIRAM, 1, 1);
1832         break;
1833      case 2:   /* ExRAM */
1834         set_nt_page(machine, page, EXRAM, 0, 1);   // actually only works during rendering.
1835         break;
1836      case 3: /* Fill Registers */
1837         set_nt_page(machine, page, MMC5FILL, 0, 0);
1838         break;
1839      default:
1840         fatalerror("This should never happen");
1841         break;
1842   }
1843}
1844
1845static READ8_HANDLER( exrom_l_r )
1846{
1847   nes_state *state = space->machine().driver_data<nes_state>();
1848   int retVal;
1849
1850   /* $5c00 - $5fff: extended videoram attributes */
1851   if ((offset >= 0x1b00) && (offset <= 0x1eff))
1852   {
1853      return state->m_mapper_ram[offset - 0x1b00];
1854   }
1855
1856   switch (offset)
1857   {
1858      case 0x1104: /* $5204 */
1859#if 0
1860         if (current_scanline == MMC5_scanline)
1861            return 0x80;
1862         else
1863            return 0x00;
1864#else
1865         retVal = state->m_IRQ_status;
1866         state->m_IRQ_status &= ~0x80;
1867         return retVal;
1868#endif
1869
1870      case 0x1105: /* $5205 */
1871         return (state->m_mult1 * state->m_mult2) & 0xff;
1872      case 0x1106: /* $5206 */
1873         return ((state->m_mult1 * state->m_mult2) & 0xff00) >> 8;
1874
1875      default:
1876         logerror("** MMC5 uncaught read, offset: %04x\n", offset + 0x4100);
1877         return 0x00;
1878   }
1879}
1880
1881
1882static WRITE8_HANDLER( exrom_l_w )
1883{
1884   nes_state *state = space->machine().driver_data<nes_state>();
1885
1886   //  LOG_MMC(("Mapper 5 write, offset: %04x, data: %02x\n", offset + 0x4100, data));
1887   /* Send $5000-$5015 to the sound chip */
1888   if ((offset >= 0xf00) && (offset <= 0xf15))
1889   {
1890      nes_psg_w(state->m_sound, offset & 0x1f, data);
1891      return;
1892   }
1893
1894   /* $5c00 - $5fff: extended videoram attributes */
1895   if ((offset >= 0x1b00) && (offset <= 0x1eff))
1896   {
1897      if (state->m_MMC5_vram_protect == 0x03)
1898         state->m_mapper_ram[offset - 0x1b00] = data;
1899      return;
1900   }
1901
1902   switch (offset)
1903   {
1904      case 0x1000: /* $5100 */
1905         state->m_mmc5_prg_mode = data & 0x03;
1906         //          mmc5_update_prg(space->machine());
1907         LOG_MMC(("MMC5 rom bank mode: %02x\n", data));
1908         break;
1909
1910      case 0x1001: /* $5101 */
1911         state->m_mmc5_chr_mode = data & 0x03;
1912         // update chr
1913         LOG_MMC(("MMC5 vrom bank mode: %02x\n", data));
1914         break;
1915
1916      case 0x1002: /* $5102 */
1917         if (data == 0x02)
1918            state->m_MMC5_vram_protect |= 1;
1919         else
1920            state->m_MMC5_vram_protect = 0;
1921         LOG_MMC(("MMC5 vram protect 1: %02x\n", data));
1922         break;
1923      case 0x1003: /* 5103 */
1924         if (data == 0x01)
1925            state->m_MMC5_vram_protect |= 2;
1926         else
1927            state->m_MMC5_vram_protect = 0;
1928         LOG_MMC(("MMC5 vram protect 2: %02x\n", data));
1929         break;
1930
1931      case 0x1004: /* $5104 - Extra VRAM (EXRAM) control */
1932         state->m_mmc5_vram_control = data & 0x03;
1933         // update render
1934         mmc5_update_render_mode(space->machine());
1935         LOG_MMC(("MMC5 exram control: %02x\n", data));
1936         break;
1937
1938      case 0x1005: /* $5105 */
1939         mmc5_ppu_mirror(space->machine(), 0, data & 0x03);
1940         mmc5_ppu_mirror(space->machine(), 1, (data & 0x0c) >> 2);
1941         mmc5_ppu_mirror(space->machine(), 2, (data & 0x30) >> 4);
1942         mmc5_ppu_mirror(space->machine(), 3, (data & 0xc0) >> 6);
1943         // update render
1944         mmc5_update_render_mode(space->machine());
1945         break;
1946
1947         /* tile data for MMC5 flood-fill NT mode */
1948      case 0x1006:
1949         state->m_MMC5_floodtile = data;
1950         break;
1951
1952         /* attr data for MMC5 flood-fill NT mode */
1953      case 0x1007:
1954         switch (data & 3)
1955      {
1956         default:
1957         case 0: state->m_MMC5_floodattr = 0x00; break;
1958         case 1: state->m_MMC5_floodattr = 0x55; break;
1959         case 2: state->m_MMC5_floodattr = 0xaa; break;
1960         case 3: state->m_MMC5_floodattr = 0xff; break;
1961      }
1962         break;
1963
1964      case 0x1013: /* $5113 */
1965         LOG_MMC(("MMC5 mid RAM bank select: %02x\n", data & 0x07));
1966         // FIXME: a few Koei games have both WRAM & BWRAM but here we don't support this (yet)
1967         if (state->m_battery)
1968            wram_bank(space->machine(), data, NES_BATTERY);
1969         else
1970            wram_bank(space->machine(), data, NES_WRAM);
1971         break;
1972
1973
1974      case 0x1014: /* $5114 */
1975      case 0x1015: /* $5115 */
1976      case 0x1016: /* $5116 */
1977      case 0x1017: /* $5117 */
1978         state->m_mmc5_prg_regs[offset & 3] = data;
1979         mmc5_update_prg(space->machine());
1980         break;
1981
1982#if 0
1983      // these do not work as expected... I guess we definitely need the bank update at proper times (with BG vs. sprite timing)
1984      case 0x1020: /* $5120 */
1985      case 0x1021: /* $5121 */
1986      case 0x1022: /* $5122 */
1987      case 0x1023: /* $5123 */
1988      case 0x1024: /* $5124 */
1989      case 0x1025: /* $5125 */
1990      case 0x1026: /* $5126 */
1991      case 0x1027: /* $5127 */
1992         data |= (state->m_mmc5_chr_high << 8);
1993         if (!state->m_mmc5_last_chr_a)
1994         {
1995            state->m_mmc5_vrom_regA[offset & 0x07] = data;
1996            state->m_mmc5_last_chr_a = 1;
1997            if (ppu2c0x_get_current_scanline(state->m_ppu) == 240 || !ppu2c0x_is_sprite_8x16(state->m_ppu))
1998               mmc5_update_chr_a(space->machine());
1999         }
2000         break;
2001
2002
2003      case 0x1028: /* $5128 */
2004      case 0x1029: /* $5129 */
2005      case 0x102a: /* $512a */
2006      case 0x102b: /* $512b */
2007         data |= (state->m_mmc5_chr_high << 8);
2008         state->m_mmc5_vrom_regB[offset & 0x03] = data;
2009         state->m_mmc5_last_chr_a = 0;
2010         if (ppu2c0x_get_current_scanline(state->m_ppu) == 240 || !ppu2c0x_is_sprite_8x16(state->m_ppu))
2011            mmc5_update_chr_b(space->machine());
2012         break;
2013
2014      case 0x1030: /* $5130 */
2015         state->m_mmc5_chr_high = data & 0x03;
2016         if (state->m_mmc5_vram_control == 1)
2017         {
2018            // in this case state->m_mmc5_chr_high selects which 256KB of CHR ROM
2019            // is to be used for all background tiles on the screen.
2020         }
2021         break;
2022
2023#endif
2024
2025      case 0x1020: /* $5120 */
2026         LOG_MMC(("MMC5 $5120 vrom select: %02x (mode: %d)\n", data, state->m_mmc5_chr_mode));
2027         switch (state->m_mmc5_chr_mode)
2028      {
2029         case 0x03:
2030            /* 1k switch */
2031            state->m_MMC5_vrom_bank[0] = data | (state->m_mmc5_high_chr << 8);
2032            //                  mapper5_sync_vrom(0);
2033            chr1_0(space->machine(), state->m_MMC5_vrom_bank[0], CHRROM);
2034            //                  state->m_nes_vram_sprite[0] = state->m_MMC5_vrom_bank[0] * 64;
2035            //                  vrom_next[0] = 4;
2036            //                  vrom_page_a = 1;
2037            //                  vrom_page_b = 0;
2038            break;
2039      }
2040         break;
2041      case 0x1021: /* $5121 */
2042         LOG_MMC(("MMC5 $5121 vrom select: %02x (mode: %d)\n", data, state->m_mmc5_chr_mode));
2043         switch (state->m_mmc5_chr_mode)
2044      {
2045         case 0x02:
2046            /* 2k switch */
2047            chr2_0(space->machine(), data | (state->m_mmc5_high_chr << 8), CHRROM);
2048            break;
2049         case 0x03:
2050            /* 1k switch */
2051            state->m_MMC5_vrom_bank[1] = data | (state->m_mmc5_high_chr << 8);
2052            //                  mapper5_sync_vrom(0);
2053            chr1_1(space->machine(), state->m_MMC5_vrom_bank[1], CHRROM);
2054            //                  state->m_nes_vram_sprite[1] = state->m_MMC5_vrom_bank[0] * 64;
2055            //                  vrom_next[1] = 5;
2056            //                  vrom_page_a = 1;
2057            //                  vrom_page_b = 0;
2058            break;
2059      }
2060         break;
2061      case 0x1022: /* $5122 */
2062         LOG_MMC(("MMC5 $5122 vrom select: %02x (mode: %d)\n", data, state->m_mmc5_chr_mode));
2063         switch (state->m_mmc5_chr_mode)
2064      {
2065         case 0x03:
2066            /* 1k switch */
2067            state->m_MMC5_vrom_bank[2] = data | (state->m_mmc5_high_chr << 8);
2068            //                  mapper5_sync_vrom(0);
2069            chr1_2(space->machine(), state->m_MMC5_vrom_bank[2], CHRROM);
2070            //                  state->m_nes_vram_sprite[2] = state->m_MMC5_vrom_bank[0] * 64;
2071            //                  vrom_next[2] = 6;
2072            //                  vrom_page_a = 1;
2073            //                  vrom_page_b = 0;
2074            break;
2075      }
2076         break;
2077      case 0x1023: /* $5123 */
2078         LOG_MMC(("MMC5 $5123 vrom select: %02x (mode: %d)\n", data, state->m_mmc5_chr_mode));
2079         switch (state->m_mmc5_chr_mode)
2080      {
2081         case 0x01:
2082            chr4_0(space->machine(), data, CHRROM);
2083            break;
2084         case 0x02:
2085            /* 2k switch */
2086            chr2_2(space->machine(), data | (state->m_mmc5_high_chr << 8), CHRROM);
2087            break;
2088         case 0x03:
2089            /* 1k switch */
2090            state->m_MMC5_vrom_bank[3] = data | (state->m_mmc5_high_chr << 8);
2091            //                  mapper5_sync_vrom(0);
2092            chr1_3(space->machine(), state->m_MMC5_vrom_bank[3], CHRROM);
2093            //                  state->m_nes_vram_sprite[3] = state->m_MMC5_vrom_bank[0] * 64;
2094            //                  vrom_next[3] = 7;
2095            //                  vrom_page_a = 1;
2096            //                  vrom_page_b = 0;
2097            break;
2098      }
2099         break;
2100      case 0x1024: /* $5124 */
2101         LOG_MMC(("MMC5 $5124 vrom select: %02x (mode: %d)\n", data, state->m_mmc5_chr_mode));
2102         switch (state->m_mmc5_chr_mode)
2103      {
2104         case 0x03:
2105            /* 1k switch */
2106            state->m_MMC5_vrom_bank[4] = data | (state->m_mmc5_high_chr << 8);
2107            //                  mapper5_sync_vrom(0);
2108            chr1_4(space->machine(), state->m_MMC5_vrom_bank[4], CHRROM);
2109            //                  state->m_nes_vram_sprite[4] = state->m_MMC5_vrom_bank[0] * 64;
2110            //                  vrom_next[0] = 0;
2111            //                  vrom_page_a = 0;
2112            //                  vrom_page_b = 0;
2113            break;
2114      }
2115         break;
2116      case 0x1025: /* $5125 */
2117         LOG_MMC(("MMC5 $5125 vrom select: %02x (mode: %d)\n", data, state->m_mmc5_chr_mode));
2118         switch (state->m_mmc5_chr_mode)
2119      {
2120         case 0x02:
2121            /* 2k switch */
2122            chr2_4(space->machine(), data | (state->m_mmc5_high_chr << 8), CHRROM);
2123            break;
2124         case 0x03:
2125            /* 1k switch */
2126            state->m_MMC5_vrom_bank[5] = data | (state->m_mmc5_high_chr << 8);
2127            //                  mapper5_sync_vrom(0);
2128            chr1_5(space->machine(), state->m_MMC5_vrom_bank[5], CHRROM);
2129            //                  state->m_nes_vram_sprite[5] = state->m_MMC5_vrom_bank[0] * 64;
2130            //                  vrom_next[1] = 1;
2131            //                  vrom_page_a = 0;
2132            //                  vrom_page_b = 0;
2133            break;
2134      }
2135         break;
2136      case 0x1026: /* $5126 */
2137         LOG_MMC(("MMC5 $5126 vrom select: %02x (mode: %d)\n", data, state->m_mmc5_chr_mode));
2138         switch (state->m_mmc5_chr_mode)
2139      {
2140         case 0x03:
2141            /* 1k switch */
2142            state->m_MMC5_vrom_bank[6] = data | (state->m_mmc5_high_chr << 8);
2143            //                  mapper5_sync_vrom(0);
2144            chr1_6(space->machine(), state->m_MMC5_vrom_bank[6], CHRROM);
2145            //                  state->m_nes_vram_sprite[6] = state->m_MMC5_vrom_bank[0] * 64;
2146            //                  vrom_next[2] = 2;
2147            //                  vrom_page_a = 0;
2148            //                  vrom_page_b = 0;
2149            break;
2150      }
2151         break;
2152      case 0x1027: /* $5127 */
2153         LOG_MMC(("MMC5 $5127 vrom select: %02x (mode: %d)\n", data, state->m_mmc5_chr_mode));
2154         switch (state->m_mmc5_chr_mode)
2155      {
2156         case 0x00:
2157            /* 8k switch */
2158            chr8(space->machine(), data, CHRROM);
2159            break;
2160         case 0x01:
2161            /* 4k switch */
2162            chr4_4(space->machine(), data, CHRROM);
2163            break;
2164         case 0x02:
2165            /* 2k switch */
2166            chr2_6(space->machine(), data | (state->m_mmc5_high_chr << 8), CHRROM);
2167            break;
2168         case 0x03:
2169            /* 1k switch */
2170            state->m_MMC5_vrom_bank[7] = data | (state->m_mmc5_high_chr << 8);
2171            //                  mapper5_sync_vrom(0);
2172            chr1_7(space->machine(), state->m_MMC5_vrom_bank[7], CHRROM);
2173            //                  state->m_nes_vram_sprite[7] = state->m_MMC5_vrom_bank[0] * 64;
2174            //                  vrom_next[3] = 3;
2175            //                  vrom_page_a = 0;
2176            //                  vrom_page_b = 0;
2177            break;
2178      }
2179         break;
2180      case 0x1028: /* $5128 */
2181         LOG_MMC(("MMC5 $5128 vrom select: %02x (mode: %d)\n", data, state->m_mmc5_chr_mode));
2182         switch (state->m_mmc5_chr_mode)
2183      {
2184         case 0x03:
2185            /* 1k switch */
2186            state->m_MMC5_vrom_bank[8] = data | (state->m_mmc5_high_chr << 8);
2187            //                  nes_vram[vrom_next[0]] = data * 64;
2188            //                  nes_vram[0 + (vrom_page_a*4)] = data * 64;
2189            //                  nes_vram[0] = data * 64;
2190            chr1_4(space->machine(), state->m_MMC5_vrom_bank[8], CHRROM);
2191            //                  mapper5_sync_vrom(1);
2192            if (!state->m_vrom_page_b)
2193            {
2194               state->m_vrom_page_a ^= 0x01;
2195               state->m_vrom_page_b = 1;
2196            }
2197            break;
2198      }
2199         break;
2200      case 0x1029: /* $5129 */
2201         LOG_MMC(("MMC5 $5129 vrom select: %02x (mode: %d)\n", data, state->m_mmc5_chr_mode));
2202         switch (state->m_mmc5_chr_mode)
2203      {
2204         case 0x02:
2205            /* 2k switch */
2206            chr2_0(space->machine(), data | (state->m_mmc5_high_chr << 8), CHRROM);
2207            chr2_4(space->machine(), data | (state->m_mmc5_high_chr << 8), CHRROM);
2208            break;
2209         case 0x03:
2210            /* 1k switch */
2211            state->m_MMC5_vrom_bank[9] = data | (state->m_mmc5_high_chr << 8);
2212            //                  nes_vram[vrom_next[1]] = data * 64;
2213            //                  nes_vram[1 + (vrom_page_a*4)] = data * 64;
2214            //                  nes_vram[1] = data * 64;
2215            chr1_5(space->machine(), state->m_MMC5_vrom_bank[9], CHRROM);
2216            //                  mapper5_sync_vrom(1);
2217            if (!state->m_vrom_page_b)
2218            {
2219               state->m_vrom_page_a ^= 0x01;
2220               state->m_vrom_page_b = 1;
2221            }
2222            break;
2223      }
2224         break;
2225      case 0x102a: /* $512a */
2226         LOG_MMC(("MMC5 $512a vrom select: %02x (mode: %d)\n", data, state->m_mmc5_chr_mode));
2227         switch (state->m_mmc5_chr_mode)
2228      {
2229         case 0x03:
2230            /* 1k switch */
2231            state->m_MMC5_vrom_bank[10] = data | (state->m_mmc5_high_chr << 8);
2232            //                  nes_vram[vrom_next[2]] = data * 64;
2233            //                  nes_vram[2 + (vrom_page_a*4)] = data * 64;
2234            //                  nes_vram[2] = data * 64;
2235            chr1_6(space->machine(), state->m_MMC5_vrom_bank[10], CHRROM);
2236            //                  mapper5_sync_vrom(1);
2237            if (!state->m_vrom_page_b)
2238            {
2239               state->m_vrom_page_a ^= 0x01;
2240               state->m_vrom_page_b = 1;
2241            }
2242            break;
2243      }
2244         break;
2245      case 0x102b: /* $512b */
2246         LOG_MMC(("MMC5 $512b vrom select: %02x (mode: %d)\n", data, state->m_mmc5_chr_mode));
2247         switch (state->m_mmc5_chr_mode)
2248      {
2249         case 0x00:
2250            /* 8k switch */
2251            /* switches in first half of an 8K bank!) */
2252            chr4_0(space->machine(), data << 1, CHRROM);
2253            chr4_4(space->machine(), data << 1, CHRROM);
2254            break;
2255         case 0x01:
2256            /* 4k switch */
2257            chr4_0(space->machine(), data, CHRROM);
2258            chr4_4(space->machine(), data, CHRROM);
2259            break;
2260         case 0x02:
2261            /* 2k switch */
2262            chr2_2(space->machine(), data | (state->m_mmc5_high_chr << 8), CHRROM);
2263            chr2_6(space->machine(), data | (state->m_mmc5_high_chr << 8), CHRROM);
2264            break;
2265         case 0x03:
2266            /* 1k switch */
2267            state->m_MMC5_vrom_bank[11] = data | (state->m_mmc5_high_chr << 8);
2268            //                  nes_vram[vrom_next[3]] = data * 64;
2269            //                  nes_vram[3 + (vrom_page_a*4)] = data * 64;
2270            //                  nes_vram[3] = data * 64;
2271            chr1_7(space->machine(), state->m_MMC5_vrom_bank[11], CHRROM);
2272            //                  mapper5_sync_vrom(1);
2273            if (!state->m_vrom_page_b)
2274            {
2275               state->m_vrom_page_a ^= 0x01;
2276               state->m_vrom_page_b = 1;
2277            }
2278            break;
2279      }
2280         break;
2281
2282      case 0x1030: /* $5130 */
2283         state->m_mmc5_high_chr = data & 0x03;
2284         if (state->m_mmc5_vram_control == 1)
2285         {
2286            // in this case state->m_mmc5_high_chr selects which 256KB of CHR ROM
2287            // is to be used for all background tiles on the screen.
2288         }
2289         break;
2290
2291
2292      case 0x1100: /* $5200 */
2293         state->m_mmc5_split_scr = data;
2294         // in EX2 and EX3 modes, no split screen
2295         if (state->m_mmc5_vram_control & 0x02)
2296            state->m_mmc5_split_scr &= 0x7f;
2297         state->m_mmc5_split_ctrl = data;
2298         break;
2299
2300      case 0x1101: /* $5201 */
2301         state->m_mmc5_split_yst = (data >= 240) ? data - 16 : data;
2302         break;
2303
2304      case 0x1102: /* $5202 */
2305         state->m_mmc5_split_bank = data;
2306         break;
2307
2308      case 0x1103: /* $5203 */
2309         state->m_IRQ_count = data;
2310         state->m_MMC5_scanline = data;
2311         LOG_MMC(("MMC5 irq scanline: %d\n", state->m_IRQ_count));
2312         break;
2313      case 0x1104: /* $5204 */
2314         state->m_IRQ_enable = data & 0x80;
2315         LOG_MMC(("MMC5 irq enable: %02x\n", data));
2316         break;
2317      case 0x1105: /* $5205 */
2318         state->m_mult1 = data;
2319         break;
2320      case 0x1106: /* $5206 */
2321         state->m_mult2 = data;
2322         break;
2323
2324      default:
2325         logerror("** MMC5 uncaught write, offset: %04x, data: %02x\n", offset + 0x4100, data);
2326         break;
2327   }
2328}
2329
2330/*************************************************************
2331
2332 NTBROM & Sunsoft-4 board emulation
2333
2334 Part of this can be used also for Sunsoft Double Cassette
2335 System... which games use it?
2336
2337 iNES: mapper 68
2338
2339 *************************************************************/
2340
2341static void ntbrom_mirror( running_machine &machine, int mirror, int mirr0, int mirr1 )
2342{
2343   switch (mirror)
2344   {
2345      case 0x00:
2346         set_nt_mirroring(machine, PPU_MIRROR_HORZ);
2347         break;
2348      case 0x01:
2349         set_nt_mirroring(machine, PPU_MIRROR_VERT);
2350         break;
2351      case 0x02:
2352         set_nt_mirroring(machine, PPU_MIRROR_LOW);
2353         break;
2354      case 0x03:
2355         set_nt_mirroring(machine, PPU_MIRROR_HIGH);
2356         break;
2357      case 0x10:
2358         set_nt_page(machine, 0, ROM, mirr0 | 0x80, 0);
2359         set_nt_page(machine, 1, ROM, mirr1 | 0x80, 0);
2360         set_nt_page(machine, 2, ROM, mirr0 | 0x80, 0);
2361         set_nt_page(machine, 3, ROM, mirr1 | 0x80, 0);
2362         break;
2363      case 0x11:
2364         set_nt_page(machine, 0, ROM, mirr0 | 0x80, 0);
2365         set_nt_page(machine, 1, ROM, mirr0 | 0x80, 0);
2366         set_nt_page(machine, 2, ROM, mirr1 | 0x80, 0);
2367         set_nt_page(machine, 3, ROM, mirr1 | 0x80, 0);
2368         break;
2369      case 0x12:
2370         set_nt_page(machine, 0, ROM, mirr0 | 0x80, 0);
2371         set_nt_page(machine, 1, ROM, mirr0 | 0x80, 0);
2372         set_nt_page(machine, 2, ROM, mirr0 | 0x80, 0);
2373         set_nt_page(machine, 3, ROM, mirr0 | 0x80, 0);
2374         break;
2375      case 0x13:
2376         set_nt_page(machine, 0, ROM, mirr1 | 0x80, 0);
2377         set_nt_page(machine, 1, ROM, mirr1 | 0x80, 0);
2378         set_nt_page(machine, 2, ROM, mirr1 | 0x80, 0);
2379         set_nt_page(machine, 3, ROM, mirr1 | 0x80, 0);
2380         break;
2381   }
2382}
2383
2384static WRITE8_HANDLER( ntbrom_w )
2385{
2386   nes_state *state = space->machine().driver_data<nes_state>();
2387
2388   LOG_MMC(("ntbrom_w, offset %04x, data: %02x\n", offset, data));
2389
2390   switch (offset & 0x7000)
2391   {
2392      case 0x0000:
2393         chr2_0(space->machine(), data, CHRROM);
2394         break;
2395      case 0x1000:
2396         chr2_2(space->machine(), data, CHRROM);
2397         break;
2398      case 0x2000:
2399         chr2_4(space->machine(), data, CHRROM);
2400         break;
2401      case 0x3000:
2402         chr2_6(space->machine(), data, CHRROM);
2403         break;
2404      case 0x4000:
2405         state->m_mmc_latch1 = data & 0x7f;
2406         ntbrom_mirror(space->machine(), state->m_mmc_reg[0], state->m_mmc_latch1, state->m_mmc_latch2);
2407         break;
2408      case 0x5000:
2409         state->m_mmc_latch2 = data & 0x7f;
2410         ntbrom_mirror(space->machine(), state->m_mmc_reg[0], state->m_mmc_latch1, state->m_mmc_latch2);
2411         break;
2412      case 0x6000:
2413         state->m_mmc_reg[0] = data & 0x13;
2414         ntbrom_mirror(space->machine(), state->m_mmc_reg[0], state->m_mmc_latch1, state->m_mmc_latch2);
2415         break;
2416      case 0x7000:
2417         prg16_89ab(space->machine(), data);
2418         break;
2419      default:
2420         LOG_MMC(("ntbrom_w uncaught write, offset: %04x, data: %02x\n", offset, data));
2421         break;
2422   }
2423}
2424
2425/*************************************************************
2426
2427 JxROM & Sunsoft 5A / 5B / FME7 board emulation
2428
2429 Notice that Sunsoft-5B = FME7 + sound chip (the latter being
2430 currently unemulated in MESS)
2431
2432 iNES: mapper 69
2433
2434 *************************************************************/
2435
2436/* Here, IRQ counter decrements every CPU cycle. Since we update it every scanline,
2437 we need to decrement it by 114 (Each scanline consists of 341 dots and, on NTSC,
2438 there are 3 dots to every 1 CPU cycle, hence 114 is the number of cycles per scanline ) */
2439static void jxrom_irq( device_t *device, int scanline, int vblank, int blanked )
2440{
2441   nes_state *state = device->machine().driver_data<nes_state>();
2442
2443   /* TODO: change to reflect the actual number of cycles spent */
2444   if ((state->m_IRQ_enable & 0x80) && (state->m_IRQ_enable & 0x01))
2445   {
2446      if (state->m_IRQ_count <= 114)
2447      {
2448         state->m_IRQ_count = 0xffff;
2449         device_set_input_line(state->m_maincpu, M6502_IRQ_LINE, HOLD_LINE);
2450      }
2451      else
2452         state->m_IRQ_count -= 114;
2453   }
2454   else if (state->m_IRQ_enable & 0x01)   // if enable bit 7 is not set, only decrement the counter!
2455   {
2456      if (state->m_IRQ_count <= 114)
2457         state->m_IRQ_count = 0xffff;
2458      else
2459         state->m_IRQ_count -= 114;
2460   }
2461}
2462
2463static WRITE8_HANDLER( jxrom_w )
2464{
2465   nes_state *state = space->machine().driver_data<nes_state>();
2466   LOG_MMC(("jxrom_w, offset %04x, data: %02x\n", offset, data));
2467
2468   switch (offset & 0x6000)
2469   {
2470      case 0x0000:
2471         state->m_mmc_latch1 = data & 0x0f;
2472         break;
2473
2474      case 0x2000:
2475         switch (state->m_mmc_latch1)
2476         {
2477         case 0: case 1: case 2: case 3: case 4: case 5: case 6: case 7:
2478            chr1_x(space->machine(), state->m_mmc_latch1, data, CHRROM);
2479            break;
2480
2481         case 8:
2482            if (!(data & 0x40))
2483            {
2484               // is PRG ROM
2485               space->unmap_write(0x6000, 0x7fff);
2486               prg8_67(space->machine(), data & 0x3f);
2487            }
2488            else if (data & 0x80)
2489            {
2490               // is PRG RAM
2491               space->install_write_bank(0x6000, 0x7fff, "bank5");
2492               state->m_prg_bank[4] = state->m_battery_bank5_start + (data & 0x3f);
2493               memory_set_bank(space->machine(), "bank5", state->m_prg_bank[4]);
2494            }
2495            break;
2496
2497         case 9:
2498            prg8_89(space->machine(), data);
2499            break;
2500         case 0x0a:
2501            prg8_ab(space->machine(), data);
2502            break;
2503         case 0x0b:
2504            prg8_cd(space->machine(), data);
2505            break;
2506         case 0x0c:
2507            switch (data & 0x03)
2508            {
2509            case 0x00: set_nt_mirroring(space->machine(), PPU_MIRROR_VERT); break;
2510            case 0x01: set_nt_mirroring(space->machine(), PPU_MIRROR_HORZ); break;
2511            case 0x02: set_nt_mirroring(space->machine(), PPU_MIRROR_LOW); break;
2512            case 0x03: set_nt_mirroring(space->machine(), PPU_MIRROR_HIGH); break;
2513            }
2514            break;
2515         case 0x0d:
2516            state->m_IRQ_enable = data;
2517            break;
2518         case 0x0e:
2519            state->m_IRQ_count = (state->m_IRQ_count & 0xff00) | data;
2520            break;
2521         case 0x0f:
2522            state->m_IRQ_count = (state->m_IRQ_count & 0x00ff) | (data << 8);
2523            break;
2524         }
2525         break;
2526
2527         /* Here we would have sound command for Sunsoft 5b variant */
2528         //      case 0x4000:
2529         //      case 0x6000:
2530
2531      case 0x4000:
2532         LOG_MMC(("Sunsoft-5B Sound: Register select write, data: %02x\n", data));
2533         break;
2534      case 0x6000:
2535         LOG_MMC(("Sunsoft-5B Sound: Register write, data: %02x\n", data));
2536         break;
2537      default:
2538         logerror("jxrom_w uncaught %04x value: %02x\n", offset + 0x8000, data);
2539         break;
2540   }
2541}
2542
2543/*************************************************************
2544
2545 DxROM & Namcot 3433 - 3443 board emulation
2546
2547 Games: Dragon Spirit - Aratanaru Densetsu, Namcot Mahjong, Quinty
2548
2549 These are the same board, but DRROM (and Tengen 800004) have
2550 4-screen mirroring
2551
2552 iNES: mappers 88, 206 (same as 88 but possibly 4-screen mirroring)
2553
2554 *************************************************************/
2555
2556static WRITE8_HANDLER( dxrom_w )
2557{
2558   nes_state *state = space->machine().driver_data<nes_state>();
2559   LOG_MMC(("dxrom_w, offset: %04x, data: %02x\n", offset, data));
2560
2561    if (offset >= 0x2000)
2562      return;
2563
2564   switch (offset & 1)
2565   {
2566      case 1:
2567         switch (state->m_mmc_latch1 & 0x07)
2568         {
2569         case 0: chr2_0(space->machine(), data >> 1, CHRROM); break;
2570         case 1: chr2_2(space->machine(), data >> 1, CHRROM); break;
2571         case 2: chr1_4(space->machine(), data | 0x40, CHRROM); break;
2572         case 3: chr1_5(space->machine(), data | 0x40, CHRROM); break;
2573         case 4: chr1_6(space->machine(), data | 0x40, CHRROM); break;
2574         case 5: chr1_7(space->machine(), data | 0x40, CHRROM); break;
2575         case 6: prg8_89(space->machine(), data); break;
2576         case 7: prg8_ab(space->machine(), data); break;
2577         }
2578         break;
2579      case 0:
2580         state->m_mmc_latch1 = data;
2581         break;
2582   }
2583}
2584
2585
2586/*************************************************************
2587
2588 Namcot 3453 board emulation
2589
2590 Games: Devil Man
2591
2592 These are the same as Namcot 34x3, but with additional mirroring
2593 control
2594
2595 iNES: mapper 154
2596
2597 *************************************************************/
2598
2599static WRITE8_HANDLER( namcot3453_w )
2600{
2601   LOG_MMC(("namcot3453_w, offset: %04x, data: %02x\n", offset, data));
2602
2603   // additional mirroring control when writing to even addresses
2604   if (!(offset & 1))
2605      set_nt_mirroring(space->machine(), BIT(data, 6) ? PPU_MIRROR_HIGH : PPU_MIRROR_LOW);
2606
2607   dxrom_w(space, offset, data);
2608}
2609
2610/*************************************************************
2611
2612 Namcot 3446 board emulation
2613
2614 Games: Digital Devil Monogatari - Megami Tensei
2615
2616 These are similar Namcot 34x3, but different bankswitch capabilities
2617
2618 iNES: mapper 76
2619
2620 *************************************************************/
2621
2622static WRITE8_HANDLER( namcot3446_w )
2623{
2624   nes_state *state = space->machine().driver_data<nes_state>();
2625   LOG_MMC(("namcot3446_w, offset: %04x, data: %02x\n", offset, data));
2626
2627   // NEStopia does not have this!
2628   if (offset >= 0x2000)
2629   {
2630      if (!(offset & 1))
2631         set_nt_mirroring(space->machine(), BIT(data, 0) ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT);
2632      return;
2633   }
2634
2635   switch (offset & 1)
2636   {
2637      case 1:
2638         switch (state->m_mmc_latch1 & 0x07)
2639         {
2640         case 2: chr2_0(space->machine(), data, CHRROM); break;
2641         case 3: chr2_2(space->machine(), data, CHRROM); break;
2642         case 4: chr2_4(space->machine(), data, CHRROM); break;
2643         case 5: chr2_6(space->machine(), data, CHRROM); break;
2644         case 6: BIT(state->m_mmc_latch1, 6) ? prg8_cd(space->machine(), data) : prg8_89(space->machine(), data); break;
2645         case 7: prg8_ab(space->machine(), data); break;
2646         }
2647         break;
2648      case 0:
2649         state->m_mmc_latch1 = data;
2650         break;
2651   }
2652}
2653
2654/*************************************************************
2655
2656 Namcot 3425 board emulation
2657
2658 Games: Dragon Buster
2659
2660 These are similar Namcot 34x3, but with NT mirroring (two
2661 different modes)
2662
2663 iNES: mapper 95
2664
2665 *************************************************************/
2666
2667static WRITE8_HANDLER( namcot3425_w )
2668{
2669   nes_state *state = space->machine().driver_data<nes_state>();
2670   UINT8 mode;
2671   LOG_MMC(("namcot3425_w, offset: %04x, data: %02x\n", offset, data));
2672   if (offset >= 0x2000)
2673      return;
2674
2675   switch (offset & 1)
2676   {
2677      case 1:
2678         mode = state->m_mmc_latch1 & 0x07;
2679         switch (mode)
2680         {
2681         case 0: chr2_0(space->machine(), data >> 1, CHRROM); break;
2682         case 1: chr2_2(space->machine(), data >> 1, CHRROM); break;
2683         case 2:
2684         case 3:
2685         case 4:
2686         case 5:
2687            chr1_x(space->machine(), 2 + mode, data, CHRROM);
2688            state->m_mmc_reg[mode - 2] = BIT(data, 5);
2689            if (!BIT(state->m_mmc_latch1, 7))
2690            {
2691                  set_nt_page(space->machine(), 0, CIRAM, state->m_mmc_reg[0], 1);
2692                  set_nt_page(space->machine(), 1, CIRAM, state->m_mmc_reg[1], 1);
2693                  set_nt_page(space->machine(), 2, CIRAM, state->m_mmc_reg[2], 1);
2694                  set_nt_page(space->machine(), 3, CIRAM, state->m_mmc_reg[3], 1);
2695            }
2696            else
2697               set_nt_mirroring(space->machine(), PPU_MIRROR_HORZ);
2698            break;
2699         case 6: prg8_89(space->machine(), data); break;
2700         case 7: prg8_ab(space->machine(), data); break;
2701         }
2702         break;
2703      case 0:
2704         state->m_mmc_latch1 = data;
2705         break;
2706   }
2707}
2708
2709/*************************************************************
2710
2711 Discrete Logic board IC 74x377 by Color Dreams / Nina-007 emulation
2712
2713 Games: many Color Dreams and Wisdom Tree titles
2714
2715 iNES: mapper 11
2716
2717 In MESS: Supported
2718
2719 *************************************************************/
2720
2721static WRITE8_HANDLER( dis_74x377_w )
2722{
2723   nes_state *state = space->machine().driver_data<nes_state>();
2724   LOG_MMC(("dis_74x377_w, offset: %04x, data: %02x\n", offset, data));
2725
2726   chr8(space->machine(), data >> 4, state->m_mmc_chr_source);
2727   prg32(space->machine(), data & 0x0f);
2728}
2729
2730/*************************************************************
2731
2732 Discrete Logic board IC 74x139x74 by Konami & Jaleco
2733
2734 iNES: mapper 87
2735
2736 *************************************************************/
2737
2738static WRITE8_HANDLER( dis_74x139x74_m_w )
2739{
2740   LOG_MMC(("dis_74x139x74_m_w, offset: %04x, data: %02x\n", offset, data));
2741
2742   chr8(space->machine(), ((data & 0x02) >> 1) | ((data & 0x01) << 1), CHRROM);
2743}
2744
2745/*************************************************************
2746
2747 Discrete Logic board IC 74x161x138
2748
2749 Games: Crime Busters
2750
2751 iNES: mapper 38
2752
2753 *************************************************************/
2754
2755static WRITE8_HANDLER( dis_74x161x138_m_w )
2756{
2757   LOG_MMC(("dis_74x161x138_m_w, offset: %04x, data: %02x\n", offset, data));
2758
2759   chr8(space->machine(), data >> 2, CHRROM);
2760   prg32(space->machine(), data);
2761}
2762
2763/*************************************************************
2764
2765 Discrete Logic board IC 74x161x161x32
2766
2767 There are two variants (one with hardwired mirroring, the
2768 other with a mirroring control), making necessary two distinct
2769 mappers & pcb_id
2770
2771 iNES: mappers 70 & 152
2772
2773 *************************************************************/
2774
2775static WRITE8_HANDLER( dis_74x161x161x32_w )
2776{
2777   nes_state *state = space->machine().driver_data<nes_state>();
2778   LOG_MMC(("dis_74x161x161x32_w, offset: %04x, data: %02x\n", offset, data));
2779
2780   if (!state->m_hard_mirroring)   // there are two 'variants' depending on hardwired or mapper ctrl mirroring
2781      set_nt_mirroring(space->machine(), BIT(data, 7) ? PPU_MIRROR_HIGH : PPU_MIRROR_LOW);
2782   chr8(space->machine(), data, CHRROM);
2783   prg16_89ab(space->machine(), data >> 4);
2784}
2785
2786/*************************************************************
2787
2788 Bandai LZ93D50 boards emulation
2789
2790 There are several variants: plain board with or without SRAM,
2791 board + 24C01 EEPROM, board + 24C02 EEPROM, board + Barcode
2792 Reader (DATACH).
2793 We currently only emulate the base hardware.
2794
2795 Games: Crayon Shin-Chan - Ora to Poi Poi, Dragon Ball Z Gaiden,
2796 Dragon Ball Z II & III, Rokudenashi Blues, SD Gundam
2797 Gaiden - KGM2, Dragon Ball Z, Magical Taruruuto-kun, SD Gundam
2798 Gaiden [with EEPROM], Dragon Ball, Dragon Ball 3, Famicom Jump,
2799 Famicom Jump II [no EEPROM], Datach Games
2800
2801 At the moment, we don't support EEPROM I/O
2802
2803 iNES: mappers 16, 153, 157 & 159
2804
2805 In MESS: Supported
2806
2807 *************************************************************/
2808
2809/* Here, IRQ counter decrements every CPU cycle. Since we update it every scanline,
2810 we need to decrement it by 114 (Each scanline consists of 341 dots and, on NTSC,
2811 there are 3 dots to every 1 CPU cycle, hence 114 is the number of cycles per scanline ) */
2812static void bandai_lz_irq( device_t *device, int scanline, int vblank, int blanked )
2813{
2814   nes_state *state = device->machine().driver_data<nes_state>();
2815
2816   /* 114 is the number of cycles per scanline */
2817   /* TODO: change to reflect the actual number of cycles spent */
2818   if (state->m_IRQ_enable)
2819   {
2820      if (state->m_IRQ_count <= 114)
2821      {
2822         device_set_input_line(state->m_maincpu, M6502_IRQ_LINE, HOLD_LINE);
2823         state->m_IRQ_count = (0xffff - 114 + state->m_IRQ_count);   // wrap around the 16 bits counter
2824      }
2825      state->m_IRQ_count -= 114;
2826   }
2827}
2828
2829static WRITE8_HANDLER( lz93d50_w )
2830{
2831   nes_state *state = space->machine().driver_data<nes_state>();
2832   LOG_MMC(("lz93d50_w, offset: %04x, data: %02x\n", offset, data));
2833
2834   switch (offset & 0x000f)
2835   {
2836      case 0: case 1: case 2: case 3:
2837      case 4: case 5: case 6: case 7:
2838         chr1_x(space->machine(), offset & 0x07, data, state->m_mmc_chr_source);
2839         break;
2840      case 8:
2841         prg16_89ab(space->machine(), data);
2842         break;
2843      case 9:
2844         switch (data & 0x03)
2845         {
2846         case 0: set_nt_mirroring(space->machine(), PPU_MIRROR_VERT); break;
2847         case 1: set_nt_mirroring(space->machine(), PPU_MIRROR_HORZ); break;
2848         case 2: set_nt_mirroring(space->machine(), PPU_MIRROR_LOW); break;
2849         case 3: set_nt_mirroring(space->machine(), PPU_MIRROR_HIGH); break;
2850         }
2851         break;
2852      case 0x0a:
2853         state->m_IRQ_enable = data & 0x01;
2854         break;
2855      case 0x0b:
2856         state->m_IRQ_count = (state->m_IRQ_count & 0xff00) | data;
2857         break;
2858      case 0x0c:
2859         state->m_IRQ_count = (state->m_IRQ_count & 0x00ff) | (data << 8);
2860         break;
2861      default:
2862         logerror("lz93d50_w uncaught write, offset: %04x, data: %02x\n", offset, data);
2863         break;
2864   }
2865}
2866
2867static WRITE8_HANDLER( lz93d50_m_w )
2868{
2869   nes_state *state = space->machine().driver_data<nes_state>();
2870   LOG_MMC(("lz93d50_m_w, offset: %04x, data: %02x\n", offset, data));
2871
2872   if (!state->m_battery && !state->m_wram)
2873      lz93d50_w(space, offset & 0x0f, data);
2874   else if (state->m_battery)
2875      state->m_battery_ram[offset] = data;
2876   else
2877      state->m_wram[offset] = data;
2878}
2879
2880static void fjump2_set_prg( running_machine &machine )
2881{
2882   nes_state *state = machine.driver_data<nes_state>();
2883   UINT8 mmc_helper = 0;
2884   int i;
2885
2886   for (i = 0; i < 8; i++)
2887      mmc_helper |= ((state->m_mmc_reg[i] & 0x01) << 4);
2888
2889   prg16_89ab(machine, mmc_helper | state->m_mmc_latch1);
2890   prg16_cdef(machine, mmc_helper | 0x0f);
2891}
2892
2893static WRITE8_HANDLER( fjump2_w )
2894{
2895   nes_state *state = space->machine().driver_data<nes_state>();
2896   LOG_MMC(("fjump2_w, offset: %04x, data: %02x\n", offset, data));
2897
2898   switch (offset & 0x000f)
2899   {
2900      case 0: case 1: case 2: case 3:
2901      case 4: case 5: case 6: case 7:
2902         state->m_mmc_reg[offset & 0x000f] = data;
2903         fjump2_set_prg(space->machine());
2904         break;
2905      case 8:
2906         state->m_mmc_latch1 = (data & 0x0f);
2907         fjump2_set_prg(space->machine());
2908         break;
2909      default:
2910         lz93d50_m_w(space, offset & 0x0f, data);
2911         break;
2912   }
2913}
2914
2915/*************************************************************
2916
2917 Bandai Karaoke Studio board emulation
2918
2919 Games: Karaoke Studio
2920
2921 Note: we currently do not emulate the mic
2922
2923 iNES: mapper 188
2924
2925 *************************************************************/
2926
2927static WRITE8_HANDLER( bandai_ks_w )
2928{
2929   LOG_MMC(("bandai_ks_w, offset: %04x, data: %02x\n", offset, data));
2930
2931   prg16_89ab(space->machine(), data ^ 0x08);
2932}
2933
2934/*************************************************************
2935
2936 Bandai Oeka Kids board emulation
2937
2938 Games: Oeka Kids - Anpanman no Hiragana Daisuki, Oeka
2939 Kids - Anpanman to Oekaki Shiyou!!
2940
2941 iNES: mapper 96
2942
2943 In MESS: Preliminary Support.
2944
2945 *************************************************************/
2946
2947static WRITE8_HANDLER( bandai_ok_w )
2948{
2949   nes_state *state = space->machine().driver_data<nes_state>();
2950   UINT8 mmc_helper;
2951   LOG_MMC(("mapper96_w, offset: %04x, data: %02x\n", offset, data));
2952
2953   prg32(space->machine(), data);
2954
2955   state->m_mmc_latch1 = data;
2956   mmc_helper = (state->m_mmc_latch1 & 0x03) | (data & 0x04);
2957   chr4_0(space->machine(), mmc_helper, CHRRAM);
2958   chr4_4(space->machine(), 0x03 | (data & 0x04), CHRRAM);
2959}
2960
2961/*************************************************************
2962
2963 Irem LROG017 - Discrete board emulation (74*161/161/21/138)
2964
2965 Games: Napoleon Senki
2966
2967 iNES: mapper 77
2968
2969 *************************************************************/
2970
2971static WRITE8_HANDLER( lrog017_w )
2972{
2973   LOG_MMC(("lrog017_w, offset: %04x, data: %02x\n", offset, data));
2974
2975   prg32(space->machine(), data);
2976   chr2_0(space->machine(), (data >> 4), CHRROM);
2977}
2978
2979/*************************************************************
2980
2981 Irem Holy Diver board emulation
2982
2983 iNES: mapper 78 (shared with JF-16)
2984
2985 *************************************************************/
2986
2987static WRITE8_HANDLER( irem_hd_w )
2988{
2989   LOG_MMC(("irem_hd_w, offset: %04x, data: %02x\n", offset, data));
2990
2991   set_nt_mirroring(space->machine(), BIT(data, 3) ? PPU_MIRROR_VERT : PPU_MIRROR_HORZ);
2992   chr8(space->machine(), data >> 4, CHRROM);
2993   prg16_89ab(space->machine(), data);
2994}
2995
2996/*************************************************************
2997
2998 Irem TAM-S1 board emulation
2999
3000 Games: Kaiketsu Yanchamaru
3001
3002 iNES: mapper 97
3003
3004 In MESS: Supported.
3005
3006 *************************************************************/
3007
3008static WRITE8_HANDLER( tam_s1_w )
3009{
3010   LOG_MMC(("tam_s1_w, offset: %04x, data: %02x\n", offset, data));
3011
3012   if (offset < 0x4000)
3013   {
3014      set_nt_mirroring(space->machine(), BIT(data, 7) ? PPU_MIRROR_VERT : PPU_MIRROR_HORZ);
3015      prg16_cdef(space->machine(), data);
3016   }
3017}
3018
3019/*************************************************************
3020
3021 Irem G-101 board emulation
3022
3023 Major League uses hardwired mirroring
3024
3025 iNES: mapper 32
3026
3027 *************************************************************/
3028
3029static WRITE8_HANDLER( g101_w )
3030{
3031   nes_state *state = space->machine().driver_data<nes_state>();
3032   LOG_MMC(("g101_w, offset: %04x, data: %02x\n", offset, data));
3033
3034   switch (offset & 0x7000)
3035   {
3036      case 0x0000:
3037         // NEStopia here differs a little bit
3038         state->m_mmc_latch1 ? prg8_cd(space->machine(), data) : prg8_89(space->machine(), data);
3039         break;
3040      case 0x1000:
3041         state->m_mmc_latch1 = BIT(data, 1);
3042         if (!state->m_hard_mirroring)   // there are two 'variants' depending on hardwired or mapper ctrl mirroring
3043            set_nt_mirroring(space->machine(), BIT(data, 0) ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT);
3044         break;
3045      case 0x2000:
3046         prg8_ab(space->machine(), data);
3047         break;
3048      case 0x3000:
3049         chr1_x(space->machine(), offset & 0x07, data, CHRROM);
3050         break;
3051   }
3052}
3053
3054/*************************************************************
3055
3056 Irem H-3001 board emulation
3057
3058 Games: Daiku no Gen San 2 - Akage no Dan no Gyakushuu,
3059 Kaiketsu Yanchamaru 3, Spartan X 2
3060
3061 iNES: mapper 65
3062
3063 In MESS: Supported.
3064
3065 *************************************************************/
3066
3067/* Here, IRQ counter decrements every CPU cycle. Since we update it every scanline,
3068 we need to decrement it by 114 (Each scanline consists of 341 dots and, on NTSC,
3069 there are 3 dots to every 1 CPU cycle, hence 114 is the number of cycles per scanline ) */
3070static void h3001_irq( device_t *device, int scanline, int vblank, int blanked )
3071{
3072   nes_state *state = device->machine().driver_data<nes_state>();
3073   if (state->m_IRQ_enable)
3074   {
3075      state->m_IRQ_count -= 114;
3076
3077      if (state->m_IRQ_count <= 114)
3078      {
3079         state->m_IRQ_enable = 0;
3080         device_set_input_line(state->m_maincpu, M6502_IRQ_LINE, HOLD_LINE);
3081      }
3082   }
3083}
3084
3085static WRITE8_HANDLER( h3001_w )
3086{
3087   nes_state *state = space->machine().driver_data<nes_state>();
3088   LOG_MMC(("h3001_w, offset %04x, data: %02x\n", offset, data));
3089
3090   switch (offset & 0x7fff)
3091   {
3092      case 0x0000:
3093         prg8_89(space->machine(), data);
3094         break;
3095
3096      case 0x1001:
3097         set_nt_mirroring(space->machine(), BIT(data, 7) ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT);
3098         break;
3099
3100      case 0x1003:
3101         state->m_IRQ_enable = data & 0x80;
3102         break;
3103
3104      case 0x1004:
3105         state->m_IRQ_count = state->m_IRQ_count_latch;
3106         break;
3107
3108      case 0x1005:
3109         state->m_IRQ_count_latch = (state->m_IRQ_count_latch & 0x00ff) | (data << 8);
3110         break;
3111
3112      case 0x1006:
3113         state->m_IRQ_count_latch = (state->m_IRQ_count_latch & 0xff00) | data;
3114         break;
3115
3116      case 0x2000:
3117         prg8_ab(space->machine(), data);
3118         break;
3119
3120      case 0x3000: case 0x3001: case 0x3002: case 0x3003:
3121      case 0x3004: case 0x3005: case 0x3006: case 0x3007:
3122         chr1_x(space->machine(), offset & 0x07, data, CHRROM);
3123         break;
3124
3125      case 0x4000:
3126         prg8_cd(space->machine(), data);
3127         break;
3128
3129      default:
3130         break;
3131   }
3132}
3133
3134/*************************************************************
3135
3136 Jaleco SS88006 board emulation, aka JF-27, JF-29, JF-30, ...,
3137 JF-38, JF-40, JF-41
3138
3139 Games: Lord of King, Magic John, Moe Pro '90, Ninja Jajamaru,
3140 Pizza Pop, Plasma Ball
3141
3142 iNES: mapper 18
3143
3144 In MESS: Supported
3145
3146 *************************************************************/
3147
3148/* Here, IRQ counter decrements every CPU cycle. Since we update it every scanline,
3149 we need to decrement it by 114 (Each scanline consists of 341 dots and, on NTSC,
3150 there are 3 dots to every 1 CPU cycle, hence 114 is the number of cycles per scanline ) */
3151static void ss88006_irq( device_t *device, int scanline, int vblank, int blanked )
3152{
3153   nes_state *state = device->machine().driver_data<nes_state>();
3154
3155   /* Increment & check the IRQ scanline counter */
3156   if (state->m_IRQ_enable)
3157   {
3158      LOG_MMC(("scanline: %d, irq count: %04x\n", scanline, state->m_IRQ_count));
3159      if (state->m_IRQ_mode & 0x08)
3160      {
3161         if ((state->m_IRQ_count & 0x000f) < 114)   // always true, but we only update the IRQ once per scanlines so we cannot be more precise :(
3162         {
3163            device_set_input_line(state->m_maincpu, M6502_IRQ_LINE, HOLD_LINE);
3164            state->m_IRQ_count = (state->m_IRQ_count & ~0x000f) | (0x0f - (114 & 0x0f) + (state->m_IRQ_count & 0x000f)); // sort of wrap around the counter
3165         }
3166         // decrements should not affect upper bits, so we don't do anything here (114 > 0x0f)
3167      }
3168      else if (state->m_IRQ_mode & 0x04)
3169      {
3170         if ((state->m_IRQ_count & 0x00ff) < 114)
3171         {
3172            device_set_input_line(state->m_maincpu, M6502_IRQ_LINE, HOLD_LINE);
3173            state->m_IRQ_count = (state->m_IRQ_count & ~0x00ff) | (0xff - 114 + (state->m_IRQ_count & 0x00ff));   // wrap around the 8 bits counter
3174         }
3175         else
3176            state->m_IRQ_count -= 114;
3177      }
3178      else if (state->m_IRQ_mode & 0x02)
3179      {
3180         if ((state->m_IRQ_count & 0x0fff)  < 114)
3181         {
3182            device_set_input_line(state->m_maincpu, M6502_IRQ_LINE, HOLD_LINE);
3183            state->m_IRQ_count = (state->m_IRQ_count & ~0x0fff) | (0xfff - 114 + (state->m_IRQ_count & 0x0fff));   // wrap around the 12 bits counter
3184         }
3185         else
3186            state->m_IRQ_count -= 114;
3187      }
3188      else if (state->m_IRQ_count < 114)
3189      {
3190         device_set_input_line(state->m_maincpu, M6502_IRQ_LINE, HOLD_LINE);
3191         state->m_IRQ_count = (0xffff - 114 + state->m_IRQ_count);   // wrap around the 16 bits counter
3192      }
3193      else
3194         state->m_IRQ_count -= 114;
3195   }
3196}
3197
3198static WRITE8_HANDLER( ss88006_w )
3199{
3200   nes_state *state = space->machine().driver_data<nes_state>();
3201   UINT8 bank;
3202   LOG_MMC(("mapper18_w, offset: %04x, data: %02x\n", offset, data));
3203
3204   switch (offset & 0x7003)
3205   {
3206      case 0x0000:
3207         state->m_mmc_prg_bank[0] = (state->m_mmc_prg_bank[0] & 0xf0) | (data & 0x0f);
3208         prg8_89(space->machine(), state->m_mmc_prg_bank[0]);
3209         break;
3210      case 0x0001:
3211         state->m_mmc_prg_bank[0] = (state->m_mmc_prg_bank[0] & 0x0f) | (data << 4);
3212         prg8_89(space->machine(), state->m_mmc_prg_bank[0]);
3213         break;
3214      case 0x0002:
3215         state->m_mmc_prg_bank[1] = (state->m_mmc_prg_bank[1] & 0xf0) | (data & 0x0f);
3216         prg8_ab(space->machine(), state->m_mmc_prg_bank[1]);
3217         break;
3218      case 0x0003:
3219         state->m_mmc_prg_bank[1] = (state->m_mmc_prg_bank[1] & 0x0f) | (data << 4);
3220         prg8_ab(space->machine(), state->m_mmc_prg_bank[1]);
3221         break;
3222      case 0x1000:
3223         state->m_mmc_prg_bank[2] = (state->m_mmc_prg_bank[2] & 0xf0) | (data & 0x0f);
3224         prg8_cd(space->machine(), state->m_mmc_prg_bank[2]);
3225         break;
3226      case 0x1001:
3227         state->m_mmc_prg_bank[2] = (state->m_mmc_prg_bank[2] & 0x0f) | (data << 4);
3228         prg8_cd(space->machine(), state->m_mmc_prg_bank[2]);
3229         break;
3230
3231         /* $9002, 3 (1002, 3) uncaught = Jaleco Baseball writes 0 */
3232         /* believe it's related to battery-backed ram enable/disable */
3233
3234      case 0x2000: case 0x2001: case 0x2002: case 0x2003:
3235      case 0x3000: case 0x3001: case 0x3002: case 0x3003:
3236      case 0x4000: case 0x4001: case 0x4002: case 0x4003:
3237      case 0x5000: case 0x5001: case 0x5002: case 0x5003:
3238         bank = ((offset & 0x7000) - 0x2000) / 0x0800 + ((offset & 0x0002) >> 1);
3239         if (offset & 0x0001)
3240            state->m_mmc_vrom_bank[bank] = (state->m_mmc_vrom_bank[bank] & 0x0f) | ((data & 0x0f)<< 4);
3241         else
3242            state->m_mmc_vrom_bank[bank] = (state->m_mmc_vrom_bank[bank] & 0xf0) | (data & 0x0f);
3243
3244         chr1_x(space->machine(), bank, state->m_mmc_vrom_bank[bank], CHRROM);
3245         break;
3246
3247      case 0x6000:
3248         state->m_IRQ_count_latch = (state->m_IRQ_count_latch & 0xfff0) | (data & 0x0f);
3249         break;
3250      case 0x6001:
3251         state->m_IRQ_count_latch = (state->m_IRQ_count_latch & 0xff0f) | ((data & 0x0f) << 4);
3252         break;
3253      case 0x6002:
3254         state->m_IRQ_count_latch = (state->m_IRQ_count_latch & 0xf0ff) | ((data & 0x0f) << 8);
3255         break;
3256      case 0x6003:
3257         state->m_IRQ_count_latch = (state->m_IRQ_count_latch & 0x0fff) | ((data & 0x0f) << 12);
3258         break;
3259
3260      case 0x7000:
3261         state->m_IRQ_count = state->m_IRQ_count_latch;
3262         break;
3263      case 0x7001:
3264         state->m_IRQ_enable = data & 0x01;
3265         state->m_IRQ_mode = data & 0x0e;
3266         break;
3267
3268      case 0x7002:
3269         switch (data & 0x03)
3270         {
3271         case 0: set_nt_mirroring(space->machine(), PPU_MIRROR_HORZ); break;
3272         case 1: set_nt_mirroring(space->machine(), PPU_MIRROR_VERT); break;
3273         case 2: set_nt_mirroring(space->machine(), PPU_MIRROR_LOW); break;
3274         case 3: set_nt_mirroring(space->machine(), PPU_MIRROR_HIGH); break;
3275         }
3276         break;
3277
3278      default:
3279         logerror("Jaleco SS88006 uncaught write, addr: %04x, value: %02x\n", offset + 0x8000, data);
3280         break;
3281   }
3282}
3283
3284/*************************************************************
3285
3286 Jaleco JF-11, JF-12 & JF-14 boards emulation
3287
3288 Games: Bio Senshi Dan, Mississippi Satsujin Jiken
3289
3290 iNES: mapper 140
3291
3292 In MESS: Supported.
3293
3294 *************************************************************/
3295
3296static WRITE8_HANDLER( jf11_m_w )
3297{
3298   LOG_MMC(("jf11_m_w, offset: %04x, data: %02x\n", offset, data));
3299   chr8(space->machine(), data, CHRROM);
3300   prg32(space->machine(), data >> 4);
3301}
3302
3303/*************************************************************
3304
3305 Jaleco JF-13 board emulation
3306
3307 Games: Moero Pro Yakyuu
3308
3309 Note: we don't emulate the additional sound hardware.
3310
3311 iNES: mapper 86
3312
3313 In MESS: Supported.
3314
3315 *************************************************************/
3316
3317static WRITE8_HANDLER( jf13_m_w )
3318{
3319   LOG_MMC(("jf13_m_w, offset: %04x, data: %02x\n", offset, data));
3320
3321   if (offset == 0)
3322   {
3323      prg32(space->machine(), (data >> 4) & 0x03);
3324      chr8(space->machine(), ((data >> 4) & 0x04) | (data & 0x03), CHRROM);
3325   }
3326
3327   if (offset == 0x1000)
3328   {
3329      LOG_MMC(("Jaleco JF-13 sound write, data: %02x\n", data));
3330      // according to NEStopia, this is the effect
3331      if ((data & 0x30) == 0x20)
3332      {
3333         // send command (data & 0x1f) to sound chip
3334      }
3335   }
3336}
3337
3338/*************************************************************
3339
3340 Jaleco JF-16 board emulation
3341
3342 iNES: mapper 78 (shared with a diff Irem board)
3343
3344 *************************************************************/
3345
3346static WRITE8_HANDLER( jf16_w )
3347{
3348   LOG_MMC(("jf16_w, offset: %04x, data: %02x\n", offset, data));
3349
3350   set_nt_mirroring(space->machine(), BIT(data, 3) ? PPU_MIRROR_HIGH : PPU_MIRROR_LOW);
3351   chr8(space->machine(), data >> 4, CHRROM);
3352   prg16_89ab(space->machine(), data);
3353}
3354
3355/*************************************************************
3356
3357 Jaleco JF-17, JF-26 & JF-28 boards emulation
3358
3359 Note: we don't emulate the additional sound hardware.
3360
3361 Games: Moero!! Juudou Warriors, Moero!! Pro Tennis, Pinball
3362 Quest Jpn
3363
3364 iNES: mapper 72
3365
3366 In MESS: Supported.
3367
3368 *************************************************************/
3369
3370static WRITE8_HANDLER( jf17_w )
3371{
3372   LOG_MMC(("jf17_w, offset: %04x, data: %02x\n", offset, data));
3373
3374   if (BIT(data, 7))
3375      prg16_89ab(space->machine(), data & 0x0f);
3376   if (BIT(data, 6))
3377      chr8(space->machine(), data & 0x0f, CHRROM);
3378   if (BIT(data, 5) && !BIT(data,4))
3379      LOG_MMC(("Jaleco JF-17 sound write, data: %02x\n", data & 0x1f));
3380}
3381
3382/*************************************************************
3383
3384 Jaleco JF-19 & JF-21 boards emulation
3385
3386 Note: we don't emulate the additional sound hardware.
3387
3388 Games: Moero Pro Soccer, Moero Pro Yakyuu '88
3389
3390 iNES: mapper 92
3391
3392 In MESS: Supported (no samples).
3393
3394 *************************************************************/
3395
3396static WRITE8_HANDLER( jf19_w )
3397{
3398   LOG_MMC(("jf19_w, offset: %04x, data: %02x\n", offset, data));
3399
3400   if (BIT(data, 7))
3401      prg16_cdef(space->machine(), data & 0x0f);
3402   if (BIT(data, 6))
3403      chr8(space->machine(), data & 0x0f, CHRROM);
3404   if (BIT(data, 5) && !BIT(data,4))
3405      LOG_MMC(("Jaleco JF-19 sound write, data: %02x\n", data & 0x1f));
3406}
3407
3408/*************************************************************
3409
3410 Konami VRC1 and Jaleco JF20, JF22
3411
3412 Games: Exciting Boxing, Ganbare Goemon!, Tetsuwan Atom
3413
3414 iNES: mapper 75
3415
3416 In MESS: Supported.
3417
3418 *************************************************************/
3419
3420static WRITE8_HANDLER( konami_vrc1_w )
3421{
3422   nes_state *state = space->machine().driver_data<nes_state>();
3423   LOG_MMC(("konami_vrc1_w, offset: %04x, data: %02x\n", offset, data));
3424
3425   switch (offset & 0x7000)
3426   {
3427      case 0x0000:
3428         prg8_89(space->machine(), data);
3429         break;
3430      case 0x1000:
3431         set_nt_mirroring(space->machine(), (data & 0x01) ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT);
3432         state->m_mmc_vrom_bank[0] = (state->m_mmc_vrom_bank[0] & 0x0f) | ((data & 0x02) << 3);
3433         state->m_mmc_vrom_bank[1] = (state->m_mmc_vrom_bank[1] & 0x0f) | ((data & 0x04) << 2);
3434         chr4_0(space->machine(), state->m_mmc_vrom_bank[0], CHRROM);
3435         chr4_4(space->machine(), state->m_mmc_vrom_bank[1], CHRROM);
3436         break;
3437      case 0x2000:
3438         prg8_ab(space->machine(), data);
3439         break;
3440      case 0x4000:
3441         prg8_cd(space->machine(), data);
3442         break;
3443      case 0x6000:
3444         state->m_mmc_vrom_bank[0] = (state->m_mmc_vrom_bank[0] & 0x10) | (data & 0x0f);
3445         chr4_0(space->machine(), state->m_mmc_vrom_bank[0], CHRROM);
3446         break;
3447      case 0x7000:
3448         state->m_mmc_vrom_bank[1] = (state->m_mmc_vrom_bank[1] & 0x10) | (data & 0x0f);
3449         chr4_4(space->machine(), state->m_mmc_vrom_bank[1], CHRROM);
3450         break;
3451   }
3452}
3453
3454/*************************************************************
3455
3456 Konami VRC-2
3457
3458 In MESS: Supported.
3459
3460 *************************************************************/
3461
3462static WRITE8_HANDLER( konami_vrc2_w )
3463{
3464   nes_state *state = space->machine().driver_data<nes_state>();
3465   UINT8 bank, shift, mask;
3466   UINT32 shifted_offs = (offset & 0x7000)
3467                  | ((offset << (9 - state->m_vrc_ls_prg_a)) & 0x200)
3468                  | ((offset << (8 - state->m_vrc_ls_prg_b)) & 0x100);
3469   LOG_MMC(("konami_vrc2_w, offset: %04x, data: %02x\n", offset, data));
3470
3471   if (offset < 0x1000)
3472      prg8_89(space->machine(), data);
3473   else if (offset < 0x2000)
3474   {
3475      switch (data & 0x03)
3476      {
3477         case 0x00: set_nt_mirroring(space->machine(), PPU_MIRROR_VERT); break;
3478         case 0x01: set_nt_mirroring(space->machine(), PPU_MIRROR_HORZ); break;
3479         case 0x02: set_nt_mirroring(space->machine(), PPU_MIRROR_LOW); break;
3480         case 0x03: set_nt_mirroring(space->machine(), PPU_MIRROR_HIGH); break;
3481      }
3482   }
3483   else if (offset < 0x3000)
3484      prg8_ab(space->machine(), data);
3485   else if (offset < 0x7000)
3486   {
3487      bank = ((shifted_offs & 0x7000) - 0x3000) / 0x0800 + BIT(shifted_offs, 9);
3488      shift = BIT(shifted_offs, 8) * 4;
3489      mask = (0xf0 >> shift);
3490      state->m_mmc_vrom_bank[bank] = (state->m_mmc_vrom_bank[bank] & mask)
3491                           | (((data >> state->m_vrc_ls_chr) & 0x0f) << shift);
3492      chr1_x(space->machine(), bank, state->m_mmc_vrom_bank[bank], CHRROM);
3493   }
3494   else
3495      logerror("konami_vrc2_w uncaught write, addr: %04x value: %02x\n", offset + 0x8000, data);
3496}
3497
3498/*************************************************************
3499
3500 Konami VRC3
3501
3502 Games: Salamander
3503
3504 iNES: mapper 73
3505
3506 In MESS: Supported. It also uses konami_irq.
3507
3508 *************************************************************/
3509
3510static WRITE8_HANDLER( konami_vrc3_w )
3511{
3512   LOG_MMC(("konami_vrc3_w, offset: %04x, data: %02x\n", offset, data));
3513   nes_state *state = space->machine().driver_data<nes_state>();
3514
3515   switch (offset & 0x7000)
3516   {
3517      case 0x0000:
3518      case 0x1000:
3519         /* dunno which address controls these */
3520         state->m_IRQ_count_latch = data;
3521         state->m_IRQ_enable_latch = data;
3522         break;
3523      case 0x2000:
3524         state->m_IRQ_enable = data;
3525         break;
3526      case 0x3000:
3527         state->m_IRQ_count &= ~0x0f;
3528         state->m_IRQ_count |= data & 0x0f;
3529         break;
3530      case 0x4000:
3531         state->m_IRQ_count &= ~0xf0;
3532         state->m_IRQ_count |= (data & 0x0f) << 4;
3533         break;
3534      case 0x7000:
3535         prg16_89ab(space->machine(), data);
3536         break;
3537      default:
3538         logerror("konami_vrc3_w uncaught write, offset %04x, data: %02x\n", offset, data);
3539         break;
3540   }
3541}
3542
3543/*************************************************************
3544
3545 Konami VRC-4
3546
3547 In MESS: Supported
3548
3549 *************************************************************/
3550
3551static void vrc4_set_prg( running_machine &machine )
3552{
3553   nes_state *state = machine.driver_data<nes_state>();
3554   if (state->m_mmc_latch1 & 0x02)
3555   {
3556      prg8_89(machine, 0xfe);
3557      prg8_cd(machine, state->m_mmc_prg_bank[0]);
3558   }
3559   else
3560   {
3561      prg8_89(machine, state->m_mmc_prg_bank[0]);
3562      prg8_cd(machine, 0xfe);
3563   }
3564}
3565
3566static void konami_irq( device_t *device, int scanline, int vblank, int blanked )
3567{
3568   nes_state *state = device->machine().driver_data<nes_state>();
3569   /* Increment & check the IRQ scanline counter */
3570   if (state->m_IRQ_enable && (++state->m_IRQ_count == 0x100))
3571   {
3572      state->m_IRQ_count = state->m_IRQ_count_latch;
3573      state->m_IRQ_enable = state->m_IRQ_enable_latch;
3574      device_set_input_line(state->m_maincpu, M6502_IRQ_LINE, HOLD_LINE);
3575   }
3576}
3577
3578static WRITE8_HANDLER( konami_vrc4_w )
3579{
3580   nes_state *state = space->machine().driver_data<nes_state>();
3581   UINT8 bank, shift, mask;
3582   UINT32 shifted_offs = (offset & 0x7000)
3583                  | ((offset << (9 - state->m_vrc_ls_prg_a)) & 0x200)
3584                  | ((offset << (8 - state->m_vrc_ls_prg_b)) & 0x100);
3585   LOG_MMC(("konami_vrc4_w, offset: %04x, data: %02x\n", offset, data));
3586
3587   if (offset < 0x1000)
3588   {
3589      state->m_mmc_prg_bank[0] = data;
3590      vrc4_set_prg(space->machine());
3591   }
3592   else if (offset >= 0x2000 && offset < 0x3000)
3593      prg8_ab(space->machine(), data);
3594   else
3595   {
3596      switch (shifted_offs & 0x7300)
3597      {
3598         case 0x1000:
3599         case 0x1100:
3600            switch (data & 0x03)
3601            {
3602            case 0x00: set_nt_mirroring(space->machine(), PPU_MIRROR_VERT); break;
3603            case 0x01: set_nt_mirroring(space->machine(), PPU_MIRROR_HORZ); break;
3604            case 0x02: set_nt_mirroring(space->machine(), PPU_MIRROR_LOW); break;
3605            case 0x03: set_nt_mirroring(space->machine(), PPU_MIRROR_HIGH); break;
3606            }
3607            break;
3608         case 0x1200:
3609         case 0x1300:
3610            state->m_mmc_latch1 = data & 0x02;
3611            vrc4_set_prg(space->machine());
3612            break;
3613         case 0x3000:
3614         case 0x3100:
3615         case 0x3200:
3616         case 0x3300:
3617         case 0x4000:
3618         case 0x4100:
3619         case 0x4200:
3620         case 0x4300:
3621         case 0x5000:
3622         case 0x5100:
3623         case 0x5200:
3624         case 0x5300:
3625         case 0x6000:
3626         case 0x6100:
3627         case 0x6200:
3628         case 0x6300:
3629            bank = ((shifted_offs & 0x7000) - 0x3000) / 0x0800 + BIT(shifted_offs, 9);
3630            shift = BIT(shifted_offs, 8) * 4;
3631            mask = (0xf0 >> shift);
3632            state->m_mmc_vrom_bank[bank] = (state->m_mmc_vrom_bank[bank] & mask) | ((data & 0x0f) << shift);
3633            chr1_x(space->machine(), bank, state->m_mmc_vrom_bank[bank], CHRROM);
3634            break;
3635         case 0x7000:
3636            state->m_IRQ_count_latch = (state->m_IRQ_count_latch & 0xf0) | (data & 0x0f);
3637            break;
3638         case 0x7100:
3639            state->m_IRQ_count_latch = (state->m_IRQ_count_latch & 0x0f) | ((data & 0x0f) << 4);
3640            break;
3641         case 0x7200:
3642            state->m_IRQ_mode = data & 0x04;   // currently not implemented: 0 = prescaler mode / 1 = CPU mode
3643            state->m_IRQ_enable = data & 0x02;
3644            state->m_IRQ_enable_latch = data & 0x01;
3645            if (data & 0x02)
3646               state->m_IRQ_count = state->m_IRQ_count_latch;
3647            break;
3648         case 0x7300:
3649            state->m_IRQ_enable = state->m_IRQ_enable_latch;
3650            break;
3651         default:
3652            logerror("konami_vrc4_w uncaught write, addr: %04x value: %02x\n", shifted_offs + 0x8000, data);
3653            break;
3654      }
3655   }
3656}
3657
3658/*************************************************************
3659
3660 Konami VRC-6
3661
3662 In MESS: Supported. It also uses konami_irq (there are IRQ
3663 issues though: see Akumajou Densetsu intro).
3664
3665 *************************************************************/
3666
3667static WRITE8_HANDLER( konami_vrc6_w )
3668{
3669   nes_state *state = space->machine().driver_data<nes_state>();
3670   UINT8 bank;
3671   UINT32 shifted_offs = (offset & 0x7000)
3672                  | ((offset << (9 - state->m_vrc_ls_prg_a)) & 0x200)
3673                  | ((offset << (8 - state->m_vrc_ls_prg_b)) & 0x100);
3674   LOG_MMC(("konami_vrc6_w, offset: %04x, data: %02x\n", offset, data));
3675
3676   if (offset < 0x1000)
3677      prg16_89ab(space->machine(), data);
3678   else if (offset >= 0x4000 && offset < 0x5000)
3679      prg8_cd(space->machine(), data);
3680   else
3681   {
3682      switch (shifted_offs & 0x7300)
3683      {
3684         case 0x1000:
3685         case 0x1100:
3686         case 0x1200:
3687         case 0x2000:
3688         case 0x2100:
3689         case 0x2200:
3690         case 0x3000:
3691         case 0x3100:
3692         case 0x3200:
3693            LOG_MMC(("Konami VRC-6 Sound write, offset: %04x, data: %02x\n", shifted_offs & 0x7300, data));
3694            break;
3695         case 0x3300:
3696            switch (data & 0x0c)
3697            {
3698            case 0x00: set_nt_mirroring(space->machine(), PPU_MIRROR_VERT); break;
3699            case 0x04: set_nt_mirroring(space->machine(), PPU_MIRROR_HORZ); break;
3700            case 0x08: set_nt_mirroring(space->machine(), PPU_MIRROR_LOW); break;
3701            case 0x0c: set_nt_mirroring(space->machine(), PPU_MIRROR_HIGH); break;
3702            }
3703            break;
3704         case 0x5000:
3705         case 0x5100:
3706         case 0x5200:
3707         case 0x5300:
3708         case 0x6000:
3709         case 0x6100:
3710         case 0x6200:
3711         case 0x6300:
3712            bank = ((shifted_offs & 0x7000) - 0x5000) / 0x0400 + ((shifted_offs & 0x0300) >> 8);
3713            chr1_x(space->machine(), bank, data, CHRROM);
3714            break;
3715         case 0x7000:
3716            state->m_IRQ_count_latch = data;
3717            break;
3718         case 0x7100:
3719            state->m_IRQ_mode = data & 0x04;   // currently not implemented: 0 = prescaler mode / 1 = CPU mode
3720            state->m_IRQ_enable = data & 0x02;
3721            state->m_IRQ_enable_latch = data & 0x01;
3722            if (data & 0x02)
3723               state->m_IRQ_count = state->m_IRQ_count_latch;
3724            break;
3725         case 0x7200:
3726            state->m_IRQ_enable = state->m_IRQ_enable_latch;
3727            break;
3728         default:
3729            logerror("konami_vrc6_w uncaught write, addr: %04x value: %02x\n", shifted_offs + 0x8000, data);
3730            break;
3731      }
3732   }
3733}
3734
3735/*************************************************************
3736
3737 Konami VRC7
3738
3739 Games: Lagrange Point, Tiny Toon Adventures 2
3740
3741 iNES: mapper 85
3742
3743 In MESS: Supported. It also uses konami_irq.
3744
3745 *************************************************************/
3746
3747static WRITE8_HANDLER( konami_vrc7_w )
3748{
3749   nes_state *state = space->machine().driver_data<nes_state>();
3750   UINT8 bank;
3751   LOG_MMC(("konami_vrc7_w, offset: %04x, data: %02x\n", offset, data));
3752
3753   switch (offset & 0x7018)
3754   {
3755      case 0x0000:
3756         prg8_89(space->machine(), data);
3757         break;
3758      case 0x0008:
3759      case 0x0010:
3760      case 0x0018:
3761         prg8_ab(space->machine(), data);
3762         break;
3763
3764      case 0x1000:
3765         prg8_cd(space->machine(), data);
3766         break;
3767
3768         /* TODO: there are sound regs in here */
3769
3770      case 0x2000:
3771      case 0x2008:
3772      case 0x2010:
3773      case 0x2018:
3774      case 0x3000:
3775      case 0x3008:
3776      case 0x3010:
3777      case 0x3018:
3778      case 0x4000:
3779      case 0x4008:
3780      case 0x4010:
3781      case 0x4018:
3782      case 0x5000:
3783      case 0x5008:
3784      case 0x5010:
3785      case 0x5018:
3786         bank = ((offset & 0x7000) - 0x2000) / 0x0800 + ((offset & 0x0018) ? 1 : 0);
3787         chr1_x(space->machine(), bank, data, state->m_mmc_chr_source);
3788         break;
3789
3790      case 0x6000:
3791         switch (data & 0x03)
3792         {
3793         case 0x00: set_nt_mirroring(space->machine(), PPU_MIRROR_VERT); break;
3794         case 0x01: set_nt_mirroring(space->machine(), PPU_MIRROR_HORZ); break;
3795         case 0x02: set_nt_mirroring(space->machine(), PPU_MIRROR_LOW); break;
3796         case 0x03: set_nt_mirroring(space->machine(), PPU_MIRROR_HIGH); break;
3797         }
3798         break;
3799      case 0x6008: case 0x6010: case 0x6018:
3800         state->m_IRQ_count_latch = data;
3801         break;
3802      case 0x7000:
3803         state->m_IRQ_mode = data & 0x04;   // currently not implemented: 0 = prescaler mode / 1 = CPU mode
3804         state->m_IRQ_enable = data & 0x02;
3805         state->m_IRQ_enable_latch = data & 0x01;
3806         if (data & 0x02)
3807            state->m_IRQ_count = state->m_IRQ_count_latch;
3808         break;
3809      case 0x7008: case 0x7010: case 0x7018:
3810         state->m_IRQ_enable = state->m_IRQ_enable_latch;
3811         break;
3812
3813      default:
3814         logerror("konami_vrc7_w uncaught write, addr: %04x value: %02x\n", offset + 0x8000, data);
3815         break;
3816   }
3817}
3818
3819/*************************************************************
3820
3821 Namcot-163 board emulation
3822
3823 Games: Battle Fleet, Family Circuit '91, Famista '90, '91,
3824 '92 & '94, Megami Tensei II, Top Striker, Wagyan Land 2 & 3
3825
3826 iNES: mapper 19
3827
3828 In MESS: Supported
3829
3830 *************************************************************/
3831
3832/* Here, IRQ counter decrements every CPU cycle. Since we update it every scanline,
3833 we need to decrement it by 114 (Each scanline consists of 341 dots and, on NTSC,
3834 there are 3 dots to every 1 CPU cycle, hence 114 is the number of cycles per scanline ) */
3835static void namcot_irq( device_t *device, int scanline, int vblank, int blanked )
3836{
3837   nes_state *state = device->machine().driver_data<nes_state>();
3838
3839   if (state->m_IRQ_enable)
3840   {
3841      if (state->m_IRQ_count >= (0x7fff - 114))
3842      {
3843         device_set_input_line(state->m_maincpu, M6502_IRQ_LINE, HOLD_LINE);
3844         state->m_IRQ_count = 0;
3845      }
3846      else
3847         state->m_IRQ_count += 114;
3848   }
3849}
3850
3851static WRITE8_HANDLER( namcot163_l_w )
3852{
3853   nes_state *state = space->machine().driver_data<nes_state>();
3854   LOG_MMC(("namcot163_l_w, offset: %04x, data: %02x\n", offset, data));
3855   offset += 0x100;
3856
3857   switch (offset & 0x1800)
3858   {
3859      case 0x0800:
3860         LOG_MMC(("Namcot-163 sound reg write, data: %02x\n", data));
3861         break;
3862      case 0x1000: /* low byte of IRQ */
3863         state->m_IRQ_count = (state->m_IRQ_count & 0x7f00) | data;
3864         break;
3865      case 0x1800: /* high byte of IRQ, IRQ enable in high bit */
3866         state->m_IRQ_count = (state->m_IRQ_count & 0xff) | ((data & 0x7f) << 8);
3867         state->m_IRQ_enable = data & 0x80;
3868         break;
3869   }
3870}
3871
3872static READ8_HANDLER( namcot163_l_r )
3873{
3874   nes_state *state = space->machine().driver_data<nes_state>();
3875   LOG_MMC(("namcot163_l_r, offset: %04x\n", offset));
3876   offset += 0x100;
3877
3878   switch (offset & 0x1800)
3879   {
3880      case 0x1000:
3881         return state->m_IRQ_count & 0xff;
3882      case 0x1800:
3883         return (state->m_IRQ_count >> 8) & 0xff;
3884      case 0x0800:
3885         LOG_MMC(("Namcot-163 sound reg read\n"));
3886      default:
3887         return 0x00;
3888   }
3889}
3890
3891static void namcot163_set_mirror( running_machine &machine, UINT8 page, UINT8 data )
3892{
3893   if (!(data < 0xe0))
3894      set_nt_page(machine, page, CIRAM, data & 0x01, 1);
3895   else
3896      set_nt_page(machine, page, ROM, data, 0);
3897}
3898
3899static WRITE8_HANDLER( namcot163_w )
3900{
3901   nes_state *state = space->machine().driver_data<nes_state>();
3902   LOG_MMC(("namcot163_w, offset: %04x, data: %02x\n", offset, data));
3903   switch (offset & 0x7800)
3904   {
3905      case 0x0000: case 0x0800:
3906      case 0x1000: case 0x1800:
3907      case 0x2000: case 0x2800:
3908      case 0x3000: case 0x3800:
3909         chr1_x(space->machine(), offset / 0x800, data, CHRROM);
3910         break;
3911      case 0x4000:
3912         namcot163_set_mirror(space->machine(), 0, data);
3913         break;
3914      case 0x4800:
3915         namcot163_set_mirror(space->machine(), 1, data);
3916         break;
3917      case 0x5000:
3918         namcot163_set_mirror(space->machine(), 2, data);
3919         break;
3920      case 0x5800:
3921         namcot163_set_mirror(space->machine(), 3, data);
3922         break;
3923      case 0x6000:
3924         prg8_89(space->machine(), data & 0x3f);
3925         break;
3926      case 0x6800:
3927         state->m_mmc_latch1 = data & 0xc0;      // this should enable High CHRRAM, but we still have to properly implement it!
3928         prg8_ab(space->machine(), data & 0x3f);
3929         break;
3930      case 0x7000:
3931         prg8_cd(space->machine(), data & 0x3f);
3932         break;
3933      case 0x7800:
3934         LOG_MMC(("Namcot-163 sound address write, data: %02x\n", data));
3935         break;
3936   }
3937}
3938
3939/*************************************************************
3940
3941 Sunsoft-1 board emulation
3942
3943 Games: Atlantis no Nazo, Kanshakudama Nage Kantarou no
3944 Toukaidou Gojuusan Tsugi, Wing of Madoola, Fantasy Zone
3945
3946 iNES: mapper 184 (Fantasy Zone uses this board with no
3947 CHRROM, and the register switches PRG banks)
3948
3949 *************************************************************/
3950
3951static WRITE8_HANDLER( sunsoft1_m_w )
3952{
3953   nes_state *state = space->machine().driver_data<nes_state>();
3954   LOG_MMC(("sunsoft1_m_w, offset: %04x, data: %02x\n", offset, data));
3955
3956   if (state->m_chr_chunks)
3957   {
3958      chr4_0(space->machine(), data & 0x0f, CHRROM);
3959      chr4_4(space->machine(), data >> 4, CHRROM);
3960   }
3961   else
3962      prg16_89ab(space->machine(), data & 0x0f);
3963}
3964
3965/*************************************************************
3966
3967 Sunsoft-2 board emulation
3968
3969 The two games using this board have incompatible mirroring
3970 wiring, making necessary two distinct mappers & pcb_id
3971
3972 iNES: mapper 89 & 93
3973
3974 *************************************************************/
3975
3976static WRITE8_HANDLER( sunsoft2_w )
3977{
3978   nes_state *state = space->machine().driver_data<nes_state>();
3979   UINT8 sunsoft_helper = (data & 0x07) | ((data & 0x80) ? 0x08 : 0x00);
3980   LOG_MMC(("sunsoft2_w, offset: %04x, data: %02x\n", offset, data));
3981
3982   if (!state->m_hard_mirroring)   // there are two 'variants' depending on hardwired or mapper ctrl mirroring
3983      set_nt_mirroring(space->machine(), BIT(data, 3) ? PPU_MIRROR_HIGH : PPU_MIRROR_LOW);
3984   if (state->m_chr_chunks)
3985      chr8(space->machine(), sunsoft_helper, CHRROM);
3986
3987   prg16_89ab(space->machine(), data >> 4);
3988}
3989
3990/*************************************************************
3991
3992 Sunsoft-3 board emulation
3993
3994 The two games using this board have incompatible mirroring
3995 wiring, making necessary two distinct mappers & pcb_id
3996
3997 iNES: mapper 67
3998
3999 *************************************************************/
4000
4001/* Here, IRQ counter decrements every CPU cycle. Since we update it every scanline,
4002 we need to decrement it by 114 (Each scanline consists of 341 dots and, on NTSC,
4003 there are 3 dots to every 1 CPU cycle, hence 114 is the number of cycles per scanline ) */
4004static void sunsoft3_irq( device_t *device, int scanline, int vblank, int blanked )
4005{
4006   nes_state *state = device->machine().driver_data<nes_state>();
4007
4008   /* TODO: change to reflect the actual number of cycles spent: both using 114 or cycling 114,114,113
4009     produces a 1-line glitch in Fantasy Zone 2: it really requires the counter to be updated each CPU cycle! */
4010   if (state->m_IRQ_enable)
4011   {
4012      if (state->m_IRQ_count <= 114)
4013      {
4014         state->m_IRQ_enable = 0;
4015         state->m_IRQ_count = 0xffff;
4016         device_set_input_line(state->m_maincpu, M6502_IRQ_LINE, HOLD_LINE);
4017      }
4018      else
4019         state->m_IRQ_count -= 114;
4020   }
4021}
4022
4023static WRITE8_HANDLER( sunsoft3_w )
4024{
4025   nes_state *state = space->machine().driver_data<nes_state>();
4026   LOG_MMC(("sunsoft3_w, offset %04x, data: %02x\n", offset, data));
4027
4028   switch (offset & 0x7800)
4029   {
4030      case 0x0800:
4031         chr2_0(space->machine(), data, CHRROM);
4032         break;
4033      case 0x1800:
4034         chr2_2(space->machine(), data, CHRROM);
4035         break;
4036      case 0x2800:
4037         chr2_4(space->machine(), data, CHRROM);
4038         break;
4039      case 0x3800:
4040         chr2_6(space->machine(), data, CHRROM);
4041         break;
4042      case 0x4000:
4043      case 0x4800:
4044         state->m_IRQ_toggle ^= 1;
4045         if (state->m_IRQ_toggle)
4046            state->m_IRQ_count = (state->m_IRQ_count & 0x00ff) | (data << 8);
4047         else
4048            state->m_IRQ_count = (state->m_IRQ_count & 0xff00) | data;
4049         break;
4050      case 0x5800:
4051         state->m_IRQ_enable = BIT(data, 4);
4052         state->m_IRQ_toggle = 0;
4053         break;
4054      case 0x6800:
4055         switch (data & 3)
4056         {
4057         case 0x00: set_nt_mirroring(space->machine(), PPU_MIRROR_VERT); break;
4058         case 0x01: set_nt_mirroring(space->machine(), PPU_MIRROR_HORZ); break;
4059         case 0x02: set_nt_mirroring(space->machine(), PPU_MIRROR_LOW); break;
4060         case 0x03: set_nt_mirroring(space->machine(), PPU_MIRROR_HIGH); break;
4061         }
4062         break;
4063      case 0x7800:
4064         prg16_89ab(space->machine(), data);
4065         break;
4066      default:
4067         LOG_MMC(("sunsoft3_w uncaught write, offset: %04x, data: %02x\n", offset, data));
4068         break;
4069   }
4070}
4071
4072/*************************************************************
4073
4074 Taito TC0190FMC + board emulation
4075
4076 Games: Akira, Bakushou!! Jinsei Gekijou, Don Doko Don,
4077 Insector X, Operation Wolf, Power Blazer, Takeshi no
4078 Sengoku Fuuunji
4079
4080 iNES: mapper 33
4081
4082 In MESS: Supported.
4083
4084 *************************************************************/
4085
4086static WRITE8_HANDLER( tc0190fmc_w )
4087{
4088   LOG_MMC(("tc0190fmc_w, offset: %04x, data: %02x\n", offset, data));
4089
4090   switch (offset & 0x7003)
4091   {
4092      case 0x0000:
4093         set_nt_mirroring(space->machine(), BIT(data, 6) ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT);
4094         prg8_89(space->machine(), data);
4095         break;
4096      case 0x0001:
4097         prg8_ab(space->machine(), data);
4098         break;
4099      case 0x0002:
4100         chr2_0(space->machine(), data, CHRROM);
4101         break;
4102      case 0x0003:
4103         chr2_2(space->machine(), data, CHRROM);
4104         break;
4105      case 0x2000:
4106         chr1_4(space->machine(), data, CHRROM);
4107         break;
4108      case 0x2001:
4109         chr1_5(space->machine(), data, CHRROM);
4110         break;
4111      case 0x2002:
4112         chr1_6(space->machine(), data, CHRROM);
4113         break;
4114      case 0x2003:
4115         chr1_7(space->machine(), data, CHRROM);
4116         break;
4117   }
4118}
4119
4120/*************************************************************
4121
4122 Taito TC0190FMC + PAL16R4 board emulation
4123
4124 Games: Bakushou!! Jinsei Gekijou 3, Bubble Bobble 2,
4125 Captain Saver, Don Doko Don 2, Flintstones, Jetsons
4126
4127 This is basically Mapper 33 + IRQ. Notably, IRQ works the
4128 same as MMC3 irq, BUT latch values are "inverted" (XOR'ed
4129 with 0xff) and there is a little delay (not implemented yet)
4130 We simply use MMC3 IRQ and XOR the value written in the
4131 register 0xc000 below
4132
4133 iNES: mapper 48
4134
4135 In MESS: Supported.
4136
4137 *************************************************************/
4138
4139static WRITE8_HANDLER( tc0190fmc_p16_w )
4140{
4141   nes_state *state = space->machine().driver_data<nes_state>();
4142   LOG_MMC(("tc0190fmc_p16_w, offset: %04x, data: %02x\n", offset, data));
4143
4144   switch (offset & 0x7003)
4145   {
4146      case 0x0000:
4147         prg8_89(space->machine(), data);
4148         break;
4149      case 0x0001:
4150      case 0x0002:
4151      case 0x0003:
4152      case 0x2000:
4153      case 0x2001:
4154      case 0x2002:
4155      case 0x2003:
4156         tc0190fmc_w(space, offset, data);
4157         break;
4158      case 0x4000:
4159         state->m_IRQ_count_latch = (0x100 - data) & 0xff;
4160         break;
4161      case 0x4001:
4162         state->m_IRQ_count = state->m_IRQ_count_latch;
4163         break;
4164      case 0x4002:
4165         state->m_IRQ_enable = 1;
4166         break;
4167      case 0x4003:
4168         state->m_IRQ_enable = 0;
4169         break;
4170      case 0x6000:
4171         set_nt_mirroring(space->machine(), BIT(data, 6) ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT);
4172         break;
4173   }
4174}
4175
4176/*************************************************************
4177
4178 Taito X1-005 board emulation
4179
4180 Actually, Fudou Myouou Den uses a variant of the board with
4181 CIRAM, making necessary two distinct mappers & pcb_id.
4182
4183 Also, we miss to emulate the security check at 0x7ef8 / 0x7ef9
4184 and the 0x80 ram!
4185
4186 iNES: mappers 80 & 207
4187
4188 *************************************************************/
4189
4190static WRITE8_HANDLER( x1005_m_w )
4191{
4192   nes_state *state = space->machine().driver_data<nes_state>();
4193   LOG_MMC(("x1005_m_w, offset: %04x, data: %02x\n", offset, data));
4194
4195   switch (offset)
4196   {
4197      case 0x1ef0:
4198         chr2_0(space->machine(), (data & 0x7f) >> 1, CHRROM);
4199         break;
4200      case 0x1ef1:
4201         chr2_2(space->machine(), (data & 0x7f) >> 1, CHRROM);
4202         break;
4203      case 0x1ef2:
4204         chr1_4(space->machine(), data, CHRROM);
4205         break;
4206      case 0x1ef3:
4207         chr1_5(space->machine(), data, CHRROM);
4208         break;
4209      case 0x1ef4:
4210         chr1_6(space->machine(), data, CHRROM);
4211         break;
4212      case 0x1ef5:
4213         chr1_7(space->machine(), data, CHRROM);
4214         break;
4215      case 0x1ef6:
4216      case 0x1ef7:
4217         set_nt_mirroring(space->machine(), BIT(data, 0) ? PPU_MIRROR_VERT : PPU_MIRROR_HORZ);
4218         break;
4219      case 0x1ef8:
4220      case 0x1ef9:
4221         state->m_mmc_latch1 = data;
4222         break;
4223      case 0x1efa:
4224      case 0x1efb:
4225         prg8_89(space->machine(), data);
4226         break;
4227      case 0x1efc:
4228      case 0x1efd:
4229         prg8_ab(space->machine(), data);
4230         break;
4231      case 0x1efe:
4232      case 0x1eff:
4233         prg8_cd(space->machine(), data);
4234         break;
4235      default:
4236         logerror("mapper80_m_w uncaught addr: %04x, value: %02x\n", offset + 0x6000, data);
4237         break;
4238   }
4239
4240   if (offset >= 0x1f00 && state->m_mapper_ram != NULL && state->m_mmc_latch1 == 0xa3)
4241      state->m_mapper_ram[offset & (state->m_mapper_ram_size - 1)] = data;
4242   else if (offset >= 0x1f00 && state->m_mapper_bram != NULL && state->m_mmc_latch1 == 0xa3)
4243      state->m_mapper_bram[offset & (state->m_mapper_bram_size - 1)] = data;
4244}
4245
4246static READ8_HANDLER( x1005_m_r )
4247{
4248   nes_state *state = space->machine().driver_data<nes_state>();
4249   LOG_MMC(("x1005a_m_r, offset: %04x\n", offset));
4250
4251   if (offset >= 0x1f00 && state->m_mapper_ram != NULL && state->m_mmc_latch1 == 0xa3)
4252      return state->m_mapper_ram[offset & (state->m_mapper_ram_size - 1)];
4253   else if (offset >= 0x1f00 && state->m_mapper_bram != NULL && state->m_mmc_latch1 == 0xa3)
4254      return state->m_mapper_bram[offset & (state->m_mapper_bram_size - 1)];
4255
4256   return 0xff;
4257}
4258
4259static WRITE8_HANDLER( x1005a_m_w )
4260{
4261   LOG_MMC(("x1005a_m_w, offset: %04x, data: %02x\n", offset, data));
4262
4263   // similar to x1005_m_w but mirroring is handled differently
4264   if (offset == 0x1ef6 || offset == 0x1ef7)
4265      return;
4266
4267   switch (offset)
4268   {
4269      case 0x1ef0:
4270         set_nt_page(space->machine(), 0, CIRAM, (data & 0x80) ? 1 : 0, 1);
4271         set_nt_page(space->machine(), 1, CIRAM, (data & 0x80) ? 1 : 0, 1);
4272         break;
4273      case 0x1ef1:
4274         set_nt_page(space->machine(), 2, CIRAM, (data & 0x80) ? 1 : 0, 1);
4275         set_nt_page(space->machine(), 3, CIRAM, (data & 0x80) ? 1 : 0, 1);
4276         break;
4277   }
4278
4279   x1005_m_w(space, offset, data);
4280}
4281
4282/*************************************************************
4283
4284 Taito X1-017 board emulation
4285
4286 We miss to emulate the security check at 0x6000-0x73ff
4287 and the ram!
4288
4289 Games: Kyuukyoku Harikiri Koushien, Kyuukyoku Harikiri
4290 Stadium, SD Keiji - Blader
4291
4292 iNES: mapper 82
4293
4294 In MESS: Supported.
4295
4296 *************************************************************/
4297
4298static void x1017_set_chr( running_machine &machine )
4299{
4300   nes_state *state = machine.driver_data<nes_state>();
4301   if (state->m_mmc_latch1)
4302   {
4303      chr2_4(machine, state->m_mmc_vrom_bank[0] >> 1, CHRROM);
4304      chr2_6(machine, state->m_mmc_vrom_bank[1] >> 1, CHRROM);
4305   }
4306   else
4307   {
4308      chr2_0(machine, state->m_mmc_vrom_bank[0] >> 1, CHRROM);
4309      chr2_2(machine, state->m_mmc_vrom_bank[1] >> 1, CHRROM);
4310   }
4311   chr1_x(machine, 4 ^ state->m_mmc_latch1, state->m_mmc_vrom_bank[2], CHRROM);
4312   chr1_x(machine, 5 ^ state->m_mmc_latch1, state->m_mmc_vrom_bank[3], CHRROM);
4313   chr1_x(machine, 6 ^ state->m_mmc_latch1, state->m_mmc_vrom_bank[4], CHRROM);
4314   chr1_x(machine, 7 ^ state->m_mmc_latch1, state->m_mmc_vrom_bank[5], CHRROM);
4315}
4316
4317static WRITE8_HANDLER( x1017_m_w )
4318{
4319   nes_state *state = space->machine().driver_data<nes_state>();
4320   UINT8 reg = offset & 0x07;
4321   LOG_MMC(("x1017_m_w, offset: %04x, data: %02x\n", offset, data));
4322
4323   switch (offset)
4324   {
4325      case 0x1ef0:
4326      case 0x1ef1:
4327         if (state->m_mmc_vrom_bank[reg] != data)
4328         {
4329            state->m_mmc_vrom_bank[reg] = data;
4330            x1017_set_chr(space->machine());
4331         }
4332         break;
4333      case 0x1ef2:
4334      case 0x1ef3:
4335      case 0x1ef4:
4336      case 0x1ef5:
4337         if (state->m_mmc_vrom_bank[reg] != data)
4338         {
4339            state->m_mmc_vrom_bank[reg] = data;
4340            x1017_set_chr(space->machine());
4341         }
4342         break;
4343      case 0x1ef6:
4344         set_nt_mirroring(space->machine(), BIT(data, 0) ? PPU_MIRROR_VERT : PPU_MIRROR_HORZ);
4345         state->m_mmc_latch1 = ((data & 0x02) << 1);
4346         x1017_set_chr(space->machine());
4347         break;
4348      case 0x1ef7:
4349      case 0x1ef8:
4350      case 0x1ef9:
4351         state->m_mmc_reg[(offset & 0x0f) - 7] = data;
4352         break;
4353      case 0x1efa:
4354         prg8_89(space->machine(), data >> 2);
4355         break;
4356      case 0x1efb:
4357         prg8_ab(space->machine(), data >> 2);
4358         break;
4359      case 0x1efc:
4360         prg8_cd(space->machine(), data >> 2);
4361         break;
4362      default:
4363         logerror("x1017_m_w uncaught write, addr: %04x, value: %02x\n", offset + 0x6000, data);
4364         break;
4365   }
4366}
4367
4368static READ8_HANDLER( x1017_m_r )
4369{
4370   nes_state *state = space->machine().driver_data<nes_state>();
4371   LOG_MMC(("x1017_m_r, offset: %04x\n", offset));
4372
4373   // 2+2+1 KB of Internal RAM can be independently enabled/disabled!
4374   if (offset < 0x0800 && state->m_mapper_bram != NULL && state->m_mmc_reg[0] == 0xca)
4375      return state->m_mapper_bram[offset & (state->m_mapper_bram_size - 1)];
4376   if (offset < 0x1000 && state->m_mapper_bram != NULL && state->m_mmc_reg[1] == 0x69)
4377      return state->m_mapper_bram[offset & (state->m_mapper_bram_size - 1)];
4378   if (offset < 0x1800 && state->m_mapper_bram != NULL && state->m_mmc_reg[2] == 0x84)
4379      return state->m_mapper_bram[offset & (state->m_mapper_bram_size - 1)];
4380
4381   return 0xff;
4382}
4383
4384/*************************************************************
4385
4386      MISC UNLICENSED BOARDS
4387
4388 *************************************************************/
4389
4390/*************************************************************
4391
4392 AGCI 50282 bootleg board emulation
4393
4394 Games: Death Race
4395
4396 iNES: mapper 144
4397
4398 In MESS: Supported.
4399
4400 *************************************************************/
4401
4402static WRITE8_HANDLER( agci_50282_w )
4403{
4404   LOG_MMC(("agci_50282_w, offset: %04x, data: %02x\n", offset, data));
4405
4406   offset += 0x8000;
4407   data |= (space->read_byte(offset) & 1);
4408
4409   chr8(space->machine(), data >> 4, CHRROM);
4410   prg32(space->machine(), data);
4411}
4412
4413/*************************************************************
4414
4415 AVE NINA-001 board emulation
4416
4417 iNES: mapper 34
4418
4419 *************************************************************/
4420
4421static WRITE8_HANDLER( nina01_m_w )
4422{
4423   LOG_MMC(("nina01_m_w, offset: %04x, data: %02x\n", offset, data));
4424
4425   switch (offset)
4426   {
4427      case 0x1ffd:
4428         prg32(space->machine(), data);
4429         break;
4430      case 0x1ffe:
4431         chr4_0(space->machine(), data, CHRROM);
4432         break;
4433      case 0x1fff:
4434         chr4_4(space->machine(), data, CHRROM);
4435         break;
4436   }
4437}
4438
4439/*************************************************************
4440
4441 AVE NINA-003, NINA-006 and MB-91 boards emulation
4442
4443 Games: Krazy Kreatures, Poke Block, Puzzle, Pyramid,
4444 Solitaire, Ultimate League Soccer
4445
4446 iNES: mapper 79
4447
4448 In MESS: Supported.
4449
4450 *************************************************************/
4451
4452static WRITE8_HANDLER( nina06_l_w )
4453{
4454   LOG_MMC(("nina06_l_w, offset: %04x, data: %02x\n", offset, data));
4455
4456   if (!(offset & 0x0100))
4457   {
4458      prg32(space->machine(), data >> 3);
4459      chr8(space->machine(), data, CHRROM);
4460   }
4461}
4462
4463/*************************************************************
4464
4465 Active Entertainment Action 52 board emulation
4466
4467 iNES: mapper 228
4468
4469 *************************************************************/
4470
4471static WRITE8_HANDLER( ae_act52_w )
4472{
4473   int pbank, cbank;
4474   UINT8 pmode;
4475   LOG_MMC(("ae_act52_w, offset: %04x, data: %02x\n", offset, data));
4476
4477   set_nt_mirroring(space->machine(), BIT(offset, 13) ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT);
4478
4479   cbank = (data & 0x03) | ((offset & 0x0f) << 2);
4480   chr8(space->machine(), cbank, CHRROM);
4481
4482   pmode = offset & 0x20;
4483   pbank = (offset & 0x1fc0) >> 6;
4484   if (pmode)
4485   {
4486      prg16_89ab(space->machine(), pbank);
4487      prg16_cdef(space->machine(), pbank);
4488   }
4489   else
4490      prg32(space->machine(), pbank >> 1);
4491}
4492
4493
4494/*************************************************************
4495
4496 C & E Bootleg Board for Decathlon
4497
4498 Games: Decathlon
4499
4500 Pretty simple mapper: writes to 0x8065-0x80a4 set prg32 to
4501 data & 3; writes to 0x80a5-0x80e4 set chr8 to data & 7
4502
4503 iNES: mapper 244
4504
4505 In MESS: Supported.
4506
4507 *************************************************************/
4508
4509static WRITE8_HANDLER( cne_decathl_w )
4510{
4511   LOG_MMC(("cne_decathl_w, offset: %04x, data: %02x\n", offset, data));
4512
4513   if (offset < 0x0065)
4514      return;
4515   if (offset < 0x00a5)
4516   {
4517      prg32(space->machine(), (offset - 0x0065) & 0x03);
4518      return;
4519   }
4520   if (offset < 0x00e5)
4521   {
4522      chr8(space->machine(), (offset - 0x00a5) & 0x07, CHRROM);
4523   }
4524}
4525
4526/*************************************************************
4527
4528 C & E Bootleg Board for Fong Shen Bang
4529
4530 Games: Fong Shen Bang - Zhu Lu Zhi Zhan
4531
4532 Simple mapper: writes to 0x6000-0x67ff set PRG and CHR banks.
4533 Namely, 0x6000->0x6003 select resp. prg8_89, prg8_ab, prg8_cd
4534 and prg8_ef. 0x6004->0x6007 select resp. crh2_0, chr2_2,
4535 chr2_4 and chr2_6. In 0x6800-0x7fff lies WRAM.
4536
4537 iNES: mapper 246
4538
4539 In MESS: Supported.
4540
4541 *************************************************************/
4542
4543static WRITE8_HANDLER( cne_fsb_m_w )
4544{
4545   nes_state *state = space->machine().driver_data<nes_state>();
4546   LOG_MMC(("cne_fsb_m_w, offset: %04x, data: %02x\n", offset, data));
4547
4548   if (offset < 0x0800)
4549   {
4550      switch (offset & 0x0007)
4551      {
4552         case 0x0000:
4553            prg8_89(space->machine(), data);
4554            break;
4555         case 0x0001:
4556            prg8_ab(space->machine(), data);
4557            break;
4558         case 0x0002:
4559            prg8_cd(space->machine(), data);
4560            break;
4561         case 0x0003:
4562            prg8_ef(space->machine(), data);
4563            break;
4564         case 0x0004:
4565            chr2_0(space->machine(), data, CHRROM);
4566            break;
4567         case 0x0005:
4568            chr2_2(space->machine(), data, CHRROM);
4569            break;
4570         case 0x0006:
4571            chr2_4(space->machine(), data, CHRROM);
4572            break;
4573         case 0x0007:
4574            chr2_6(space->machine(), data, CHRROM);
4575            break;
4576      }
4577   }
4578   else
4579      state->m_battery_ram[offset] = data;
4580}
4581
4582/*************************************************************
4583
4584 C & E Bootleg Board for Sheng Huo Lie Zhuan
4585
4586 Games: Jing Ke Xin Zhuan, Sheng Huo Lie Zhuan
4587
4588 Simple Mapper: writes to 0x4020-0x5fff sets prg32 to
4589 data>>4 and chr8 to data&f. We currently do not map
4590 writes to 0x4020-0x40ff (to do: verify if this produces
4591 issues)
4592
4593 iNES: mapper 240
4594
4595 In MESS: Supported.
4596
4597 *************************************************************/
4598
4599static WRITE8_HANDLER( cne_shlz_l_w )
4600{
4601   LOG_MMC(("cne_shlz_l_w, offset: %04x, data: %02x\n", offset, data));
4602
4603   prg32(space->machine(), data >> 4);
4604   chr8(space->machine(), data & 0x0f, CHRROM);
4605}
4606
4607/*************************************************************
4608
4609 Caltron 6 in 1 Board
4610
4611 Games: 6 in 1 by Caltron
4612
4613 iNES: mapper 41
4614
4615 In MESS: Supported.
4616
4617 *************************************************************/
4618
4619static WRITE8_HANDLER( caltron6in1_m_w )
4620{
4621   nes_state *state = space->machine().driver_data<nes_state>();
4622   LOG_MMC(("caltron6in1_m_w, offset: %04x, data: %02x\n", offset, data));
4623
4624   state->m_mmc_latch1 = offset & 0xff;
4625   set_nt_mirroring(space->machine(), BIT(data, 5) ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT);
4626   prg32(space->machine(), offset & 0x07);
4627}
4628
4629static WRITE8_HANDLER( caltron6in1_w )
4630{
4631   nes_state *state = space->machine().driver_data<nes_state>();
4632   LOG_MMC(("caltron6in1_w, offset: %04x, data: %02x\n", offset, data));
4633
4634   if (state->m_mmc_latch1 & 0x04)
4635      chr8(space->machine(), ((state->m_mmc_latch1 & 0x18) >> 1) | (data & 0x03), CHRROM);
4636}
4637
4638/*************************************************************
4639
4640 Camerica Boards (BF9093, BF9097, BF909X, ALGNV11)
4641
4642 Games: Linus Spacehead's Cosmic Crusade, Micro Machines,
4643 Mig-29, Stunt Kids
4644
4645 To emulate NT mirroring for BF9097 board (missing in BF9093)
4646 we use crc_hack, however Fire Hawk is broken (but without
4647 mirroring there would be no helicopter graphics).
4648
4649 iNES: mapper 71
4650
4651 In MESS: Partially Supported.
4652
4653 *************************************************************/
4654
4655static WRITE8_HANDLER( bf9093_w )
4656{
4657   nes_state *state = space->machine().driver_data<nes_state>();
4658   LOG_MMC(("bf9093_w, offset: %04x, data: %02x\n", offset, data));
4659
4660   switch (offset & 0x7000)
4661   {
4662      case 0x0000:
4663      case 0x1000:
4664         if (!state->m_hard_mirroring)
4665            set_nt_mirroring(space->machine(), BIT(data, 4) ? PPU_MIRROR_HIGH : PPU_MIRROR_LOW);
4666         break;
4667      case 0x4000:
4668      case 0x5000:
4669      case 0x6000:
4670      case 0x7000:
4671         prg16_89ab(space->machine(), data);
4672         break;
4673   }
4674}
4675
4676/*************************************************************
4677
4678 Camerica BF9096 & ALGQV11 Boards
4679
4680 Games: Quattro Adventure, Quattro Arcade, Quattro Sports
4681
4682 Writes to 0x8000-0x9fff set prg block to (data&0x18)>>1,
4683 writes to 0xa000-0xbfff set prg page to data&3. selected
4684 prg are: prg16_89ab = block|page, prg_cdef = 3|page.
4685 For more info on the hardware to bypass the NES lockout, see
4686 Kevtris' Camerica Mappers documentation.
4687
4688 iNES: mapper 232
4689
4690 In MESS: Supported.
4691
4692 *************************************************************/
4693
4694static void bf9096_set_prg( running_machine &machine )
4695{
4696   nes_state *state = machine.driver_data<nes_state>();
4697   prg16_89ab(machine, (state->m_mmc_latch2 & 0x03) | ((state->m_mmc_latch1 & 0x18) >> 1));
4698   prg16_cdef(machine, 0x03 | ((state->m_mmc_latch1 & 0x18) >> 1));
4699}
4700
4701static WRITE8_HANDLER( bf9096_w )
4702{
4703   nes_state *state = space->machine().driver_data<nes_state>();
4704   LOG_MMC(("bf9096_w, offset: %04x, data: %02x\n", offset, data));
4705
4706   if (offset < 0x2000)
4707      state->m_mmc_latch1 = data;
4708   else
4709      state->m_mmc_latch2 = data;
4710
4711   bf9096_set_prg(space->machine());
4712}
4713
4714/*************************************************************
4715
4716 Camerica Golden Five board
4717
4718 Games: Pegasus 5 in 1
4719
4720 iNES: mapper 104
4721
4722 In MESS: Supported.
4723
4724 *************************************************************/
4725
4726static WRITE8_HANDLER( golden5_w )
4727{
4728   nes_state *state = space->machine().driver_data<nes_state>();
4729   LOG_MMC(("golden5_w, offset: %04x, data: %02x\n", offset, data));
4730
4731   if (offset < 0x4000)
4732   {
4733      if (data & 0x08)
4734      {
4735         state->m_mmc_prg_bank[0] = ((data & 0x07) << 4) | (state->m_mmc_prg_bank[0] & 0x0f);
4736         prg16_89ab(space->machine(), state->m_mmc_prg_bank[0]);
4737         prg16_cdef(space->machine(), ((data & 0x07) << 4) | 0x0f);
4738      }
4739
4740   }
4741   else
4742   {
4743      state->m_mmc_prg_bank[0] = (state->m_mmc_prg_bank[0] & 0x70) | (data & 0x0f);
4744      prg16_89ab(space->machine(), state->m_mmc_prg_bank[0]);
4745   }
4746}
4747
4748/*************************************************************
4749
4750 Cony Bootleg Board
4751
4752 Games: Dragon Ball Party, Fatal Fury 2, Street Blaster II
4753 Pro, World Heroes 2
4754
4755 iNES: mapper 83
4756
4757 In MESS: Supported.
4758
4759 *************************************************************/
4760
4761static WRITE8_HANDLER( cony_l_w )
4762{
4763   nes_state *state = space->machine().driver_data<nes_state>();
4764   LOG_MMC(("cony_l_w, offset: %04x, data: %02x\n", offset, data));
4765
4766   if (offset >= 0x1000 && offset < 0x1103) // from 0x5100-0x51ff
4767      state->m_mapper83_low_reg[offset & 0x03] = data;
4768}
4769
4770static READ8_HANDLER( cony_l_r )
4771{
4772   nes_state *state = space->machine().driver_data<nes_state>();
4773   LOG_MMC(("cony_l_r, offset: %04x\n", offset));
4774
4775   if (offset == 0x0f00)   // 0x5000
4776   {
4777      // read dipswitch bit! - currently unimplemented
4778   }
4779   if (offset >= 0x1000 && offset < 0x1103) // from 0x5100-0x51ff
4780      return state->m_mapper83_low_reg[offset & 0x03];
4781   else
4782      return 0x00;
4783}
4784
4785static void cony_set_prg( running_machine &machine )
4786{
4787   nes_state *state = machine.driver_data<nes_state>();
4788   prg16_89ab(machine, state->m_mapper83_reg[8] & 0x3f);
4789   prg16_cdef(machine, (state->m_mapper83_reg[8] & 0x30) | 0x0f);
4790}
4791
4792static void cony_set_chr( running_machine &machine )
4793{
4794   nes_state *state = machine.driver_data<nes_state>();
4795   // FIXME: here we emulate at least 3 different boards!!!
4796   // one board switches 1k VROM banks only
4797   // one writes to 0x8000 and then switches 2k VROM banks only
4798   // one writes to 0x831n (n=2,3,4,5) and then switches 2k VROM banks only
4799   // we should split them and possibly document the proper behavior of each variant
4800   if (state->m_mmc_latch1 && !state->m_mmc_latch2)
4801   {
4802      chr2_0(machine, state->m_mapper83_reg[0], CHRROM);
4803      chr2_2(machine, state->m_mapper83_reg[1], CHRROM);
4804      chr2_4(machine, state->m_mapper83_reg[6], CHRROM);
4805      chr2_6(machine, state->m_mapper83_reg[7], CHRROM);
4806   }
4807   else
4808   {
4809      chr1_0(machine, state->m_mapper83_reg[0] | ((state->m_mapper83_reg[8] & 0x30) << 4), CHRROM);
4810      chr1_1(machine, state->m_mapper83_reg[1] | ((state->m_mapper83_reg[8] & 0x30) << 4), CHRROM);
4811      chr1_2(machine, state->m_mapper83_reg[2] | ((state->m_mapper83_reg[8] & 0x30) << 4), CHRROM);
4812      chr1_3(machine, state->m_mapper83_reg[3] | ((state->m_mapper83_reg[8] & 0x30) << 4), CHRROM);
4813      chr1_4(machine, state->m_mapper83_reg[4] | ((state->m_mapper83_reg[8] & 0x30) << 4), CHRROM);
4814      chr1_5(machine, state->m_mapper83_reg[5] | ((state->m_mapper83_reg[8] & 0x30) << 4), CHRROM);
4815      chr1_6(machine, state->m_mapper83_reg[6] | ((state->m_mapper83_reg[8] & 0x30) << 4), CHRROM);
4816      chr1_7(machine, state->m_mapper83_reg[7] | ((state->m_mapper83_reg[8] & 0x30) << 4), CHRROM);
4817   }
4818}
4819
4820static WRITE8_HANDLER( cony_w )
4821{
4822   nes_state *state = space->machine().driver_data<nes_state>();
4823   LOG_MMC(("cony_w, offset: %04x, data: %02x\n", offset, data));
4824
4825   switch (offset)
4826   {
4827      case 0x0000:
4828         state->m_mmc_latch1 = 1;
4829      case 0x3000:
4830      case 0x30ff:
4831      case 0x31ff:
4832         state->m_mapper83_reg[8] = data;
4833         cony_set_prg(space->machine());
4834         cony_set_chr(space->machine());
4835         break;
4836      case 0x0100:
4837         state->m_mmc_reg[0] = data & 0x80;
4838         switch (data & 0x03)
4839         {
4840         case 0:
4841            set_nt_mirroring(space->machine(), PPU_MIRROR_VERT);
4842            break;
4843         case 1:
4844            set_nt_mirroring(space->machine(), PPU_MIRROR_HORZ);
4845            break;
4846         case 2:
4847            set_nt_mirroring(space->machine(), PPU_MIRROR_LOW);
4848            break;
4849         case 3:
4850            set_nt_mirroring(space->machine(), PPU_MIRROR_HIGH);
4851            break;
4852         }
4853         break;
4854      case 0x0200:
4855         state->m_IRQ_count = (state->m_IRQ_count & 0xff00) | data;
4856         break;
4857      case 0x0201:
4858         state->m_IRQ_enable = state->m_mmc_reg[0];
4859         state->m_IRQ_count = (data << 8) | (state->m_IRQ_count & 0xff);
4860         break;
4861      case 0x0300:
4862         prg8_89(space->machine(), data);
4863         break;
4864      case 0x0301:
4865         prg8_ab(space->machine(), data);
4866         break;
4867      case 0x0302:
4868         prg8_cd(space->machine(), data);
4869         break;
4870      case 0x0312:
4871      case 0x0313:
4872      case 0x0314:
4873      case 0x0315:
4874         state->m_mmc_latch2 = 1;
4875      case 0x0310:
4876      case 0x0311:
4877      case 0x0316:
4878      case 0x0317:
4879         state->m_mapper83_reg[offset - 0x0310] = data;
4880         cony_set_chr(space->machine());
4881         break;
4882      case 0x0318:
4883         state->m_mapper83_reg[9] = data;
4884         cony_set_prg(space->machine());
4885         break;
4886   }
4887}
4888
4889/*************************************************************
4890
4891 Board DREAMTECH01
4892
4893 Games: Korean Igo
4894
4895 In MESS: Supported
4896
4897 *************************************************************/
4898
4899static WRITE8_HANDLER( dreamtech_l_w )
4900{
4901   LOG_MMC(("dreamtech_l_w offset: %04x, data: %02x\n", offset, data));
4902   offset += 0x100;
4903
4904   if (offset == 0x1020)   /* 0x5020 */
4905      prg16_89ab(space->machine(), data);
4906}
4907
4908/*************************************************************
4909
4910 Bootleg Board by Fukutake
4911
4912 Games: Study Box
4913
4914 iNES: mapper 186
4915
4916 In MESS: Unsupported.
4917
4918
4919 *************************************************************/
4920
4921static WRITE8_HANDLER( fukutake_l_w )
4922{
4923   nes_state *state = space->machine().driver_data<nes_state>();
4924   LOG_MMC(("fukutake_l_w offset: %04x, data: %02x\n", offset, data));
4925   offset += 0x100;
4926
4927   if (offset >= 0x200 && offset < 0x400)
4928   {
4929      if (offset & 1)
4930         prg16_89ab(space->machine(), data);
4931      else
4932         wram_bank(space->machine(), data >> 6, NES_WRAM);
4933   }
4934   else if (offset >= 0x400 && offset < 0xf00)
4935      state->m_mapper_ram[offset - 0x400] = data;
4936}
4937
4938static READ8_HANDLER( fukutake_l_r )
4939{
4940   nes_state *state = space->machine().driver_data<nes_state>();
4941   LOG_MMC(("fukutake_l_r offset: %04x\n", offset));
4942   offset += 0x100;
4943
4944   if (offset >= 0x200 && offset < 0x400)
4945   {
4946      if (offset == 0x200 || offset == 0x201 || offset == 0x203)
4947         return 0x00;
4948      else if (offset == 0x202)
4949         return 0x40;
4950      else
4951         return 0xff;
4952   }
4953   else if (offset >= 0x400 && offset < 0xf00)
4954      return state->m_mapper_ram[offset - 0x400];
4955
4956   return 0;
4957}
4958
4959/*************************************************************
4960
4961 Bootleg Board by Future Media
4962
4963 Games: Crayon Shin-chan (C), San Guo Zhi 4 - Chi Bi Feng Yun
4964
4965 iNES: mapper 117
4966
4967 In MESS: Unsupported.
4968
4969 *************************************************************/
4970
4971static void futuremedia_irq( device_t *device, int scanline, int vblank, int blanked )
4972{
4973   nes_state *state = device->machine().driver_data<nes_state>();
4974   //  if (scanline < PPU_BOTTOM_VISIBLE_SCANLINE)
4975   {
4976      if (state->m_IRQ_enable && state->m_IRQ_count)
4977      {
4978         state->m_IRQ_count--;
4979         if (!state->m_IRQ_count)
4980            device_set_input_line(state->m_maincpu, M6502_IRQ_LINE, HOLD_LINE);
4981      }
4982   }
4983}
4984
4985static WRITE8_HANDLER( futuremedia_w )
4986{
4987   nes_state *state = space->machine().driver_data<nes_state>();
4988   LOG_MMC(("futuremedia_w, offset: %04x, data: %02x\n", offset, data));
4989
4990   switch (offset)
4991   {
4992      case 0x0000:
4993         prg8_89(space->machine(), data);
4994         break;
4995      case 0x0001:
4996         prg8_ab(space->machine(), data);
4997         break;
4998      case 0x0002:
4999         prg8_cd(space->machine(), data);
5000         break;
5001      case 0x0003:
5002         prg8_ef(space->machine(), data);
5003         break;
5004      case 0x2000:
5005      case 0x2001:
5006      case 0x2002:
5007      case 0x2003:
5008      case 0x2004:
5009      case 0x2005:
5010      case 0x2006:
5011      case 0x2007:
5012         chr1_x(space->machine(), offset & 0x07, data, CHRROM);
5013         break;
5014
5015      case 0x5000:
5016         set_nt_mirroring(space->machine(), BIT(data, 0) ?  PPU_MIRROR_HORZ : PPU_MIRROR_VERT);
5017         break;
5018
5019      case 0x4001:
5020         state->m_IRQ_count_latch = data;
5021         break;
5022      case 0x4002:
5023         // IRQ cleared
5024         break;
5025      case 0x4003:
5026         state->m_IRQ_count = state->m_IRQ_count_latch;
5027         break;
5028      case 0x6000:
5029         state->m_IRQ_enable = data & 0x01;
5030         break;
5031   }
5032}
5033
5034/*************************************************************
5035
5036 Bootleg Board 37017 (?) by Gouder
5037
5038 Games: Street Fighter IV
5039
5040 MMC3 clone. It also requires reads from 0x5000-0x7fff.
5041
5042 iNES: mapper 208
5043
5044 In MESS: Preliminary Support.
5045
5046 *************************************************************/
5047
5048static WRITE8_HANDLER( gouder_sf4_l_w )
5049{
5050   nes_state *state = space->machine().driver_data<nes_state>();
5051   static const UINT8 conv_table[256] =
5052   {
5053      0x59,0x59,0x59,0x59,0x59,0x59,0x59,0x59,0x59,0x49,0x19,0x09,0x59,0x49,0x19,0x09,
5054      0x59,0x59,0x59,0x59,0x59,0x59,0x59,0x59,0x51,0x41,0x11,0x01,0x51,0x41,0x11,0x01,
5055      0x59,0x59,0x59,0x59,0x59,0x59,0x59,0x59,0x59,0x49,0x19,0x09,0x59,0x49,0x19,0x09,
5056      0x59,0x59,0x59,0x59,0x59,0x59,0x59,0x59,0x51,0x41,0x11,0x01,0x51,0x41,0x11,0x01,
5057      0x00,0x10,0x40,0x50,0x00,0x10,0x40,0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
5058      0x08,0x18,0x48,0x58,0x08,0x18,0x48,0x58,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
5059      0x00,0x10,0x40,0x50,0x00,0x10,0x40,0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
5060      0x08,0x18,0x48,0x58,0x08,0x18,0x48,0x58,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
5061      0x59,0x59,0x59,0x59,0x59,0x59,0x59,0x59,0x58,0x48,0x18,0x08,0x58,0x48,0x18,0x08,
5062      0x59,0x59,0x59,0x59,0x59,0x59,0x59,0x59,0x50,0x40,0x10,0x00,0x50,0x40,0x10,0x00,
5063      0x59,0x59,0x59,0x59,0x59,0x59,0x59,0x59,0x58,0x48,0x18,0x08,0x58,0x48,0x18,0x08,
5064      0x59,0x59,0x59,0x59,0x59,0x59,0x59,0x59,0x50,0x40,0x10,0x00,0x50,0x40,0x10,0x00,
5065      0x01,0x11,0x41,0x51,0x01,0x11,0x41,0x51,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
5066      0x09,0x19,0x49,0x59,0x09,0x19,0x49,0x59,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
5067      0x01,0x11,0x41,0x51,0x01,0x11,0x41,0x51,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
5068      0x09,0x19,0x49,0x59,0x09,0x19,0x49,0x59,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
5069   };
5070
5071   LOG_MMC(("gouder_sf4_l_w, offset: %04x, data: %02x\n", offset, data));
5072
5073   if (!(offset < 0x1700))
5074      state->m_mmc_reg[offset & 0x03] = data ^ conv_table[state->m_mmc_reg[4]];
5075   else if (!(offset < 0xf00))
5076      state->m_mmc_reg[4] = data;
5077   else if (!(offset < 0x700))
5078      prg32(space->machine(), ((data >> 3) & 0x02) | (data & 0x01));
5079}
5080
5081static READ8_HANDLER( gouder_sf4_l_r )
5082{
5083   nes_state *state = space->machine().driver_data<nes_state>();
5084   LOG_MMC(("gouder_sf4_l_r, offset: %04x\n", offset));
5085
5086   if (!(offset < 0x1700))
5087      return state->m_mmc_reg[offset & 0x03];
5088
5089   return 0x00;
5090}
5091
5092/* writes to 0x8000-0xffff are like MMC3 but no PRG bankswitch (beacuse it is handled by low writes) */
5093static void gouder_sf4_prg_cb( running_machine &machine, int start, int bank )
5094{
5095   return;
5096}
5097
5098
5099/*************************************************************
5100
5101 Bootleg Board by Henggedianzi
5102
5103 Games: Mei Guo Fu Hao, Shang Gu Shen Jian , Wang Zi Fu
5104 Chou Ji
5105
5106 Writes to 0x8000-0xffff set prg32. Moreover, data&0x20 sets
5107 NT mirroring.
5108
5109 iNES: mapper 177
5110
5111 In MESS: Supported.
5112
5113 *************************************************************/
5114
5115static WRITE8_HANDLER( henggedianzi_w )
5116{
5117   LOG_MMC(("henggedianzi_w, offset: %04x, data: %02x\n", offset, data));
5118
5119   prg32(space->machine(), data);
5120   set_nt_mirroring(space->machine(), BIT(data, 5) ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT);
5121}
5122
5123/*************************************************************
5124
5125 Bootleg Board by Henggedianzi
5126
5127 Games: Xing He Zhan Shi
5128
5129 Writes to 0x5000-0x5fff set prg32 banks, writes to 0x8000-
5130 0xffff set NT mirroring
5131
5132 iNES: mapper 179
5133
5134 In MESS: Supported.
5135
5136 *************************************************************/
5137
5138static WRITE8_HANDLER( heng_xjzb_l_w )
5139{
5140   LOG_MMC(("heng_xjzb_l_w, offset: %04x, data: %02x\n", offset, data));
5141   offset += 0x4100;
5142
5143   if (offset & 0x5000)
5144      prg32(space->machine(), data >> 1);
5145}
5146
5147static WRITE8_HANDLER( heng_xjzb_w )
5148{
5149   LOG_MMC(("heng_xjzb_w, offset: %04x, data: %02x\n", offset, data));
5150
5151   set_nt_mirroring(space->machine(), BIT(data, 0) ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT);
5152}
5153
5154/*************************************************************
5155
5156 Bootleg Board by HES (also used by others)
5157
5158 Games: AV Hanafuda Club, AV Soccer, Papillon, Sidewinder,
5159 Total Funpack
5160
5161 Actually, two variant: one for HES 6-in-1 with mirroring control
5162 and one for AV Soccer and others with hardwired mirroring
5163
5164 iNES: mapper 113
5165
5166 In MESS: Supported.
5167
5168 *************************************************************/
5169
5170static WRITE8_HANDLER( hes6in1_l_w )
5171{
5172   LOG_MMC(("hes6in1_l_w, offset: %04x, data: %02x\n", offset, data));
5173
5174   if (!(offset & 0x100))
5175   {
5176      prg32(space->machine(), (data & 0x38) >> 3);
5177      chr8(space->machine(), (data & 0x07) | ((data & 0x40) >> 3), CHRROM);
5178      set_nt_mirroring(space->machine(), BIT(data, 7) ? PPU_MIRROR_VERT : PPU_MIRROR_HORZ);
5179   }
5180}
5181
5182static WRITE8_HANDLER( hes_l_w )
5183{
5184   LOG_MMC(("hes_l_w, offset: %04x, data: %02x\n", offset, data));
5185
5186   if (!(offset & 0x100))
5187   {
5188      prg32(space->machine(), (data & 0x38) >> 3);
5189      chr8(space->machine(), (data & 0x07) | ((data & 0x40) >> 3), CHRROM);
5190   }
5191}
5192
5193/*************************************************************
5194
5195 Bootleg Board by Hosenkan
5196
5197 Games: Pocahontas, Super Donkey Kong
5198
5199 iNES: mapper 182
5200
5201 In MESS: Supported.
5202
5203 *************************************************************/
5204
5205static WRITE8_HANDLER( hosenkan_w )
5206{
5207   nes_state *state = space->machine().driver_data<nes_state>();
5208   LOG_MMC(("hosenkan_w, offset: %04x, data: %02x\n", offset, data));
5209
5210   switch (offset & 0x7003)
5211   {
5212      case 0x0001:
5213         set_nt_mirroring(space->machine(), BIT(data, 0) ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT);
5214         break;
5215      case 0x2000:
5216         state->m_mmc_latch1 = data;
5217         break;
5218      case 0x4000:
5219         switch (state->m_mmc_latch1)
5220      {
5221         case 0:
5222            chr2_0(space->machine(), data >> 1, CHRROM);
5223            break;
5224         case 1:
5225            chr1_5(space->machine(), data, CHRROM);
5226            break;
5227         case 2:
5228            chr2_2(space->machine(), data >> 1, CHRROM);
5229            break;
5230         case 3:
5231            chr1_7(space->machine(), data, CHRROM);
5232            break;
5233         case 4:
5234            prg8_89(space->machine(), data);
5235            break;
5236         case 5:
5237            prg8_ab(space->machine(), data);
5238            break;
5239         case 6:
5240            chr1_4(space->machine(), data, CHRROM);
5241            break;
5242         case 7:
5243            chr1_6(space->machine(), data, CHRROM);
5244            break;
5245      }
5246         break;
5247      case 0x6003:
5248         if (data)
5249         {
5250            state->m_IRQ_count = data;
5251            state->m_IRQ_enable = 1;
5252         }
5253         else
5254            state->m_IRQ_enable = 0;
5255         break;
5256   }
5257}
5258
5259/*************************************************************
5260
5261 Kaiser Board KS7058
5262
5263 Games: Tui Do Woo Ma Jeung
5264
5265 Writes to 0xf000-0xffff set 4k chr banks. Namely, if
5266 offset&0x80 is 0 the lower 4k are set, if it is 1 the
5267 upper 4k are set.
5268
5269 iNES: mapper 171
5270
5271 In MESS: Supported.
5272
5273 *************************************************************/
5274
5275static WRITE8_HANDLER( ks7058_w )
5276{
5277   LOG_MMC(("ks7058_w, offset: %04x, data: %02x\n", offset, data));
5278
5279   switch (offset & 0x7080)
5280   {
5281      case 0x7000:
5282         chr4_0(space->machine(), data, CHRROM);
5283         break;
5284      case 0x7080:
5285         chr4_4(space->machine(), data, CHRROM);
5286         break;
5287   }
5288}
5289
5290/*************************************************************
5291
5292 Kaiser Board KS7022
5293
5294 Games: 15 in 1
5295
5296 iNES: mapper 175
5297
5298 In MESS: Supported?
5299
5300 *************************************************************/
5301
5302static WRITE8_HANDLER( ks7022_w )
5303{
5304   nes_state *state = space->machine().driver_data<nes_state>();
5305   LOG_MMC(("ks7022_w, offset: %04x, data: %02x\n", offset, data));
5306
5307   if (offset == 0)
5308      set_nt_mirroring(space->machine(), BIT(data, 2) ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT);
5309
5310   if (offset == 0x2000)
5311      state->m_mmc_latch1 = data & 0x0f;
5312}
5313
5314static READ8_HANDLER( ks7022_r )
5315{
5316   nes_state *state = space->machine().driver_data<nes_state>();
5317   LOG_MMC(("ks7022_r, offset: %04x\n", offset));
5318
5319   if (offset == 0x7ffc)
5320   {
5321      chr8(space->machine(), state->m_mmc_latch1, CHRROM);
5322      prg16_89ab(space->machine(), state->m_mmc_latch1);
5323      prg16_cdef(space->machine(), state->m_mmc_latch1);
5324   }
5325
5326   return mmc_hi_access_rom(space->machine(), offset);
5327}
5328
5329/*************************************************************
5330
5331 Kaiser Board KS7032
5332
5333 Games:
5334
5335 iNES:
5336
5337 In MESS:
5338
5339 *************************************************************/
5340
5341static void ks7032_prg_update( running_machine &machine )
5342{
5343   nes_state *state = machine.driver_data<nes_state>();
5344
5345   prg8_67(machine, state->m_mmc_reg[4]);
5346   prg8_89(machine, state->m_mmc_reg[1]);
5347   prg8_ab(machine, state->m_mmc_reg[2]);
5348   prg8_cd(machine, state->m_mmc_reg[3]);
5349}
5350
5351static void ks7032_irq( device_t *device, int scanline, int vblank, int blanked )
5352{
5353   nes_state *state = device->machine().driver_data<nes_state>();
5354
5355   if (state->m_IRQ_enable)
5356   {
5357      if (state->m_IRQ_count >= (0xffff - 114))
5358      {
5359         state->m_IRQ_enable = 0;
5360         state->m_IRQ_count = state->m_IRQ_count_latch;
5361         device_set_input_line(state->m_maincpu, M6502_IRQ_LINE, HOLD_LINE);
5362      }
5363      else
5364         state->m_IRQ_count += 114;
5365   }
5366}
5367
5368static WRITE8_HANDLER( ks7032_w )
5369{
5370   nes_state *state = space->machine().driver_data<nes_state>();
5371   LOG_MMC(("ks7032_w, offset: %04x, data: %02x\n", offset, data));
5372
5373   switch (offset & 0x7000)
5374   {
5375      case 0x0000:
5376         state->m_IRQ_count = (state->m_IRQ_count & 0xfff0) | (data & 0x0f);
5377         break;
5378      case 0x1000:
5379         state->m_IRQ_count = (state->m_IRQ_count & 0xff0f) | ((data & 0x0f) << 4);
5380         break;
5381      case 0x2000:
5382         state->m_IRQ_count = (state->m_IRQ_count & 0xf0ff) | ((data & 0x0f) << 8);
5383         break;
5384      case 0x3000:
5385         state->m_IRQ_count = (state->m_IRQ_count & 0x0fff) | ((data & 0x0f) << 12);
5386         break;
5387      case 0x4000:
5388         state->m_IRQ_enable = 1;
5389         break;
5390      case 0x6000:
5391         state->m_mmc_latch1 = data & 0x07;
5392         break;
5393      case 0x7000:
5394         state->m_mmc_reg[state->m_mmc_latch1] = data;
5395         ks7032_prg_update(space->machine());
5396         break;
5397   }
5398}
5399
5400/*************************************************************
5401
5402 Kaiser Board KS202
5403
5404 Games:
5405
5406 iNES:
5407
5408 In MESS: Supported?
5409
5410 *************************************************************/
5411
5412
5413static WRITE8_HANDLER( ks202_w )
5414{
5415   nes_state *state = space->machine().driver_data<nes_state>();
5416   LOG_MMC(("ks202_w, offset: %04x, data: %02x\n", offset, data));
5417
5418   switch (offset & 0x7000)
5419   {
5420      case 0x0000:
5421         state->m_IRQ_count = (state->m_IRQ_count & 0xfff0) | (data & 0x0f);
5422         break;
5423      case 0x1000:
5424         state->m_IRQ_count = (state->m_IRQ_count & 0xff0f) | ((data & 0x0f) << 4);
5425         break;
5426      case 0x2000:
5427         state->m_IRQ_count = (state->m_IRQ_count & 0xf0ff) | ((data & 0x0f) << 8);
5428         break;
5429      case 0x3000:
5430         state->m_IRQ_count = (state->m_IRQ_count & 0x0fff) | ((data & 0x0f) << 12);
5431         break;
5432      case 0x4000:
5433         state->m_IRQ_enable = 1;
5434         break;
5435      case 0x6000:
5436         state->m_mmc_latch1 = data & 0x07;
5437         break;
5438      case 0x7000:
5439         state->m_mmc_reg[state->m_mmc_latch1] = data;
5440         ks7032_prg_update(space->machine());
5441         switch (offset & 0xc00)
5442         {
5443         case 0x800:
5444            set_nt_mirroring(space->machine(), BIT(data, 0) ? PPU_MIRROR_VERT : PPU_MIRROR_HORZ);
5445            break;
5446         case 0xc00:
5447            chr1_x(space->machine(), offset & 0x07, data, CHRROM);
5448            break;
5449         }
5450         break;
5451   }
5452}
5453
5454/*************************************************************
5455
5456 Kaiser Board KS7017
5457
5458 Games:
5459
5460 iNES:
5461
5462 In MESS: Not working
5463
5464 *************************************************************/
5465
5466static void mmc_fds_irq( device_t *device, int scanline, int vblank, int blanked )
5467{
5468   nes_state *state = device->machine().driver_data<nes_state>();
5469
5470   if (state->m_IRQ_enable)
5471   {
5472      if (state->m_IRQ_count <= 114)
5473      {
5474         device_set_input_line(state->m_maincpu, M6502_IRQ_LINE, HOLD_LINE);
5475         state->m_IRQ_enable = 0;
5476         state->m_IRQ_status |= 0x01;
5477      }
5478      else
5479         state->m_IRQ_count -= 114;
5480   }
5481}
5482
5483static WRITE8_HANDLER( ks7017_l_w )
5484{
5485   nes_state *state = space->machine().driver_data<nes_state>();
5486   LOG_MMC(("ks7022_w, offset: %04x, data: %02x\n", offset, data));
5487
5488   offset += 0x100;
5489
5490   if (offset >= 0xa00 && offset < 0xb00)
5491      state->m_mmc_latch1 = ((offset >> 2) & 0x03) | ((offset >> 4) & 0x04);
5492
5493   if (offset >= 0x1000 && offset < 0x1100)
5494      prg16_89ab(space->machine(), state->m_mmc_latch1);
5495}
5496
5497WRITE8_HANDLER( ks7017_extra_w )
5498{
5499   nes_state *state = space->machine().driver_data<nes_state>();
5500   LOG_MMC(("ks7017_extra_w, offset: %04x, data: %02x\n", offset, data));
5501
5502   offset += 0x20;
5503
5504   if (offset == 0x0020) /* 0x4020 */
5505      state->m_IRQ_count = (state->m_IRQ_count & 0xff00) | data;
5506
5507   if (offset == 0x0021) /* 0x4021 */
5508      state->m_IRQ_count = (state->m_IRQ_count & 0x00ff) | (data << 8);
5509
5510   if (offset == 0x0025) /* 0x4025 */
5511      set_nt_mirroring(space->machine(), BIT(data, 3) ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT);
5512}
5513
5514READ8_HANDLER( ks7017_extra_r )
5515{
5516   nes_state *state = space->machine().driver_data<nes_state>();
5517   LOG_MMC(("ks7017_extra_r, offset: %04x\n", offset));
5518
5519   state->m_IRQ_status &= ~0x01;
5520   return state->m_IRQ_status;
5521}
5522
5523/*************************************************************
5524
5525 Bootleg Board by Kay (for Panda Prince)
5526
5527 Games: The Panda Prince, Sonic 3d Blast 6, SFZ2 '97, YuYu '97
5528 (and its title hack MK6), UMK3, Super Lion King 2
5529
5530 MMC3 clone. This is basically KOF96 board + protection
5531
5532 iNES: mapper 121
5533
5534 In MESS: Most game works, with some graphical issues.
5535
5536 *************************************************************/
5537
5538static WRITE8_HANDLER( kay_pp_l_w )
5539{
5540   nes_state *state = space->machine().driver_data<nes_state>();
5541   LOG_MMC(("kay_pp_l_w, offset: %04x, data: %02x\n", offset, data));
5542   offset += 0x100;
5543
5544   if (offset >= 0x1000)
5545   {
5546      switch (data & 0x03)
5547      {
5548         case 0x00:
5549         case 0x01:
5550            state->m_mmc_reg[0] = 0x83;
5551            break;
5552         case 0x02:
5553            state->m_mmc_reg[0] = 0x42;
5554            break;
5555         case 0x03:
5556            state->m_mmc_reg[0] = 0x00;
5557            break;
5558      }
5559   }
5560}
5561
5562static READ8_HANDLER( kay_pp_l_r )
5563{
5564   nes_state *state = space->machine().driver_data<nes_state>();
5565   LOG_MMC(("kay_pp_l_r, offset: %04x\n", offset));
5566   offset += 0x100;
5567
5568   if (offset >= 0x1000)
5569      return state->m_mmc_reg[0];
5570   else
5571      return 0xff;
5572}
5573
5574static void kay_pp_update_regs( running_machine &machine )
5575{
5576   nes_state *state = machine.driver_data<nes_state>();
5577
5578   switch (state->m_mmc_reg[5] & 0x3f)
5579   {
5580      case 0x20:
5581      case 0x29:
5582      case 0x2b:
5583      case 0x3f:
5584         state->m_mmc_reg[7] = 1;
5585         state->m_mmc_reg[1] = state->m_mmc_reg[6];
5586         break;
5587      case 0x26:
5588         state->m_mmc_reg[7] = 0;
5589         state->m_mmc_reg[1] = state->m_mmc_reg[6];
5590         break;
5591      case 0x2c:
5592         state->m_mmc_reg[7] = 1;
5593         if (state->m_mmc_reg[6])
5594            state->m_mmc_reg[1] = state->m_mmc_reg[6];
5595         break;
5596
5597      case 0x28:
5598         state->m_mmc_reg[7] = 0;
5599         state->m_mmc_reg[2] = state->m_mmc_reg[6];
5600         break;
5601
5602      case 0x2a:
5603         state->m_mmc_reg[7] = 0;
5604         state->m_mmc_reg[3] = state->m_mmc_reg[6];
5605         break;
5606
5607      case 0x2f:
5608         break;
5609
5610      default:
5611         state->m_mmc_reg[5] = 0;
5612         break;
5613   }
5614}
5615
5616static void kay_pp_prg_cb( running_machine &machine, int start, int bank )
5617{
5618   nes_state *state = machine.driver_data<nes_state>();
5619
5620   if (state->m_mmc_reg[5] & 0x3f)
5621   {
5622      prg8_x(machine, start, bank & 0x3f);
5623      prg8_ef(machine, state->m_mmc_reg[1]);
5624      prg8_cd(machine, state->m_mmc_reg[2]);
5625      prg8_ab(machine, state->m_mmc_reg[3]);
5626   }
5627   else
5628      prg8_x(machine, start, bank & 0x3f);
5629}
5630
5631static void kay_pp_chr_cb( running_machine &machine, int start, int bank, int source )
5632{
5633   nes_state *state = machine.driver_data<nes_state>();
5634   UINT8 chr_page = (state->m_mmc3_latch & 0x80) >> 5;
5635
5636   if ((start & 0x04) == chr_page)
5637      bank |= 0x100;
5638
5639   chr1_x(machine, start, bank, source);
5640}
5641
5642static WRITE8_HANDLER( kay_pp_w )
5643{
5644   nes_state *state = space->machine().driver_data<nes_state>();
5645   LOG_MMC(("kay_pp_w, offset: %04x, data: %02x\n", offset, data));
5646
5647   switch (offset & 0x6003)
5648   {
5649      case 0x0000:
5650         txrom_w(space, offset, data);
5651         mmc3_set_prg(space->machine(), state->m_mmc_prg_base, state->m_mmc_prg_mask);
5652         break;
5653
5654      case 0x0001:
5655         state->m_mmc_reg[6] = (BIT(data, 0) << 5) | (BIT(data, 1) << 4) | (BIT(data, 2) << 3)
5656                        | (BIT(data, 3) << 2) | (BIT(data, 4) << 1) | BIT(data, 5);
5657         if (!state->m_mmc_reg[7])
5658            kay_pp_update_regs(space->machine());
5659         txrom_w(space, offset, data);
5660         mmc3_set_prg(space->machine(), state->m_mmc_prg_base, state->m_mmc_prg_mask);
5661         break;
5662
5663      case 0x0003:
5664         state->m_mmc_reg[5] = data;
5665         kay_pp_update_regs(space->machine());
5666         txrom_w(space, 0x0000, data);
5667         mmc3_set_prg(space->machine(), state->m_mmc_prg_base, state->m_mmc_prg_mask);
5668         break;
5669
5670      default:
5671         txrom_w(space, offset, data);
5672         break;
5673   }
5674}
5675
5676/*************************************************************
5677
5678 Bootleg Board by Kasing
5679
5680 Games: AV Jiu Ji Mahjong, Bao Qing Tian, Thunderbolt 2,
5681 Shisen Mahjong 2
5682
5683 MMC3 clone
5684
5685 iNES: mapper 115
5686
5687 In MESS: Supported
5688
5689 *************************************************************/
5690
5691static void kasing_prg_cb( running_machine &machine, int start, int bank )
5692{
5693   nes_state *state = machine.driver_data<nes_state>();
5694   if (BIT(state->m_mmc_reg[0], 7))
5695      prg32(machine, state->m_mmc_reg[0] >> 1);
5696   else
5697      prg8_x(machine, start, bank);
5698}
5699
5700static WRITE8_HANDLER( kasing_m_w )
5701{
5702   nes_state *state = space->machine().driver_data<nes_state>();
5703   LOG_MMC(("kasing_m_w, offset: %04x, data: %02x\n", offset, data));
5704
5705   switch (offset & 0x01)
5706   {
5707      case 0x00:
5708         state->m_mmc_reg[0] = data;
5709         mmc3_set_prg(space->machine(), state->m_mmc_prg_base, state->m_mmc_prg_mask);
5710         break;
5711      case 0x01:
5712         state->m_mmc_chr_base = (data & 0x01) ? 0x100 : 0x000;
5713         mmc3_set_chr(space->machine(), state->m_mmc_chr_source, state->m_mmc_chr_base, state->m_mmc_chr_mask);
5714         break;
5715   }
5716}
5717
5718/*************************************************************
5719
5720 Bootleg Board by Magic Series
5721
5722 Games: Magic Dragon
5723
5724 Very simple mapper: writes to 0x8000-0xffff set prg32 and chr8
5725 banks
5726
5727 iNES: mapper 107
5728
5729 In MESS: Supported.
5730
5731 *************************************************************/
5732
5733static WRITE8_HANDLER( magics_md_w )
5734{
5735   LOG_MMC(("magics_md_w, offset: %04x, data: %02x\n", offset, data));
5736
5737   prg32(space->machine(), data >> 1);
5738   chr8(space->machine(), data, CHRROM);
5739}
5740
5741/*************************************************************
5742
5743 Bootleg Board by Nanjing
5744
5745 Games: A lot of pirate originals
5746
5747 iNES: mapper 163
5748
5749 In MESS: Unsupported.
5750
5751 *************************************************************/
5752
5753static void nanjing_irq( device_t *device, int scanline, int vblank, int blanked )
5754{
5755   nes_state *state = device->machine().driver_data<nes_state>();
5756
5757   if (BIT(state->m_mmc_reg[0], 7))
5758   {
5759      if (scanline == 127)
5760      {
5761         chr4_0(device->machine(), 1, CHRRAM);
5762         chr4_4(device->machine(), 1, CHRRAM);
5763      }
5764
5765      if (scanline == 239)
5766      {
5767         chr4_0(device->machine(), 0, CHRRAM);
5768         chr4_4(device->machine(), 0, CHRRAM);
5769      }
5770   }
5771
5772}
5773
5774static WRITE8_HANDLER( nanjing_l_w )
5775{
5776   nes_state *state = space->machine().driver_data<nes_state>();
5777   LOG_MMC(("nanjing_l_w, offset: %04x, data: %02x\n", offset, data));
5778
5779   offset += 0x100;
5780
5781   if (offset < 0x1000)
5782      return;
5783
5784   if (offset == 0x1100)   // 0x5100
5785   {
5786      if (data == 6)
5787         prg32(space->machine(), 3);
5788      return;
5789   }
5790
5791   if (offset == 0x1101)   // 0x5101
5792   {
5793      UINT8 temp = state->m_mmc_count;
5794      state->m_mmc_count = data;
5795
5796      if (temp & !data)
5797         state->m_mmc_latch2 ^= 0xff;
5798   }
5799
5800   switch (offset & 0x300)
5801   {
5802      case 0x000:
5803      case 0x200:
5804         state->m_mmc_reg[BIT(offset, 9)] = data;
5805         if (!BIT(state->m_mmc_reg[0], 7) && ppu2c0x_get_current_scanline(state->m_ppu) <= 127)
5806            chr8(space->machine(), 0, CHRRAM);
5807         break;
5808      case 0x300:
5809         state->m_mmc_latch1 = data;
5810         break;
5811   }
5812
5813   prg32(space->machine(), (state->m_mmc_reg[0] & 0x0f) | ((state->m_mmc_reg[1] & 0x0f) << 4));
5814}
5815
5816static READ8_HANDLER( nanjing_l_r )
5817{
5818   nes_state *state = space->machine().driver_data<nes_state>();
5819   UINT8 value = 0;
5820   LOG_MMC(("nanjing_l_r, offset: %04x\n", offset));
5821
5822   offset += 0x100;
5823
5824   if (offset < 0x1000)
5825      return 0;
5826
5827   switch (offset & 0x700)
5828   {
5829      case 0x100:
5830         value = state->m_mmc_latch1;
5831         break;
5832      case 0x500:
5833         value = state->m_mmc_latch2 & state->m_mmc_latch1;
5834         break;
5835      case 0x000:
5836      case 0x200:
5837      case 0x300:
5838      case 0x400:
5839      case 0x600:
5840      case 0x700:
5841         value = 4;
5842         break;
5843   }
5844   return value;
5845}
5846
5847/*************************************************************
5848
5849 Bootleg Board by Nitra
5850
5851 Games: Time Diver Avenger
5852
5853 This acts basically like a MMC3 with different use of write
5854 address.
5855
5856 iNES: mapper 250
5857
5858 In MESS: Supported.
5859
5860 *************************************************************/
5861
5862static WRITE8_HANDLER( nitra_w )
5863{
5864   LOG_MMC(("nitra_w, offset: %04x, data: %02x\n", offset, data));
5865
5866   txrom_w(space, (offset & 0x6000) | ((offset & 0x400) >> 10), offset & 0xff);
5867}
5868
5869/*************************************************************
5870
5871 NTDEC ASDER Bootleg Board
5872
5873 Games: Cobra Mission, Fighting Hero III, Huang Di, Master
5874 Shooter
5875
5876 iNES: mapper 112
5877
5878 In MESS: Supported.
5879
5880 *************************************************************/
5881
5882static WRITE8_HANDLER( ntdec_asder_w )
5883{
5884   nes_state *state = space->machine().driver_data<nes_state>();
5885   LOG_MMC(("ntdec_asder_w, offset: %04x, data: %02x\n", offset, data));
5886
5887   switch (offset)
5888   {
5889      case 0x0000:
5890         state->m_mmc_latch1 = data & 0x07;
5891         break;
5892      case 0x2000:
5893         switch (state->m_mmc_latch1)
5894      {
5895         case 0:
5896            prg8_89(space->machine(), data);
5897            break;
5898         case 1:
5899            prg8_ab(space->machine(), data);
5900            break;
5901         case 2:
5902            data &= 0xfe;
5903            chr1_0(space->machine(), data, CHRROM);
5904            chr1_1(space->machine(), data + 1, CHRROM);
5905            break;
5906         case 3:
5907            data &= 0xfe;
5908            chr1_2(space->machine(), data, CHRROM);
5909            chr1_3(space->machine(), data + 1, CHRROM);
5910            break;
5911         case 4:
5912            chr1_4(space->machine(), data, CHRROM);
5913            break;
5914         case 5:
5915            chr1_5(space->machine(), data, CHRROM);
5916            break;
5917         case 6:
5918            chr1_6(space->machine(), data, CHRROM);
5919            break;
5920         case 7:
5921            chr1_7(space->machine(), data, CHRROM);
5922            break;
5923      }
5924         break;
5925      case 0x6000:
5926         set_nt_mirroring(space->machine(), BIT(data, 0) ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT);
5927         break;
5928   }
5929}
5930
5931/*************************************************************
5932
5933 Bootleg Board by NTDEC for Fighting Hero
5934
5935 Games: Fighting Hero
5936
5937 Very simple mapper: writes to 0x6000-0x7fff swap PRG and
5938 CHR banks.
5939
5940 iNES: mapper 193
5941
5942 In MESS: Supported.
5943
5944 *************************************************************/
5945
5946static WRITE8_HANDLER( ntdec_fh_m_w )
5947{
5948   LOG_MMC(("ntdec_fh_m_w, offset: %04x, data: %02x\n", offset, data));
5949
5950   switch (offset & 0x03)
5951   {
5952      case 0:
5953         chr4_0(space->machine(), data >> 2, CHRROM);
5954         break;
5955      case 1:
5956         chr2_4(space->machine(), data >> 1, CHRROM);
5957         break;
5958      case 2:
5959         chr2_6(space->machine(), data >> 1 , CHRROM);
5960         break;
5961      case 3:
5962         prg8_89(space->machine(), data);
5963         break;
5964   }
5965}
5966
5967/*************************************************************
5968
5969 Open Corp DAOU306 board
5970
5971 Games: Metal Force (K)
5972
5973 iNES: mapper 156
5974
5975 In MESS: Supported.
5976
5977 *************************************************************/
5978
5979static WRITE8_HANDLER( daou306_w )
5980{
5981   LOG_MMC(("daou306_w, offset: %04x, data: %02x\n", offset, data));
5982
5983   switch (offset)
5984   {
5985      case 0x4000:
5986         chr1_0(space->machine(), data, CHRROM);
5987         break;
5988      case 0x4001:
5989         chr1_1(space->machine(), data, CHRROM);
5990         break;
5991      case 0x4002:
5992         chr1_2(space->machine(), data, CHRROM);
5993         break;
5994      case 0x4003:
5995         chr1_3(space->machine(), data, CHRROM);
5996         break;
5997      case 0x4008:
5998         chr1_4(space->machine(), data, CHRROM);
5999         break;
6000      case 0x4009:
6001         chr1_5(space->machine(), data, CHRROM);
6002         break;
6003      case 0x400a:
6004         chr1_6(space->machine(), data, CHRROM);
6005         break;
6006      case 0x400b:
6007         chr1_7(space->machine(), data, CHRROM);
6008         break;
6009      case 0x4010:
6010         prg16_89ab(space->machine(), data);
6011         break;
6012   }
6013}
6014
6015/*************************************************************
6016
6017 RCM GS2015 Board
6018
6019 Games: Bonza, Magic Jewelry 2
6020
6021 Very simple mapper: writes to 0x8000-0xffff sets prg32
6022 to offset and chr8 to offset>>1 (when chrrom is present)
6023
6024 iNES: mapper 216
6025
6026 In MESS: Supported.
6027
6028 *************************************************************/
6029
6030static WRITE8_HANDLER( gs2015_w )
6031{
6032   nes_state *state = space->machine().driver_data<nes_state>();
6033   LOG_MMC(("gs2015_w, offset: %04x, data: %02x\n", offset, data));
6034
6035   prg32(space->machine(), offset);
6036   chr8(space->machine(), offset >> 1, state->m_mmc_chr_source);
6037}
6038
6039/*************************************************************
6040
6041 Bootleg Board by RCM for Tetris Family
6042
6043 Games: Tetris Family 9 in 1, 20 in 1
6044
6045 Simple Mapper: prg/chr/nt are swapped depending on the offset
6046 of writes in 0x8000-0xffff. offset&0x80 set NT mirroring,
6047 when (offset&0x30) is 0,3 prg32 is set; when it is 1,2
6048 two 16k prg banks are set. See below for the values used in
6049 these banks.
6050
6051 iNES: mapper 61
6052
6053 In MESS: Supported.
6054
6055 *************************************************************/
6056
6057static WRITE8_HANDLER( rcm_tf_w )
6058{
6059   LOG_MMC(("rcm_tf_w, offset: %04x, data: %02x\n", offset, data));
6060
6061   switch (offset & 0x30)
6062   {
6063      case 0x00:
6064      case 0x30:
6065         prg32(space->machine(), offset & 0x0f);
6066         break;
6067      case 0x10:
6068      case 0x20:
6069         prg16_89ab(space->machine(), ((offset & 0x0f) << 1) | ((offset & 0x20) >> 4));
6070         prg16_cdef(space->machine(), ((offset & 0x0f) << 1) | ((offset & 0x20) >> 4));
6071         break;
6072   }
6073   set_nt_mirroring(space->machine(), BIT(data, 7) ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT);
6074}
6075
6076/*************************************************************
6077
6078 Bootleg Board by Rex Soft
6079
6080 Games: Dragon Ball Z 5, Dragon Ball Z Super
6081
6082 MMC3 clone
6083
6084 iNES: mapper 12
6085
6086 In MESS: Supported
6087
6088 *************************************************************/
6089
6090static WRITE8_HANDLER( rex_dbz_l_w )
6091{
6092   nes_state *state = space->machine().driver_data<nes_state>();
6093   LOG_MMC(("rex_dbz_l_w, offset: %04x, data: %02x\n", offset, data));
6094
6095   state->m_mmc_reg[0] = data;
6096   mmc3_set_chr(space->machine(), state->m_mmc_chr_source, state->m_mmc_chr_base, state->m_mmc_chr_mask);
6097}
6098
6099/* we would need to use this read handler in 0x6000-0x7fff as well */
6100static READ8_HANDLER( rex_dbz_l_r )
6101{
6102   LOG_MMC(("rex_dbz_l_r, offset: %04x\n", offset));
6103   return 0x01;
6104}
6105
6106static void rex_dbz_chr_cb( running_machine &machine, int start, int bank, int source )
6107{
6108   nes_state *state = machine.driver_data<nes_state>();
6109   int shift = (start < 4) ? 8 : 4;
6110
6111   bank |= ((state->m_mmc_reg[0] << shift) & 0x100);
6112   chr1_x(machine, start, bank, source);
6113}
6114
6115/*************************************************************
6116
6117 Rex Soft SL1632 Board
6118
6119 Games: Samurai Spirits
6120
6121 MMC3 clone
6122
6123 iNES: mapper 14
6124
6125 In MESS: Supported
6126
6127 *************************************************************/
6128
6129static void rex_sl1632_set_prg( running_machine &machine, int prg_base, int prg_mask )
6130{
6131   nes_state *state = machine.driver_data<nes_state>();
6132
6133   if (state->m_mmc_reg[0] & 0x02)
6134   {
6135      mmc3_set_prg(machine, prg_base, prg_mask);
6136   }
6137   else
6138   {
6139      prg8_89(machine, state->m_mmc_extra_bank[0]);
6140      prg8_ab(machine, state->m_mmc_extra_bank[1]);
6141      prg8_cd(machine, state->m_mmc_extra_bank[2]);
6142      prg8_ef(machine, state->m_mmc_extra_bank[3]);
6143   }
6144}
6145
6146static void rex_sl1632_set_chr( running_machine &machine, UINT8 chr, int chr_base, int chr_mask )
6147{
6148   nes_state *state = machine.driver_data<nes_state>();
6149   static const UINT8 conv_table[8] = {5, 5, 5, 5, 3, 3, 1, 1};
6150   UINT8 chr_page = (state->m_mmc3_latch & 0x80) >> 5;
6151   UINT8 bank[8];
6152   UINT8 chr_base2[8];
6153   int i;
6154
6155   if (state->m_mmc_reg[0] & 0x02)
6156   {
6157      for(i = 0; i < 8; i++)
6158      {
6159         bank[i] = state->m_mmc_vrom_bank[i];
6160         chr_base2[i] = chr_base | ((state->m_mmc_reg[0] << conv_table[i]) & 0x100);
6161      }
6162   }
6163   else
6164   {
6165      for(i = 0; i < 8; i++)
6166      {
6167         bank[i] = state->m_mmc_extra_bank[i + 4];   // first 4 state->m_mmc_extra_banks are PRG
6168         chr_base2[i] = chr_base;
6169      }
6170   }
6171
6172   chr1_x(machine, chr_page ^ 0, chr_base2[0] | (bank[0] & chr_mask), chr);
6173   chr1_x(machine, chr_page ^ 1, chr_base2[1] | (bank[1] & chr_mask), chr);
6174   chr1_x(machine, chr_page ^ 2, chr_base2[2] | (bank[2] & chr_mask), chr);
6175   chr1_x(machine, chr_page ^ 3, chr_base2[3] | (bank[3] & chr_mask), chr);
6176   chr1_x(machine, chr_page ^ 4, chr_base2[4] | (bank[4] & chr_mask), chr);
6177   chr1_x(machine, chr_page ^ 5, chr_base2[5] | (bank[5] & chr_mask), chr);
6178   chr1_x(machine, chr_page ^ 6, chr_base2[6] | (bank[6] & chr_mask), chr);
6179   chr1_x(machine, chr_page ^ 7, chr_base2[7] | (bank[7] & chr_mask), chr);
6180}
6181
6182static WRITE8_HANDLER( rex_sl1632_w )
6183{
6184   nes_state *state = space->machine().driver_data<nes_state>();
6185   UINT8 map14_helper1, map14_helper2, mmc_helper, cmd;
6186   LOG_MMC(("rex_sl1632_w, offset: %04x, data: %02x\n", offset, data));
6187
6188   if (offset == 0x2131)
6189   {
6190      state->m_mmc_reg[0] = data;
6191      rex_sl1632_set_prg(space->machine(), state->m_mmc_prg_base, state->m_mmc_prg_mask);
6192      rex_sl1632_set_chr(space->machine(), state->m_mmc_chr_source, state->m_mmc_chr_base, state->m_mmc_chr_mask);
6193
6194      if (!(state->m_mmc_reg[0] & 0x02))
6195         set_nt_mirroring(space->machine(), BIT(state->m_mmc_reg[1], 0) ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT);
6196   }
6197
6198   if (state->m_mmc_reg[0] & 0x02)
6199   {
6200      switch (offset & 0x6001)
6201      {
6202         case 0x0000:
6203            mmc_helper = state->m_mmc3_latch ^ data;
6204            state->m_mmc3_latch = data;
6205
6206            /* Has PRG Mode changed? */
6207            if (mmc_helper & 0x40)
6208               rex_sl1632_set_prg(space->machine(), state->m_mmc_prg_base, state->m_mmc_prg_mask);
6209
6210            /* Has CHR Mode changed? */
6211            if (mmc_helper & 0x80)
6212               rex_sl1632_set_chr(space->machine(), state->m_mmc_chr_source, state->m_mmc_chr_base, state->m_mmc_chr_mask);
6213            break;
6214
6215         case 0x0001:
6216            cmd = state->m_mmc3_latch & 0x07;
6217            switch (cmd)
6218            {
6219            case 0: case 1:   // these have to be changed due to the different way rex_sl1632_set_chr works (it handles 1k banks)!
6220               state->m_mmc_vrom_bank[2 * cmd] = data;
6221               state->m_mmc_vrom_bank[2 * cmd + 1] = data;
6222               rex_sl1632_set_chr(space->machine(), state->m_mmc_chr_source, state->m_mmc_chr_base, state->m_mmc_chr_mask);
6223               break;
6224            case 2: case 3: case 4: case 5:
6225               state->m_mmc_vrom_bank[cmd + 2] = data;
6226               rex_sl1632_set_chr(space->machine(), state->m_mmc_chr_source, state->m_mmc_chr_base, state->m_mmc_chr_mask);
6227               break;
6228            case 6:
6229            case 7:
6230               state->m_mmc_prg_bank[cmd - 6] = data;
6231               rex_sl1632_set_prg(space->machine(), state->m_mmc_prg_base, state->m_mmc_prg_mask);
6232               break;
6233            }
6234            break;
6235
6236         case 0x2000:
6237            set_nt_mirroring(space->machine(), BIT(state->m_mmc_reg[1], 0) ? PPU_MIRROR_VERT : PPU_MIRROR_HORZ);
6238            break;
6239
6240         default:
6241            txrom_w(space, offset, data);
6242            break;
6243      }
6244   }
6245   else if (offset >= 0x3000 && offset <= 0x6003 )
6246   {
6247      map14_helper1 = (offset & 0x01) << 2;
6248      offset = ((offset & 0x02) | (offset >> 10)) >> 1;
6249      map14_helper2 = ((offset + 2) & 0x07) + 4; // '+4' because first 4 state->m_mmc_extra_banks are for PRG!
6250      state->m_mmc_extra_bank[map14_helper2] = (state->m_mmc_extra_bank[map14_helper2] & (0xf0 >> map14_helper1)) | ((data & 0x0f) << map14_helper1);
6251      rex_sl1632_set_chr(space->machine(), state->m_mmc_chr_source, state->m_mmc_chr_base, state->m_mmc_chr_mask);
6252   }
6253   else
6254   {
6255      switch (offset & 0x7003)
6256      {
6257         case 0x0000:
6258         case 0x2000:
6259            state->m_mmc_extra_bank[offset >> 13] = data;
6260            rex_sl1632_set_prg(space->machine(), state->m_mmc_prg_base, state->m_mmc_prg_mask);
6261            break;
6262
6263         case 0x1000:
6264            state->m_mmc_reg[1] = data;
6265            set_nt_mirroring(space->machine(), BIT(state->m_mmc_reg[1], 0) ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT);
6266            break;
6267      }
6268   }
6269}
6270
6271/*************************************************************
6272
6273 Rumblestation Board
6274
6275 Games: Rumblestation 15 in 1
6276
6277 iNES: mapper 46
6278
6279 In MESS: Supported.
6280
6281 *************************************************************/
6282
6283static WRITE8_HANDLER( rumblestation_m_w )
6284{
6285   nes_state *state = space->machine().driver_data<nes_state>();
6286   LOG_MMC(("rumblestation_m_w, offset: %04x, data: %02x\n", offset, data));
6287
6288   state->m_mmc_prg_bank[0] = (state->m_mmc_prg_bank[0] & 0x01) | ((data & 0x0f) << 1);
6289   state->m_mmc_vrom_bank[0] = (state->m_mmc_vrom_bank[0] & 0x07) | ((data & 0xf0) >> 1);
6290   prg32(space->machine(), state->m_mmc_prg_bank[0]);
6291   chr8(space->machine(), state->m_mmc_vrom_bank[0], CHRROM);
6292}
6293
6294static WRITE8_HANDLER( rumblestation_w )
6295{
6296   nes_state *state = space->machine().driver_data<nes_state>();
6297   LOG_MMC(("rumblestation_w, offset: %04x, data: %02x\n", offset, data));
6298
6299   state->m_mmc_prg_bank[0] = (state->m_mmc_prg_bank[0] & ~0x01) | (data & 0x01);
6300   state->m_mmc_vrom_bank[0] = (state->m_mmc_vrom_bank[0] & ~0x07) | ((data & 0x70) >> 4);
6301   prg32(space->machine(), state->m_mmc_prg_bank[0]);
6302   chr8(space->machine(), state->m_mmc_vrom_bank[0], CHRROM);
6303}
6304
6305/*************************************************************
6306
6307 Sachen 74x374 bootleg boards
6308
6309 Games: Chess Academy, Chinese Checkers Jpn, Mahjong Academy,
6310 Olympic IQ, Poker II, Tasac [150], Poker III [243]
6311
6312 iNES: mappers 150 & 243
6313
6314 *************************************************************/
6315
6316static void sachen_set_mirror( running_machine &machine, UINT8 nt ) // used by mappers 137, 138, 139, 141
6317{
6318   switch (nt)
6319   {
6320      case 0:
6321      case 1:
6322         set_nt_mirroring(machine, nt ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT);
6323         break;
6324      case 2:
6325         set_nt_page(machine, 0, CIRAM, 0, 1);
6326         set_nt_page(machine, 1, CIRAM, 1, 1);
6327         set_nt_page(machine, 2, CIRAM, 1, 1);
6328         set_nt_page(machine, 3, CIRAM, 1, 1);
6329         break;
6330      case 3:
6331         set_nt_mirroring(machine, PPU_MIRROR_LOW);
6332         break;
6333      default:
6334         LOG_MMC(("Mapper set NT to invalid value %02x", nt));
6335         break;
6336   }
6337}
6338
6339static WRITE8_HANDLER( sachen_74x374_l_w )
6340{
6341   nes_state *state = space->machine().driver_data<nes_state>();
6342   LOG_MMC(("sachen_74x374_l_w, offset: %04x, data: %02x\n", offset, data));
6343
6344   /* write happens only if we are at 0x4100 + k * 0x200, but 0x4100 is offset = 0 */
6345   if (!(offset & 0x100))
6346   {
6347      if (!(offset & 0x01))
6348         state->m_mmc_latch1 = data & 0x07;
6349      else
6350      {
6351         switch (state->m_mmc_latch1)
6352         {
6353            case 0x02:
6354               state->m_mmc_vrom_bank[0] = (state->m_mmc_vrom_bank[0] & ~0x08) | ((data << 3) & 0x08);
6355               chr8(space->machine(), state->m_mmc_vrom_bank[0], CHRROM);
6356               prg32(space->machine(), data & 0x01);
6357               break;
6358            case 0x04:
6359               state->m_mmc_vrom_bank[0] = (state->m_mmc_vrom_bank[0] & ~0x04) | ((data << 2) & 0x04);
6360               chr8(space->machine(), state->m_mmc_vrom_bank[0], CHRROM);
6361               break;
6362            case 0x05:
6363               prg32(space->machine(), data & 0x07);
6364               break;
6365            case 0x06:
6366               state->m_mmc_vrom_bank[0] = (state->m_mmc_vrom_bank[0] & ~0x03) | ((data << 0) & 0x03);
6367               chr8(space->machine(), state->m_mmc_vrom_bank[0], CHRROM);
6368               break;
6369            case 0x07:
6370               sachen_set_mirror(space->machine(), (data >> 1) & 0x03);
6371               break;
6372            default:
6373               break;
6374         }
6375      }
6376   }
6377}
6378
6379static READ8_HANDLER( sachen_74x374_l_r )
6380{
6381   nes_state *state = space->machine().driver_data<nes_state>();
6382   LOG_MMC(("sachen_74x374_l_r, offset: %04x", offset));
6383
6384   /* read  happens only if we are at 0x4100 + k * 0x200, but 0x4100 is offset = 0 */
6385   if (!(offset & 0x100))
6386      return (~state->m_mmc_latch1 & 0x3f) /* ^ dips*/;   // we would need to check the Dips here
6387   else
6388      return 0;
6389}
6390
6391static WRITE8_HANDLER( sachen_74x374a_l_w )
6392{
6393   nes_state *state = space->machine().driver_data<nes_state>();
6394   LOG_MMC(("sachen_74x374a_l_w, offset: %04x, data: %02x\n", offset, data));
6395
6396   /* write happens only if we are at 0x4100 + k * 0x200, but 0x4100 is offset = 0 */
6397   if (!(offset & 0x100))
6398   {
6399      if (!(offset & 0x01))
6400         state->m_mmc_latch1 = data;
6401      else
6402      {
6403         switch (state->m_mmc_latch1 & 0x07)
6404         {
6405            case 0x00:
6406               prg32(space->machine(), 0);
6407               chr8(space->machine(), 3, CHRROM);
6408               break;
6409            case 0x02:
6410               state->m_mmc_vrom_bank[0] = (state->m_mmc_vrom_bank[0] & ~0x08) | ((data << 3) & 0x08);
6411               chr8(space->machine(), state->m_mmc_vrom_bank[0], CHRROM);
6412               break;
6413            case 0x04:
6414               state->m_mmc_vrom_bank[0] = (state->m_mmc_vrom_bank[0] & ~0x01) | ((data << 0) & 0x01);
6415               chr8(space->machine(), state->m_mmc_vrom_bank[0], CHRROM);
6416               break;
6417            case 0x05:
6418               prg32(space->machine(), data & 0x01);
6419               break;
6420            case 0x06:
6421               state->m_mmc_vrom_bank[0] = (state->m_mmc_vrom_bank[0] & ~0x06) | ((data << 1) & 0x06);
6422               chr8(space->machine(), state->m_mmc_vrom_bank[0], CHRROM);
6423               break;
6424            case 0x07:
6425               sachen_set_mirror(space->machine(), BIT(data, 0));
6426               break;
6427            default:
6428               break;
6429         }
6430      }
6431   }
6432}
6433
6434/*************************************************************
6435
6436 Sachen S8259 bootleg boards
6437
6438 iNES: mapper 141 (A), 138 (B), 139 (C), 137 (D)
6439
6440 *************************************************************/
6441
6442static void common_s8259_write_handler( address_space *space, offs_t offset, UINT8 data, int board )
6443{
6444   nes_state *state = space->machine().driver_data<nes_state>();
6445   UINT8 bank_helper1, bank_helper2, shift, add1, add2, add3;
6446
6447   /* write happens only if we are at 0x4100 + k * 0x200, but 0x4100 is offset = 0 */
6448   if (!(offset & 0x100))
6449   {
6450      if (!(offset & 0x01))
6451         state->m_mmc_latch1 = data & 0x07;
6452      else
6453      {
6454         state->m_sachen_reg[state->m_mmc_latch1] = data;
6455
6456         switch (state->m_mmc_latch1)
6457         {
6458            case 0x05:
6459               prg32(space->machine(), data);
6460               break;
6461            case 0x07:
6462               sachen_set_mirror(space->machine(), BIT(data, 0) ? 0 : (data >> 1) & 0x03);
6463               break;
6464            default:
6465               if (board == SACHEN_8259D)
6466               {
6467                  if (state->m_mmc_chr_source == CHRROM)
6468                  {
6469                     chr1_0(space->machine(), (state->m_sachen_reg[0] & 0x07), CHRROM);
6470                     chr1_1(space->machine(), (state->m_sachen_reg[1] & 0x07) | (state->m_sachen_reg[4] << 4 & 0x10), CHRROM);
6471                     chr1_2(space->machine(), (state->m_sachen_reg[2] & 0x07) | (state->m_sachen_reg[4] << 3 & 0x10), CHRROM);
6472                     chr1_3(space->machine(), (state->m_sachen_reg[3] & 0x07) | (state->m_sachen_reg[4] << 2 & 0x10) | (state->m_sachen_reg[6] << 3 & 0x08), CHRROM);
6473                  }
6474               }
6475               else
6476               {
6477                  bank_helper1 = state->m_sachen_reg[7] & 0x01;
6478                  bank_helper2 = (state->m_sachen_reg[4] & 0x07) << 3;
6479                  shift = (board == SACHEN_8259A) ? 1 : (board == SACHEN_8259C) ? 2 : 0;
6480                  add1 = (board == SACHEN_8259B) ? 0 : 1;
6481                  add2 = (board == SACHEN_8259C) ? 2 : 0;
6482                  add3 = (board == SACHEN_8259A) ? 1 : (board == SACHEN_8259C) ? 3 : 0;
6483
6484                  if (state->m_mmc_chr_source == CHRROM)
6485                  {
6486                     chr2_0(space->machine(), ((state->m_sachen_reg[bank_helper1 ? 0 : 0] & 0x07) | bank_helper2) << shift, CHRROM);
6487                     chr2_2(space->machine(), ((state->m_sachen_reg[bank_helper1 ? 0 : 1] & 0x07) | bank_helper2) << shift | add1, CHRROM);
6488                     chr2_4(space->machine(), ((state->m_sachen_reg[bank_helper1 ? 0 : 2] & 0x07) | bank_helper2) << shift | add2, CHRROM);
6489                     chr2_6(space->machine(), ((state->m_sachen_reg[bank_helper1 ? 0 : 3] & 0x07) | bank_helper2) << shift | add3, CHRROM);
6490                  }
6491               }
6492               break;
6493         }
6494      }
6495   }
6496}
6497
6498static WRITE8_HANDLER( s8259_l_w )
6499{
6500   nes_state *state = space->machine().driver_data<nes_state>();
6501   LOG_MMC(("s8259_w, type: %d, offset: %04x, data: %02x\n", state->m_pcb_id, offset, data));
6502
6503   common_s8259_write_handler(space, offset, data, state->m_pcb_id);
6504}
6505
6506static WRITE8_HANDLER( s8259_m_w )
6507{
6508   nes_state *state = space->machine().driver_data<nes_state>();
6509   LOG_MMC(("s8259_w, type: %d, offset: %04x, data: %02x\n", state->m_pcb_id, offset, data));
6510
6511   common_s8259_write_handler(space, (offset + 0x100) & 0xfff, data, state->m_pcb_id);
6512}
6513
6514
6515/*************************************************************
6516
6517 Sachen SA009 bootleg boards
6518
6519 Games: Pipe 5
6520
6521 iNES: mapper 160
6522
6523 In MESS: Supported.
6524
6525 *************************************************************/
6526
6527static WRITE8_HANDLER( sa009_l_w )
6528{
6529   nes_state *state = space->machine().driver_data<nes_state>();
6530   LOG_MMC(("sa009_l_w, offset: %04x, data: %02x\n", offset, data));
6531
6532   chr8(space->machine(), data, state->m_mmc_chr_source);
6533}
6534
6535/*************************************************************
6536
6537 Sachen SA0036 bootleg boards
6538
6539 Games: Taiwan Mahjong 16
6540
6541 iNES: mapper 149
6542
6543 In MESS: Supported.
6544
6545 *************************************************************/
6546
6547static WRITE8_HANDLER( sa0036_w )
6548{
6549   LOG_MMC(("sa0036_w, offset: %04x, data: %02x\n", offset, data));
6550
6551   chr8(space->machine(), data >> 7, CHRROM);
6552}
6553
6554/*************************************************************
6555
6556 Sachen SA0037 bootleg boards
6557
6558 Games: Mahjong World, Shisen Mahjong
6559
6560 iNES: mapper 148
6561
6562 In MESS: Supported.
6563
6564 *************************************************************/
6565
6566static WRITE8_HANDLER( sa0037_w )
6567{
6568   LOG_MMC(("sa0037_w, offset: %04x, data: %02x\n", offset, data));
6569
6570   prg32(space->machine(), data >> 3);
6571   chr8(space->machine(), data, CHRROM);
6572}
6573
6574/*************************************************************
6575
6576 Sachen SA72007 bootleg boards
6577
6578 Games: Sidewinder
6579
6580 iNES: mapper 145
6581
6582 In MESS: Supported.
6583
6584 *************************************************************/
6585
6586static WRITE8_HANDLER( sa72007_l_w )
6587{
6588   LOG_MMC(("sa72007_l_w, offset: %04x, data: %02x\n", offset, data));
6589
6590   /* only if we are at 0x4100 + k * 0x200, but 0x4100 is offset = 0 */
6591   if (!(offset & 0x100))
6592      chr8(space->machine(), data >> 7, CHRROM);
6593}
6594
6595/*************************************************************
6596
6597 Sachen SA72008 bootleg boards
6598
6599 Games: Jovial Race, Qi Wang
6600
6601 iNES: mapper 133
6602
6603 In MESS: Supported.
6604
6605 *************************************************************/
6606
6607static WRITE8_HANDLER( sa72008_l_w )
6608{
6609   LOG_MMC(("sa72008_l_w, offset: %04x, data: %02x\n", offset, data));
6610
6611   prg32(space->machine(), data >> 2);
6612   chr8(space->machine(), data, CHRROM);
6613}
6614
6615/*************************************************************
6616
6617 Sachen TCA-01 bootleg boards
6618
6619 iNES: mapper 143
6620
6621 Games: Dancing Blocks, Magic Mathematic
6622
6623 In MESS: Supported.
6624
6625 *************************************************************/
6626
6627static READ8_HANDLER( tca01_l_r )
6628{
6629   LOG_MMC(("tca01_l_r, offset: %04x\n", offset));
6630
6631   /* the address is read only if we are at 0x4100 + k * 0x200, but 0x4100 is offset = 0 */
6632   if (!(offset & 0x100))
6633      return (~offset & 0x3f) | 0x40;
6634   else
6635      return 0x00;
6636}
6637
6638/*************************************************************
6639
6640 Sachen TCU-01 bootleg boards
6641
6642 Games: Challenge of the Dragon, Chinese Kungfu
6643
6644 iNES: mapper 147
6645
6646 In MESS: Supported.
6647
6648 *************************************************************/
6649
6650static WRITE8_HANDLER( tcu01_l_w )
6651{
6652   LOG_MMC(("tcu01_l_w, offset: %04x, data: %02x\n", offset, data));
6653
6654   if ((offset & 0x103) == 0x002)
6655   {
6656      prg32(space->machine(), ((data >> 6) & 0x02) | ((data >> 2) & 0x01));
6657      chr8(space->machine(), data >> 3, CHRROM);
6658   }
6659}
6660
6661static WRITE8_HANDLER( tcu01_m_w )
6662{
6663   LOG_MMC(("tcu01_m_w, offset: %04x, data: %02x\n", offset, data));
6664
6665   tcu01_l_w(space, (offset + 0x100) & 0xfff, data);
6666}
6667
6668static WRITE8_HANDLER( tcu01_w )
6669{
6670   LOG_MMC(("tcu01_w, offset: %04x, data: %02x\n", offset, data));
6671
6672   tcu01_l_w(space, (offset + 0x100) & 0xfff, data);
6673}
6674
6675/*************************************************************
6676
6677 Sachen TCU-02 bootleg boards
6678
6679 Games: Mei Loi Siu Ji
6680
6681 iNES: mapper 136
6682
6683 In MESS: Supported.
6684
6685 *************************************************************/
6686
6687static WRITE8_HANDLER( tcu02_l_w )
6688{
6689   nes_state *state = space->machine().driver_data<nes_state>();
6690   LOG_MMC(("tcu02_l_w, offset: %04x, data: %02x\n", offset, data));
6691
6692   if ((offset & 0x103) == 0x002)
6693   {
6694      state->m_mmc_latch1 = (data & 0x30) | ((data + 3) & 0x0f);
6695      chr8(space->machine(), state->m_mmc_latch1, CHRROM);
6696   }
6697}
6698
6699static READ8_HANDLER( tcu02_l_r )
6700{
6701   nes_state *state = space->machine().driver_data<nes_state>();
6702   LOG_MMC(("tcu02_l_r, offset: %04x\n", offset));
6703
6704   if ((offset & 0x103) == 0x000)
6705      return state->m_mmc_latch1 | 0x40;
6706   else
6707      return 0x00;
6708}
6709
6710
6711/*************************************************************
6712
6713 Subor bootleg board Type 0
6714
6715 iNES: mapper 167
6716
6717 *************************************************************/
6718
6719static WRITE8_HANDLER( subor0_w )
6720{
6721   nes_state *state = space->machine().driver_data<nes_state>();
6722   UINT8 subor_helper1, subor_helper2;
6723   LOG_MMC(("subor0_w, offset: %04x, data: %02x\n", offset, data));
6724
6725   state->m_subor_reg[(offset >> 13) & 0x03] = data;
6726   subor_helper1 = ((state->m_subor_reg[0] ^ state->m_subor_reg[1]) << 1) & 0x20;
6727   subor_helper2 = ((state->m_subor_reg[2] ^ state->m_subor_reg[3]) << 0) & 0x1f;
6728
6729   if (state->m_subor_reg[1] & 0x08)
6730   {
6731      subor_helper1 += subor_helper2 & 0xfe;
6732      subor_helper2 = subor_helper1;
6733      subor_helper1 += 1;
6734   }
6735   else if (state->m_subor_reg[1] & 0x04)
6736   {
6737      subor_helper2 += subor_helper1;
6738      subor_helper1 = 0x1f;
6739   }
6740   else
6741   {
6742      subor_helper1 += subor_helper2;
6743      subor_helper2 = 0x20;
6744   }
6745
6746   prg16_89ab(space->machine(), subor_helper1);
6747   prg16_cdef(space->machine(), subor_helper2);
6748}
6749
6750/*************************************************************
6751
6752 Subor bootleg board Type 1
6753
6754 iNES: mapper 166
6755
6756 *************************************************************/
6757
6758static WRITE8_HANDLER( subor1_w )
6759{
6760   nes_state *state = space->machine().driver_data<nes_state>();
6761   UINT8 subor_helper1, subor_helper2;
6762   LOG_MMC(("subor1_w, offset: %04x, data: %02x\n", offset, data));
6763
6764   state->m_subor_reg[(offset >> 13) & 0x03] = data;
6765   subor_helper1 = ((state->m_subor_reg[0] ^ state->m_subor_reg[1]) << 1) & 0x20;
6766   subor_helper2 = ((state->m_subor_reg[2] ^ state->m_subor_reg[3]) << 0) & 0x1f;
6767
6768   if (state->m_subor_reg[1] & 0x08)
6769   {
6770      subor_helper1 += subor_helper2 & 0xfe;
6771      subor_helper2 = subor_helper1;
6772      subor_helper2 += 1;
6773   }
6774   else if (state->m_subor_reg[1] & 0x04)
6775   {
6776      subor_helper2 += subor_helper1;
6777      subor_helper1 = 0x1f;
6778   }
6779   else
6780   {
6781      subor_helper1 += subor_helper2;
6782      subor_helper2 = 0x07;
6783   }
6784
6785   prg16_89ab(space->machine(), subor_helper1);
6786   prg16_cdef(space->machine(), subor_helper2);
6787}
6788
6789/*************************************************************
6790
6791 Bootleg Board by Super Game
6792
6793 Games: Boogerman, Mortal Kombat III
6794
6795 MMC3 clone. Also, it probably needs a hack to support both
6796 variants (Boogerman & MK3).
6797
6798 iNES: mapper 215
6799
6800 In MESS: Preliminary support.
6801
6802 *************************************************************/
6803
6804static void sgame_boog_prg_cb( running_machine &machine, int start, int bank )
6805{
6806   nes_state *state = machine.driver_data<nes_state>();
6807   if (!(state->m_mmc_reg[0] & 0x80))   // if this is != 0 we should never even arrive here
6808   {
6809      if (state->m_mmc_reg[1] & 0x08)
6810         bank = (bank & 0x1f) | 0x20;
6811      else
6812         bank = (bank & 0x0f) | (state->m_mmc_reg[1] & 0x10);
6813
6814      prg8_x(machine, start, bank);
6815   }
6816}
6817
6818static void sgame_boog_chr_cb( running_machine &machine, int start, int bank, int source )
6819{
6820   nes_state *state = machine.driver_data<nes_state>();
6821
6822   if ((state->m_mmc_reg[1] & 0x04))
6823      bank |= 0x100;
6824   else
6825      bank = (bank & 0x7f) | ((state->m_mmc_reg[1] & 0x10) << 3);
6826
6827   chr1_x(machine, start, bank, source);
6828}
6829
6830static void sgame_boog_set_prg( running_machine &machine )
6831{
6832   nes_state *state = machine.driver_data<nes_state>();
6833   if (state->m_mmc_reg[0] & 0x80)
6834   {
6835      prg16_89ab(machine, (state->m_mmc_reg[0] & 0xf0) | (state->m_mmc_reg[1] & 0x10));
6836      prg16_cdef(machine, (state->m_mmc_reg[0] & 0xf0) | (state->m_mmc_reg[1] & 0x10));
6837   }
6838   else
6839      mmc3_set_prg(machine, state->m_mmc_prg_base, state->m_mmc_prg_mask);
6840}
6841
6842static WRITE8_HANDLER( sgame_boog_l_w )
6843{
6844   nes_state *state = space->machine().driver_data<nes_state>();
6845   LOG_MMC(("sgame_boog_l_w, offset: %04x, data: %02x\n", offset, data));
6846   offset += 0x100;
6847
6848   if (offset == 0x1000)
6849   {
6850      state->m_mmc_reg[0] = data;
6851      sgame_boog_set_prg(space->machine());
6852   }
6853   else if (offset == 0x1001)
6854   {
6855      state->m_mmc_reg[1] = data;
6856      mmc3_set_chr(space->machine(), state->m_mmc_chr_source, state->m_mmc_chr_base, state->m_mmc_chr_mask);
6857   }
6858   else if (offset == 0x1007)
6859   {
6860      state->m_mmc3_latch = 0;
6861      state->m_mmc_reg[2] = data;
6862      sgame_boog_set_prg(space->machine());
6863      mmc3_set_chr(space->machine(), state->m_mmc_chr_source, state->m_mmc_chr_base, state->m_mmc_chr_mask);
6864   }
6865}
6866
6867static WRITE8_HANDLER( sgame_boog_m_w )
6868{
6869   nes_state *state = space->machine().driver_data<nes_state>();
6870   LOG_MMC(("sgame_boog_m_w, offset: %04x, data: %02x\n", offset, data));
6871
6872   if (offset == 0x0000)
6873   {
6874      state->m_mmc_reg[0] = data;
6875      sgame_boog_set_prg(space->machine());
6876   }
6877   else if (offset == 0x0001)
6878   {
6879      state->m_mmc_reg[1] = data;
6880      mmc3_set_chr(space->machine(), state->m_mmc_chr_source, state->m_mmc_chr_base, state->m_mmc_chr_mask);
6881   }
6882   else if (offset == 0x0007)
6883   {
6884      state->m_mmc3_latch = 0;
6885      state->m_mmc_reg[2] = data;
6886      sgame_boog_set_prg(space->machine());
6887      mmc3_set_chr(space->machine(), state->m_mmc_chr_source, state->m_mmc_chr_base, state->m_mmc_chr_mask);
6888   }
6889}
6890
6891static WRITE8_HANDLER( sgame_boog_w )
6892{
6893   nes_state *state = space->machine().driver_data<nes_state>();
6894   static const UINT8 conv_table[8] = {0,2,5,3,6,1,7,4};
6895   LOG_MMC(("sgame_boog_w, offset: %04x, data: %02x\n", offset, data));
6896
6897   switch (offset & 0x6001)
6898   {
6899      case 0x0000:
6900         if (!state->m_mmc_reg[2])
6901            txrom_w(space, 0x0000, data);
6902         break;
6903
6904      case 0x0001:
6905         if (!state->m_mmc_reg[2])
6906            txrom_w(space, 0x0001, data);
6907         else if (state->m_mmc_reg[3] && ((state->m_mmc_reg[0] & 0x80) == 0 || (state->m_mmc_latch1 & 0x07) < 6))   // if we use the prg16 banks and cmd=6,7 DON'T enter!
6908         {
6909            state->m_mmc_reg[3] = 0;
6910            txrom_w(space, 0x0001, data);
6911         }
6912         break;
6913
6914      case 0x2000:
6915         if (!state->m_mmc_reg[2])
6916            txrom_w(space, 0x2000, data);
6917         else
6918         {
6919            data = (data & 0xc0) | conv_table[data & 0x07];
6920            state->m_mmc_reg[3] = 1;
6921            txrom_w(space, 0x0000, data);
6922            break;
6923         }
6924         break;
6925
6926      case 0x4000:
6927         if (!state->m_mmc_reg[2])
6928            txrom_w(space, 0x4000, data);
6929         else
6930            set_nt_mirroring(space->machine(), ((data >> 7) | data) & 0x01 ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT);
6931         break;
6932
6933      case 0x4001:
6934         if (!state->m_mmc_reg[2])
6935            txrom_w(space, 0x4001, data);
6936         else
6937            txrom_w(space, 0x6001, data);
6938         break;
6939
6940      case 0x6001:
6941         if (!state->m_mmc_reg[2])
6942            txrom_w(space, 0x6001, data);
6943         else
6944         {
6945            txrom_w(space, 0x4000, data);
6946            txrom_w(space, 0x4001, data);
6947         }
6948         break;
6949
6950      default:
6951         txrom_w(space, offset, data);
6952         break;
6953   }
6954}
6955
6956/*************************************************************
6957
6958 Bootleg Board by Super Game
6959
6960 Games: The Lion King
6961
6962 MMC3 clone.
6963
6964 iNES: mapper 114
6965
6966 In MESS: Supported.
6967
6968 *************************************************************/
6969
6970static WRITE8_HANDLER( sgame_lion_m_w )
6971{
6972   nes_state *state = space->machine().driver_data<nes_state>();
6973   LOG_MMC(("sgame_lion_m_w, offset: %04x, data: %02x\n", offset, data));
6974
6975   state->m_map114_reg = data;
6976
6977   if (state->m_map114_reg & 0x80)
6978   {
6979      prg16_89ab(space->machine(), data & 0x1f);
6980      prg16_cdef(space->machine(), data & 0x1f);
6981   }
6982   else
6983      mmc3_set_prg(space->machine(), state->m_mmc_prg_base, state->m_mmc_prg_mask);
6984
6985}
6986
6987static WRITE8_HANDLER( sgame_lion_w )
6988{
6989   nes_state *state = space->machine().driver_data<nes_state>();
6990   static const UINT8 conv_table[8] = {0, 3, 1, 5, 6, 7, 2, 4};
6991   LOG_MMC(("sgame_lion_w, offset: %04x, data: %02x\n", offset, data));
6992
6993   if (offset < 0x6000)
6994   {
6995      switch (offset & 0x6000)
6996      {
6997         case 0x0000:
6998            set_nt_mirroring(space->machine(), BIT(data, 0) ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT);
6999            break;
7000         case 0x2000:
7001            state->m_map114_reg_enabled = 1;
7002            data = (data & 0xc0) | conv_table[data & 0x07];
7003            txrom_w(space, 0x0000, data);
7004            break;
7005         case 0x4000:
7006            if (state->m_map114_reg_enabled && (state->m_map114_reg & 0x80) == 0)
7007            {
7008               state->m_map114_reg_enabled = 0;
7009               txrom_w(space, 0x0001, data);
7010            }
7011            break;
7012      }
7013   }
7014   else
7015   {
7016      switch (offset & 0x03)
7017      {
7018         case 0x02:
7019            txrom_w(space, 0x6000, data);
7020            break;
7021         case 0x03:
7022            txrom_w(space, 0x6001, data);
7023            txrom_w(space, 0x4000, data);
7024            txrom_w(space, 0x4001, data);
7025            break;
7026      }
7027   }
7028}
7029
7030/*************************************************************
7031
7032 Tengen 800008 Board
7033
7034 iNES: mapper 3?
7035
7036 In MESS: Supported.
7037
7038 *************************************************************/
7039
7040static WRITE8_HANDLER( tengen_800008_w )
7041{
7042   LOG_MMC(("tengen_800008_w, offset: %04x, data: %02x\n", offset, data));
7043
7044   prg32(space->machine(), data >> 3);
7045   chr8(space->machine(), data, CHRROM);
7046}
7047
7048/*************************************************************
7049
7050 Tengen 800032 Board
7051
7052 Games: Klax, Road Runner, Rolling Thunder, Shinobi, Skulls
7053 & Croosbones, Xybots
7054
7055 iNES: mapper 64
7056
7057 In MESS: Partially Supported.
7058
7059 *************************************************************/
7060
7061static void tengen_800032_irq( device_t *device, int scanline, int vblank, int blanked )
7062{
7063   nes_state *state = device->machine().driver_data<nes_state>();
7064   if (!state->m_IRQ_mode)   // we are in scanline mode!
7065   {
7066      if (scanline < PPU_BOTTOM_VISIBLE_SCANLINE)
7067      {
7068         if (!state->m_IRQ_reset)
7069         {
7070            if (!state->m_IRQ_count)
7071               state->m_IRQ_count = state->m_IRQ_count_latch;
7072            else
7073            {
7074               state->m_IRQ_count--;
7075               if (state->m_IRQ_enable && !blanked && !state->m_IRQ_count)
7076               {
7077                  LOG_MMC(("irq fired, scanline: %d (MAME %d, beam pos: %d)\n", scanline,
7078                         device->machine().primary_screen->vpos(), device->machine().primary_screen->hpos()));
7079                  device_set_input_line(state->m_maincpu, M6502_IRQ_LINE, HOLD_LINE);
7080               }
7081            }
7082         }
7083         else
7084         {
7085            state->m_IRQ_reset = 0;
7086            state->m_IRQ_count = state->m_IRQ_count_latch + 1;
7087         }
7088      }
7089   }
7090   /* otherwise, we are in CPU cycles mode --> decrement count of 114 every scanline
7091     --> in the meanwhile anything can have happened to IRQ_reset and we would not know
7092     --> Skulls and Crossbones does not show anything!! */
7093   else
7094   {
7095      //      if (!state->m_IRQ_reset)
7096      {
7097         if (state->m_IRQ_count <= 114)
7098            state->m_IRQ_count = state->m_IRQ_count_latch;
7099         else
7100         {
7101            state->m_IRQ_count -= 114;
7102            if (state->m_IRQ_enable && !blanked && (state->m_IRQ_count <= 114))
7103            {
7104               LOG_MMC(("irq fired, scanline: %d (MAME %d, beam pos: %d)\n", scanline,
7105                      device->machine().primary_screen->vpos(), device->machine().primary_screen->hpos()));
7106               device_set_input_line(state->m_maincpu, M6502_IRQ_LINE, HOLD_LINE);
7107            }
7108         }
7109      }
7110      //      else
7111      //      {
7112      //          state->m_IRQ_reset = 0;
7113      //          state->m_IRQ_count = state->m_IRQ_count_latch + 1;
7114      //      }
7115   }
7116}
7117
7118static void tengen_800032_set_prg( running_machine &machine )
7119{
7120   nes_state *state = machine.driver_data<nes_state>();
7121   UINT8 prg_mode = state->m_mmc_latch1 & 0x40;
7122
7123   prg8_89(machine, state->m_mmc_prg_bank[prg_mode ? 2: 0]);
7124   prg8_ab(machine, state->m_mmc_prg_bank[prg_mode ? 0: 1]);
7125   prg8_cd(machine, state->m_mmc_prg_bank[prg_mode ? 1: 2]);
7126}
7127
7128static void tengen_800032_set_chr( running_machine &machine )
7129{
7130   nes_state *state = machine.driver_data<nes_state>();
7131   UINT8 chr_page = (state->m_mmc_latch1 & 0x80) >> 5;
7132
7133   if (state->m_mmc_latch1 & 0x20)
7134   {
7135      chr1_x(machine, 0 ^ chr_page, state->m_mmc_vrom_bank[0], CHRROM);
7136      chr1_x(machine, 1 ^ chr_page, state->m_mmc_vrom_bank[8], CHRROM);
7137      chr1_x(machine, 2 ^ chr_page, state->m_mmc_vrom_bank[1], CHRROM);
7138      chr1_x(machine, 3 ^ chr_page, state->m_mmc_vrom_bank[9], CHRROM);
7139   }
7140   else
7141   {
7142      chr1_x(machine, 0 ^ chr_page, state->m_mmc_vrom_bank[0] & ~0x01, CHRROM);
7143      chr1_x(machine, 1 ^ chr_page, state->m_mmc_vrom_bank[0] |  0x01, CHRROM);
7144      chr1_x(machine, 2 ^ chr_page, state->m_mmc_vrom_bank[1] & ~0x01, CHRROM);
7145      chr1_x(machine, 3 ^ chr_page, state->m_mmc_vrom_bank[1] |  0x01, CHRROM);
7146   }
7147
7148   chr1_x(machine, 4 ^ chr_page, state->m_mmc_vrom_bank[2], CHRROM);
7149   chr1_x(machine, 5 ^ chr_page, state->m_mmc_vrom_bank[3], CHRROM);
7150   chr1_x(machine, 6 ^ chr_page, state->m_mmc_vrom_bank[4], CHRROM);
7151   chr1_x(machine, 7 ^ chr_page, state->m_mmc_vrom_bank[5], CHRROM);
7152}
7153
7154static WRITE8_HANDLER( tengen_800032_w )
7155{
7156   nes_state *state = space->machine().driver_data<nes_state>();
7157   UINT8 map64_helper, cmd;
7158   LOG_MMC(("tengen_800032_w, offset: %04x, data: %02x\n", offset, data));
7159
7160   switch (offset & 0x6001)
7161   {
7162      case 0x0000:
7163         map64_helper = state->m_mmc_latch1 ^ data;
7164         state->m_mmc_latch1 = data;
7165
7166         /* Has PRG Mode changed? */
7167         if (map64_helper & 0x40)
7168            tengen_800032_set_prg(space->machine());
7169
7170         /* Has CHR Mode changed? */
7171         if (map64_helper & 0xa0)
7172            tengen_800032_set_chr(space->machine());
7173         break;
7174
7175      case 0x0001:
7176         cmd = state->m_mmc_latch1 & 0x0f;
7177         switch (cmd)
7178      {
7179         case 0: case 1:
7180         case 2: case 3:
7181         case 4: case 5:
7182            state->m_mmc_vrom_bank[cmd] = data;
7183            tengen_800032_set_chr(space->machine());
7184            break;
7185         case 6: case 7:
7186            state->m_mmc_prg_bank[cmd - 6] = data;
7187            tengen_800032_set_prg(space->machine());
7188            break;
7189         case 8: case 9:
7190            state->m_mmc_vrom_bank[cmd - 2] = data;
7191            tengen_800032_set_chr(space->machine());
7192            break;
7193         case 0x0f:
7194            state->m_mmc_prg_bank[2] = data;
7195            tengen_800032_set_prg(space->machine());
7196            break;
7197      }
7198         break;
7199
7200      case 0x2000:
7201         set_nt_mirroring(space->machine(), BIT(data, 0) ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT);
7202         break;
7203
7204      case 0x4000:
7205         state->m_IRQ_count_latch = data;
7206         break;
7207
7208      case 0x4001: /* $c001 - IRQ scanline latch */
7209         state->m_IRQ_mode = data & 0x01;
7210         state->m_IRQ_reset = 1;
7211         break;
7212
7213      case 0x6000:
7214         state->m_IRQ_enable = 0;
7215         break;
7216
7217      case 0x6001:
7218         state->m_IRQ_enable = 1;
7219         break;
7220
7221      default:
7222         LOG_MMC(("Mapper 64 write. addr: %04x value: %02x\n", offset + 0x8000, data));
7223         break;
7224   }
7225}
7226
7227/*************************************************************
7228
7229 Tengen 800037 Board
7230
7231 Games: Alien Syndrome
7232
7233 iNES: mapper 158
7234
7235 In MESS: Very preliminary support.
7236
7237 *************************************************************/
7238
7239// probably wrong...
7240static void tengen_800037_set_mirror( running_machine &machine )
7241{
7242   nes_state *state = machine.driver_data<nes_state>();
7243   UINT8 nt_mode = state->m_mmc_latch1 & 0x80;
7244
7245   set_nt_page(machine, 0, ROM, state->m_mmc_vrom_bank[nt_mode ? 2 : 0], 0);
7246   set_nt_page(machine, 1, ROM, state->m_mmc_vrom_bank[nt_mode ? 3 : 0], 0);
7247   set_nt_page(machine, 2, ROM, state->m_mmc_vrom_bank[nt_mode ? 4 : 1], 0);
7248   set_nt_page(machine, 3, ROM, state->m_mmc_vrom_bank[nt_mode ? 5 : 1], 0);
7249}
7250
7251static WRITE8_HANDLER( tengen_800037_w )
7252{
7253   nes_state *state = space->machine().driver_data<nes_state>();
7254   UINT8 map158_helper, cmd;
7255   LOG_MMC(("tengen_800037_w, offset: %04x, data: %02x\n", offset, data));
7256
7257   switch (offset & 0x6001)
7258   {
7259      case 0x0000:
7260         map158_helper = state->m_mmc_latch1 ^ data;
7261         state->m_mmc_latch1 = data;
7262
7263         /* Has PRG Mode changed? */
7264         if (map158_helper & 0x40)
7265            tengen_800032_set_prg(space->machine());
7266
7267         /* Has CHR Mode changed? */
7268         if (map158_helper & 0xa0)
7269         {
7270            tengen_800032_set_chr(space->machine());
7271            tengen_800037_set_mirror(space->machine());
7272         }
7273         break;
7274
7275      case 0x0001:
7276         cmd = state->m_mmc_latch1 & 0x0f;
7277         switch (cmd)
7278      {
7279         case 0: case 1:
7280         case 2: case 3:
7281         case 4: case 5:
7282            state->m_mmc_vrom_bank[cmd] = data;
7283            tengen_800032_set_chr(space->machine());
7284            tengen_800037_set_mirror(space->machine());
7285            break;
7286         case 6: case 7:
7287            state->m_mmc_prg_bank[cmd - 6] = data;
7288            tengen_800032_set_prg(space->machine());
7289            break;
7290         case 8: case 9:
7291            state->m_mmc_vrom_bank[cmd - 2] = data;
7292            tengen_800032_set_chr(space->machine());
7293            tengen_800037_set_mirror(space->machine());
7294            break;
7295         case 0x0f:
7296            state->m_mmc_prg_bank[2] = data;
7297            tengen_800032_set_prg(space->machine());
7298            break;
7299      }
7300         break;
7301
7302      case 0x2000:
7303         break;
7304
7305      default:
7306         tengen_800032_w(space, offset, data);
7307         break;
7308   }
7309}
7310
7311/*************************************************************
7312
7313 Bootleg Board 22211 by TXC (Type A)
7314
7315 Games: Creatom
7316
7317 Info from NEStopia: this mapper features write to four
7318 registers (0x4100-0x4103). The third one is used to select
7319 PRG and CHR banks.
7320
7321 iNES: mapper 132
7322
7323 In MESS: Supported.
7324
7325 *************************************************************/
7326
7327static WRITE8_HANDLER( txc_22211_l_w )
7328{
7329   nes_state *state = space->machine().driver_data<nes_state>();
7330   LOG_MMC(("txc_22211_l_w, offset: %04x, data: %02x\n", offset, data));
7331
7332   if (offset < 4)
7333      state->m_txc_reg[offset & 0x03] = data;
7334}
7335
7336static READ8_HANDLER( txc_22211_l_r )
7337{
7338   nes_state *state = space->machine().driver_data<nes_state>();
7339   LOG_MMC(("txc_22211_l_r, offset: %04x\n", offset));
7340
7341   if (offset == 0x0000)
7342      return (state->m_txc_reg[1] ^ state->m_txc_reg[2]) | 0x40;
7343   else
7344      return 0x00;
7345}
7346
7347static WRITE8_HANDLER( txc_22211_w )
7348{
7349   nes_state *state = space->machine().driver_data<nes_state>();
7350   LOG_MMC(("txc_22211_w, offset: %04x, data: %02x\n", offset, data));
7351
7352   prg32(space->machine(), state->m_txc_reg[2] >> 2);
7353   chr8(space->machine(), state->m_txc_reg[2], CHRROM);
7354}
7355
7356/*************************************************************
7357
7358 Bootleg Board 22211 by TXC (Type B)
7359
7360 Games: 1991 Du Ma Racing
7361
7362 This mapper is basically the same as Type A. Only difference is
7363 in the way CHR banks are selected (see below)
7364
7365 iNES: mapper 172
7366
7367 In MESS: Supported.
7368
7369 *************************************************************/
7370
7371static WRITE8_HANDLER( txc_22211b_w )
7372{
7373   nes_state *state = space->machine().driver_data<nes_state>();
7374   LOG_MMC(("txc_22211b_w, offset: %04x, data: %02x\n", offset, data));
7375
7376   prg32(space->machine(), state->m_txc_reg[2] >> 2);
7377   chr8(space->machine(), (((data ^ state->m_txc_reg[2]) >> 3) & 0x02) | (((data ^ state->m_txc_reg[2]) >> 5) & 0x01), CHRROM);
7378}
7379
7380/*************************************************************
7381
7382 Bootleg Board 22211 by TXC (Type C)
7383
7384 Games: Mahjong Block, Xiao Ma Li
7385
7386 This mapper is basically the same as 132 too. Only difference is
7387 in 0x4100 reads which expect also bit 0 to be set
7388
7389 iNES: mapper 172
7390
7391 In MESS: Supported.
7392
7393 *************************************************************/
7394
7395static READ8_HANDLER( txc_22211c_l_r )
7396{
7397   nes_state *state = space->machine().driver_data<nes_state>();
7398   LOG_MMC(("txc_22211c_l_r, offset: %04x\n", offset));
7399
7400   if (offset == 0x0000)
7401      return (state->m_txc_reg[1] ^ state->m_txc_reg[2]) | 0x41;
7402   else
7403      return 0x00;
7404}
7405
7406/*************************************************************
7407
7408 Bootleg Board 'Thunder Warrior' by TXC
7409
7410 Games: Master Fighter II, Master Fighter 3, Thunder Warrior
7411
7412 MMC3 clone
7413
7414 iNES: mapper 189
7415
7416 In MESS: Supported.
7417
7418 *************************************************************/
7419
7420static WRITE8_HANDLER( txc_tw_l_w )
7421{
7422   LOG_MMC(("txctw_l_w, offset: %04x, data: %02x\n", offset, data));
7423
7424   prg32(space->machine(), (data >> 4) | data);
7425}
7426
7427static WRITE8_HANDLER( txc_tw_m_w )
7428{
7429   LOG_MMC(("txctw_m_w, offset: %04x, data: %04x\n", offset, data));
7430
7431   txc_tw_l_w(space, offset & 0xff, data);   // offset does not really count for this mapper
7432}
7433
7434/* writes to 0x8000-0xffff are like MMC3 but no PRG bankswitch (beacuse it is handled by low writes) */
7435static void txc_tw_prg_cb( running_machine &machine, int start, int bank )
7436{
7437   return;
7438}
7439
7440/*************************************************************
7441
7442 Bootleg Board 'Strike Wolf' by TXC
7443
7444 Games: Strike Wolf (also Policeman?? according to Nestopia)
7445
7446 iNES: mapper 36
7447
7448 Known Boards: Bootleg Board by TXC
7449
7450 In MESS: Supported.
7451
7452 *************************************************************/
7453
7454static WRITE8_HANDLER( txc_strikewolf_w )
7455{
7456   LOG_MMC(("txc_strikewolf_w, offset: %04x, data: %02x\n", offset, data));
7457
7458   if ((offset >= 0x400) && (offset < 0x7fff))
7459   {
7460      prg32(space->machine(), data >> 4);
7461      chr8(space->machine(), data & 0x0f, CHRROM);
7462   }
7463}
7464
7465/*************************************************************
7466
7467 Bootleg Board MXMDHTWO by TXC
7468
7469 Games: Commandos, Journey to the West, Ma Bu Mi Zhen &
7470 Qu Wei Cheng Yu Wu, Si Lu Chuan Qi
7471
7472 Simple Mapper: writes to 0x8000-0xffff sets the prg32 bank.
7473 Not sure if returning 0x50 for reads in 0x4100-0x5000 is correct.
7474
7475 iNES: mapper 241
7476
7477 In MESS: Supported.
7478
7479 *************************************************************/
7480
7481static READ8_HANDLER( txc_mxmdhtwo_l_r )
7482{
7483   return 0x50;
7484}
7485
7486static WRITE8_HANDLER( txc_mxmdhtwo_w )
7487{
7488   LOG_MMC(("txc_mxmdhtwo_w, offset: %04x, data: %02x\n", offset, data));
7489
7490   prg32(space->machine(), data);
7491}
7492
7493/*************************************************************
7494
7495 Waixing Board Type A
7496
7497 Games: Columbus - Ougon no Yoake (C), Ji Jia Zhan Shi,
7498 Jia A Fung Yun, Wei Luo Chuan Qi
7499
7500 This mapper is quite similar to MMC3, but with two differences:
7501 mirroring is not the same, and when VROM banks 8,9 are accessed
7502 they point to CHRRAM and not CHRROM.
7503
7504 iNES: mapper 74
7505
7506 In MESS: Supported
7507
7508 *************************************************************/
7509
7510/* MIRROR_LOW and MIRROR_HIGH are swapped! */
7511static void waixing_set_mirror( running_machine &machine, UINT8 nt )
7512{
7513   switch (nt)
7514   {
7515      case 0:
7516      case 1:
7517         set_nt_mirroring(machine, nt ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT);
7518         break;
7519      case 2:
7520         set_nt_mirroring(machine, PPU_MIRROR_LOW);
7521         break;
7522      case 3:
7523         set_nt_mirroring(machine, PPU_MIRROR_HIGH);
7524         break;
7525      default:
7526         LOG_MMC(("Mapper set NT to invalid value %02x", nt));
7527         break;
7528   }
7529}
7530
7531/* Luo Ke Ren X only works with this */
7532static void waixing_a_chr_cb( running_machine &machine, int start, int bank, int source )
7533{
7534   int chr_src = (bank <= 9) ? CHRRAM : CHRROM;
7535   chr1_x(machine, start, bank, chr_src);
7536}
7537
7538/* Ji Jia Zhan Shi only works with this */
7539static void waixing_a1_chr_cb( running_machine &machine, int start, int bank, int source )
7540{
7541   int chr_src = ((bank == 8) || (bank == 9)) ? CHRRAM : CHRROM;
7542   chr1_x(machine, start, bank, chr_src);
7543}
7544
7545static WRITE8_HANDLER( waixing_a_w )
7546{
7547   LOG_MMC(("waixing_a_w, offset: %04x, data: %02x\n", offset, data));
7548
7549   switch (offset & 0x6001)
7550   {
7551      case 0x2000:
7552         waixing_set_mirror(space->machine(), data);   //maybe data & 0x03?
7553         break;
7554
7555      case 0x2001:
7556         break;
7557
7558      default:
7559         txrom_w(space, offset, data);
7560         break;
7561   }
7562}
7563
7564/*************************************************************
7565
7566 Waixing Board Type B
7567
7568 Games: Sugoro Quest (C)
7569
7570 MMC3 clone. This is a minor modification of Mapper 74,
7571 in the sense that it is the same board except for the
7572 CHRRAM pages.
7573
7574 iNES: mapper 191
7575
7576 In MESS: Supported.
7577
7578 *************************************************************/
7579
7580static void waixing_b_chr_cb( running_machine &machine, int start, int bank, int source )
7581{
7582   int chr_src = BIT(bank, 7) ? CHRRAM : CHRROM;
7583   chr1_x(machine, start, bank, chr_src);
7584}
7585
7586/*************************************************************
7587
7588 Waixing Board Type C
7589
7590 Games: Ying Lie Qun Xia Zhuan, Young Chivalry
7591
7592 MMC3 clone. This is a minor modification of Mapper 74,
7593 in the sense that it is the same board except for the
7594 CHRRAM pages.
7595
7596 iNES: mapper 192
7597
7598 In MESS: Supported.
7599
7600 *************************************************************/
7601
7602static void waixing_c_chr_cb( running_machine &machine, int start, int bank, int source )
7603{
7604   int chr_src = ((bank == 0x08) || (bank == 0x09) || (bank == 0x0a) || (bank == 0x0b)) ? CHRRAM : CHRROM;
7605   chr1_x(machine, start, bank, chr_src);
7606}
7607
7608/*************************************************************
7609
7610 Waixing Board Type D
7611
7612 Games: Super Robot Taisen (C)
7613
7614 MMC3 clone. This is a minor modification of Mapper 74,
7615 in the sense that it is the same board except for the
7616 CHRRAM pages.
7617
7618 iNES: mapper 194
7619
7620 In MESS: Supported.
7621
7622 *************************************************************/
7623
7624static void waixing_d_chr_cb( running_machine &machine, int start, int bank, int source )
7625{
7626   int chr_src = (bank < 0x02) ? CHRRAM : CHRROM;
7627   chr1_x(machine, start, bank, chr_src);
7628}
7629
7630/*************************************************************
7631
7632 Waixing Board Type E
7633
7634 Games: Captain Tsubasa Vol. II (C), Chaos World, God
7635 Slayer (C), Zu Qiu Xiao Jiang
7636
7637 MMC3 clone. This is a minor modification of Mapper 74,
7638 in the sense that it is the same board except for the
7639 CHRRAM pages.
7640
7641 iNES: mapper 195
7642
7643 In MESS: Supported.
7644
7645 *************************************************************/
7646
7647static void waixing_e_chr_cb( running_machine &machine, int start, int bank, int source )
7648{
7649   int chr_src = (bank < 0x04) ? CHRRAM : CHRROM;
7650   chr1_x(machine, start, bank, chr_src);
7651}
7652
7653/*************************************************************
7654
7655 Waixing Board Type F
7656
7657 Games: Tenchi wo Kurau II (C)
7658
7659 MMC3 clone.
7660
7661 iNES: mapper 198
7662
7663 In MESS: Preliminary support.
7664
7665 *************************************************************/
7666
7667static WRITE8_HANDLER( waixing_f_w )
7668{
7669   nes_state *state = space->machine().driver_data<nes_state>();
7670   UINT8 cmd;
7671   LOG_MMC(("waixing_f_w, offset: %04x, data: %02x\n", offset, data));
7672
7673   switch (offset & 0x6001)
7674   {
7675      case 0x0001:
7676         cmd = state->m_mmc_latch1 & 0x07;
7677         if (cmd >= 6)
7678         {
7679            state->m_mmc_prg_bank[cmd - 6] = data & ((data > 0x3f) ? 0x4f : 0x3f);
7680            mmc3_set_prg(space->machine(), state->m_mmc_prg_base, state->m_mmc_prg_mask);
7681         }
7682         else
7683            waixing_a_w(space, offset, data);
7684         break;
7685
7686      default:
7687         waixing_a_w(space, offset, data);
7688         break;
7689   }
7690}
7691
7692/*************************************************************
7693
7694 Waixing Board Type G
7695
7696 Games: San Guo Zhi 2, Dragon Ball Z Gaiden (C), Dragon
7697 Ball Z II (C)
7698
7699 MMC3 clone
7700
7701 iNES: mapper 199
7702
7703 In MESS: Supported.
7704
7705 *************************************************************/
7706
7707static void waixing_g_chr_cb( running_machine &machine, int start, int bank, int source )
7708{
7709   int chr_src = (bank < 0x08) ? CHRRAM : CHRROM;
7710   chr1_x(machine, start, bank, chr_src);
7711}
7712
7713static void waixing_g_set_chr( running_machine &machine, int chr_base, int chr_mask )
7714{
7715   nes_state *state = machine.driver_data<nes_state>();
7716   UINT8 chr_page = (state->m_mmc_latch1 & 0x80) >> 5;
7717
7718   state->m_mmc3_chr_cb(machine, chr_page ^ 0, chr_base | (state->m_mmc_vrom_bank[0] & chr_mask), state->m_mmc_chr_source);
7719   state->m_mmc3_chr_cb(machine, chr_page ^ 1, chr_base | (state->m_mmc_vrom_bank[6] & chr_mask), state->m_mmc_chr_source);
7720   state->m_mmc3_chr_cb(machine, chr_page ^ 2, chr_base | (state->m_mmc_vrom_bank[1] & chr_mask), state->m_mmc_chr_source);
7721   state->m_mmc3_chr_cb(machine, chr_page ^ 3, chr_base | (state->m_mmc_vrom_bank[7] & chr_mask), state->m_mmc_chr_source);
7722   state->m_mmc3_chr_cb(machine, chr_page ^ 4, chr_base | (state->m_mmc_vrom_bank[2] & chr_mask), state->m_mmc_chr_source);
7723   state->m_mmc3_chr_cb(machine, chr_page ^ 5, chr_base | (state->m_mmc_vrom_bank[3] & chr_mask), state->m_mmc_chr_source);
7724   state->m_mmc3_chr_cb(machine, chr_page ^ 6, chr_base | (state->m_mmc_vrom_bank[4] & chr_mask), state->m_mmc_chr_source);
7725   state->m_mmc3_chr_cb(machine, chr_page ^ 7, chr_base | (state->m_mmc_vrom_bank[5] & chr_mask), state->m_mmc_chr_source);
7726}
7727
7728static WRITE8_HANDLER( waixing_g_w )
7729{
7730   nes_state *state = space->machine().driver_data<nes_state>();
7731   UINT8 MMC3_helper, cmd;
7732   LOG_MMC(("waixing_g_w, offset: %04x, data: %02x\n", offset, data));
7733
7734   switch (offset & 0x6001)
7735   {
7736      case 0x0000:
7737         MMC3_helper = state->m_mmc_latch1 ^ data;
7738         state->m_mmc_latch1 = data;
7739
7740         /* Has PRG Mode changed? */
7741         if (MMC3_helper & 0x40)
7742            mmc3_set_prg(space->machine(), state->m_mmc_prg_base, state->m_mmc_prg_mask);
7743
7744         /* Has CHR Mode changed? */
7745         if (MMC3_helper & 0x80)
7746            waixing_g_set_chr(space->machine(), state->m_mmc_chr_base, state->m_mmc_chr_mask);
7747         break;
7748
7749      case 0x0001:
7750         cmd = state->m_mmc_latch1 & 0x0f;
7751         switch (cmd)
7752         {
7753         case 0: case 1:   // these do not need to be separated: we take care of them in set_chr!
7754         case 2: case 3: case 4: case 5:
7755            state->m_mmc_vrom_bank[cmd] = data;
7756            waixing_g_set_chr(space->machine(), state->m_mmc_chr_base, state->m_mmc_chr_mask);
7757            break;
7758         case 6:
7759         case 7:
7760         case 8:
7761         case 9:
7762            state->m_mmc_prg_bank[cmd - 6] = data;
7763            mmc3_set_prg(space->machine(), state->m_mmc_prg_base, state->m_mmc_prg_mask);
7764            break;
7765         case 0x0a: case 0x0b:
7766            state->m_mmc_vrom_bank[cmd - 4] = data;
7767            waixing_g_set_chr(space->machine(), state->m_mmc_chr_base, state->m_mmc_chr_mask);
7768            break;
7769         }
7770         break;
7771
7772      default:
7773         waixing_a_w(space, offset, data);
7774         break;
7775   }
7776}
7777
7778/*************************************************************
7779
7780 Waixing Board Type H
7781
7782 Games: Ying Xiong Yuan Yi Jing Chuan Qi, Yong Zhe Dou E
7783 Long - Dragon Quest VII
7784
7785 MMC3 clone. More info to come.
7786
7787 iNES: mapper 245
7788
7789 In MESS: Supported.
7790
7791 *************************************************************/
7792
7793static void waixing_h_chr_cb( running_machine &machine, int start, int bank, int source )
7794{
7795   if (source == CHRROM)
7796      chr1_x(machine, start, bank, source);
7797}
7798
7799static WRITE8_HANDLER( waixing_h_w )
7800{
7801   nes_state *state = space->machine().driver_data<nes_state>();
7802   UINT8 cmd;
7803   LOG_MMC(("waixing_h_w, offset: %04x, data: %02x\n", offset, data));
7804
7805   switch (offset & 0x6001)
7806   {
7807      case 0x0001:
7808         cmd = state->m_mmc3_latch & 0x07;
7809         switch (cmd)
7810         {
7811         case 0:    // in this case we set prg_base in addition to state->m_mmc_vrom_bank!
7812            state->m_mmc_prg_base = (data << 5) & 0x40;
7813            state->m_mmc_prg_mask = 0x3f;
7814            mmc3_set_prg(space->machine(), state->m_mmc_prg_base, state->m_mmc_prg_mask);
7815            txrom_w(space, offset, data);
7816         default:
7817            txrom_w(space, offset, data);
7818            break;
7819         }
7820         break;
7821
7822      case 0x2001:
7823         break;
7824
7825      default:
7826         txrom_w(space, offset, data);
7827         break;
7828   }
7829}
7830
7831/*************************************************************
7832
7833 Waixing San Guo Zhi Board
7834
7835 Games: San Guo Zhi
7836
7837 This board uses Konami IRQ
7838
7839 iNES: mapper 252
7840
7841 In MESS: Unsupported.
7842
7843 *************************************************************/
7844
7845static WRITE8_HANDLER( waixing_sgz_w )
7846{
7847   nes_state *state = space->machine().driver_data<nes_state>();
7848   UINT8 mmc_helper, bank;
7849   LOG_MMC(("waixing_sgz_w, offset: %04x, data: %02x\n", offset, data));
7850
7851   switch (offset & 0x7000)
7852   {
7853      case 0x0000:
7854         prg8_89(space->machine(), data);
7855         break;
7856      case 0x2000:
7857         prg8_ab(space->machine(), data);
7858         break;
7859      case 0x3000:
7860      case 0x4000:
7861      case 0x5000:
7862      case 0x6000:
7863         bank = ((offset & 0x7000) - 0x3000) / 0x0800 + ((offset & 0x0008) >> 3);
7864         mmc_helper = offset & 0x04;
7865         if (mmc_helper)
7866            state->m_mmc_vrom_bank[bank] = (state->m_mmc_vrom_bank[bank] & 0x0f) | ((data & 0x0f) << 4);
7867         else
7868            state->m_mmc_vrom_bank[bank] = (state->m_mmc_vrom_bank[bank] & 0xf0) | (data & 0x0f);
7869         chr1_x(space->machine(), bank, state->m_mmc_vrom_bank[bank], CHRROM);
7870         break;
7871      case 0x7000:
7872         switch (offset & 0x0c)
7873         {
7874         case 0x00:
7875            state->m_IRQ_count_latch = (state->m_IRQ_count_latch & 0xf0) | (data & 0x0f);
7876            break;
7877         case 0x04:
7878            state->m_IRQ_count_latch = (state->m_IRQ_count_latch & 0x0f) | ((data & 0x0f) << 4);
7879            break;
7880         case 0x08:
7881            state->m_IRQ_enable = data & 0x02;
7882            state->m_IRQ_enable_latch = data & 0x01;
7883            if (data & 0x02)
7884               state->m_IRQ_count = state->m_IRQ_count_latch;
7885            break;
7886         case 0x0c:
7887            state->m_IRQ_enable = state->m_IRQ_enable_latch;
7888            break;
7889         }
7890         break;
7891   }
7892}
7893
7894
7895/*************************************************************
7896
7897 Waixing San Guo Zhong Lie Zhuan Board
7898
7899 Games: Fan Kong Jing Ying, San Guo Zhong Lie Zhuan, Xing
7900 Ji Zheng Ba
7901
7902 iNES: mapper 178
7903
7904 In MESS: Supported.
7905
7906 *************************************************************/
7907
7908static WRITE8_HANDLER( waixing_sgzlz_l_w )
7909{
7910   nes_state *state = space->machine().driver_data<nes_state>();
7911   LOG_MMC(("waixing_sgzlz_l_w, offset: %04x, data: %02x\n", offset, data));
7912
7913   switch (offset)
7914   {
7915      case 0x700:
7916         set_nt_mirroring(space->machine(), data ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT);
7917         break;
7918      case 0x701:
7919         state->m_mmc_latch1 = (state->m_mmc_latch1 & 0x0c) | ((data >> 1) & 0x03);
7920         prg32(space->machine(), state->m_mmc_latch1);
7921         break;
7922      case 0x702:
7923         state->m_mmc_latch1 = (state->m_mmc_latch1 & 0x03) | ((data << 2) & 0x0c);
7924         break;
7925   }
7926}
7927
7928/*************************************************************
7929
7930 Waixing Final Fantasy V Board
7931
7932 Games: Darkseed, Digital Dragon, Final Fantasy V, Pocket
7933 Monster Red
7934
7935 iNES: mapper 164
7936
7937 In MESS: Supported.
7938
7939 *************************************************************/
7940
7941static WRITE8_HANDLER( waixing_ffv_l_w )
7942{
7943   nes_state *state = space->machine().driver_data<nes_state>();
7944   UINT8 mmc_helper;
7945   LOG_MMC(("waixing_ffv_l_w, offset: %04x, data: %02x\n", offset, data));
7946   offset += 0x100; /* the checks work better on addresses */
7947
7948   if (0x1000 == (offset & 0x1200))
7949   {
7950      state->m_mmc_reg[BIT(offset, 8)] = data;
7951      mmc_helper = BIT(state->m_mmc_reg[1], 0) << 5;
7952      switch (state->m_mmc_reg[0] & 0x70)
7953      {
7954         case 0x00:
7955         case 0x20:
7956         case 0x40:
7957         case 0x60:
7958            prg16_89ab(space->machine(), mmc_helper | ((state->m_mmc_reg[0] >> 1) & 0x10) | (state->m_mmc_reg[0] & 0x0f));
7959            prg16_cdef(space->machine(), mmc_helper & 0x1f);
7960            break;
7961         case 0x50:
7962            prg32(space->machine(), (mmc_helper >> 1) | (state->m_mmc_reg[0] & 0x0f));
7963            break;
7964         case 0x70:
7965            prg16_89ab(space->machine(), mmc_helper | ((state->m_mmc_reg[0] << 1) & 0x10) | (state->m_mmc_reg[0] & 0x0f));
7966            prg16_cdef(space->machine(), mmc_helper & 0x1f);
7967            break;
7968      }
7969   }
7970}
7971
7972/*************************************************************
7973
7974 Waixing Zhan Shi Board
7975
7976 Games: Wai Xing Zhan Shi
7977
7978 Simple mapper: writes to 0x8000-0xffff sets prg32 banks to
7979 (offset>>3)&f. written data&3 sets the mirroring (with
7980 switched high/low compared to the standard one).
7981
7982 A crc check is required to support Dragon Quest VIII (which
7983 uses a slightly different board)
7984
7985 iNES: mapper 242
7986
7987 In MESS: Supported.
7988
7989 *************************************************************/
7990
7991static WRITE8_HANDLER( waixing_zs_w )
7992{
7993   LOG_MMC(("waixing_zs_w, offset: %04x, data: %02x\n", offset, data));
7994
7995   prg32(space->machine(), offset >> 3);
7996
7997   switch (data & 0x03)
7998   {
7999      case 0: set_nt_mirroring(space->machine(), PPU_MIRROR_VERT); break;
8000      case 1: set_nt_mirroring(space->machine(), PPU_MIRROR_HORZ); break;
8001      case 2: set_nt_mirroring(space->machine(), PPU_MIRROR_LOW); break;
8002      case 3: set_nt_mirroring(space->machine(), PPU_MIRROR_HIGH); break;
8003   }
8004}
8005
8006/*************************************************************
8007
8008 Waixing Dragon Quest VIII Board
8009
8010 Games: Dragon Quest VIII
8011
8012 Simple mapper: writes to 0x8000-0xffff sets prg32 banks to
8013 (offset>>3)&f.
8014
8015 iNES: mapper 242
8016
8017 In MESS: Supported.
8018
8019 *************************************************************/
8020
8021static WRITE8_HANDLER( waixing_dq8_w )
8022{
8023   LOG_MMC(("waixing_dq8_w, offset: %04x, data: %02x\n", offset, data));
8024
8025   prg32(space->machine(), offset >> 3);
8026}
8027
8028
8029/*************************************************************
8030
8031 Waixing PS2 board
8032
8033 Games: Bao Xiao Tien Guo, Bio Hazard, Pokemon Gold, Subor (R)
8034
8035 iNES: mapper 15
8036
8037 In MESS: Supported
8038
8039 *************************************************************/
8040
8041static WRITE8_HANDLER( waixing_ps2_w )
8042{
8043   UINT8 map15_flip = (data & 0x80) >> 7;
8044   UINT8 map15_helper = (data & 0x7f) << 1;
8045
8046   LOG_MMC(("waixing_ps2_w, offset: %04x, data: %02x\n", offset, data));
8047
8048   set_nt_mirroring(space->machine(), BIT(data, 6) ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT);
8049
8050   switch (offset & 0x0fff)
8051   {
8052      case 0x000:
8053         prg8_89(space->machine(), (map15_helper + 0) ^ map15_flip);
8054         prg8_ab(space->machine(), (map15_helper + 1) ^ map15_flip);
8055         prg8_cd(space->machine(), (map15_helper + 2) ^ map15_flip);
8056         prg8_ef(space->machine(), (map15_helper + 3) ^ map15_flip);
8057         break;
8058      case 0x001:
8059         map15_helper |= map15_flip;
8060         prg8_89(space->machine(), map15_helper);
8061         prg8_ab(space->machine(), map15_helper + 1);
8062         prg8_cd(space->machine(), map15_helper + 1);
8063         prg8_ef(space->machine(), map15_helper + 1);
8064         break;
8065      case 0x002:
8066         map15_helper |= map15_flip;
8067         prg8_89(space->machine(), map15_helper);
8068         prg8_ab(space->machine(), map15_helper);
8069         prg8_cd(space->machine(), map15_helper);
8070         prg8_ef(space->machine(), map15_helper);
8071         break;
8072      case 0x003:
8073         map15_helper |= map15_flip;
8074         prg8_89(space->machine(), map15_helper);
8075         prg8_ab(space->machine(), map15_helper + 1);
8076         prg8_cd(space->machine(), map15_helper);
8077         prg8_ef(space->machine(), map15_helper + 1);
8078         break;
8079   }
8080}
8081
8082/*************************************************************
8083
8084 Waixing Board with Security Chip
8085
8086 Games: Duo Bao Xiao Ying Hao - Guang Ming yu An Hei Chuan Shuo,
8087 Myth Struggle, San Shi Liu Ji, Shui Hu Zhuan
8088
8089 MMC3 clone
8090
8091 iNES: mapper 249
8092
8093 In MESS: Partially Supported.
8094
8095 *************************************************************/
8096
8097static void waixing_sec_prg_cb( running_machine &machine, int start, int bank )
8098{
8099   nes_state *state = machine.driver_data<nes_state>();
8100
8101   if (state->m_mmc_reg[0])
8102      bank = ((bank & 0x01)) | ((bank >> 3) & 0x02) | ((bank >> 1) & 0x04) | ((bank << 2) & 0x18);
8103
8104   prg8_x(machine, start, bank);
8105}
8106
8107static void waixing_sec_chr_cb( running_machine &machine, int start, int bank, int source )
8108{
8109   nes_state *state = machine.driver_data<nes_state>();
8110
8111   if (state->m_mmc_reg[0])
8112      bank = ((bank & 0x03)) | ((bank >> 1) & 0x04) | ((bank >> 4) & 0x08) |
8113            ((bank >> 2) & 0x10) | ((bank << 3) & 0x20) | ((bank << 2) & 0xc0);
8114
8115   chr1_x(machine, start, bank, source);
8116}
8117
8118static WRITE8_HANDLER( waixing_sec_l_w )
8119{
8120   nes_state *state = space->machine().driver_data<nes_state>();
8121   LOG_MMC(("waixing_sec_l_w, offset: %04x, data: %02x\n", offset, data));
8122
8123   offset += 0x100;
8124
8125   if (offset == 0x1000)
8126   {
8127      state->m_mmc_reg[0] = data & 0x02;
8128      mmc3_set_prg(space->machine(), state->m_mmc_prg_base, state->m_mmc_prg_mask);
8129      mmc3_set_chr(space->machine(), state->m_mmc_chr_source, state->m_mmc_chr_base, state->m_mmc_chr_mask);
8130   }
8131}
8132
8133/*************************************************************
8134
8135 Waixing SH2 Board
8136
8137 Games: Fire Emblem (C) and Fire Emblem Gaiden (C)
8138
8139 MMC3 clone with different access to CHR
8140
8141 iNES: mapper 165
8142
8143 In MESS: Partially Supported.
8144
8145 *************************************************************/
8146
8147static void waixing_sh2_chr_cb( running_machine &machine, int start, int bank, int source )
8148{
8149   nes_state *state = machine.driver_data<nes_state>();
8150
8151   chr4_0(machine, state->m_mmc_reg[0], state->m_mmc_reg[0] ? CHRRAM : CHRROM);
8152   chr4_4(machine, state->m_mmc_reg[1], state->m_mmc_reg[1] ? CHRRAM : CHRROM);
8153}
8154
8155READ8_HANDLER( waixing_sh2_chr_r )
8156{
8157   nes_state *state = space->machine().driver_data<nes_state>();
8158   int bank = offset >> 10;
8159   UINT8 val = state->m_chr_map[bank].access[offset & 0x3ff];   // this would be usual return value
8160   int chr_helper;
8161
8162   switch (offset & 0xff8)
8163   {
8164      case 0xfd0: chr_helper = (bank & 0x4) | 0x0; break;
8165      case 0xfe8: chr_helper = (bank & 0x4) | 0x2; break;
8166      default: return val;
8167   }
8168
8169   state->m_mmc_reg[offset >> 12] = chr_helper;
8170   if (offset & 0x1000)
8171      chr4_4(space->machine(), state->m_mmc_reg[1], state->m_mmc_reg[1] ? CHRRAM : CHRROM);
8172   else
8173      chr4_0(space->machine(), state->m_mmc_reg[0], state->m_mmc_reg[0] ? CHRRAM : CHRROM);
8174
8175   return val;
8176}
8177
8178/*************************************************************
8179
8180 Board UNL-8237
8181
8182 Games: Pocahontas 2
8183
8184 MMC3 clone
8185
8186 In MESS: Supported
8187
8188 *************************************************************/
8189
8190static void unl_8237_prg_cb( running_machine &machine, int start, int bank )
8191{
8192   nes_state *state = machine.driver_data<nes_state>();
8193
8194   if (!(state->m_mmc_reg[0] & 0x80))
8195      prg8_x(machine, start, bank);
8196}
8197
8198static void unl_8237_chr_cb( running_machine &machine, int start, int bank, int source )
8199{
8200   nes_state *state = machine.driver_data<nes_state>();
8201   bank |= ((state->m_mmc_reg[1] << 6) & 0x100);
8202
8203   chr1_x(machine, start, bank, source);
8204}
8205
8206static WRITE8_HANDLER( unl_8237_l_w )
8207{
8208   nes_state *state = space->machine().driver_data<nes_state>();
8209   LOG_MMC(("unl_8237_l_w offset: %04x, data: %02x\n", offset, data));
8210   offset += 0x100;
8211
8212   if (offset == 0x1000)
8213   {
8214      state->m_mmc_reg[0] = data;
8215      if (state->m_mmc_reg[0] & 0x80)
8216      {
8217         if (state->m_mmc_reg[0] & 0x20)
8218            prg32(space->machine(), (state->m_mmc_reg[0] & 0x0f) >> 1);
8219         else
8220         {
8221            prg16_89ab(space->machine(), state->m_mmc_reg[0] & 0x1f);
8222            prg16_cdef(space->machine(), state->m_mmc_reg[0] & 0x1f);
8223         }
8224      }
8225      else
8226         mmc3_set_prg(space->machine(), state->m_mmc_prg_base, state->m_mmc_prg_mask);
8227   }
8228
8229   if (offset == 0x1001)
8230   {
8231      state->m_mmc_reg[1] = data;
8232      mmc3_set_chr(space->machine(), state->m_mmc_chr_source, state->m_mmc_chr_base, state->m_mmc_chr_mask);
8233   }
8234}
8235
8236static WRITE8_HANDLER( unl_8237_w )
8237{
8238   nes_state *state = space->machine().driver_data<nes_state>();
8239   static const UINT8 conv_table[8] = {0, 2, 6, 1, 7, 3, 4, 5};
8240   LOG_MMC(("unl_8237_w offset: %04x, data: %02x\n", offset, data));
8241
8242   switch (offset & 0x7000)
8243   {
8244      case 0x0000:
8245      case 0x1000:
8246         set_nt_mirroring(space->machine(), (data | (data >> 7)) & 0x01 ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT);
8247         break;
8248
8249      case 0x2000:
8250      case 0x3000:
8251         state->m_mmc_reg[2] = 1;
8252         data = (data & 0xc0) | conv_table[data & 0x07];
8253         txrom_w(space, 0x0000, data);
8254         break;
8255
8256      case 0x4000:
8257      case 0x5000:
8258         if (state->m_mmc_reg[2])
8259         {
8260            state->m_mmc_reg[2] = 0;
8261            txrom_w(space, 0x0001, data);
8262         }
8263         break;
8264
8265      case 0x6000:
8266         break;
8267
8268      case 0x7000:
8269         txrom_w(space, 0x6001, data);
8270         txrom_w(space, 0x4000, data);
8271         txrom_w(space, 0x4001, data);
8272         break;
8273   }
8274}
8275
8276/*************************************************************
8277
8278 Board UNL-AX5705
8279
8280 Games: Super Mario Bros. Pocker Mali (Crayon Shin-chan pirate hack)
8281
8282 In MESS: Supported
8283
8284 *************************************************************/
8285
8286static void unl_ax5705_set_prg( running_machine &machine )
8287{
8288   nes_state *state = machine.driver_data<nes_state>();
8289   prg8_89(machine, state->m_mmc_prg_bank[0]);
8290   prg8_ab(machine, state->m_mmc_prg_bank[1]);
8291}
8292
8293static WRITE8_HANDLER( unl_ax5705_w )
8294{
8295   nes_state *state = space->machine().driver_data<nes_state>();
8296   UINT8 bank;
8297   LOG_MMC(("unl_ax5705_w offset: %04x, data: %02x\n", offset, data));
8298
8299   switch (offset & 0x700f)
8300   {
8301      case 0x0000:
8302         state->m_mmc_prg_bank[0] = (data & 0x05) | ((data & 0x08) >> 2) | ((data & 0x02) << 2);
8303         unl_ax5705_set_prg(space->machine());
8304         break;
8305      case 0x0008:
8306         set_nt_mirroring(space->machine(), BIT(data, 0) ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT);
8307         break;
8308      case 0x2000:
8309         state->m_mmc_prg_bank[1] = (data & 0x05) | ((data & 0x08) >> 2) | ((data & 0x02) << 2);
8310         unl_ax5705_set_prg(space->machine());
8311         break;
8312         /* CHR banks 0, 1, 4, 5 */
8313      case 0x2008:
8314      case 0x200a:
8315      case 0x4008:
8316      case 0x400a:
8317         bank = ((offset & 0x4000) ? 4 : 0) + ((offset & 0x0002) ? 1 : 0);
8318         state->m_mmc_vrom_bank[bank] = (state->m_mmc_vrom_bank[bank] & 0xf0) | (data & 0x0f);
8319         chr1_x(space->machine(), bank, state->m_mmc_vrom_bank[bank], CHRROM);
8320         break;
8321      case 0x2009:
8322      case 0x200b:
8323      case 0x4009:
8324      case 0x400b:
8325         bank = ((offset & 0x4000) ? 4 : 0) + ((offset & 0x0002) ? 1 : 0);
8326         state->m_mmc_vrom_bank[bank] = (state->m_mmc_vrom_bank[bank] & 0x0f) | ((data & 0x04) << 3) | ((data & 0x02) << 5) | ((data & 0x09) << 4);
8327         chr1_x(space->machine(), bank, state->m_mmc_vrom_bank[bank], CHRROM);
8328         break;
8329         /* CHR banks 2, 3, 6, 7 */
8330      case 0x4000:
8331      case 0x4002:
8332      case 0x6000:
8333      case 0x6002:
8334         bank = 2 + ((offset & 0x2000) ? 4 : 0) + ((offset & 0x0002) ? 1 : 0);
8335         state->m_mmc_vrom_bank[bank] = (state->m_mmc_vrom_bank[bank] & 0xf0) | (data & 0x0f);
8336         chr1_x(space->machine(), bank, state->m_mmc_vrom_bank[bank], CHRROM);
8337         break;
8338      case 0x4001:
8339      case 0x4003:
8340      case 0x6001:
8341      case 0x6003:
8342         bank = 2 + ((offset & 0x2000) ? 4 : 0) + ((offset & 0x0002) ? 1 : 0);
8343         state->m_mmc_vrom_bank[bank] = (state->m_mmc_vrom_bank[bank] & 0x0f) | ((data & 0x04) << 3) | ((data & 0x02) << 5) | ((data & 0x09) << 4);
8344         chr1_x(space->machine(), bank, state->m_mmc_vrom_bank[bank], CHRROM);
8345         break;
8346   }
8347}
8348
8349/*************************************************************
8350
8351 Board UNL-CC-21
8352
8353 Games: Mi Hun Che
8354
8355 In MESS: Supported
8356
8357 *************************************************************/
8358
8359static WRITE8_HANDLER( unl_cc21_w )
8360{
8361   LOG_MMC(("unl_cc21_w offset: %04x, data: %02x\n", offset, data));
8362
8363   set_nt_mirroring(space->machine(), BIT(data, 1) ? PPU_MIRROR_HIGH : PPU_MIRROR_LOW);
8364   chr8(space->machine(), (offset & 0x01), CHRROM);
8365}
8366
8367/*************************************************************
8368
8369 Board UNL-KOF97
8370
8371 Games: King of Fighters 97 (Rex Soft)
8372
8373 MMC3 clone
8374
8375 In MESS: Not working
8376
8377 *************************************************************/
8378
8379static UINT8 unl_kof97_unscramble( UINT8 data )
8380{
8381   return ((data >> 1) & 0x01) | ((data >> 4) & 0x02) | ((data << 2) & 0x04) | ((data >> 0) & 0xd8) | ((data << 3) & 0x20);
8382}
8383
8384static WRITE8_HANDLER( unl_kof97_w )
8385{
8386   LOG_MMC(("unl_kof97_w offset: %04x, data: %02x\n", offset, data));
8387
8388   /* Addresses 0x9000, 0xa000, 0xd000 & 0xf000 behaves differently than MMC3 */
8389   if (offset == 0x1000)
8390   {
8391      data = unl_kof97_unscramble(data);
8392      txrom_w(space, 0x0001, data);
8393   }
8394   else if (offset == 0x2000)
8395   {
8396      data = unl_kof97_unscramble(data);
8397      txrom_w(space, 0x0000, data);
8398   }
8399   else if (offset == 0x5000)
8400   {
8401      data = unl_kof97_unscramble(data);
8402      txrom_w(space, 0x4001, data);
8403   }
8404   else if (offset == 0x7000)
8405   {
8406      data = unl_kof97_unscramble(data);
8407      txrom_w(space, 0x6001, data);
8408   }
8409   else      /* Other addresses behaves like MMC3, up to unscrambling data */
8410   {
8411      switch (offset & 0x6001)
8412      {
8413         case 0x0000:
8414         case 0x0001:
8415         case 0x4000:
8416         case 0x4001:
8417         case 0x6000:
8418         case 0x6001:
8419         case 0x2000:   /* are these ever called?!? */
8420         case 0x2001:
8421            data = unl_kof97_unscramble(data);
8422            txrom_w(space, offset, data);
8423            break;
8424      }
8425   }
8426}
8427
8428/*************************************************************
8429
8430 Board UNL-T-230
8431
8432 Games: Dragon Ball Z IV (Unl)
8433
8434 In MESS: Supported
8435
8436 *************************************************************/
8437
8438static WRITE8_HANDLER( unl_t230_w )
8439{
8440   nes_state *state = space->machine().driver_data<nes_state>();
8441   UINT8 bank;
8442   LOG_MMC(("unl_t230_w offset: %04x, data: %02x\n", offset, data));
8443
8444   switch (offset & 0x700c)
8445   {
8446      case 0x0000:
8447         break;
8448      case 0x2000:
8449         prg16_89ab(space->machine(), data);
8450         break;
8451
8452      // the part below works like VRC-2. how was the original board wired up?
8453      // was there a VRC2? if so, we can use VRC-2 and add proper pin settings to xml!
8454      case 0x1000:
8455      case 0x1004:
8456      case 0x1008:
8457      case 0x100c:
8458         switch (data & 0x03)
8459         {
8460         case 0x00: set_nt_mirroring(space->machine(), PPU_MIRROR_VERT); break;
8461         case 0x01: set_nt_mirroring(space->machine(), PPU_MIRROR_HORZ); break;
8462         case 0x02: set_nt_mirroring(space->machine(), PPU_MIRROR_LOW); break;
8463         case 0x03: set_nt_mirroring(space->machine(), PPU_MIRROR_HIGH); break;
8464         }
8465         break;
8466
8467      case 0x3000:
8468      case 0x3004:
8469      case 0x3008:
8470      case 0x300c:
8471      case 0x4000:
8472      case 0x4004:
8473      case 0x4008:
8474      case 0x400c:
8475      case 0x5000:
8476      case 0x5004:
8477      case 0x5008:
8478      case 0x500c:
8479      case 0x6000:
8480      case 0x6004:
8481      case 0x6008:
8482      case 0x600c:
8483         bank = ((offset & 0x7000) - 0x3000) / 0x0800 + ((offset & 0x0008) >> 2);
8484         if (offset & 0x0004)
8485            state->m_mmc_vrom_bank[bank] = (state->m_mmc_vrom_bank[bank] & 0x0f) | (data << 4);
8486         else
8487            state->m_mmc_vrom_bank[bank] = (state->m_mmc_vrom_bank[bank] & 0xf0) | (data & 0x0f);
8488
8489         chr1_x(space->machine(), bank, state->m_mmc_vrom_bank[bank], state->m_mmc_chr_source);
8490         break;
8491      case 0x7000:
8492         state->m_IRQ_count_latch &= ~0x0f;
8493         state->m_IRQ_count_latch |= data & 0x0f;
8494         break;
8495      case 0x7004:
8496         state->m_IRQ_count_latch &= ~0xf0;
8497         state->m_IRQ_count_latch |= (data << 4) & 0xf0;
8498         break;
8499      case 0x7008:
8500         state->m_IRQ_mode = data & 0x04;   // currently not implemented: 0 = prescaler mode / 1 = CPU mode
8501         state->m_IRQ_enable = data & 0x02;
8502         state->m_IRQ_enable_latch = data & 0x01;
8503         if (data & 0x02)
8504            state->m_IRQ_count = state->m_IRQ_count_latch;
8505         break;
8506
8507      default:
8508         logerror("unl_t230_w uncaught offset: %04x value: %02x\n", offset, data);
8509         break;
8510   }
8511}
8512
8513/*************************************************************
8514
8515 Bootleg Board for KOF96
8516
8517 Games: The King of Fighters 96, Sonic 3D Blast 6, Street
8518 Fighter Zero 2
8519
8520 MMC3 clone
8521
8522 iNES: mapper 187
8523
8524 In MESS: Preliminary Support.
8525
8526 *************************************************************/
8527
8528static void kof96_prg_cb( running_machine &machine, int start, int bank )
8529{
8530   nes_state *state = machine.driver_data<nes_state>();
8531
8532   if (!(state->m_mmc_reg[0] & 0x80))
8533      prg8_x(machine, start, bank);
8534}
8535
8536static void kof96_chr_cb( running_machine &machine, int start, int bank, int source )
8537{
8538   nes_state *state = machine.driver_data<nes_state>();
8539   UINT8 chr_page = (state->m_mmc_latch1 & 0x80) >> 5;
8540
8541   if ((start & 0x04) == chr_page)
8542      bank |= 0x100;
8543
8544   chr1_x(machine, start, bank, source);
8545}
8546
8547static WRITE8_HANDLER( kof96_l_w )
8548{
8549   nes_state *state = space->machine().driver_data<nes_state>();
8550   UINT8 new_bank;
8551   LOG_MMC(("kof96_l_w, offset: %04x, data: %02x\n", offset, data));
8552   offset += 0x100;
8553
8554   if (offset == 0x1000)
8555   {
8556      state->m_mmc_reg[0] = data;
8557
8558      if (state->m_mmc_reg[0] & 0x80)
8559      {
8560         new_bank = (state->m_mmc_reg[0] & 0x1f);
8561
8562         if (state->m_mmc_reg[0] & 0x20)
8563            prg32(space->machine(), new_bank >> 2);
8564         else
8565         {
8566            prg16_89ab(space->machine(), new_bank);
8567            prg16_cdef(space->machine(), new_bank);
8568         }
8569      }
8570      else
8571         mmc3_set_prg(space->machine(), state->m_mmc_prg_base, state->m_mmc_prg_mask);
8572   }
8573
8574   if (offset >= 0x1000)
8575   {
8576      switch (data & 0x03)
8577      {
8578         case 0x00:
8579         case 0x01:
8580            state->m_mmc_reg[1] = 0x83;
8581            break;
8582         case 0x02:
8583            state->m_mmc_reg[1] = 0x42;
8584            break;
8585         case 0x03:
8586            state->m_mmc_reg[1] = 0x00;
8587            break;
8588      }
8589
8590   }
8591
8592   if (!state->m_mmc_reg[3] && offset > 0x1000)
8593   {
8594      state->m_mmc_reg[3] = 1;
8595      space->write_byte(0x4017, 0x40);
8596   }
8597}
8598
8599static READ8_HANDLER( kof96_l_r )
8600{
8601   nes_state *state = space->machine().driver_data<nes_state>();
8602   LOG_MMC(("kof96_l_r, offset: %04x\n", offset));
8603   offset += 0x100;
8604
8605   if (!(offset < 0x1000))
8606      return state->m_mmc_reg[1];
8607   else
8608      return 0;
8609}
8610
8611static WRITE8_HANDLER( kof96_w )
8612{
8613   nes_state *state = space->machine().driver_data<nes_state>();
8614   LOG_MMC(("kof96_w, offset: %04x, data: %02x\n", offset, data));
8615
8616   switch (offset & 0x6003)
8617   {
8618      case 0x0000:
8619         state->m_mmc_reg[2] = 1;
8620         txrom_w(space, 0x0000, data);
8621         break;
8622
8623      case 0x0001:
8624         if (state->m_mmc_reg[2])
8625            txrom_w(space, 0x0001, data);
8626         break;
8627
8628      case 0x0002:
8629         break;
8630
8631      case 0x0003:
8632         state->m_mmc_reg[2] = 0;
8633
8634         if (data == 0x28)
8635            prg8_cd(space->machine(), 0x17);
8636         else if (data == 0x2a)
8637            prg8_ab(space->machine(), 0x0f);
8638         break;
8639
8640      default:
8641         txrom_w(space, offset, data);
8642         break;
8643   }
8644}
8645
8646/*************************************************************
8647
8648 Bootleg Board for MK2
8649
8650 Games: Mortal Kombat II, Street Fighter III, Super Mario
8651 Kart Rider
8652
8653 This board uses an IRQ system very similar to MMC3. We indeed
8654 use mapper4_irq, but there is some small glitch!
8655
8656 iNES: mapper 91
8657
8658 In MESS: Supported.
8659
8660 *************************************************************/
8661
8662static WRITE8_HANDLER( mk2_m_w )
8663{
8664   nes_state *state = space->machine().driver_data<nes_state>();
8665   LOG_MMC(("mk2_m_w, offset: %04x, data: %02x\n", offset, data));
8666
8667   switch (offset & 0x1000)
8668   {
8669      case 0x0000:
8670         switch (offset & 0x03)
8671         {
8672         case 0x00: chr2_0(space->machine(), data, CHRROM); break;
8673         case 0x01: chr2_2(space->machine(), data, CHRROM); break;
8674         case 0x02: chr2_4(space->machine(), data, CHRROM); break;
8675         case 0x03: chr2_6(space->machine(), data, CHRROM); break;
8676         }
8677         break;
8678      case 0x1000:
8679         switch (offset & 0x03)
8680         {
8681         case 0x00: prg8_89(space->machine(), data); break;
8682         case 0x01: prg8_ab(space->machine(), data); break;
8683         case 0x02: state->m_IRQ_enable = 0; state->m_IRQ_count = 0; break;
8684         case 0x03: state->m_IRQ_enable = 1; state->m_IRQ_count = 7; break;
8685         }
8686         break;
8687      default:
8688         logerror("mk2_m_w uncaught addr: %04x value: %02x\n", offset + 0x6000, data);
8689         break;
8690   }
8691}
8692
8693/*************************************************************
8694
8695 Bootleg Board N625092
8696
8697 Games: 400 in 1, 700 in 1, 1000 in 1
8698
8699 iNES: mapper 221
8700
8701 In MESS: Supported.
8702
8703 *************************************************************/
8704
8705static void n625092_set_prg( running_machine &machine, UINT8 reg1, UINT8 reg2 )
8706{
8707   UINT8 map221_helper1, map221_helper2;
8708
8709   map221_helper1 = !(reg1 & 0x01) ? reg2 :
8710   (reg1 & 0x80) ? reg2 : (reg2 & 0x06) | 0x00;
8711   map221_helper2 = !(reg1 & 0x01) ? reg2 :
8712   (reg1 & 0x80) ? 0x07 : (reg2 & 0x06) | 0x01;
8713
8714   prg16_89ab(machine, map221_helper1 | ((reg1 & 0x70) >> 1));
8715   prg16_cdef(machine, map221_helper2 | ((reg1 & 0x70) >> 1));
8716}
8717
8718static WRITE8_HANDLER( n625092_w )
8719{
8720   nes_state *state = space->machine().driver_data<nes_state>();
8721   LOG_MMC(("n625092_w, offset: %04x, data: %02x\n", offset, data));
8722
8723   if (offset < 0x4000)
8724   {
8725      set_nt_mirroring(space->machine(), BIT(data, 0) ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT);
8726      offset = (offset >> 1) & 0xff;
8727
8728      if (state->m_mmc_latch1 != offset)
8729      {
8730         state->m_mmc_latch1 = offset;
8731         n625092_set_prg(space->machine(), state->m_mmc_latch1, state->m_mmc_latch2);
8732      }
8733   }
8734   else
8735   {
8736      offset &= 0x07;
8737
8738      if (state->m_mmc_latch2 != offset)
8739      {
8740         state->m_mmc_latch2 = offset;
8741         n625092_set_prg(space->machine(), state->m_mmc_latch1, state->m_mmc_latch2);
8742      }
8743   }
8744}
8745
8746/*************************************************************
8747
8748 SC-127 Board
8749
8750 Games: Wario World II (Kirby Hack)
8751
8752 iNES: mapper 35
8753
8754 In MESS: Supported
8755
8756 *************************************************************/
8757
8758static void sc127_irq( device_t *device, int scanline, int vblank, int blanked )
8759{
8760   nes_state *state = device->machine().driver_data<nes_state>();
8761
8762   if (scanline < PPU_BOTTOM_VISIBLE_SCANLINE && state->m_IRQ_enable)
8763   {
8764      state->m_IRQ_count--;
8765
8766      if (!blanked && (state->m_IRQ_count == 0))
8767      {
8768         LOG_MMC(("irq fired, scanline: %d (MAME %d, beam pos: %d)\n", scanline,
8769                device->machine().primary_screen->vpos(), device->machine().primary_screen->hpos()));
8770         device_set_input_line(state->m_maincpu, M6502_IRQ_LINE, HOLD_LINE);
8771         state->m_IRQ_enable = 0;
8772      }
8773   }
8774}
8775
8776static WRITE8_HANDLER( sc127_w )
8777{
8778   nes_state *state = space->machine().driver_data<nes_state>();
8779   LOG_MMC(("sc127_w, offset: %04x, data: %02x\n", offset, data));
8780
8781   switch (offset)
8782   {
8783      case 0x0000:
8784         prg8_89(space->machine(), data);
8785         break;
8786      case 0x0001:
8787         prg8_ab(space->machine(), data);
8788         break;
8789      case 0x0002:
8790         //      state->m_mmc_prg_bank[offset & 0x02] = data;
8791         prg8_cd(space->machine(), data);
8792         break;
8793      case 0x1000:
8794      case 0x1001:
8795      case 0x1002:
8796      case 0x1003:
8797      case 0x1004:
8798      case 0x1005:
8799      case 0x1006:
8800      case 0x1007:
8801         //      state->m_mmc_vrom_bank[offset & 0x07] = data;
8802         chr1_x(space->machine(), offset & 0x07, data, CHRROM);
8803         break;
8804      case 0x4002:
8805         state->m_IRQ_enable = 0;
8806         break;
8807      case 0x4003:
8808         state->m_IRQ_enable = 1;
8809         break;
8810      case 0x4005:
8811         state->m_IRQ_count = data;
8812         break;
8813      case 0x5001:
8814         set_nt_mirroring(space->machine(), BIT(data, 0) ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT);
8815         break;
8816   }
8817}
8818
8819/*************************************************************
8820
8821 Bootleg Board SMB2J
8822
8823 Games: Super Mario Bros. 2 Pirate (LF36)
8824
8825 iNES: mapper 43
8826
8827 In MESS: Supported? The only image I found is not working
8828 (not even in NEStopia).
8829
8830 *************************************************************/
8831
8832static WRITE8_HANDLER( smb2j_w )
8833{
8834   nes_state *state = space->machine().driver_data<nes_state>();
8835   int bank = (((offset >> 8) & 0x03) * 0x20) + (offset & 0x1f);
8836
8837   LOG_MMC(("smb2j_w, offset: %04x, data: %02x\n", offset, data));
8838
8839   set_nt_mirroring(space->machine(), (offset & 0x2000) ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT);
8840
8841   if (offset & 0x0800)
8842   {
8843      if (offset & 0x1000)
8844      {
8845         if (bank * 2 >= state->m_prg_chunks)
8846         {
8847            memory_set_bankptr(space->machine(), "bank3", state->m_wram);
8848            memory_set_bankptr(space->machine(), "bank4", state->m_wram);
8849         }
8850         else
8851         {
8852            LOG_MMC(("smb2j_w, selecting upper 16KB bank of #%02x\n", bank));
8853            prg16_cdef(space->machine(), 2 * bank + 1);
8854         }
8855      }
8856      else
8857      {
8858         if (bank * 2 >= state->m_prg_chunks)
8859         {
8860            memory_set_bankptr(space->machine(), "bank1", state->m_wram);
8861            memory_set_bankptr(space->machine(), "bank2", state->m_wram);
8862         }
8863         else
8864         {
8865            LOG_MMC(("smb2j_w, selecting lower 16KB bank of #%02x\n", bank));
8866            prg16_89ab(space->machine(), 2 * bank);
8867         }
8868      }
8869   }
8870   else
8871   {
8872      if (bank * 2 >= state->m_prg_chunks)
8873      {
8874         memory_set_bankptr(space->machine(), "bank1", state->m_wram);
8875         memory_set_bankptr(space->machine(), "bank2", state->m_wram);
8876         memory_set_bankptr(space->machine(), "bank3", state->m_wram);
8877         memory_set_bankptr(space->machine(), "bank4", state->m_wram);
8878      }
8879      else
8880      {
8881         LOG_MMC(("smb2j_w, selecting 32KB bank #%02x\n", bank));
8882         prg32(space->machine(), bank);
8883      }
8884   }
8885}
8886
8887/*************************************************************
8888
8889 BTL-SMB2B
8890
8891 Games: Super Mario Bros. 2 Pirate (Jpn version of SMB2)
8892
8893 This was marked as Alt. Levels. is it true?
8894
8895 iNES: mapper 50
8896
8897 In MESS: Supported.
8898
8899 *************************************************************/
8900
8901static void smb2jb_irq( device_t *device, int scanline, int vblank, int blanked )
8902{
8903   nes_state *state = device->machine().driver_data<nes_state>();
8904   if (state->m_IRQ_enable)
8905   {
8906      if (state->m_IRQ_count < 0x1000)
8907      {
8908         if ((0x1000 - state->m_IRQ_count) <= 114)
8909            device_set_input_line(state->m_maincpu, M6502_IRQ_LINE, HOLD_LINE);
8910         else
8911            state->m_IRQ_count += 114;
8912      }
8913      else
8914         state->m_IRQ_count += 114;
8915
8916      state->m_IRQ_count &= 0xffff;   // according to docs is 16bit counter -> it wraps only after 0xffff
8917   }
8918}
8919
8920static WRITE8_HANDLER( smb2jb_l_w )
8921{
8922   nes_state *state = space->machine().driver_data<nes_state>();
8923   UINT8 prg;
8924   LOG_MMC(("smb2jb_l_w, offset: %04x, data: %02x\n", offset, data));
8925   offset += 0x100;
8926
8927   switch (offset & 0x160)
8928   {
8929      case 0x020:
8930         prg = (data & 0x08) | ((data & 0x06) >> 1) | ((data & 0x01) << 2);
8931         prg8_cd(space->machine(), prg);
8932         break;
8933      case 0x120:
8934         state->m_IRQ_enable = data & 0x01;
8935         break;
8936   }
8937}
8938
8939/* This goes to 0x4020-0x403f */
8940WRITE8_HANDLER( smb2jb_extra_w )
8941{
8942   UINT8 prg;
8943   LOG_MMC(("smb2jb_extra_w, offset: %04x, data: %02x\n", offset, data));
8944
8945   prg = (data & 0x08) | ((data & 0x06) >> 1) | ((data & 0x01) << 2);
8946   prg8_cd(space->machine(), prg);
8947}
8948
8949/*************************************************************
8950
8951 Bootleg Board for Super Fighter III
8952
8953 MMC3 clone
8954
8955 iNES: mapper 197
8956
8957 In MESS: Supported.
8958
8959 *************************************************************/
8960
8961static void unl_sf3_set_chr( running_machine &machine, UINT8 chr_source, int chr_base, int chr_mask )
8962{
8963   nes_state *state = machine.driver_data<nes_state>();
8964   chr4_0(machine, chr_base | ((state->m_mmc_vrom_bank[0] >> 1) & chr_mask), chr_source);
8965   chr2_4(machine, chr_base | (state->m_mmc_vrom_bank[1] & chr_mask), chr_source);
8966   chr2_6(machine, chr_base | (state->m_mmc_vrom_bank[2] & chr_mask), chr_source);
8967}
8968
8969static WRITE8_HANDLER( unl_sf3_w )
8970{
8971   nes_state *state = space->machine().driver_data<nes_state>();
8972   UINT8 mmc_helper, cmd;
8973   LOG_MMC(("unl_sf3_w, offset: %04x, data: %02x\n", offset, data));
8974
8975   switch (offset & 0x6001)
8976   {
8977      case 0x0000:
8978         mmc_helper = state->m_mmc3_latch ^ data;
8979         state->m_mmc3_latch = data;
8980
8981         /* Has PRG Mode changed? */
8982         if (mmc_helper & 0x40)
8983            mmc3_set_prg(space->machine(), state->m_mmc_prg_base, state->m_mmc_prg_mask);
8984
8985         /* Has CHR Mode changed? */
8986         if (mmc_helper & 0x80)
8987            unl_sf3_set_chr(space->machine(), state->m_mmc_chr_source, state->m_mmc_chr_base, state->m_mmc_chr_mask);
8988         break;
8989
8990      case 0x0001:
8991         cmd = state->m_mmc3_latch & 0x0f;
8992         switch (cmd)
8993         {
8994         case 0: case 2: case 4:
8995            state->m_mmc_vrom_bank[cmd >> 1] = data;
8996            unl_sf3_set_chr(space->machine(), state->m_mmc_chr_source, state->m_mmc_chr_base, state->m_mmc_chr_mask);
8997            break;
8998         case 6:
8999         case 7:
9000            state->m_mmc_prg_bank[cmd - 6] = data;
9001            mmc3_set_prg(space->machine(), state->m_mmc_prg_base, state->m_mmc_prg_mask);
9002            break;
9003         }
9004         break;
9005
9006      default:
9007         txrom_w(space, offset, data);
9008         break;
9009   }
9010}
9011
9012/*************************************************************
9013
9014 Bootleg Board for Xiao Zhuan Yuan
9015
9016 Games: Shu Qi Yu - Zhi Li Xiao Zhuan Yuan
9017
9018 Very simple mapper: writes to 0x5ff1 set prg32 (to data>>1),
9019 while writes to 0x5ff2 set chr8
9020
9021 iNES: mapper 176
9022
9023 In MESS: Supported.
9024
9025 *************************************************************/
9026
9027static WRITE8_HANDLER( unl_xzy_l_w )
9028{
9029   LOG_MMC(("unl_xzy_l_w, offset: %04x, data: %02x\n", offset, data));
9030
9031   switch (offset)
9032   {
9033      case 0x1ef1:   /* 0x5ff1 */
9034         prg32(space->machine(), data >> 1);
9035         break;
9036      case 0x1ef2:   /* 0x5ff2 */
9037         chr8(space->machine(), data, CHRROM);
9038         break;
9039   }
9040}
9041
9042/*************************************************************
9043
9044 Board UNL-RACERMATE
9045
9046 In MESS: *VERY* preliminary support. Also, it seems that this
9047 board saves to battery the CHRRAM!!!
9048
9049 *************************************************************/
9050
9051static void racmate_update_banks( running_machine &machine )
9052{
9053   nes_state *state = machine.driver_data<nes_state>();
9054   chr4_4(machine, state->m_mmc_latch1 & 0x0f, state->m_mmc_chr_source);
9055   prg16_89ab(machine, state->m_mmc_latch1 >> 1);
9056}
9057
9058static WRITE8_HANDLER( unl_racmate_w )
9059{
9060   nes_state *state = space->machine().driver_data<nes_state>();
9061   LOG_MMC(("unl_racmate_w offset: %04x, data: %02x\n", offset, data));
9062
9063   if (offset == 0x3000)
9064   {
9065      state->m_mmc_latch1 = data;
9066      racmate_update_banks(space->machine());
9067   }
9068}
9069
9070/*************************************************************
9071
9072        BOOTLEG CART VERSIONS OF FDS GAMES
9073
9074 *************************************************************/
9075
9076/*************************************************************
9077
9078 BTL-SUPERBROS11
9079
9080 Games: Super Mario Bros. 11, Super Mario Bros. 17
9081
9082 This acts basically like a MMC3 with different use of write
9083 address.
9084
9085 iNES: mapper 196
9086
9087 In MESS: Supported.
9088
9089 *************************************************************/
9090
9091static WRITE8_HANDLER( btl_smb11_w )
9092{
9093   LOG_MMC(("btl_smb11_w, offset: %04x, data: %02x\n", offset, data));
9094
9095   txrom_w(space, (offset & 0x6000) | ((offset & 0x04) >> 2), data);
9096}
9097
9098/*************************************************************
9099
9100 BTL-MARIOBABY
9101
9102 Games: Mario Baby, Ai Senshi Nicol
9103
9104 iNES: mapper 42
9105
9106 In MESS: Supported.
9107
9108 *************************************************************/
9109
9110// is the code fine for ai senshi nicol?!?
9111static WRITE8_HANDLER( btl_mariobaby_w )
9112{
9113   nes_state *state = space->machine().driver_data<nes_state>();
9114   LOG_MMC(("btl_mariobaby_w, offset: %04x, data: %02x\n", offset, data));
9115
9116   if (offset >= 0x7000)
9117   {
9118      switch (offset & 0x03)
9119      {
9120         case 0x00:
9121            prg8_67(space->machine(), data);
9122            break;
9123         case 0x01:
9124            set_nt_mirroring(space->machine(), BIT(data, 3) ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT);
9125            break;
9126         case 0x02:
9127            /* Check if IRQ is being enabled */
9128            if (!state->m_IRQ_enable && (data & 0x02))
9129            {
9130               state->m_IRQ_enable = 1;
9131               state->m_irq_timer->adjust(downcast<cpu_device *>(state->m_maincpu)->cycles_to_attotime(24576));
9132            }
9133            if (!(data & 0x02))
9134            {
9135               state->m_IRQ_enable = 0;
9136               state->m_irq_timer->adjust(attotime::never);
9137            }
9138            break;
9139      }
9140   }
9141}
9142
9143/*************************************************************
9144
9145 BTL-SMB2A
9146
9147 Games: Super Mario Bros. 2 Pirate (Jpn version of SMB2)
9148
9149 iNES: mapper 40
9150
9151 In MESS: Supported.
9152
9153 *************************************************************/
9154
9155static void btl_smb2a_irq( device_t *device, int scanline, int vblank, int blanked )
9156{
9157   nes_state *state = device->machine().driver_data<nes_state>();
9158
9159   if (state->m_IRQ_enable)
9160   {
9161      if ((0xfff - state->m_IRQ_count) <= 114)
9162      {
9163         state->m_IRQ_count = (state->m_IRQ_count + 1) & 0xfff;
9164         state->m_IRQ_enable = 0;
9165         device_set_input_line(state->m_maincpu, M6502_IRQ_LINE, HOLD_LINE);
9166      }
9167      else
9168         state->m_IRQ_count += 114;
9169   }
9170}
9171
9172static WRITE8_HANDLER( btl_smb2a_w )
9173{
9174   nes_state *state = space->machine().driver_data<nes_state>();
9175   LOG_MMC(("btl_smb2a_w, offset: %04x, data: %02x\n", offset, data));
9176
9177   switch (offset & 0x6000)
9178   {
9179      case 0x0000:
9180         state->m_IRQ_enable = 0;
9181         state->m_IRQ_count = 0;
9182         break;
9183      case 0x2000:
9184         state->m_IRQ_enable = 1;
9185         break;
9186      case 0x6000:
9187         prg8_cd(space->machine(), data);
9188         break;
9189   }
9190}
9191
9192/*************************************************************
9193
9194 WHIRLWIND-2706
9195
9196 Games: Meikyuu Jiin Dababa (FDS conversion)
9197
9198 iNES: mapper 108
9199
9200 In MESS: Supported.
9201
9202 *************************************************************/
9203
9204static WRITE8_HANDLER( whirl2706_w )
9205{
9206   LOG_MMC(("whirl2706_w, offset: %04x, data: %02x\n", offset, data));
9207   prg8_67(space->machine(), data);
9208}
9209
9210/*************************************************************
9211
9212 Bootleg Board used for FDS conversion
9213
9214 Games: Tobidase Daisakusen (FDS conversion)
9215
9216 iNES: mapper 120
9217
9218 In MESS: Partially Supported.
9219
9220 *************************************************************/
9221
9222static WRITE8_HANDLER( btl_tobi_l_w )
9223{
9224   LOG_MMC(("btl_tobi_l_w, offset: %04x, data: %02x\n", offset, data));
9225   offset += 0x100;
9226
9227   if ((offset & 0x43c0) == 0x41c0)
9228      prg8_67(space->machine(), data & 0x07);
9229}
9230
9231/*************************************************************
9232
9233 BTL-SMB3
9234
9235 Games: Super Mario Bros. 3 Pirate
9236
9237 iNES: mapper 106
9238
9239 In MESS: Supported.
9240
9241 *************************************************************/
9242
9243static void btl_smb3_irq( device_t *device, int scanline, int vblank, int blanked )
9244{
9245   nes_state *state = device->machine().driver_data<nes_state>();
9246
9247   if (state->m_IRQ_enable)
9248   {
9249      if ((0xffff - state->m_IRQ_count) < 114)
9250      {
9251         device_set_input_line(state->m_maincpu, M6502_IRQ_LINE, HOLD_LINE);
9252         state->m_IRQ_enable = 0;
9253      }
9254
9255      state->m_IRQ_count = (state->m_IRQ_count + 114) & 0xffff;
9256   }
9257}
9258
9259static WRITE8_HANDLER( btl_smb3_w )
9260{
9261   nes_state *state = space->machine().driver_data<nes_state>();
9262   LOG_MMC(("btl_smb3_w, offset: %04x, data: %02x\n", offset, data));
9263   switch (offset & 0x0f)
9264   {
9265      case 0x00:
9266      case 0x02:
9267         chr1_x(space->machine(), offset & 0x07, data & 0xfe, CHRROM);
9268         break;
9269      case 0x01:
9270      case 0x03:
9271         chr1_x(space->machine(), offset & 0x07, data | 0x01, CHRROM);
9272         break;
9273      case 0x04: case 0x05:
9274      case 0x06: case 0x07:
9275         chr1_x(space->machine(), offset & 0x07, data, CHRROM);
9276         break;
9277      case 0x08:
9278         prg8_89(space->machine(), data | 0x10);
9279         break;
9280      case 0x09:
9281         prg8_ab(space->machine(), data);
9282         break;
9283      case 0x0a:
9284         prg8_cd(space->machine(), data);
9285         break;
9286      case 0x0b:
9287         prg8_ef(space->machine(), data | 0x10);
9288         break;
9289      case 0x0c:
9290         set_nt_mirroring(space->machine(), BIT(data, 0) ?  PPU_MIRROR_HORZ : PPU_MIRROR_VERT);
9291         break;
9292      case 0x0d:
9293         state->m_IRQ_count = 0;
9294         state->m_IRQ_enable = 0;
9295         break;
9296      case 0x0e:
9297         state->m_IRQ_count = (state->m_IRQ_count & 0xff00) | data;
9298         break;
9299      case 0x0f:
9300         state->m_IRQ_count = (state->m_IRQ_count & 0x00ff) | (data << 8);
9301         state->m_IRQ_enable = 1;
9302         break;
9303   }
9304}
9305
9306/*************************************************************
9307
9308 BTL-DRAGONNINJA
9309
9310 Games: Dragon Ninja (Bootleg), Super Mario Bros. 8
9311
9312 iNES: mapper 222
9313
9314 In MESS: Unsupported.
9315
9316 *************************************************************/
9317
9318/* Scanline based IRQ ? */
9319static void btl_dn_irq( device_t *device, int scanline, int vblank, int blanked )
9320{
9321   nes_state *state = device->machine().driver_data<nes_state>();
9322   if (scanline < PPU_BOTTOM_VISIBLE_SCANLINE)
9323   {
9324      if (!state->m_IRQ_count || ++state->m_IRQ_count < 240)
9325         return;
9326
9327      state->m_IRQ_count = 0;
9328      LOG_MMC(("irq fired, scanline: %d (MAME %d, beam pos: %d)\n", scanline,
9329             device->machine().primary_screen->vpos(), device->machine().primary_screen->hpos()));
9330      device_set_input_line(state->m_maincpu, M6502_IRQ_LINE, HOLD_LINE);
9331   }
9332}
9333
9334static WRITE8_HANDLER( btl_dn_w )
9335{
9336   nes_state *state = space->machine().driver_data<nes_state>();
9337   UINT8 bank;
9338   LOG_MMC(("btl_dn_w, offset: %04x, data: %02x\n", offset, data));
9339
9340   switch (offset & 0x7003)
9341   {
9342      case 0x0000:
9343         prg8_89(space->machine(), data);
9344         break;
9345      case 0x1000:
9346         set_nt_mirroring(space->machine(), BIT(data, 0) ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT);
9347         break;
9348      case 0x2000:
9349         prg8_ab(space->machine(), data);
9350         break;
9351      case 0x3000:
9352      case 0x3002:
9353      case 0x4000:
9354      case 0x4002:
9355      case 0x5000:
9356      case 0x5002:
9357      case 0x6000:
9358      case 0x6002:
9359         bank = ((offset & 0x7000) - 0x3000) / 0x0800 + ((offset & 0x0002) >> 3);
9360         chr1_x(space->machine(), bank, data, CHRROM);
9361         break;
9362      case 0x7000:
9363         state->m_IRQ_count = data;
9364         break;
9365   }
9366}
9367
9368/*************************************************************
9369
9370 BTL-PIKACHUY2K
9371
9372 Games: Pikachu Y2k
9373
9374 iNES: mapper 254
9375
9376 In MESS:
9377
9378 *************************************************************/
9379
9380static WRITE8_HANDLER( btl_pika_y2k_w )
9381{
9382   nes_state *state = space->machine().driver_data<nes_state>();
9383   LOG_MMC(("btl_pika_y2k_w, offset: %04x, data: %02x\n", offset, data));
9384
9385   switch (offset & 0x6001)
9386   {
9387      case 0x2001:
9388         state->m_mmc_latch2 = data;
9389         break;
9390
9391      case 0x2000:
9392         state->m_mmc_reg[0] = 0;
9393      default:
9394         txrom_w(space, offset, data);
9395         break;
9396   }
9397}
9398
9399// strange WRAM usage: it is protected at start, and gets unprotected after the first write to 0xa000
9400static WRITE8_HANDLER( btl_pika_y2k_m_w )
9401{
9402   nes_state *state = space->machine().driver_data<nes_state>();
9403   LOG_MMC(("btl_pika_y2k_m_w, offset: %04x, data: %02x\n", offset, data));
9404
9405   state->m_wram[offset] = data;
9406}
9407
9408static READ8_HANDLER( btl_pika_y2k_m_r )
9409{
9410   nes_state *state = space->machine().driver_data<nes_state>();
9411   LOG_MMC(("btl_pika_y2k_m_r, offset: %04x\n", offset));
9412
9413   return   state->m_wram[offset] ^ (state->m_mmc_latch2 & state->m_mmc_reg[0]);
9414}
9415
9416/*************************************************************
9417
9418          MULTICART
9419
9420 *************************************************************/
9421
9422/*************************************************************
9423
9424 Board BMC-FK23C
9425
9426 In MESS: partially supported (still to sort initial banking
9427 for many games)
9428
9429 *************************************************************/
9430
9431#if 0
9432static void fk23c_prg_cb( running_machine &machine, int start, int bank )
9433{
9434   nes_state *state = machine.driver_data<nes_state>();
9435
9436   if (((state->m_mmc_reg[0] & 0x07) - 3) > 1 && (!(state->m_mmc_reg[3] & 0x02) || start < 2))
9437   {
9438      if (state->m_mmc_reg[0] & 0x03)
9439         bank = (bank & (0x3f >> (state->m_mmc_reg[0] & 0x03))) | (state->m_mmc_reg[1] << 1);
9440
9441      prg8_x(machine, start, bank);
9442   }
9443}
9444
9445static void fk23c_chr_cb( running_machine &machine, int start, int bank, int source )
9446{
9447   nes_state *state = machine.driver_data<nes_state>();
9448
9449   if (!(state->m_mmc_reg[0] & 0x40) && (!(state->m_mmc_reg[3] & 0x02) || (start != 1 && start != 3)))
9450      chr1_x(machine, start, ((state->m_mmc_reg[2] & 0x7f) << 3) | bank, source);
9451}
9452
9453#endif
9454
9455static void fk23c_prg_cb( running_machine &machine, int start, int bank )
9456{
9457   nes_state *state = machine.driver_data<nes_state>();
9458   UINT8 mask = (0x3f >> (state->m_mmc_reg[0] & 0x03));
9459
9460   if ((state->m_mmc_reg[0] & 0x07) < 3)
9461   {
9462      if (!(state->m_mmc_reg[0] & 0x03))
9463         bank = (bank & mask) | ((state->m_mmc_reg[1]  & (0x7f ^ mask)) << 1);
9464
9465      prg8_x(machine, start, bank);
9466   }
9467}
9468
9469static void fk23c_chr_cb( running_machine &machine, int start, int bank, int source )
9470{
9471   nes_state *state = machine.driver_data<nes_state>();
9472
9473   if (!(state->m_mmc_reg[0] & 0x40) && (!(state->m_mmc_reg[3] & 0x02) || (start != 1 && start != 3)))
9474      chr1_x(machine, start, ((state->m_mmc_reg[2] & 0x7f) << 3) | bank, source);
9475}
9476
9477static void fk23c_set_prg( running_machine &machine )
9478{
9479   nes_state *state = machine.driver_data<nes_state>();
9480
9481   if ((state->m_mmc_reg[0] & 0x07) == 4)
9482      prg32(machine, (state->m_mmc_reg[1] & 0x7f) >> 1);
9483   else if ((state->m_mmc_reg[0] & 0x07) == 3)
9484   {
9485      prg16_89ab(machine, state->m_mmc_reg[1] & 0x7f);
9486      prg16_cdef(machine, state->m_mmc_reg[1] & 0x7f);
9487   }
9488   else
9489   {
9490      if (state->m_mmc_reg[3] & 0x02)
9491      {
9492         prg8_cd(machine, state->m_mmc_reg[4]);
9493         prg8_ef(machine, state->m_mmc_reg[5]);
9494      }
9495
9496      mmc3_set_prg(machine, state->m_mmc_prg_base, state->m_mmc_prg_mask);
9497   }
9498}
9499
9500static void fk23c_set_chr( running_machine &machine )
9501{
9502   nes_state *state = machine.driver_data<nes_state>();
9503
9504   if (state->m_mmc_reg[0] & 0x40)
9505      chr8(machine, state->m_mmc_reg[2] | state->m_mmc_cmd1, state->m_mmc_chr_source);
9506   else
9507   {
9508      if (state->m_mmc_reg[3] & 0x02)
9509      {
9510         int base = (state->m_mmc_reg[2] & 0x7f) << 3;
9511         chr1_x(machine, 1, base | state->m_mmc_reg[6], state->m_mmc_chr_source);
9512         chr1_x(machine, 3, base | state->m_mmc_reg[7], state->m_mmc_chr_source);
9513      }
9514
9515      mmc3_set_chr(machine, state->m_mmc_chr_source, state->m_mmc_chr_base, state->m_mmc_chr_mask);
9516   }
9517}
9518
9519static WRITE8_HANDLER( fk23c_l_w )
9520{
9521   nes_state *state = space->machine().driver_data<nes_state>();
9522   LOG_MMC(("fk23c_l_w, offset: %04x, data: %02x\n", offset, data));
9523   offset += 0x100;
9524
9525   if (offset >= 0x1000)
9526   {
9527      if (offset & (1 << 4))   // here it should be (4 + state->m_mmc_dipsetting)
9528      {
9529         state->m_mmc_reg[offset & 0x03] = data;
9530
9531         fk23c_set_prg(space->machine());
9532         fk23c_set_chr(space->machine());
9533      }
9534   }
9535}
9536
9537static WRITE8_HANDLER( fk23c_w )
9538{
9539   nes_state *state = space->machine().driver_data<nes_state>();
9540   LOG_MMC(("fk23c_w, offset: %04x, data: %02x\n", offset, data));
9541
9542   if (state->m_mmc_reg[0] & 0x40)
9543   {
9544      if (state->m_mmc_reg[0] & 0x30)
9545         state->m_mmc_cmd1 = 0;
9546      else
9547      {
9548         state->m_mmc_cmd1 = data & 0x03;
9549         fk23c_set_chr(space->machine());
9550      }
9551   }
9552   else
9553   {
9554      switch (offset & 0x6001)
9555      {
9556         case 0x0001:
9557            if ((state->m_mmc_reg[3] & 0x02) && (state->m_mmc3_latch & 0x08))
9558            {
9559               state->m_mmc_reg[4 | (state->m_mmc3_latch & 0x03)] = data;
9560               fk23c_set_prg(space->machine());
9561               fk23c_set_chr(space->machine());
9562            }
9563            else
9564               txrom_w(space, offset, data);
9565            break;
9566
9567         case 0x2000:
9568            set_nt_mirroring(space->machine(), data ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT);
9569            break;
9570
9571         default:
9572            txrom_w(space, offset, data);
9573            break;
9574      }
9575   }
9576}
9577
9578
9579/*************************************************************
9580
9581 Board BMC-64IN1NOREPEAT
9582
9583 Games: 64-in-1 Y2K
9584
9585 In MESS: Supported
9586
9587 *************************************************************/
9588
9589static void bmc_64in1nr_set_prg( running_machine &machine )
9590{
9591   nes_state *state = machine.driver_data<nes_state>();
9592   UINT8 helper1 = (state->m_mmc_reg[1] & 0x1f);
9593   UINT8 helper2 = (helper1 << 1) | ((state->m_mmc_reg[1] & 0x40) >> 6);
9594
9595   if (state->m_mmc_reg[0] & 0x80)
9596   {
9597      if (state->m_mmc_reg[1] & 0x80)
9598         prg32(machine, helper1);
9599      else
9600      {
9601         prg16_89ab(machine, helper2);
9602         prg16_cdef(machine, helper2);
9603      }
9604   }
9605   else
9606      prg16_cdef(machine, helper2);
9607}
9608
9609static WRITE8_HANDLER( bmc_64in1nr_l_w )
9610{
9611   nes_state *state = space->machine().driver_data<nes_state>();
9612   LOG_MMC(("bmc_64in1nr_l_w offset: %04x, data: %02x\n", offset, data));
9613   offset += 0x100;
9614
9615   switch (offset)
9616   {
9617      case 0x1000:
9618      case 0x1001:
9619      case 0x1002:
9620      case 0x1003:
9621         state->m_mmc_reg[offset & 0x03] = data;
9622         bmc_64in1nr_set_prg(space->machine());
9623         chr8(space->machine(), ((state->m_mmc_reg[0] >> 1) & 0x03) | (state->m_mmc_reg[2] << 2), CHRROM);
9624         break;
9625   }
9626   if (offset == 0x1000)   /* reg[0] also sets mirroring */
9627      set_nt_mirroring(space->machine(), BIT(data, 5) ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT);
9628}
9629
9630static WRITE8_HANDLER( bmc_64in1nr_w )
9631{
9632   nes_state *state = space->machine().driver_data<nes_state>();
9633   LOG_MMC(("bmc_64in1nr_w offset: %04x, data: %02x\n", offset, data));
9634
9635   state->m_mmc_reg[3] = data;   // reg[3] is currently unused?!?
9636}
9637
9638/*************************************************************
9639
9640 Board BMC-190IN1
9641
9642 Games: 190-in-1
9643
9644 In MESS: Supported
9645
9646 *************************************************************/
9647
9648static WRITE8_HANDLER( bmc_190in1_w )
9649{
9650   LOG_MMC(("bmc_190in1_w offset: %04x, data: %02x\n", offset, data));
9651
9652   set_nt_mirroring(space->machine(), BIT(data, 0) ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT);
9653   offset >>= 2;
9654   prg16_89ab(space->machine(), offset);
9655   prg16_cdef(space->machine(), offset);
9656   chr8(space->machine(), offset, CHRROM);
9657}
9658
9659/*************************************************************
9660
9661 Board BMC-A65AS
9662
9663 Games: 3-in-1 (N068)
9664
9665 In MESS: Supported
9666
9667 *************************************************************/
9668
9669static WRITE8_HANDLER( bmc_a65as_w )
9670{
9671   UINT8 helper = (data & 0x30) >> 1;
9672   LOG_MMC(("bmc_a65as_w offset: %04x, data: %02x\n", offset, data));
9673
9674   if (data & 0x80)
9675      set_nt_mirroring(space->machine(), BIT(data, 5) ? PPU_MIRROR_HIGH : PPU_MIRROR_LOW);
9676   else
9677      set_nt_mirroring(space->machine(), BIT(data, 3) ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT);
9678
9679   if (data & 0x40)
9680      prg32(space->machine(), data >> 1);
9681   else
9682   {
9683      prg16_89ab(space->machine(), helper | (data & 0x07));
9684      prg16_cdef(space->machine(), helper | 0x07);
9685   }
9686}
9687
9688/*************************************************************
9689
9690 Board BMC-GS2004
9691
9692 Games: Tetris Family 6-in-1
9693
9694 In MESS: Preliminary Support. It also misses WRAM handling
9695 (we need reads from 0x6000-0x7fff)
9696
9697 *************************************************************/
9698
9699static WRITE8_HANDLER( bmc_gs2004_w )
9700{
9701   LOG_MMC(("bmc_gs2004_w offset: %04x, data: %02x\n", offset, data));
9702
9703   prg32(space->machine(), data);
9704}
9705
9706/*************************************************************
9707
9708 Board BMC-GS2013
9709
9710 Games: Tetris Family 12-in-1
9711
9712 In MESS: Preliminary Support. It also misses WRAM handling
9713 (we need reads from 0x6000-0x7fff)
9714
9715 *************************************************************/
9716
9717static WRITE8_HANDLER( bmc_gs2013_w )
9718{
9719   LOG_MMC(("bmc_gs2013_w offset: %04x, data: %02x\n", offset, data));
9720
9721   if (data & 0x08)
9722      prg32(space->machine(), data & 0x09);
9723   else
9724      prg32(space->machine(), data & 0x07);
9725}
9726
9727/*************************************************************
9728
9729 Board BMC-SUPER24IN1SC03
9730
9731 Games: Super 24-in-1
9732
9733 In MESS: Partially Supported
9734
9735 *************************************************************/
9736
9737static void bmc_s24in1sc03_prg_cb( running_machine &machine, int start, int bank )
9738{
9739   nes_state *state = machine.driver_data<nes_state>();
9740   static const UINT8 masks[8] = {0x3f, 0x1f, 0x0f, 0x01, 0x03, 0x00, 0x00, 0x00};
9741   int prg_base = state->m_mmc_reg[1] << 1;
9742   int prg_mask = masks[state->m_mmc_reg[0] & 0x07];
9743
9744   bank = prg_base | (bank & prg_mask);
9745   prg8_x(machine, start, bank);
9746}
9747
9748static void bmc_s24in1sc03_chr_cb( running_machine &machine, int start, int bank, int source )
9749{
9750   nes_state *state = machine.driver_data<nes_state>();
9751   UINT8 chr = BIT(state->m_mmc_reg[0], 5) ? CHRRAM : CHRROM;
9752   int chr_base = (state->m_mmc_reg[2] << 3) & 0xf00;
9753
9754   chr1_x(machine, start, chr_base | bank, chr);
9755}
9756
9757static WRITE8_HANDLER( bmc_s24in1sc03_l_w )
9758{
9759   nes_state *state = space->machine().driver_data<nes_state>();
9760   LOG_MMC(("bmc_s24in1sc03_l_w offset: %04x, data: %02x\n", offset, data));
9761   offset += 0x100;
9762
9763   if (offset == 0x1ff0)
9764   {
9765      state->m_mmc_reg[0] = data;
9766      mmc3_set_chr(space->machine(), state->m_mmc_chr_source, state->m_mmc_chr_base, state->m_mmc_chr_mask);
9767      mmc3_set_prg(space->machine(), state->m_mmc_prg_base, state->m_mmc_prg_mask);
9768   }
9769
9770   if (offset == 0x1ff1)
9771   {
9772      state->m_mmc_reg[1] = data;
9773      mmc3_set_prg(space->machine(), state->m_mmc_prg_base, state->m_mmc_prg_mask);
9774   }
9775
9776   if (offset == 0x1ff2)
9777   {
9778      state->m_mmc_reg[2] = data;
9779      mmc3_set_chr(space->machine(), state->m_mmc_chr_source, state->m_mmc_chr_base, state->m_mmc_chr_mask);
9780   }
9781}
9782
9783/*************************************************************
9784
9785 Board BMC-T-262
9786
9787 Games: 4-in-1 (D-010), 8-in-1 (A-020)
9788
9789 In MESS: Supported
9790
9791 *************************************************************/
9792
9793static WRITE8_HANDLER( bmc_t262_w )
9794{
9795   nes_state *state = space->machine().driver_data<nes_state>();
9796   UINT8 mmc_helper;
9797   LOG_MMC(("bmc_t262_w offset: %04x, data: %02x\n", offset, data));
9798
9799   if (state->m_mmc_latch2 || offset == 0)
9800   {
9801      state->m_mmc_latch1 = (state->m_mmc_latch1 & 0x38) | (data & 0x07);
9802      prg16_89ab(space->machine(), state->m_mmc_latch1);
9803   }
9804   else
9805   {
9806      state->m_mmc_latch2 = 1;
9807      set_nt_mirroring(space->machine(), BIT(data, 1) ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT);
9808      mmc_helper = ((offset >> 3) & 0x20) | ((offset >> 2) & 0x18);
9809      state->m_mmc_latch1 = mmc_helper | (state->m_mmc_latch1 & 0x07);
9810      prg16_89ab(space->machine(), state->m_mmc_latch1);
9811      prg16_cdef(space->machine(), mmc_helper | 0x07);
9812   }
9813}
9814
9815/*************************************************************
9816
9817 Board BMC-WS
9818
9819 Games: Super 40-in-1
9820
9821 In MESS: Partially Supported (some games, like Galaxian, have
9822 issues)
9823
9824 *************************************************************/
9825
9826static WRITE8_HANDLER( bmc_ws_m_w )
9827{
9828   nes_state *state = space->machine().driver_data<nes_state>();
9829   UINT8 mmc_helper;
9830   LOG_MMC(("bmc_ws_m_w offset: %04x, data: %02x\n", offset, data));
9831
9832   if (offset < 0x1000)
9833   {
9834      switch (offset & 0x01)
9835      {
9836         case 0:
9837            if (!state->m_mmc_latch1)
9838            {
9839               state->m_mmc_latch1 = data & 0x20;
9840               set_nt_mirroring(space->machine(), BIT(data, 4) ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT);
9841               mmc_helper = (~data & 0x08) >> 3;
9842               prg16_89ab(space->machine(), data & ~mmc_helper);
9843               prg16_cdef(space->machine(), data |  mmc_helper);
9844            }
9845            break;
9846         case 1:
9847            if (!state->m_mmc_latch1)
9848            {
9849               chr8(space->machine(), data, CHRROM);
9850            }
9851            break;
9852      }
9853   }
9854}
9855
9856/*************************************************************
9857
9858 BMC-NOVELDIAMOND and BMC-999999in1
9859
9860 Unknown Bootleg Multigame Board
9861 Games: I only found 'Novel Diamond 999999-in-1.unf' using
9862 this mapper (hence the code is used for BMC_NOVELDIAMOND
9863 board). The code is included here in case a mapper 54
9864 dump arises.
9865
9866 iNES: mappers 54 and 213
9867
9868 In MESS: Partial Support.
9869
9870 *************************************************************/
9871
9872// Are this correct or should they work the same?
9873static WRITE8_HANDLER( novel1_w )
9874{
9875   LOG_MMC(("novel1_w, offset: %04x, data: %02x\n", offset, data));
9876
9877   prg32(space->machine(), offset & 0x03);
9878   chr8(space->machine(), offset & 0x07, CHRROM);
9879}
9880
9881static WRITE8_HANDLER( novel2_w )
9882{
9883   LOG_MMC(("novel2_w, offset: %04x, data: %02x\n", offset, data));
9884
9885   prg32(space->machine(), offset >> 1);
9886   chr8(space->machine(), offset >> 3, CHRROM);
9887}
9888
9889/*************************************************************
9890
9891 Board BMC-GKA
9892
9893 Unknown Bootleg Multigame Board
9894 Games: 6 in 1, 54 in 1, 106 in 1
9895
9896 iNES: mapper 57
9897
9898 In MESS: Supported.
9899
9900 *************************************************************/
9901
9902static WRITE8_HANDLER( bmc_gka_w )
9903{
9904   nes_state *state = space->machine().driver_data<nes_state>();
9905   LOG_MMC(("bmc_gka_w, offset: %04x, data: %02x\n", offset, data));
9906
9907   if (offset & 0x0800)
9908      state->m_mmc_latch2 = data;
9909   else
9910      state->m_mmc_latch1 = data;
9911
9912   if (state->m_mmc_latch2 & 0x80)
9913      prg32(space->machine(), 2 | (state->m_mmc_latch2 >> 6));
9914   else
9915   {
9916      prg16_89ab(space->machine(), (state->m_mmc_latch2 >> 5) & 0x03);
9917      prg16_cdef(space->machine(), (state->m_mmc_latch2 >> 5) & 0x03);
9918   }
9919
9920   set_nt_mirroring(space->machine(), (state->m_mmc_latch2 & 0x08) ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT);
9921
9922   chr8(space->machine(), (state->m_mmc_latch1 & 0x03) | (state->m_mmc_latch2 & 0x07) | ((state->m_mmc_latch2 & 0x10) >> 1), CHRROM);
9923}
9924
9925
9926/*************************************************************
9927
9928 Board UNL-STUDYNGAME
9929
9930 Games: Study n Game 32 in 1
9931
9932 iNES: mapper 39
9933
9934 In MESS: Partially Supported (problems with PRG bankswitch,
9935 only keyboard exercise work).
9936
9937 *************************************************************/
9938
9939static WRITE8_HANDLER( sng32_w )
9940{
9941   LOG_MMC(("sng32_w, offset: %04x, data: %02x\n", offset, data));
9942   prg32(space->machine(), data);
9943}
9944
9945/*************************************************************
9946
9947 Board BMC-GKB
9948
9949 Unknown Bootleg Multigame Board
9950 Games: 68 in 1, 73 in 1, 98 in 1
9951
9952 iNES: mapper 58
9953
9954 In MESS: Supported.
9955
9956 *************************************************************/
9957
9958static WRITE8_HANDLER( bmc_gkb_w )
9959{
9960   nes_state *state = space->machine().driver_data<nes_state>();
9961   UINT8 bank = (offset & 0x40) ? 0 : 1;
9962   LOG_MMC(("bmc_gkb_w, offset: %04x, data: %02x\n", offset, data));
9963
9964   prg16_89ab(space->machine(), offset & ~bank);
9965   prg16_cdef(space->machine(), offset | bank);
9966   chr8(space->machine(), offset >> 3, state->m_mmc_chr_source);
9967   set_nt_mirroring(space->machine(), BIT(data, 7) ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT);
9968}
9969
9970/*************************************************************
9971
9972 BMC-SUPER-700IN1
9973
9974 Unknown Bootleg Multigame Board
9975 Games: Super 700 in 1
9976
9977 iNES: mapper 62
9978
9979 In MESS: Supported.
9980
9981 *************************************************************/
9982
9983static WRITE8_HANDLER( bmc_super700in1_w )
9984{
9985   LOG_MMC(("bmc_super700in1_w, offset :%04x, data: %02x\n", offset, data));
9986
9987   chr8(space->machine(), ((offset & 0x1f) << 2) | (data & 0x03), CHRROM);
9988
9989   if (offset & 0x20)
9990   {
9991      prg16_89ab(space->machine(), (offset & 0x40) | ((offset >> 8) & 0x3f));
9992      prg16_cdef(space->machine(), (offset & 0x40) | ((offset >> 8) & 0x3f));
9993   }
9994   else
9995   {
9996      prg32(space->machine(), ((offset & 0x40) | ((offset >> 8) & 0x3f)) >> 1);
9997   }
9998
9999   set_nt_mirroring(space->machine(), BIT(data, 7) ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT);
10000}
10001
10002/*************************************************************
10003
10004 BMC-36IN1
10005
10006 Unknown Bootleg Multigame Board
10007 Games: 36 in 1, 1200 in 1
10008
10009 iNES: mapper 200
10010
10011 In MESS: Supported.
10012
10013 *************************************************************/
10014
10015static WRITE8_HANDLER( bmc_36in1_w )
10016{
10017   LOG_MMC(("bmc_36in1_w, offset: %04x, data: %02x\n", offset, data));
10018
10019   prg16_89ab(space->machine(), offset & 0x07);
10020   prg16_cdef(space->machine(), offset & 0x07);
10021   chr8(space->machine(), offset & 0x07, CHRROM);
10022
10023   set_nt_mirroring(space->machine(), BIT(data, 3) ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT);
10024}
10025
10026/*************************************************************
10027
10028 BMC-21IN1
10029
10030 Unknown Bootleg Multigame Board
10031 Games: 8 in 1, 21 in 1
10032
10033 iNES: mapper 201
10034
10035 In MESS: Supported.
10036
10037 *************************************************************/
10038
10039static WRITE8_HANDLER( bmc_21in1_w )
10040{
10041   LOG_MMC(("bmc_21in1_w, offset: %04x, data: %02x\n", offset, data));
10042
10043   prg32(space->machine(), offset & 0x03);
10044   chr8(space->machine(), offset & 0x03, CHRROM);
10045}
10046
10047/*************************************************************
10048
10049 BMC-150IN1
10050
10051 Unknown Bootleg Multigame Board
10052 Games: 150 in 1
10053
10054 iNES: mapper 202
10055
10056 In MESS: Supported.
10057
10058 *************************************************************/
10059
10060static WRITE8_HANDLER( bmc_150in1_w )
10061{
10062   int bank = (offset >> 1) & 0x07;
10063
10064   LOG_MMC(("bmc_150in1_w, offset: %04x, data: %02x\n", offset, data));
10065
10066   prg16_89ab(space->machine(), bank);
10067   prg16_cdef(space->machine(), bank + (((bank & 0x06) == 0x06) ? 1 : 0));
10068   chr8(space->machine(), bank, CHRROM);
10069
10070   set_nt_mirroring(space->machine(), BIT(data, 0) ? PPU_MIRROR_HORZ: PPU_MIRROR_VERT);
10071}
10072
10073/*************************************************************
10074
10075 BMC-35IN1
10076
10077 Unknown Bootleg Multigame Board
10078 Games: 35 in 1
10079
10080 iNES: mapper 203
10081
10082 In MESS: Supported.
10083
10084 *************************************************************/
10085
10086static WRITE8_HANDLER( bmc_35in1_w )
10087{
10088   LOG_MMC(("bmc_35in1_w, offset: %04x, data: %02x\n", offset, data));
10089
10090   prg16_89ab(space->machine(), (data >> 2) & 0x03);
10091   prg16_cdef(space->machine(), (data >> 2) & 0x03);
10092   chr8(space->machine(), data & 0x03, CHRROM);
10093}
10094
10095/*************************************************************
10096
10097 BMC-64IN1
10098
10099 Unknown Bootleg Multigame Board
10100 Games: 64 in 1
10101
10102 iNES: mapper 204
10103
10104 In MESS: Supported.
10105
10106 *************************************************************/
10107
10108static WRITE8_HANDLER( bmc_64in1_w )
10109{
10110   int bank = (offset >> 1) & (offset >> 2) & 0x01;
10111
10112   LOG_MMC(("bmc_64in1_w, offset: %04x, data: %02x\n", offset, data));
10113
10114   prg16_89ab(space->machine(), offset & ~bank);
10115   prg16_cdef(space->machine(), offset | bank);
10116   chr8(space->machine(), offset & ~bank, CHRROM);
10117
10118   set_nt_mirroring(space->machine(), BIT(data, 4) ? PPU_MIRROR_HORZ: PPU_MIRROR_VERT);
10119}
10120
10121/*************************************************************
10122
10123 BMC-15IN1
10124
10125 Unknown Bootleg Multigame Board
10126 Games: 3 in 1, 15 in 1
10127
10128 iNES: mapper 205, MMC3 clone
10129
10130 In MESS: Supported.
10131
10132 *************************************************************/
10133
10134static WRITE8_HANDLER( bmc_15in1_m_w )
10135{
10136   nes_state *state = space->machine().driver_data<nes_state>();
10137   LOG_MMC(("bmc_15in1_m_w, offset: %04x, data: %02x\n", offset, data));
10138
10139   if (offset & 0x0800)
10140   {
10141      state->m_mmc_prg_base = (data & 0x03) << 4;
10142      state->m_mmc_prg_mask = (data & 0x02) ? 0x0f : 0x1f;
10143      state->m_mmc_chr_base = (data & 0x03) << 7;
10144      state->m_mmc_chr_mask = (data & 0x02) ? 0x7f : 0xff;
10145      mmc3_set_prg(space->machine(), state->m_mmc_prg_base, state->m_mmc_prg_mask);
10146      mmc3_set_chr(space->machine(), state->m_mmc_chr_source, state->m_mmc_chr_base, state->m_mmc_chr_mask);
10147   }
10148}
10149
10150/*************************************************************
10151
10152 BMC-SUPERHIK_300IN1
10153
10154 Unknown Bootleg Multigame Board
10155 Games: 100000 in 1, Super HIK 300 in 1, 1997 in 1
10156
10157 iNES: mapper 212
10158
10159 In MESS: Supported.
10160
10161 *************************************************************/
10162
10163static WRITE8_HANDLER( bmc_hik300_w )
10164{
10165   LOG_MMC(("bmc_hik300_w, offset: %04x, data: %02x\n", offset, data));
10166
10167   set_nt_mirroring(space->machine(), BIT(data, 3) ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT);
10168   chr8(space->machine(), offset, CHRROM);
10169
10170   if (offset < 0x4000)
10171   {
10172      prg16_89ab(space->machine(), offset);
10173      prg16_cdef(space->machine(), offset);
10174   }
10175   else
10176      prg32(space->machine(), offset >> 1);
10177}
10178
10179/*************************************************************
10180
10181 BMC-SUPERGUN-20IN1
10182
10183 Unknown Bootleg Multigame Board
10184 Games: Super Gun 20 in 1
10185
10186 iNES: mapper 214
10187
10188 In MESS: Supported.
10189
10190 *************************************************************/
10191
10192static WRITE8_HANDLER( supergun20in1_w )
10193{
10194   LOG_MMC(("supergun20in1_w, offset: %04x, data: %02x\n", offset, data));
10195
10196   prg16_89ab(space->machine(), offset >> 2);
10197   prg16_cdef(space->machine(), offset >> 2);
10198   chr8(space->machine(), offset, CHRROM);
10199}
10200
10201/*************************************************************
10202
10203 BMC-72IN1
10204
10205 Unknown Bootleg Multigame Board
10206 Games: 72 in 1, 115 in 1 and other multigame carts
10207
10208 iNES: mapper 225
10209
10210 In MESS: Supported.
10211
10212 *************************************************************/
10213
10214static WRITE8_HANDLER( bmc_72in1_w )
10215{
10216   int hi_bank;
10217   int size_16;
10218   int bank;
10219
10220   LOG_MMC(("bmc_72in1_w, offset: %04x, data: %02x\n", offset, data));
10221
10222   chr8(space->machine(), offset, CHRROM);
10223   set_nt_mirroring(space->machine(), (offset & 0x2000) ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT);
10224
10225   hi_bank = offset & 0x40;
10226   size_16 = offset & 0x1000;
10227   bank = (offset & 0xf80) >> 7;
10228   if (size_16)
10229   {
10230      bank <<= 1;
10231      if (hi_bank)
10232         bank ++;
10233
10234      prg16_89ab(space->machine(), bank);
10235      prg16_cdef(space->machine(), bank);
10236   }
10237   else
10238      prg32(space->machine(), bank);
10239}
10240
10241/*************************************************************
10242
10243 BMC-76IN1
10244
10245 Unknown Bootleg Multigame Board
10246 Games: 76 in 1, Super 42 in 1
10247
10248 iNES: mapper 226
10249
10250 In MESS: Supported.
10251
10252 *************************************************************/
10253
10254// does this work for super42in1 as well?!?
10255static WRITE8_HANDLER( bmc_76in1_w )
10256{
10257   nes_state *state = space->machine().driver_data<nes_state>();
10258   int hi_bank;
10259   int size_16;
10260   int bank;
10261
10262   LOG_MMC(("bmc_76in1_w, offset: %04x, data: %02x\n", offset, data));
10263
10264   if (offset & 0x01)
10265      state->m_mmc_latch2 = data;
10266   else
10267      state->m_mmc_latch1 = data;
10268
10269   set_nt_mirroring(space->machine(), BIT(state->m_mmc_latch1, 6) ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT);
10270
10271   hi_bank = state->m_mmc_latch1 & 0x01;
10272   size_16 = state->m_mmc_latch1 & 0x20;
10273   bank = ((state->m_mmc_latch1 & 0x1e) >> 1) | ((state->m_mmc_latch1 & 0x80) >> 3) | ((state->m_mmc_latch2 & 0x01) << 5);
10274
10275   if (size_16)
10276   {
10277      bank <<= 1;
10278      if (hi_bank)
10279         bank ++;
10280
10281      prg16_89ab(space->machine(), bank);
10282      prg16_cdef(space->machine(), bank);
10283   }
10284   else
10285      prg32(space->machine(), bank);
10286}
10287
10288/*************************************************************
10289
10290 BMC-1200IN1
10291
10292 Unknown Bootleg Multigame Board
10293 Games: 1200 in 1, 295 in 1, 76 in 1
10294
10295 iNES: mapper 227
10296
10297 In MESS: Supported.
10298
10299 *************************************************************/
10300
10301static WRITE8_HANDLER( bmc_1200in1_w )
10302{
10303   int hi_bank;
10304   int size_32;
10305   int bank;
10306
10307   LOG_MMC(("bmc_1200in1_w, offset: %04x, data: %02x\n", offset, data));
10308
10309   hi_bank = offset & 0x04;
10310   size_32 = offset & 0x01;
10311   bank = ((offset & 0x78) >> 3) | ((offset & 0x0100) >> 4);
10312   if (!size_32)
10313   {
10314      bank <<= 1;
10315      if (hi_bank)
10316         bank ++;
10317
10318      prg16_89ab(space->machine(), bank);
10319      prg16_cdef(space->machine(), bank);
10320   }
10321   else
10322      prg32(space->machine(), bank);
10323
10324   if (!(offset & 0x80))
10325   {
10326      if (offset & 0x200)
10327         prg16_cdef(space->machine(), ((bank << 1) & 0x38) + 7);
10328      else
10329         prg16_cdef(space->machine(), ((bank << 1) & 0x38));
10330   }
10331
10332   set_nt_mirroring(space->machine(), BIT(data, 1) ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT);
10333}
10334
10335/*************************************************************
10336
10337 BMC-31IN1
10338
10339 Unknown Bootleg Multigame Board
10340 Games: 31 in 1
10341
10342 iNES: mapper 229
10343
10344 In MESS: Supported.
10345
10346 *************************************************************/
10347
10348static WRITE8_HANDLER( bmc_31in1_w )
10349{
10350   LOG_MMC(("bmc_31in1_w, offset: %04x, data: %02x\n", offset, data));
10351
10352   set_nt_mirroring(space->machine(), BIT(data, 5) ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT);
10353   chr8(space->machine(), offset, CHRROM);
10354
10355   if ((offset & 0x1e) == 0)
10356   {
10357      prg16_89ab(space->machine(), 0);
10358      prg16_89ab(space->machine(), 1);
10359   }
10360   else
10361   {
10362      prg16_89ab(space->machine(), offset & 0x1f);
10363      prg16_89ab(space->machine(), offset & 0x1f);
10364   }
10365}
10366
10367/*************************************************************
10368
10369 BMC-22GAMES
10370
10371 Unknown Bootleg Multigame Board
10372 Games: 22 in 1
10373
10374 iNES: mapper 230
10375
10376 In MESS: Partially Supported. It would need a reset
10377 to work (not possible yet)
10378
10379 *************************************************************/
10380
10381static WRITE8_HANDLER( bmc_22g_w )
10382{
10383   LOG_MMC(("bmc_22g_w, offset: %04x, data: %02x\n", offset, data));
10384
10385   if (1)   // this should flip at reset
10386   {
10387      prg16_89ab(space->machine(), data & 0x07);
10388   }
10389   else
10390   {
10391      if (data & 0x20)
10392      {
10393         prg16_89ab(space->machine(), (data & 0x1f) + 8);
10394         prg16_cdef(space->machine(), (data & 0x1f) + 8);
10395      }
10396      else
10397      {
10398         prg16_89ab(space->machine(), (data & 0x1f) + 8);
10399         prg16_cdef(space->machine(), (data & 0x1f) + 9);
10400      }
10401      set_nt_mirroring(space->machine(), BIT(data, 6) ? PPU_MIRROR_VERT : PPU_MIRROR_HORZ);
10402   }
10403}
10404
10405/*************************************************************
10406
10407 BMC-20IN1
10408
10409 Unknown Bootleg Multigame Board
10410 Games: 20 in 1
10411
10412 iNES: mapper 231
10413
10414 In MESS: Supported.
10415
10416 *************************************************************/
10417
10418static WRITE8_HANDLER( bmc_20in1_w )
10419{
10420   LOG_MMC(("bmc_20in1_w, offset: %04x, data: %02x\n", offset, data));
10421
10422   set_nt_mirroring(space->machine(), BIT(data, 7) ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT);
10423
10424   prg16_89ab(space->machine(), (offset & 0x1e));
10425   prg16_cdef(space->machine(), (offset & 0x1e) | ((offset & 0x20) ? 1 : 0));
10426}
10427
10428/*************************************************************
10429
10430 BMC-110IN1
10431
10432 Known Boards: Unknown Bootleg Board
10433 Games: 110 in 1
10434
10435 iNES: mapper 255
10436
10437 In MESS: Preliminary support.
10438
10439 *************************************************************/
10440
10441static WRITE8_HANDLER( bmc_110in1_w )
10442{
10443   UINT8 map255_helper1 = (offset >> 12) ? 0 : 1;
10444   UINT8 map255_helper2 = ((offset >> 8) & 0x40) | ((offset >> 6) & 0x3f);
10445
10446   LOG_MMC(("bmc_110in1_w, offset: %04x, data: %02x\n", offset, data));
10447
10448   set_nt_mirroring(space->machine(), (offset & 0x2000) ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT);
10449   prg16_89ab(space->machine(), map255_helper1 & ~map255_helper2);
10450   prg16_cdef(space->machine(), map255_helper1 | map255_helper2);
10451   chr8(space->machine(), ((offset >> 8) & 0x40) | (offset & 0x3f), CHRROM);
10452}
10453
10454/*************************************************************
10455
10456 BMC-SUPERBIG-7IN1
10457
10458 Known Boards: Unknown Multigame Bootleg Board
10459 Games: Kunio 8 in 1, Super Big 7 in 1
10460
10461 iNES: mapper 44
10462
10463 In MESS: Supported. It also uses mmc3_irq.
10464
10465 *************************************************************/
10466
10467static WRITE8_HANDLER( bmc_sbig7_w )
10468{
10469   nes_state *state = space->machine().driver_data<nes_state>();
10470   UINT8 page;
10471   LOG_MMC(("bmc_sbig7_w, offset: %04x, data: %02x\n", offset, data));
10472
10473   switch (offset & 0x6001)
10474   {
10475      case 0x2001: /* $a001 - Select 128K ROM/VROM base (0..5) or last 256K ROM/VRAM base (6) */
10476         page = (data & 0x07);
10477         if (page > 6)
10478            page = 6;
10479
10480         state->m_mmc_prg_base = page << 4;
10481         state->m_mmc_prg_mask = (page > 5) ? 0x1f : 0x0f;
10482         state->m_mmc_chr_base = page << 7;
10483         state->m_mmc_chr_mask = (page > 5) ? 0xff : 0x7f;
10484         mmc3_set_prg(space->machine(), state->m_mmc_prg_base, state->m_mmc_prg_mask);
10485         mmc3_set_chr(space->machine(), state->m_mmc_chr_source, state->m_mmc_chr_base, state->m_mmc_chr_mask);
10486         break;
10487
10488      default:
10489         txrom_w(space, offset, data);
10490         break;
10491   }
10492}
10493
10494/*************************************************************
10495
10496 BMC-HIK8IN1
10497
10498 Known Boards: Unknown Multigame Bootleg Board
10499 Games: Street Fighter V, various multigame carts
10500
10501 iNES: mapper 45
10502
10503 In MESS: Supported. It also uses mmc3_irq.
10504
10505 *************************************************************/
10506
10507static WRITE8_HANDLER( bmc_hik8_m_w )
10508{
10509   nes_state *state = space->machine().driver_data<nes_state>();
10510   LOG_MMC(("bmc_hik8_m_w, offset: %04x, data: %02x\n", offset, data));
10511
10512   /* This bit is the "register lock". Once register are locked, writes go to WRAM
10513     and there is no way to unlock them (except by resetting the machine) */
10514   if ((state->m_mmc_reg[3] & 0x40) && state->m_wram != NULL)
10515      state->m_wram[offset] = data;
10516   else
10517   {
10518      state->m_mmc_reg[state->m_mmc_count] = data;
10519      state->m_mmc_count = (state->m_mmc_count + 1) & 0x03;
10520
10521      if (!state->m_mmc_count)
10522      {
10523         LOG_MMC(("bmc_hik8_m_w, command completed %02x %02x %02x %02x\n", state->m_mmc_reg[3],
10524                state->m_mmc_reg[2], state->m_mmc_reg[1], state->m_mmc_reg[0]));
10525
10526         state->m_mmc_prg_base = state->m_mmc_reg[1];
10527         state->m_mmc_prg_mask = 0x3f ^ (state->m_mmc_reg[3] & 0x3f);
10528         state->m_mmc_chr_base = ((state->m_mmc_reg[2] & 0xf0) << 4) | state->m_mmc_reg[0];
10529         if (BIT(state->m_mmc_reg[2], 3))
10530            state->m_mmc_chr_mask = (1 << ((state->m_mmc_reg[2] & 7) + 1)) - 1;
10531         else if (state->m_mmc_reg[2])
10532            state->m_mmc_chr_mask = 0;
10533         else
10534            state->m_mmc_chr_mask = 0xff;   // i.e. we use the vrom_bank with no masking
10535
10536         mmc3_set_prg(space->machine(), state->m_mmc_prg_base, state->m_mmc_prg_mask);
10537         mmc3_set_chr(space->machine(), state->m_mmc_chr_source, state->m_mmc_chr_base, state->m_mmc_chr_mask);
10538      }
10539   }
10540}
10541
10542/*************************************************************
10543
10544 BMC-SUPERHIK-4IN1
10545
10546 Known Boards: Unknown Multigame Bootleg Board
10547 Games: Super HIK 4 in 1
10548
10549 iNES: mapper 49
10550
10551 In MESS: Supported. It also uses mmc3_irq.
10552
10553 *************************************************************/
10554
10555static WRITE8_HANDLER( bmc_hik4in1_m_w )
10556{
10557   nes_state *state = space->machine().driver_data<nes_state>();
10558   LOG_MMC(("bmc_hik4in1_m_w, offset: %04x, data: %02x\n", offset, data));
10559
10560   /* mid writes only work when WRAM is enabled. not sure if I should
10561     change the condition to state->m_mmc_latch2==0x80 (i.e. what is the effect of
10562     the read-only bit?) */
10563   if (state->m_mmc3_wram_protect & 0x80)
10564   {
10565      if (data & 0x01)   /* if this is 0, then we have 32k PRG blocks */
10566      {
10567         state->m_mmc_prg_base = (data & 0xc0) >> 2;
10568         state->m_mmc_prg_mask = 0x0f;
10569         mmc3_set_prg(space->machine(), state->m_mmc_prg_base, state->m_mmc_prg_mask);
10570      }
10571      else
10572         prg32(space->machine(), (data & 0x30) >> 4);
10573
10574      state->m_mmc_chr_base = (data & 0xc0) << 1;
10575      state->m_mmc_chr_mask = 0x7f;
10576      mmc3_set_chr(space->machine(), state->m_mmc_chr_source, state->m_mmc_chr_base, state->m_mmc_chr_mask);
10577   }
10578}
10579
10580/*************************************************************
10581
10582 BMC-BALLGAMES-11IN1
10583
10584 Known Boards: Unknown Multigame Bootleg Board
10585 Games: 11 in 1 Ball Games
10586
10587 iNES: mapper 51
10588
10589 In MESS: Partially Supported.
10590
10591 *************************************************************/
10592
10593static void bmc_ball11_set_banks( running_machine &machine )
10594{
10595   nes_state *state = machine.driver_data<nes_state>();
10596   set_nt_mirroring(machine, (state->m_mmc_reg[0] == 3) ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT);
10597
10598   if (state->m_mmc_reg[0] & 0x01)
10599   {
10600      prg32(machine, state->m_mmc_reg[1]);
10601   }
10602   else
10603   {
10604      prg16_89ab(machine, (state->m_mmc_reg[1] << 1) | (state->m_mmc_reg[0] >> 1));
10605      prg16_cdef(machine, (state->m_mmc_reg[1] << 1) | 0x07);
10606   }
10607}
10608
10609static WRITE8_HANDLER( bmc_ball11_m_w )
10610{
10611   nes_state *state = space->machine().driver_data<nes_state>();
10612
10613   LOG_MMC(("bmc_ball11_m_w, offset: %04x, data: %02x\n", offset, data));
10614
10615   state->m_mmc_reg[0] = ((data >> 1) & 0x01) | ((data >> 3) & 0x02);
10616   bmc_ball11_set_banks(space->machine());
10617}
10618
10619static WRITE8_HANDLER( bmc_ball11_w )
10620{
10621   nes_state *state = space->machine().driver_data<nes_state>();
10622
10623   LOG_MMC(("bmc_ball11_w, offset: %04x, data: %02x\n", offset, data));
10624
10625   switch (offset & 0x6000)
10626   {
10627      case 0x4000:   // here we also update reg[0] upper bit
10628         state->m_mmc_reg[0] = (state->m_mmc_reg[0] & 0x01) | ((data >> 3) & 0x02);
10629      case 0x0000:
10630      case 0x2000:
10631      case 0x6000:
10632         state->m_mmc_reg[1] = data & 0x0f;
10633         bmc_ball11_set_banks(space->machine());
10634         break;
10635   }
10636}
10637
10638/*************************************************************
10639
10640 BMC-MARIOPARTY-7IN1
10641
10642 Known Boards: Unknown Multigame Bootleg Board
10643 Games: Mario 7 in 1
10644
10645 MMC3 clone
10646
10647 iNES: mapper 52
10648
10649 In MESS: Supported.
10650
10651 *************************************************************/
10652
10653static WRITE8_HANDLER( bmc_mario7in1_m_w )
10654{
10655   nes_state *state = space->machine().driver_data<nes_state>();
10656   UINT8 map52_helper1, map52_helper2;
10657   LOG_MMC(("bmc_mario7in1_m_w, offset: %04x, data: %02x\n", offset, data));
10658
10659   /* mid writes only work when WRAM is enabled. not sure if I should
10660     change the condition to state->m_mmc_latch2==0x80 (i.e. what is the effect of
10661     the read-only bit?) and it only can happen once! */
10662   if ((state->m_mmc3_wram_protect & 0x80) && !state->m_map52_reg_written)
10663   {
10664      map52_helper1 = (data & 0x08);
10665      map52_helper2 = (data & 0x40);
10666
10667      state->m_mmc_prg_base = map52_helper1 ? ((data & 0x07) << 4) : ((data & 0x06) << 4);
10668      state->m_mmc_prg_mask = map52_helper1 ? 0x0f : 0x1f;
10669      state->m_mmc_chr_base = ((data & 0x20) << 4) | ((data & 0x04) << 6) | (map52_helper2 ? ((data & 0x10) << 3) : 0);
10670      state->m_mmc_chr_mask = map52_helper2 ? 0x7f : 0xff;
10671      mmc3_set_prg(space->machine(), state->m_mmc_prg_base, state->m_mmc_prg_mask);
10672      mmc3_set_chr(space->machine(), state->m_mmc_chr_source, state->m_mmc_chr_base, state->m_mmc_chr_mask);
10673
10674      state->m_map52_reg_written = 1;
10675   }
10676   else
10677      state->m_wram[offset] = data;
10678}
10679
10680/*************************************************************
10681
10682 BMC-GOLDENCARD-6IN1
10683
10684 Known Boards: Unknown Bootleg Multigame Board
10685 Games: Golden Card 6 in 1
10686
10687 MMC3 clone
10688
10689 iNES: mapper 217
10690
10691 In MESS: Supported.
10692
10693 *************************************************************/
10694
10695// remove mask & base parameters!
10696static void bmc_gc6in1_set_prg( running_machine &machine, int prg_base, int prg_mask )
10697{
10698   nes_state *state = machine.driver_data<nes_state>();
10699   state->m_mmc_prg_base = (state->m_mmc_reg[1] & 0x08) ? 0 : (state->m_mmc_reg[1] & 0x10);
10700   state->m_mmc_prg_mask = (state->m_mmc_reg[1] & 0x08) ? 0x1f : 0x0f;
10701
10702   state->m_mmc_prg_base |= ((state->m_mmc_reg[1] & 0x03) << 5);
10703
10704   mmc3_set_prg(machine, state->m_mmc_prg_base, state->m_mmc_prg_mask);
10705}
10706
10707static void bmc_gc6in1_set_chr( running_machine &machine, UINT8 chr )
10708{
10709   nes_state *state = machine.driver_data<nes_state>();
10710   UINT8 chr_page = (state->m_mmc_latch1 & 0x80) >> 5;
10711   int chr_base = (state->m_mmc_reg[1] & 0x08) ? 0x00 : ((state->m_mmc_reg[1] & 0x10) << 3);
10712   int chr_mask = (state->m_mmc_reg[1] & 0x08) ? 0xff : 0x7f;
10713
10714   chr_base |= ((state->m_mmc_reg[1] & 0x03) << 8);
10715
10716   chr1_x(machine, chr_page ^ 0, chr_base | ((state->m_mmc_vrom_bank[0] & ~0x01) & chr_mask), chr);
10717   chr1_x(machine, chr_page ^ 1, chr_base | ((state->m_mmc_vrom_bank[0] |  0x01) & chr_mask), chr);
10718   chr1_x(machine, chr_page ^ 2, chr_base | ((state->m_mmc_vrom_bank[1] & ~0x01) & chr_mask), chr);
10719   chr1_x(machine, chr_page ^ 3, chr_base | ((state->m_mmc_vrom_bank[1] |  0x01) & chr_mask), chr);
10720   chr1_x(machine, chr_page ^ 4, chr_base | (state->m_mmc_vrom_bank[2] & chr_mask), chr);
10721   chr1_x(machine, chr_page ^ 5, chr_base | (state->m_mmc_vrom_bank[3] & chr_mask), chr);
10722   chr1_x(machine, chr_page ^ 6, chr_base | (state->m_mmc_vrom_bank[4] & chr_mask), chr);
10723   chr1_x(machine, chr_page ^ 7, chr_base | (state->m_mmc_vrom_bank[5] & chr_mask), chr);
10724}
10725
10726static WRITE8_HANDLER( bmc_gc6in1_l_w )
10727{
10728   nes_state *state = space->machine().driver_data<nes_state>();
10729   UINT8 bank;
10730   LOG_MMC(("bmc_gc6in1_l_w, offset: %04x, data: %02x\n", offset, data));
10731   offset += 0x100;
10732
10733   if (offset == 0x1000)
10734   {
10735      state->m_mmc_reg[0] = data;
10736      if (data & 0x80)
10737      {
10738         bank = (data & 0x0f) | ((state->m_mmc_reg[1] & 0x03) << 4);
10739         prg16_89ab(space->machine(), bank);
10740         prg16_cdef(space->machine(), bank);
10741      }
10742      else
10743         bmc_gc6in1_set_prg(space->machine(), state->m_mmc_prg_base, state->m_mmc_prg_mask);
10744   }
10745   else if (offset == 0x1001)
10746   {
10747      state->m_mmc_reg[1] = data;
10748      bmc_gc6in1_set_prg(space->machine(), state->m_mmc_prg_base, state->m_mmc_prg_mask);
10749   }
10750   else if (offset == 0x1007)
10751   {
10752      state->m_mmc_reg[2] = data;
10753   }
10754}
10755
10756static WRITE8_HANDLER( bmc_gc6in1_w )
10757{
10758   nes_state *state = space->machine().driver_data<nes_state>();
10759   UINT8 mmc_helper, cmd;
10760   static const UINT8 conv_table[8] = {0, 6, 3, 7, 5, 2, 4, 1};
10761   LOG_MMC(("bmc_gc6in1_w, offset: %04x, data: %02x\n", offset, data));
10762
10763   if (!state->m_mmc_reg[2]) // in this case we act like MMC3, only with alt prg/chr handlers
10764   {
10765      switch (offset & 0x6001)
10766      {
10767         case 0x0000:
10768            mmc_helper = state->m_mmc3_latch ^ data;
10769            state->m_mmc3_latch = data;
10770
10771            /* Has PRG Mode changed? */
10772            if (mmc_helper & 0x40)
10773               bmc_gc6in1_set_prg(space->machine(), state->m_mmc_prg_base, state->m_mmc_prg_mask);
10774
10775            /* Has CHR Mode changed? */
10776            if (mmc_helper & 0x80)
10777               bmc_gc6in1_set_chr(space->machine(), state->m_mmc_chr_source);
10778            break;
10779
10780         case 0x0001:
10781            cmd = state->m_mmc3_latch & 0x07;
10782            switch (cmd)
10783         {
10784            case 0: case 1:   // these do not need to be separated: we take care of them in set_chr!
10785            case 2: case 3: case 4: case 5:
10786               state->m_mmc_vrom_bank[cmd] = data;
10787               bmc_gc6in1_set_chr(space->machine(), state->m_mmc_chr_source);
10788               break;
10789            case 6:
10790            case 7:
10791               state->m_mmc_prg_bank[cmd - 6] = data;
10792               bmc_gc6in1_set_prg(space->machine(), state->m_mmc_prg_base, state->m_mmc_prg_mask);
10793               break;
10794         }
10795            break;
10796
10797         default:
10798            txrom_w(space, offset, data);
10799            break;
10800      }
10801   }
10802   else
10803   {
10804      switch (offset & 0x6001)
10805      {
10806         case 0x0000:
10807            txrom_w(space, 0x4000, data);
10808            break;
10809
10810         case 0x0001:
10811            data = (data & 0xc0) | conv_table[data & 0x07];
10812            mmc_helper = state->m_mmc3_latch ^ data;
10813            state->m_mmc3_latch = data;
10814
10815            /* Has PRG Mode changed? */
10816            if (mmc_helper & 0x40)
10817               bmc_gc6in1_set_prg(space->machine(), state->m_mmc_prg_base, state->m_mmc_prg_mask);
10818
10819            /* Has CHR Mode changed? */
10820            if (mmc_helper & 0x80)
10821               bmc_gc6in1_set_chr(space->machine(), state->m_mmc_chr_source);
10822
10823            state->m_mmc_reg[3] = 1;
10824            break;
10825
10826         case 0x2000:
10827            cmd = state->m_mmc3_latch & 0x07;
10828            if (state->m_mmc_reg[3])
10829            {
10830               state->m_mmc_reg[3] = 0;
10831               switch (cmd)
10832               {
10833                  case 0: case 1:   // these do not need to be separated: we take care of them in set_chr!
10834                  case 2: case 3: case 4: case 5:
10835                     state->m_mmc_vrom_bank[cmd] = data;
10836                     bmc_gc6in1_set_chr(space->machine(), state->m_mmc_chr_source);
10837                     break;
10838                  case 6:
10839                  case 7:
10840                     state->m_mmc_prg_bank[cmd - 6] = data;
10841                     bmc_gc6in1_set_prg(space->machine(), state->m_mmc_prg_base, state->m_mmc_prg_mask);
10842                     break;
10843               }
10844            }
10845            break;
10846
10847
10848         case 0x2001:
10849            set_nt_mirroring(space->machine(), BIT(data, 0) ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT);
10850            break;
10851
10852         default:
10853            txrom_w(space, offset, data);
10854            break;
10855      }
10856   }
10857}
10858
10859/*************************************************************
10860
10861 BMC-FAMILY-4646B
10862
10863 Known Boards: Unknown Multigame Bootleg Board (4646B)
10864 Games: 2 in 1 - Family Kid & Aladdin 4
10865
10866 MMC3 clone
10867
10868 iNES: mapper 134
10869
10870 In MESS: Supported.
10871
10872 *************************************************************/
10873
10874static WRITE8_HANDLER( bmc_family4646_m_w )
10875{
10876   nes_state *state = space->machine().driver_data<nes_state>();
10877   LOG_MMC(("bmc_family4646_m_w, offset: %04x, data: %02x\n", offset, data));
10878
10879   if (offset == 0x01)
10880   {
10881      state->m_mmc_prg_base = (data & 0x02) << 4;
10882      state->m_mmc_prg_mask = 0x1f;
10883      state->m_mmc_chr_base = (data & 0x20) << 3;
10884      state->m_mmc_chr_mask = 0xff;
10885      mmc3_set_prg(space->machine(), state->m_mmc_prg_base, state->m_mmc_prg_mask);
10886      mmc3_set_chr(space->machine(), state->m_mmc_chr_source, state->m_mmc_chr_base, state->m_mmc_chr_mask);
10887   }
10888}
10889
10890/*************************************************************
10891
10892 BMC-VT5201
10893
10894 *************************************************************/
10895
10896static WRITE8_HANDLER( bmc_vt5201_w )
10897{
10898   nes_state *state = space->machine().driver_data<nes_state>();
10899   LOG_MMC(("bmc_vt5201_w, offset: %04x, data: %02x\n", offset, data));
10900
10901   state->m_mmc_latch1 = BIT(offset, 8);
10902
10903   // not sure about this mirroring bit!!
10904   // without it TN 95 in 1 has glitches in Lunar Ball; with it TN 95 in 1 has glitches in Galaxian!
10905   set_nt_mirroring(space->machine(), BIT(data, 3) ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT);
10906   if (BIT(offset, 7))
10907   {
10908      prg16_89ab(space->machine(), (offset >> 4) & 0x07);
10909      prg16_cdef(space->machine(), (offset >> 4) & 0x07);
10910   }
10911   else
10912      prg32(space->machine(), (offset >> 5) & 0x03);
10913   chr8(space->machine(), offset, CHRROM);
10914}
10915
10916static READ8_HANDLER( bmc_vt5201_r )
10917{
10918   nes_state *state = space->machine().driver_data<nes_state>();
10919   LOG_MMC(("bmc_vt5201_r, offset: %04x\n", offset));
10920   //  state->m_mmc_dipsetting = input_port_read(space->machine(), "CARTDIPS");
10921
10922   if (state->m_mmc_latch1)
10923      return state->m_mmc_dipsetting; // cart mode, depending on the Dip Switches (always zero atm, given we have no way to add cart-based DIPs)
10924   else
10925      return mmc_hi_access_rom(space->machine(), offset);
10926}
10927
10928/*************************************************************
10929
10930 BMC-BS-5
10931
10932 Games: a few 4 in 1 multicarts
10933
10934 *************************************************************/
10935
10936static void bmc_bs5_update_banks( running_machine &machine )
10937{
10938   nes_state *state = machine.driver_data<nes_state>();
10939
10940   prg8_89(machine, state->m_mmc_prg_bank[0]);
10941   prg8_ab(machine, state->m_mmc_prg_bank[1]);
10942   prg8_cd(machine, state->m_mmc_prg_bank[2]);
10943   prg8_ef(machine, state->m_mmc_prg_bank[3]);
10944   chr2_0(machine, state->m_mmc_vrom_bank[0], CHRROM);
10945   chr2_2(machine, state->m_mmc_vrom_bank[1], CHRROM);
10946   chr2_4(machine, state->m_mmc_vrom_bank[2], CHRROM);
10947   chr2_6(machine, state->m_mmc_vrom_bank[3], CHRROM);
10948}
10949
10950static WRITE8_HANDLER( bmc_bs5_w )
10951{
10952   nes_state *state = space->machine().driver_data<nes_state>();
10953   UINT8 bs5_helper = (offset & 0xc00) >> 10;
10954   LOG_MMC(("bmc_bs5_w, offset: %04x, data: %02x\n", offset, data));
10955//  state->m_mmc_dipsetting = input_port_read(space->machine(), "CARTDIPS");
10956
10957   switch (offset & 0x7000)
10958   {
10959      case 0x0000:
10960         state->m_mmc_vrom_bank[bs5_helper] = offset & 0x1f;
10961         break;
10962      case 0x2000:
10963         if (BIT(offset, state->m_mmc_dipsetting + 4))   // mmc_dipsetting is always zero atm, given we have no way to add cart-based DIPs
10964            state->m_mmc_prg_bank[bs5_helper] = offset & 0x0f;
10965         break;
10966   }
10967   bmc_bs5_update_banks(space->machine());
10968}
10969
10970/*************************************************************
10971
10972 BMC-810544-C-A1
10973
10974 Games: 200-in-1 Elfland
10975
10976 *************************************************************/
10977
10978static WRITE8_HANDLER( bmc_810544_w )
10979{
10980   UINT8 bank = (offset >> 7);
10981   LOG_MMC(("bmc_810544_w, offset: %04x, data: %02x\n", offset, data));
10982
10983   if (!BIT(offset, 6))
10984   {
10985      prg16_89ab(space->machine(), (bank << 1) | BIT(offset, 5));
10986      prg16_cdef(space->machine(), (bank << 1) | BIT(offset, 5));
10987   }
10988   else
10989      prg32(space->machine(), bank);
10990
10991   set_nt_mirroring(space->machine(), BIT(offset, 4) ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT);
10992
10993   chr8(space->machine(), offset & 0x0f, CHRROM);
10994}
10995
10996/*************************************************************
10997
10998 BMC-NTD-03
10999
11000 *************************************************************/
11001
11002static WRITE8_HANDLER( bmc_ntd03_w )
11003{
11004   UINT8 pbank, cbank;
11005   LOG_MMC(("bmc_ntd03_w, offset: %04x, data: %02x\n", offset, data));
11006
11007   pbank = (offset >> 10) & 0x1e;
11008   cbank = ((offset & 0x300) >> 5) | (offset & 0x07);
11009
11010   if (BIT(offset, 7))
11011   {
11012      prg16_89ab(space->machine(), pbank | BIT(offset, 6));
11013      prg16_cdef(space->machine(), pbank | BIT(offset, 6));
11014   }
11015   else
11016      prg32(space->machine(), pbank >> 1);
11017
11018   set_nt_mirroring(space->machine(), BIT(offset, 10) ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT);
11019
11020   chr8(space->machine(), cbank, CHRROM);
11021}
11022
11023/*************************************************************
11024
11025 BMC-GHOSTBUSTERS63IN1
11026
11027 in MESS: only preliminar support
11028
11029 *************************************************************/
11030
11031static void bmc_gb63_update( running_machine &machine )
11032{
11033   nes_state *state = machine.driver_data<nes_state>();
11034
11035   set_nt_mirroring(machine, BIT(state->m_mmc_reg[0], 6) ? PPU_MIRROR_VERT : PPU_MIRROR_HORZ);
11036
11037   if (BIT(state->m_mmc_reg[0], 5))
11038   {
11039      prg16_89ab(machine, state->m_mmc_reg[0] & 0x1f);   // FIXME: here probably we could also have PRGRAM, depending on mmc_latch1!
11040      prg16_cdef(machine, state->m_mmc_reg[0] & 0x1f);   // FIXME: here probably we could also have PRGRAM, depending on mmc_latch1!
11041   }
11042   else
11043      prg32(machine, (state->m_mmc_reg[0] & 0x1f) >> 1);   // FIXME: here probably we could also have PRGRAM, depending on mmc_latch1!
11044
11045   if (BIT(state->m_mmc_reg[1], 2))
11046      chr8(machine, 0, CHRRAM);
11047//  else
11048//      chr8(machine, 0, CHRROM);
11049}
11050
11051static WRITE8_HANDLER( bmc_gb63_w )
11052{
11053   nes_state *state = space->machine().driver_data<nes_state>();
11054   LOG_MMC(("bmc_gb63_w, offset: %04x, data: %02x\n", offset, data));
11055
11056   state->m_mmc_reg[offset & 1] = data;
11057   state->m_mmc_latch1 = BIT(state->m_mmc_reg[0], 7) | (BIT(state->m_mmc_reg[1], 0) << 1);
11058
11059}
11060
11061static READ8_HANDLER( bmc_gb63_r )
11062{
11063   nes_state *state = space->machine().driver_data<nes_state>();
11064   LOG_MMC(("bmc_gb63_r, offset: %04x\n", offset));
11065   //  state->m_mmc_dipsetting = input_port_read(space->machine(), "CARTDIPS");
11066
11067   if (state->m_mmc_latch1 == 1)
11068      return 0xff;   // open bus
11069   else
11070      return mmc_hi_access_rom(space->machine(), offset);
11071}
11072
11073/*************************************************************
11074
11075 UNL-EDU2000
11076
11077 *************************************************************/
11078
11079static WRITE8_HANDLER( edu2k_w )
11080{
11081   LOG_MMC(("edu2k_w, offset: %04x, data: %02x\n", offset, data));
11082
11083   prg32(space->machine(), data & 0x1f);
11084   wram_bank(space->machine(), (data & 0xc0) >> 6, NES_WRAM);
11085}
11086
11087/*************************************************************
11088
11089 UNL-H2288
11090
11091 *************************************************************/
11092
11093static void h2288_prg_cb( running_machine &machine, int start, int bank )
11094{
11095   nes_state *state = machine.driver_data<nes_state>();
11096
11097   if (!(state->m_mmc_reg[0] & 0x40))
11098      prg8_x(machine, start, bank);
11099}
11100
11101static WRITE8_HANDLER( h2288_l_w )
11102{
11103   nes_state *state = space->machine().driver_data<nes_state>();
11104   LOG_MMC(("h2288_l_w offset: %04x, data: %02x\n", offset, data));
11105   offset += 0x100;
11106
11107   if (offset >= 0x1800)
11108   {
11109      state->m_mmc_reg[offset & 1] = data;
11110      if (state->m_mmc_reg[0] & 0x40)
11111      {
11112         UINT8 helper1 = (state->m_mmc_reg[0] & 0x05) | ((state->m_mmc_reg[0] >> 2) & 0x0a);
11113         UINT8 helper2 = BIT(state->m_mmc_reg[0], 1);
11114         prg16_89ab(space->machine(), helper1 & ~helper2);
11115         prg16_cdef(space->machine(), helper1 |  helper2);
11116      }
11117      else
11118         mmc3_set_prg(space->machine(), state->m_mmc_prg_base, state->m_mmc_prg_mask);
11119   }
11120}
11121
11122static READ8_HANDLER( h2288_l_r )
11123{
11124   LOG_MMC(("h2288_l_r offset: %04x\n", offset));
11125   offset += 0x100;
11126
11127   if (offset >= 0x1000)
11128   {
11129      int helper = offset >> 8;
11130      if (offset & 1)
11131         return helper | 0x01;
11132      else
11133         return helper ^ 0x01;
11134   }
11135
11136   return 0;
11137}
11138
11139static WRITE8_HANDLER( h2288_w )
11140{
11141   static const UINT8 conv_table[8] = {0, 3, 1, 5, 6, 7, 2, 4};
11142   LOG_MMC(("h2288_w, offset: %04x, data: %02x\n", offset, data));
11143
11144   switch (offset & 0x6001)
11145   {
11146      case 0x0000:
11147         txrom_w(space, 0x0000, (data & 0xc0) | conv_table[data & 0x07]);
11148         break;
11149
11150      default:
11151         txrom_w(space, offset, data);
11152         break;
11153   }
11154}
11155
11156/*************************************************************
11157
11158 UNL-SHJY3
11159
11160 *************************************************************/
11161
11162/* I think the IRQ should only get fired if enough CPU cycles have passed, but we don't implement (yet) this part */
11163static void shjy3_irq( device_t *device, int scanline, int vblank, int blanked )
11164{
11165   nes_state *state = device->machine().driver_data<nes_state>();
11166   if (state->m_IRQ_enable & 0x02)
11167   {
11168      if (state->m_IRQ_count == 0xff)
11169      {
11170         state->m_IRQ_count = state->m_IRQ_count_latch;
11171         state->m_IRQ_enable = state->m_IRQ_enable | ((state->m_IRQ_enable & 0x01) << 1);
11172         device_set_input_line(state->m_maincpu, M6502_IRQ_LINE, HOLD_LINE);
11173      }
11174      else
11175         state->m_IRQ_count++;
11176   }
11177}
11178
11179static void shjy3_update( running_machine &machine )
11180{
11181   nes_state *state = machine.driver_data<nes_state>();
11182   int i;
11183
11184   prg8_89(machine, state->m_mmc_prg_bank[0]);
11185   prg8_ab(machine, state->m_mmc_prg_bank[1]);
11186
11187   for (i = 0; i < 8; i++)
11188   {
11189      UINT8 chr_bank = state->m_mmc_vrom_bank[i] | (state->m_mmc_extra_bank[i] << 4);
11190      if (state->m_mmc_vrom_bank[i] == 0xc8)
11191      {
11192         state->m_mmc_latch1 = 0;
11193         continue;
11194      }
11195      else if (state->m_mmc_vrom_bank[i] == 0x88)
11196      {
11197         state->m_mmc_latch1 = 1;
11198         continue;
11199      }
11200      if ((state->m_mmc_vrom_bank[i] == 4 || state->m_mmc_vrom_bank[i] == 5) && !state->m_mmc_latch1)
11201         chr1_x(machine, i, chr_bank & 1, CHRRAM);
11202      else
11203         chr1_x(machine, i, chr_bank, CHRROM);
11204   }
11205}
11206
11207static WRITE8_HANDLER( shjy3_w )
11208{
11209   nes_state *state = space->machine().driver_data<nes_state>();
11210   UINT8 mmc_helper, shift;
11211   LOG_MMC(("shjy3_w, offset: %04x, data: %02x\n", offset, data));
11212
11213   if (offset >= 0x3000 && offset <= 0x600c)
11214   {
11215      mmc_helper = ((offset & 8) | (offset >> 8)) >> 3;
11216      mmc_helper += 2;
11217      mmc_helper &= 7;
11218      shift = offset & 4;
11219
11220      state->m_mmc_vrom_bank[mmc_helper] = (state->m_mmc_vrom_bank[mmc_helper] & (0xf0 >> shift)) | ((data & 0x0f) << shift);
11221      if (shift)
11222         state->m_mmc_extra_bank[mmc_helper] = data >> 4;
11223   }
11224   else
11225   {
11226      switch (offset)
11227      {
11228         case 0x0010:
11229            state->m_mmc_prg_bank[0] = data;
11230            break;
11231         case 0x2010:
11232            state->m_mmc_prg_bank[1] = data;
11233            break;
11234         case 0x1400:
11235            switch (data & 0x03)
11236            {
11237               case 0: set_nt_mirroring(space->machine(), PPU_MIRROR_VERT); break;
11238               case 1: set_nt_mirroring(space->machine(), PPU_MIRROR_HORZ); break;
11239               case 2: set_nt_mirroring(space->machine(), PPU_MIRROR_LOW); break;
11240               case 3: set_nt_mirroring(space->machine(), PPU_MIRROR_HIGH); break;
11241            }
11242            break;
11243         case 0x7000:
11244            state->m_IRQ_count_latch = (state->m_IRQ_count_latch & 0xf0) | (data & 0x0f);
11245            break;
11246         case 0x7004:
11247            state->m_IRQ_count_latch = (state->m_IRQ_count_latch & 0x0f) | ((data & 0x0f) << 4);
11248            break;
11249         case 0x7008:
11250            state->m_IRQ_enable = data & 0x03;
11251            if (state->m_IRQ_enable & 0x02)
11252               state->m_IRQ_count = state->m_IRQ_count_latch;
11253            break;
11254      }
11255   }
11256   shjy3_update(space->machine());
11257}
11258
11259/*************************************************************
11260
11261 UNL-603-5052
11262
11263 MMC3 + protection access in 0x4020 - 0x7fff
11264
11265 in MESS: Partial support
11266
11267 *************************************************************/
11268
11269WRITE8_HANDLER( unl_6035052_extra_w )
11270{
11271   nes_state *state = space->machine().driver_data<nes_state>();
11272   LOG_MMC(("unl_6035052_extra_w, offset: %04x, data: %02x\n", offset, data));
11273   state->m_mmc_latch1 = data & 0x03;
11274   if (state->m_mmc_latch1 == 1)
11275      state->m_mmc_latch1 = 2;
11276}
11277
11278READ8_HANDLER( unl_6035052_extra_r )
11279{
11280   nes_state *state = space->machine().driver_data<nes_state>();
11281   LOG_MMC(("unl_6035052_extra_r, offset: %04x\n", offset));
11282   return state->m_mmc_latch1;
11283}
11284
11285
11286/*************************************************************
11287
11288 BMC-POWERJOY
11289
11290 *************************************************************/
11291
11292static void pjoy84_prg_cb( running_machine &machine, int start, int bank )
11293{
11294   nes_state *state = machine.driver_data<nes_state>();
11295   UINT8 flip = (state->m_mmc3_latch & 0x40) ? 2 : 0;
11296
11297   if (!(state->m_mmc_reg[3] & 0x03))
11298      prg8_x(machine, start, bank);
11299   else if (start == flip)
11300   {
11301      if ((state->m_mmc_reg[3] & 0x03) == 0x03)
11302         prg32(machine, bank >> 2);
11303      else
11304      {
11305         prg16_89ab(machine, bank >> 1);
11306         prg16_cdef(machine, bank >> 1);
11307      }
11308   }
11309}
11310
11311static void pjoy84_chr_cb( running_machine &machine, int start, int bank, int source )
11312{
11313   nes_state *state = machine.driver_data<nes_state>();
11314
11315   if (!(state->m_mmc_reg[3] & 0x10))
11316      chr1_x(machine, start, bank, source);
11317}
11318
11319INLINE void pjoy84_set_base_mask( running_machine &machine )
11320{
11321   nes_state *state = machine.driver_data<nes_state>();
11322
11323   state->m_mmc_prg_base = ((state->m_mmc_reg[0] & (0x06 | BIT(state->m_mmc_reg[0], 6))) << 4) |
11324                  (BIT(state->m_mmc_reg[0], 4) << 7);
11325
11326   state->m_mmc_chr_base = ((~state->m_mmc_reg[0] << 0) & 0x080 & state->m_mmc_reg[2]) |
11327                  ((state->m_mmc_reg[0] << 4) & 0x080 & state->m_mmc_reg[0]) |
11328                  ((state->m_mmc_reg[0] << 3) & 0x100) |
11329                  ((state->m_mmc_reg[0] << 5) & 0x200);
11330
11331   state->m_mmc_prg_mask = BIT(state->m_mmc_reg[0], 6) ? 0x0f : 0x1f;
11332   state->m_mmc_chr_mask = BIT(state->m_mmc_reg[0], 7) ? 0x7f : 0xff;
11333}
11334
11335static WRITE8_HANDLER( pjoy84_m_w )
11336{
11337   nes_state *state = space->machine().driver_data<nes_state>();
11338   LOG_MMC(("pjoy84_m_w offset: %04x, data: %02x\n", offset, data));
11339
11340   switch (offset & 0x03)
11341   {
11342      case 0x00:
11343      case 0x03:
11344         if (state->m_mmc_reg[3] & 0x80)
11345            return;   // else we act as if offset & 3 = 1,2
11346      case 0x01:
11347      case 0x02:
11348         state->m_mmc_reg[offset & 0x03] = data;
11349         pjoy84_set_base_mask(space->machine());
11350         if (state->m_mmc_reg[3] & 0x10)
11351            chr8(space->machine(), (state->m_mmc_chr_base >> 3) | (state->m_mmc_reg[2] & 0x0f), state->m_mmc_chr_source);
11352         else
11353            mmc3_set_chr(space->machine(), state->m_mmc_chr_source, state->m_mmc_chr_base, state->m_mmc_chr_mask);
11354         mmc3_set_prg(space->machine(), state->m_mmc_prg_base, state->m_mmc_prg_mask);
11355         break;
11356   }
11357}
11358
11359/*************************************************************
11360
11361 SOMERI TEAM
11362
11363 iNES: mapper 116
11364
11365 Emulation note about regs in MESS: currently,
11366 - state->m_mmc_cmd1 represent the board mode
11367 - state->m_mmc_reg[n] for n=0,1,2,3 represent the MMC1 regs
11368 - state->m_mmc_prg_bank[n] for n=0,...,3 represent the MMC3 PRG banks
11369 - state->m_mmc_vrom_bank[n] for n=0,...,5 represent the MMC3 CHR banks
11370 - state->m_mmc_prg_bank[n] for n=4,5 represent the VRC2 PRG banks
11371 - state->m_mmc_vrom_bank[n] for n=6,...,13 represent the VRC2 CHR banks
11372
11373 In MESS: Preliminary support
11374
11375 *************************************************************/
11376
11377// MMC1 Mode emulation
11378static void someri_mmc1_set_prg( running_machine &machine )
11379{
11380   nes_state *state = machine.driver_data<nes_state>();
11381   UINT8 prg_mode = state->m_mmc_reg[0] & 0x0c;
11382   UINT8 prg_offset = state->m_mmc_reg[1] & 0x10;
11383
11384   switch (prg_mode)
11385   {
11386      case 0x00:
11387      case 0x04:
11388         prg32(machine, (prg_offset + state->m_mmc_reg[3]) >> 1);
11389         break;
11390      case 0x08:
11391         prg16_89ab(machine, prg_offset + 0);
11392         prg16_cdef(machine, prg_offset + state->m_mmc_reg[3]);
11393         break;
11394      case 0x0c:
11395         prg16_89ab(machine, prg_offset + state->m_mmc_reg[3]);
11396         prg16_cdef(machine, prg_offset + 0x0f);
11397         break;
11398   }
11399}
11400
11401static void someri_mmc1_set_chr( running_machine &machine )
11402{
11403   nes_state *state = machine.driver_data<nes_state>();
11404   UINT8 chr_mode = BIT(state->m_mmc_reg[0], 4);
11405
11406   if (chr_mode)
11407   {
11408      chr4_0(machine, state->m_mmc_reg[1] & 0x1f, state->m_mmc_chr_source);
11409      chr4_4(machine, state->m_mmc_reg[2] & 0x1f, state->m_mmc_chr_source);
11410   }
11411   else
11412      chr8(machine, (state->m_mmc_reg[1] & 0x1f) >> 1, state->m_mmc_chr_source);
11413}
11414
11415static WRITE8_HANDLER( someri_mmc1_w )
11416{
11417   nes_state *state = space->machine().driver_data<nes_state>();
11418
11419   assert(state->m_mmc_cmd1 == 2);
11420
11421   if (data & 0x80)
11422   {
11423      state->m_mmc1_count = 0;
11424      state->m_mmc1_latch = 0;
11425
11426      state->m_mmc_reg[0] |= 0x0c;
11427      someri_mmc1_set_prg(space->machine());
11428      return;
11429   }
11430
11431   if (state->m_mmc1_count < 5)
11432   {
11433      if (state->m_mmc1_count == 0) state->m_mmc1_latch = 0;
11434      state->m_mmc1_latch >>= 1;
11435      state->m_mmc1_latch |= (data & 0x01) ? 0x10 : 0x00;
11436      state->m_mmc1_count++;
11437   }
11438
11439   if (state->m_mmc1_count == 5)
11440   {
11441      switch (offset & 0x6000)
11442      {
11443         case 0x0000:
11444            state->m_mmc_reg[0] = state->m_mmc1_latch;
11445            switch (state->m_mmc_reg[0] & 0x03)
11446            {
11447            case 0: set_nt_mirroring(space->machine(), PPU_MIRROR_LOW); break;
11448            case 1: set_nt_mirroring(space->machine(), PPU_MIRROR_HIGH); break;
11449            case 2: set_nt_mirroring(space->machine(), PPU_MIRROR_VERT); break;
11450            case 3: set_nt_mirroring(space->machine(), PPU_MIRROR_HORZ); break;
11451            }
11452            someri_mmc1_set_chr(space->machine());
11453            someri_mmc1_set_prg(space->machine());
11454            break;
11455         case 0x2000:
11456            state->m_mmc_reg[1] = state->m_mmc1_latch;
11457            someri_mmc1_set_chr(space->machine());
11458            someri_mmc1_set_prg(space->machine());
11459            break;
11460         case 0x4000:
11461            state->m_mmc_reg[2] = state->m_mmc1_latch;
11462            someri_mmc1_set_chr(space->machine());
11463            break;
11464         case 0x6000:
11465            state->m_mmc_reg[3] = state->m_mmc1_latch;
11466            someri_mmc1_set_prg(space->machine());
11467            break;
11468      }
11469
11470      state->m_mmc1_count = 0;
11471   }
11472}
11473
11474// MMC3 Mode emulation
11475static WRITE8_HANDLER( someri_mmc3_w )
11476{
11477   nes_state *state = space->machine().driver_data<nes_state>();
11478   UINT8 mmc_helper, cmd;
11479
11480   assert(state->m_mmc_cmd1 == 1);
11481   switch (offset & 0x6001)
11482   {
11483      case 0x0000:
11484         mmc_helper = state->m_mmc3_latch ^ data;
11485         state->m_mmc3_latch = data;
11486
11487         if (mmc_helper & 0x40)
11488            mmc3_set_prg(space->machine(), state->m_mmc_prg_base, state->m_mmc_prg_mask);
11489
11490         if (mmc_helper & 0x80)
11491            mmc3_set_chr(space->machine(), state->m_mmc_chr_source, state->m_mmc_chr_base, state->m_mmc_chr_mask);
11492         break;
11493
11494      case 0x0001:
11495         cmd = state->m_mmc3_latch & 0x07;
11496         switch (cmd)
11497         {
11498         case 0: case 1:
11499         case 2: case 3: case 4: case 5:
11500            state->m_mmc_vrom_bank[cmd] = data;
11501            mmc3_set_chr(space->machine(), state->m_mmc_chr_source, state->m_mmc_chr_base, state->m_mmc_chr_mask);
11502            break;
11503         case 6:
11504         case 7:
11505            state->m_mmc_prg_bank[cmd - 6] = data;
11506            mmc3_set_prg(space->machine(), state->m_mmc_prg_base, state->m_mmc_prg_mask);
11507            break;
11508         }
11509         break;
11510
11511      case 0x2000:
11512         set_nt_mirroring(space->machine(), BIT(data, 0) ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT);
11513         break;
11514      case 0x2001: break;
11515      case 0x4000: state->m_IRQ_count_latch = data; break;
11516      case 0x4001: state->m_IRQ_count = 0; break;
11517      case 0x6000: state->m_IRQ_enable = 0; break;
11518      case 0x6001: state->m_IRQ_enable = 1; break;
11519   }
11520}
11521
11522// VRC2 Mode emulation
11523static WRITE8_HANDLER( someri_vrc2_w )
11524{
11525   nes_state *state = space->machine().driver_data<nes_state>();
11526   UINT8 bank, shift;
11527
11528   assert(state->m_mmc_cmd1 == 0);
11529
11530   if (offset < 0x1000)
11531   {
11532      state->m_mmc_prg_bank[4] = data;
11533      prg8_89(space->machine(), state->m_mmc_prg_bank[4]);
11534   }
11535   else if (offset < 0x2000)
11536   {
11537      switch (data & 0x03)
11538      {
11539         case 0x00: set_nt_mirroring(space->machine(), PPU_MIRROR_VERT); break;
11540         case 0x01: set_nt_mirroring(space->machine(), PPU_MIRROR_HORZ); break;
11541         case 0x02: set_nt_mirroring(space->machine(), PPU_MIRROR_LOW); break;
11542         case 0x03: set_nt_mirroring(space->machine(), PPU_MIRROR_HIGH); break;
11543      }
11544   }
11545   else if (offset < 0x3000)
11546   {
11547      state->m_mmc_prg_bank[5] = data;
11548      prg8_ab(space->machine(), state->m_mmc_prg_bank[5]);
11549   }
11550   else if (offset < 0x7000)
11551   {
11552      bank = ((offset & 0x7000) - 0x3000) / 0x0800 + BIT(offset, 1);
11553      shift = BIT(offset, 2) * 4;
11554      data = (data & 0x0f) << shift;
11555      state->m_mmc_vrom_bank[6 + bank] = data | state->m_mmc_chr_base;
11556      chr1_x(space->machine(), bank, state->m_mmc_vrom_bank[6 + bank], CHRROM);
11557   }
11558}
11559
11560static WRITE8_HANDLER( someri_w )
11561{
11562   nes_state *state = space->machine().driver_data<nes_state>();
11563   LOG_MMC(("someri_w mode %d, offset: %04x, data: %02x\n", state->m_mmc_cmd1, offset, data));
11564
11565   switch (state->m_mmc_cmd1)
11566   {
11567      case 0x00: someri_vrc2_w(space, offset, data); break;
11568      case 0x01: someri_mmc3_w(space, offset, data); break;
11569      case 0x02: someri_mmc1_w(space, offset, data); break;
11570   }
11571}
11572
11573static void someri_mode_update( running_machine &machine )
11574{
11575   nes_state *state = machine.driver_data<nes_state>();
11576   int i;
11577
11578   switch (state->m_mmc_cmd1)
11579   {
11580      case 0x00:
11581         prg8_89(machine, state->m_mmc_prg_bank[4]);
11582         prg8_ab(machine, state->m_mmc_prg_bank[5]);
11583         for (i = 0; i < 8; i++)
11584            chr1_x(machine, i, state->m_mmc_vrom_bank[6 + i], CHRROM);
11585         break;
11586      case 0x01:
11587         mmc3_set_prg(machine, state->m_mmc_prg_base, state->m_mmc_prg_mask);
11588         mmc3_set_chr(machine, state->m_mmc_chr_source, state->m_mmc_chr_base, state->m_mmc_chr_mask);
11589         break;
11590      case 0x02:
11591         someri_mmc1_set_prg(machine);
11592         someri_mmc1_set_chr(machine);
11593         break;
11594   }
11595}
11596
11597static WRITE8_HANDLER( someri_l_w )
11598{
11599   nes_state *state = space->machine().driver_data<nes_state>();
11600   LOG_MMC(("someri_l_w, offset: %04x, data: %02x\n", offset, data));
11601   offset += 0x100;
11602
11603   if (offset & 0x100)
11604   {
11605      state->m_mmc_cmd1 = data & 0x03;
11606      state->m_mmc_chr_base = ((state->m_mmc_cmd1 & 0x04) << 6);
11607      if (state->m_mmc_cmd1 != 1)
11608         state->m_IRQ_enable = 0;
11609      someri_mode_update(space->machine());
11610   }
11611}
11612
11613#ifdef UNUSED_FUNCTION
11614/*************************************************************
11615
11616 FUJIYA Board - mapper 170 according to NEStopia
11617
11618 Which games are supposed to use this?
11619
11620 *************************************************************/
11621
11622static WRITE8_HANDLER( fujiya_m_w )
11623{
11624   nes_state *state = space->machine().driver_data<nes_state>();
11625   LOG_MMC(("fujiya_m_w, offset: %04x, data: %02x\n", offset, data));
11626   offset += 0x6000;
11627
11628   if (offset == 0x6502 || offset == 0x7000)
11629      state->m_mmc_latch1 = (data & 0x40) << 1;
11630}
11631
11632static READ8_HANDLER( fujiya_m_r )
11633{
11634   nes_state *state = space->machine().driver_data<nes_state>();
11635   LOG_MMC(("fujiya_m_r, offset: %04x\n", offset));
11636   offset += 0x6000;
11637
11638   if (offset == 0x7001 || offset == 0x7777)
11639      return state->m_mmc_latch1 | ((offset >> 8) & 0x7f);
11640
11641   return 0;
11642}
11643#endif
11644
11645
11646
11647
11648typedef void (*nes_ppu_latch)(device_t *device, offs_t offset);
11649
11650struct nes_memory_accessor
11651{
11652   write8_space_func write;
11653   const char        *write_name;
11654   read8_space_func  read;
11655   const char        *read_name;
11656};
11657
11658typedef struct _nes_pcb_intf  nes_pcb_intf;
11659struct _nes_pcb_intf
11660{
11661   int                     mmc_pcb;
11662   nes_memory_accessor     mmc_l;  /* $4100-$5fff read/write routines */
11663   nes_memory_accessor     mmc_m;  /* $6000-$7fff read/write routines */
11664   nes_memory_accessor     mmc_h;  /* $8000-$ffff read/write routines */
11665   nes_ppu_latch           mmc_ppu_latch;
11666   ppu2c0x_scanline_cb      mmc_scanline;
11667   ppu2c0x_hblank_cb      mmc_hblank;
11668};
11669
11670#define NES_NOACCESS \
11671{FUNC_NULL, FUNC_NULL}
11672
11673#define NES_READONLY(a) \
11674{FUNC_NULL, FUNC(a)}
11675
11676#define NES_WRITEONLY(a) \
11677{FUNC(a), FUNC_NULL}
11678
11679static WRITE8_HANDLER( dummy_l_w )
11680{
11681   logerror("write access, offset: %04x, data: %02x\n", offset + 0x4100, data);
11682}
11683
11684static WRITE8_HANDLER( dummy_m_w )
11685{
11686   logerror("write access, offset: %04x, data: %02x\n", offset + 0x6000, data);
11687}
11688
11689static WRITE8_HANDLER( dummy_w )
11690{
11691   logerror("write access, offset: %04x, data: %02x\n", offset + 0x8000, data);
11692}
11693
11694static READ8_HANDLER( dummy_l_r )
11695{
11696   logerror("read access, offset: %04x\n", offset + 0x4100);
11697   return 0x00;
11698}
11699
11700static READ8_HANDLER( dummy_m_r )
11701{
11702   logerror("read access, offset: %04x\n", offset + 0x6000);
11703   return 0x00;
11704}
11705
11706static READ8_HANDLER( dummy_r )
11707{
11708   logerror("read access, offset: %04x\n", offset + 0x8000);
11709   return 0x00;
11710}
11711
11712static const nes_pcb_intf nes_intf_list[] =
11713{
11714   { STD_NROM,             NES_NOACCESS, NES_NOACCESS, NES_NOACCESS,                         NULL, NULL, NULL },
11715   { HVC_FAMBASIC,         NES_NOACCESS, NES_NOACCESS, NES_NOACCESS,                         NULL, NULL, NULL },
11716   { GG_NROM,              NES_NOACCESS, NES_NOACCESS, NES_NOACCESS,                         NULL, NULL, NULL },
11717   { STD_UXROM,            NES_NOACCESS, NES_NOACCESS, NES_WRITEONLY(uxrom_w),               NULL, NULL, NULL },
11718   { STD_UN1ROM,           NES_NOACCESS, NES_NOACCESS, NES_WRITEONLY(un1rom_w),              NULL, NULL, NULL },
11719   { STD_CPROM,            NES_NOACCESS, NES_NOACCESS, NES_WRITEONLY(cprom_w),               NULL, NULL, NULL },
11720   { STD_CNROM,            NES_NOACCESS, NES_NOACCESS, NES_WRITEONLY(cnrom_w),               NULL, NULL, NULL },
11721   { BANDAI_PT554,         NES_NOACCESS, NES_WRITEONLY(bandai_pt554_m_w), NES_WRITEONLY(cnrom_w), NULL, NULL, NULL },
11722   { STD_AXROM,            NES_NOACCESS, NES_NOACCESS, NES_WRITEONLY(axrom_w),               NULL, NULL, NULL },
11723   { STD_PXROM,            NES_NOACCESS, NES_NOACCESS, NES_WRITEONLY(pxrom_w),               mmc2_latch, NULL, NULL },
11724   { STD_FXROM,            NES_NOACCESS, NES_NOACCESS, NES_WRITEONLY(fxrom_w),               mmc2_latch, NULL, NULL },
11725   { STD_BXROM,            NES_NOACCESS, NES_NOACCESS, NES_WRITEONLY(bxrom_w),               NULL, NULL, NULL },
11726   { STD_GXROM,            NES_NOACCESS, NES_NOACCESS, NES_WRITEONLY(gxrom_w),               NULL, NULL, NULL },
11727   { STD_MXROM,            NES_NOACCESS, NES_NOACCESS, NES_WRITEONLY(gxrom_w),               NULL, NULL, NULL },
11728   { STD_NXROM,            NES_NOACCESS, NES_NOACCESS, NES_WRITEONLY(ntbrom_w),              NULL, NULL, NULL },
11729   { SUNSOFT_DCS,          NES_NOACCESS, NES_NOACCESS, NES_WRITEONLY(ntbrom_w),              NULL, NULL, NULL },
11730   { STD_JXROM,            NES_NOACCESS, NES_NOACCESS, NES_WRITEONLY(jxrom_w),               NULL, NULL, jxrom_irq },
11731   { STD_SXROM,            NES_NOACCESS, NES_NOACCESS, NES_WRITEONLY(sxrom_w),               NULL, NULL, NULL },
11732   { STD_SOROM,            NES_NOACCESS, NES_NOACCESS, NES_WRITEONLY(sxrom_w),               NULL, NULL, NULL },
11733   { STD_SXROM_A,          NES_NOACCESS, NES_NOACCESS, NES_WRITEONLY(sxrom_w),               NULL, NULL, NULL },
11734   { STD_SOROM_A,          NES_NOACCESS, NES_NOACCESS, NES_WRITEONLY(sxrom_w),               NULL, NULL, NULL },
11735   { STD_TXROM,            NES_NOACCESS, NES_NOACCESS, NES_WRITEONLY(txrom_w),               NULL, NULL, mmc3_irq },
11736   { STD_TVROM,            NES_NOACCESS, NES_NOACCESS, NES_WRITEONLY(txrom_w),               NULL, NULL, mmc3_irq },
11737   { STD_TKROM,            NES_NOACCESS, NES_NOACCESS, NES_WRITEONLY(txrom_w),               NULL, NULL, mmc3_irq },
11738   { STD_HKROM,            NES_NOACCESS, {FUNC(hkrom_m_w), FUNC(hkrom_m_r)}, NES_WRITEONLY(hkrom_w),     NULL, NULL, mmc3_irq },
11739   { STD_TQROM,            NES_NOACCESS, NES_NOACCESS, NES_WRITEONLY(tqrom_w),               NULL, NULL, mmc3_irq },
11740   { STD_TXSROM,           NES_NOACCESS, NES_NOACCESS, NES_WRITEONLY(txsrom_w),              NULL, NULL, mmc3_irq },
11741   { STD_DXROM,            NES_NOACCESS, NES_NOACCESS, NES_WRITEONLY(dxrom_w),               NULL, NULL, NULL },
11742   { STD_DRROM,            NES_NOACCESS, NES_NOACCESS, NES_WRITEONLY(dxrom_w),               NULL, NULL, NULL },
11743   { NAMCOT_34X3,          NES_NOACCESS, NES_NOACCESS, NES_WRITEONLY(dxrom_w),               NULL, NULL, NULL },
11744   { NAMCOT_3425,          NES_NOACCESS, NES_NOACCESS, NES_WRITEONLY(namcot3425_w),          NULL, NULL, NULL },
11745   { NAMCOT_3446,          NES_NOACCESS, NES_NOACCESS, NES_WRITEONLY(namcot3446_w),          NULL, NULL, NULL },
11746   { NAMCOT_3453,          NES_NOACCESS, NES_NOACCESS, NES_WRITEONLY(namcot3453_w),          NULL, NULL, NULL },
11747   { STD_EXROM,            {FUNC(exrom_l_w), FUNC(exrom_l_r)}, NES_NOACCESS, NES_NOACCESS,               NULL, NULL, mmc5_irq },
11748   { NES_QJ,               NES_NOACCESS, NES_WRITEONLY(qj_m_w), NES_WRITEONLY(txrom_w),      NULL, NULL, mmc3_irq },
11749   { PAL_ZZ,               NES_NOACCESS, NES_WRITEONLY(zz_m_w), NES_WRITEONLY(txrom_w),      NULL, NULL, mmc3_irq },
11750   { UXROM_CC,             NES_NOACCESS, NES_NOACCESS, NES_WRITEONLY(uxrom_cc_w),            NULL, NULL, NULL },
11751   //
11752   { DIS_74X139X74,        NES_NOACCESS, NES_WRITEONLY(dis_74x139x74_m_w), NES_NOACCESS,     NULL, NULL, NULL },
11753   { DIS_74X377,           NES_NOACCESS, NES_NOACCESS, NES_WRITEONLY(dis_74x377_w),          NULL, NULL, NULL },
11754   { DIS_74X161X161X32,    NES_NOACCESS, NES_NOACCESS, NES_WRITEONLY(dis_74x161x161x32_w),   NULL, NULL, NULL },
11755   { DIS_74X161X138,       NES_NOACCESS, NES_WRITEONLY(dis_74x161x138_m_w), NES_NOACCESS,    NULL, NULL, NULL },
11756   { BANDAI_LZ93,          NES_NOACCESS, NES_WRITEONLY(lz93d50_m_w), NES_WRITEONLY(lz93d50_w), NULL, NULL, bandai_lz_irq },
11757   { BANDAI_LZ93EX,        NES_NOACCESS, NES_WRITEONLY(lz93d50_m_w), NES_WRITEONLY(lz93d50_w), NULL, NULL, bandai_lz_irq },
11758   { BANDAI_FCG,           NES_NOACCESS, NES_WRITEONLY(lz93d50_m_w), NES_WRITEONLY(lz93d50_w), NULL, NULL, bandai_lz_irq },
11759   { BANDAI_DATACH,        NES_NOACCESS, NES_WRITEONLY(lz93d50_m_w), NES_WRITEONLY(lz93d50_w), NULL, NULL, bandai_lz_irq },
11760   { BANDAI_JUMP2,         NES_NOACCESS, NES_NOACCESS, NES_WRITEONLY(fjump2_w),              NULL, NULL, bandai_lz_irq },
11761   { BANDAI_KARAOKE,       NES_NOACCESS, NES_NOACCESS, NES_WRITEONLY(bandai_ks_w),           NULL, NULL, NULL },
11762   { BANDAI_OEKAKIDS,      NES_NOACCESS, NES_NOACCESS, NES_WRITEONLY(bandai_ok_w),           NULL, NULL, NULL },
11763   { IREM_G101,            NES_NOACCESS, NES_NOACCESS, NES_WRITEONLY(g101_w),                NULL, NULL, NULL },
11764   { IREM_LROG017,         NES_NOACCESS, NES_NOACCESS, NES_WRITEONLY(lrog017_w),             NULL, NULL, NULL },
11765   { IREM_H3001,           NES_NOACCESS, NES_NOACCESS, NES_WRITEONLY(h3001_w),               NULL, NULL, h3001_irq },
11766   { IREM_TAM_S1,          NES_NOACCESS, NES_NOACCESS, NES_WRITEONLY(tam_s1_w),              NULL, NULL, NULL },
11767   { IREM_HOLYDIV,         NES_NOACCESS, NES_NOACCESS, NES_WRITEONLY(irem_hd_w),             NULL, NULL, NULL },
11768   { JALECO_SS88006,       NES_NOACCESS, NES_NOACCESS, NES_WRITEONLY(ss88006_w),             NULL, NULL, ss88006_irq },
11769   { JALECO_JF11,          NES_NOACCESS, NES_WRITEONLY(jf11_m_w), NES_NOACCESS,              NULL, NULL, NULL },
11770   { JALECO_JF13,          NES_NOACCESS, NES_WRITEONLY(jf13_m_w), NES_NOACCESS,              NULL, NULL, NULL },
11771   { JALECO_JF16,          NES_NOACCESS, NES_NOACCESS, NES_WRITEONLY(jf16_w),                NULL, NULL, NULL },
11772   { JALECO_JF17,          NES_NOACCESS, NES_NOACCESS, NES_WRITEONLY(jf17_w),                NULL, NULL, NULL },
11773   { JALECO_JF19,          NES_NOACCESS, NES_NOACCESS, NES_WRITEONLY(jf19_w),                NULL, NULL, NULL },
11774   { KONAMI_VRC1,          NES_NOACCESS, NES_NOACCESS, NES_WRITEONLY(konami_vrc1_w),         NULL, NULL, NULL },
11775   { KONAMI_VRC2,          NES_NOACCESS, NES_NOACCESS, NES_WRITEONLY(konami_vrc2_w),         NULL, NULL, NULL },
11776   { KONAMI_VRC3,          NES_NOACCESS, NES_NOACCESS, NES_WRITEONLY(konami_vrc3_w),         NULL, NULL, konami_irq },
11777   { KONAMI_VRC4,          NES_NOACCESS, NES_NOACCESS, NES_WRITEONLY(konami_vrc4_w),         NULL, NULL, konami_irq },
11778   { KONAMI_VRC6,          NES_NOACCESS, NES_NOACCESS, NES_WRITEONLY(konami_vrc6_w),         NULL, NULL, konami_irq },
11779   { KONAMI_VRC7,          NES_NOACCESS, NES_NOACCESS, NES_WRITEONLY(konami_vrc7_w),         NULL, NULL, konami_irq },
11780   { NAMCOT_163,           {FUNC(namcot163_l_w), FUNC(namcot163_l_r) }, NES_NOACCESS, NES_WRITEONLY(namcot163_w), NULL, NULL, namcot_irq },
11781   { SUNSOFT_1,            NES_NOACCESS, NES_WRITEONLY(sunsoft1_m_w), NES_NOACCESS,          NULL, NULL, NULL },
11782   { SUNSOFT_2,            NES_NOACCESS, NES_NOACCESS, NES_WRITEONLY(sunsoft2_w),            NULL, NULL, NULL },
11783   { SUNSOFT_3,            NES_NOACCESS, NES_NOACCESS, NES_WRITEONLY(sunsoft3_w),            NULL, NULL, sunsoft3_irq },
11784   { TAITO_TC0190FMC,      NES_NOACCESS, NES_NOACCESS, NES_WRITEONLY(tc0190fmc_w),           NULL, NULL, NULL },
11785   { TAITO_TC0190FMCP,     NES_NOACCESS, NES_NOACCESS, NES_WRITEONLY(tc0190fmc_p16_w),       NULL, NULL, mmc3_irq },
11786   { TAITO_X1_005,         NES_NOACCESS, {FUNC(x1005_m_w), FUNC(x1005_m_r)}, NES_NOACCESS,               NULL, NULL, NULL },
11787   { TAITO_X1_005_A,       NES_NOACCESS, {FUNC(x1005a_m_w), FUNC(x1005_m_r)}, NES_NOACCESS,              NULL, NULL, NULL },
11788   { TAITO_X1_017,         NES_NOACCESS, {FUNC(x1017_m_w), FUNC(x1017_m_r)}, NES_NOACCESS,               NULL, NULL, NULL },
11789   //
11790   { AGCI_50282,           NES_NOACCESS, NES_NOACCESS, NES_WRITEONLY(agci_50282_w),          NULL, NULL, NULL },
11791   { ACTENT_ACT52,         NES_NOACCESS, NES_NOACCESS, NES_WRITEONLY(ae_act52_w),            NULL, NULL, NULL },
11792   { AVE_NINA01,           NES_NOACCESS, NES_WRITEONLY(nina01_m_w), NES_NOACCESS,            NULL, NULL, NULL },
11793   { AVE_NINA06,           NES_WRITEONLY(nina06_l_w), NES_NOACCESS, NES_NOACCESS,            NULL, NULL, NULL },
11794   { CNE_DECATHLON,        NES_NOACCESS, NES_NOACCESS, NES_WRITEONLY(cne_decathl_w),         NULL, NULL, NULL },
11795   { CNE_FSB,              NES_NOACCESS, NES_WRITEONLY(cne_fsb_m_w), NES_NOACCESS,           NULL, NULL, NULL },
11796   { CNE_SHLZ,             NES_WRITEONLY(cne_shlz_l_w), NES_NOACCESS, NES_NOACCESS,          NULL, NULL, NULL },
11797   { CALTRON_6IN1,         NES_NOACCESS, NES_WRITEONLY(caltron6in1_m_w), NES_WRITEONLY(caltron6in1_w),      NULL, NULL, NULL },
11798   { CAMERICA_BF9093,      NES_NOACCESS, NES_NOACCESS, NES_WRITEONLY(bf9093_w),              NULL, NULL, NULL },
11799   { CAMERICA_BF9097,      NES_NOACCESS, NES_NOACCESS, NES_WRITEONLY(bf9093_w),              NULL, NULL, NULL },
11800   { CAMERICA_BF9096,      NES_NOACCESS, NES_WRITEONLY(bf9096_w), NES_WRITEONLY(bf9096_w),   NULL, NULL, NULL },
11801   { CAMERICA_GOLDENFIVE,  NES_NOACCESS, NES_NOACCESS, NES_WRITEONLY(golden5_w),             NULL, NULL, NULL },
11802   { CONY_BOARD,           {FUNC(cony_l_w), FUNC(cony_l_r)}, NES_NOACCESS, NES_WRITEONLY(cony_w),        NULL, NULL, sunsoft3_irq },
11803   { DREAMTECH_BOARD,      NES_WRITEONLY(dreamtech_l_w), NES_NOACCESS, NES_NOACCESS,         NULL, NULL, NULL },
11804   { FUTUREMEDIA_BOARD,    NES_NOACCESS, NES_NOACCESS, NES_WRITEONLY(futuremedia_w),         NULL, NULL, futuremedia_irq },
11805   { FUKUTAKE_BOARD,       {FUNC(fukutake_l_w), FUNC(fukutake_l_r)}, NES_NOACCESS, NES_NOACCESS,         NULL, NULL, NULL },
11806   { GOUDER_37017,         {FUNC(gouder_sf4_l_w), FUNC(gouder_sf4_l_r)}, NES_NOACCESS, NES_WRITEONLY(txrom_w), NULL, NULL, mmc3_irq },
11807   { HENGEDIANZI_BOARD,    NES_NOACCESS, NES_NOACCESS, NES_WRITEONLY(henggedianzi_w),        NULL, NULL, NULL },
11808   { HENGEDIANZI_XJZB,     NES_WRITEONLY(heng_xjzb_l_w), NES_NOACCESS, NES_WRITEONLY(heng_xjzb_w), NULL, NULL, NULL },
11809   { HES6IN1_BOARD,        NES_WRITEONLY(hes6in1_l_w), NES_NOACCESS, NES_NOACCESS,           NULL, NULL, NULL },
11810   { HES_BOARD,            NES_WRITEONLY(hes_l_w), NES_NOACCESS, NES_NOACCESS,               NULL, NULL, NULL },
11811   { HOSENKAN_BOARD,       NES_NOACCESS, NES_NOACCESS, NES_WRITEONLY(hosenkan_w),            NULL, NULL, mmc3_irq },
11812   { KAISER_KS7058,        NES_NOACCESS, NES_NOACCESS, NES_WRITEONLY(ks7058_w),              NULL, NULL, NULL },
11813   { KAISER_KS7022,        NES_NOACCESS, NES_NOACCESS, {FUNC(ks7022_w), FUNC(ks7022_r)},                 NULL, NULL, NULL },
11814   { KAISER_KS7032,        NES_NOACCESS, NES_NOACCESS, NES_WRITEONLY(ks7032_w),              NULL, NULL, ks7032_irq },
11815   { KAISER_KS202,         NES_NOACCESS, NES_NOACCESS, NES_WRITEONLY(ks202_w),               NULL, NULL, ks7032_irq },
11816   { KAISER_KS7017,      NES_WRITEONLY(ks7017_l_w), NES_NOACCESS, NES_NOACCESS,            NULL, NULL, mmc_fds_irq },
11817   { KAY_PANDAPRINCE,      {FUNC(kay_pp_l_w), FUNC(kay_pp_l_r)}, NES_NOACCESS, NES_WRITEONLY(kay_pp_w),  NULL, NULL, mmc3_irq },
11818   { KASING_BOARD,         NES_NOACCESS, NES_WRITEONLY(kasing_m_w), NES_WRITEONLY(txrom_w),  NULL, NULL, mmc3_irq },
11819   { SACHEN_74LS374,       {FUNC(sachen_74x374_l_w), FUNC(sachen_74x374_l_r)}, NES_NOACCESS, NES_NOACCESS, NULL, NULL, NULL },
11820   { SACHEN_74LS374_A,     NES_WRITEONLY(sachen_74x374a_l_w), NES_NOACCESS, NES_NOACCESS,    NULL, NULL, NULL },
11821   { SACHEN_8259A,         NES_WRITEONLY(s8259_l_w), NES_WRITEONLY(s8259_m_w), NES_NOACCESS, NULL, NULL, NULL },
11822   { SACHEN_8259B,         NES_WRITEONLY(s8259_l_w), NES_WRITEONLY(s8259_m_w), NES_NOACCESS, NULL, NULL, NULL },
11823   { SACHEN_8259C,         NES_WRITEONLY(s8259_l_w), NES_WRITEONLY(s8259_m_w), NES_NOACCESS, NULL, NULL, NULL },
11824   { SACHEN_8259D,         NES_WRITEONLY(s8259_l_w), NES_WRITEONLY(s8259_m_w), NES_NOACCESS, NULL, NULL, NULL },
11825   { SACHEN_SA009,         NES_WRITEONLY(sa009_l_w), NES_NOACCESS, NES_NOACCESS,             NULL, NULL, NULL },
11826   { SACHEN_SA0036,        NES_NOACCESS, NES_NOACCESS, NES_WRITEONLY(sa0036_w),              NULL, NULL, NULL },
11827   { SACHEN_SA0037,        NES_NOACCESS, NES_NOACCESS, NES_WRITEONLY(sa0037_w),              NULL, NULL, NULL },
11828   { SACHEN_SA72007,       NES_WRITEONLY(sa72007_l_w), NES_NOACCESS, NES_NOACCESS,           NULL, NULL, NULL },
11829   { SACHEN_SA72008,       NES_WRITEONLY(sa72008_l_w), NES_NOACCESS, NES_NOACCESS,           NULL, NULL, NULL },
11830   { SACHEN_TCA01,         NES_READONLY(tca01_l_r), NES_NOACCESS, NES_NOACCESS,              NULL, NULL, NULL },
11831   { SACHEN_TCU01,         NES_WRITEONLY(tcu01_l_w), NES_WRITEONLY(tcu01_m_w), NES_WRITEONLY(tcu01_w), NULL, NULL, NULL },
11832   { SACHEN_TCU02,         {FUNC(tcu02_l_w), FUNC(tcu02_l_r)}, NES_NOACCESS, NES_NOACCESS,               NULL, NULL, NULL },
11833   { SUBOR_TYPE0,          NES_NOACCESS, NES_NOACCESS, NES_WRITEONLY(subor0_w),              NULL, NULL, NULL },
11834   { SUBOR_TYPE1,          NES_NOACCESS, NES_NOACCESS, NES_WRITEONLY(subor1_w),              NULL, NULL, NULL },
11835   { MAGICSERIES_MD,       NES_NOACCESS, NES_NOACCESS, NES_WRITEONLY(magics_md_w),           NULL, NULL, NULL },
11836   { NANJING_BOARD,        {FUNC(nanjing_l_w), FUNC(nanjing_l_r)}, NES_NOACCESS, NES_NOACCESS,           NULL, NULL, nanjing_irq },
11837   { NITRA_TDA,            NES_NOACCESS, NES_NOACCESS, NES_WRITEONLY(nitra_w),               NULL, NULL, mmc3_irq },
11838   { NTDEC_ASDER,          NES_NOACCESS, NES_NOACCESS, NES_WRITEONLY(ntdec_asder_w),         NULL, NULL, NULL },
11839   { NTDEC_FIGHTINGHERO,   NES_NOACCESS, NES_WRITEONLY(ntdec_fh_m_w), NES_NOACCESS,          NULL, NULL, NULL },
11840   { OPENCORP_DAOU306,     NES_NOACCESS, NES_NOACCESS, NES_WRITEONLY(daou306_w),             NULL, NULL, NULL },
11841   { RCM_GS2015,           NES_NOACCESS, NES_NOACCESS, NES_WRITEONLY(gs2015_w),              NULL, NULL, NULL },
11842   { RCM_TETRISFAMILY,     NES_NOACCESS, NES_NOACCESS, NES_WRITEONLY(rcm_tf_w),              NULL, NULL, NULL },
11843   { REXSOFT_DBZ5,         {FUNC(rex_dbz_l_w), FUNC(rex_dbz_l_r)}, NES_READONLY(rex_dbz_l_r), NES_WRITEONLY(txrom_w), NULL, NULL, mmc3_irq },
11844   { REXSOFT_SL1632,       NES_NOACCESS, NES_NOACCESS, NES_WRITEONLY(rex_sl1632_w),          NULL, NULL, mmc3_irq },
11845   { RUMBLESTATION_BOARD,  NES_NOACCESS, NES_WRITEONLY(rumblestation_m_w), NES_WRITEONLY(rumblestation_w),      NULL, NULL, NULL },
11846   { SOMERI_SL12,          NES_WRITEONLY(someri_l_w), NES_NOACCESS, NES_WRITEONLY(someri_w), NULL, NULL, mmc3_irq },
11847   { SUPERGAME_BOOGERMAN,  NES_WRITEONLY(sgame_boog_l_w), NES_WRITEONLY(sgame_boog_m_w), NES_WRITEONLY(sgame_boog_w), NULL, NULL, mmc3_irq },
11848   { SUPERGAME_LIONKING,   NES_NOACCESS, NES_WRITEONLY(sgame_lion_m_w), NES_WRITEONLY(sgame_lion_w), NULL, NULL, mmc3_irq },
11849   { TENGEN_800008,        NES_NOACCESS, NES_NOACCESS, NES_WRITEONLY(tengen_800008_w),       NULL, NULL, NULL },
11850   { TENGEN_800032,        NES_NOACCESS, NES_NOACCESS, NES_WRITEONLY(tengen_800032_w),       NULL, NULL, tengen_800032_irq },
11851   { TENGEN_800037,        NES_NOACCESS, NES_NOACCESS, NES_WRITEONLY(tengen_800037_w),       NULL, NULL, tengen_800032_irq },
11852   { TXC_22211A,           {FUNC(txc_22211_l_w), FUNC(txc_22211_l_r)}, NES_NOACCESS, NES_WRITEONLY(txc_22211_w), NULL, NULL, NULL },
11853   { TXC_22211B,           {FUNC(txc_22211_l_w), FUNC(txc_22211_l_r)}, NES_NOACCESS, NES_WRITEONLY(txc_22211b_w), NULL, NULL, NULL },
11854   { TXC_22211C,           {FUNC(txc_22211_l_w), FUNC(txc_22211c_l_r)}, NES_NOACCESS, NES_WRITEONLY(txc_22211_w), NULL, NULL, NULL },
11855   { TXC_TW,               NES_WRITEONLY(txc_tw_l_w), NES_WRITEONLY(txc_tw_m_w), NES_WRITEONLY(txrom_w), NULL, NULL, mmc3_irq },
11856   { TXC_STRIKEWOLF,       NES_NOACCESS, NES_NOACCESS, NES_WRITEONLY(txc_strikewolf_w),      NULL, NULL, NULL },
11857   { TXC_MXMDHTWO,         NES_READONLY(txc_mxmdhtwo_l_r), NES_NOACCESS, NES_WRITEONLY(txc_mxmdhtwo_w), NULL, NULL, NULL },
11858   { WAIXING_TYPE_A,       NES_NOACCESS, NES_NOACCESS, NES_WRITEONLY(waixing_a_w),           NULL, NULL, mmc3_irq },
11859   { WAIXING_TYPE_A_1,     NES_NOACCESS, NES_NOACCESS, NES_WRITEONLY(waixing_a_w),           NULL, NULL, mmc3_irq },
11860   { WAIXING_TYPE_B,       NES_NOACCESS, NES_NOACCESS, NES_WRITEONLY(waixing_a_w),           NULL, NULL, mmc3_irq },
11861   { WAIXING_TYPE_C,       NES_NOACCESS, NES_NOACCESS, NES_WRITEONLY(waixing_a_w),           NULL, NULL, mmc3_irq },
11862   { WAIXING_TYPE_D,       NES_NOACCESS, NES_NOACCESS, NES_WRITEONLY(waixing_a_w),           NULL, NULL, mmc3_irq },
11863   { WAIXING_TYPE_E,       NES_NOACCESS, NES_NOACCESS, NES_WRITEONLY(waixing_a_w),           NULL, NULL, mmc3_irq },
11864   { WAIXING_TYPE_F,       NES_NOACCESS, NES_NOACCESS, NES_WRITEONLY(waixing_f_w),           NULL, NULL, mmc3_irq },
11865   { WAIXING_TYPE_G,       NES_NOACCESS, NES_NOACCESS, NES_WRITEONLY(waixing_g_w),           NULL, NULL, mmc3_irq },
11866   { WAIXING_TYPE_H,       NES_NOACCESS, NES_NOACCESS, NES_WRITEONLY(waixing_h_w),           NULL, NULL, mmc3_irq },
11867   { WAIXING_TYPE_I,       NES_NOACCESS, NES_NOACCESS, NES_WRITEONLY(txrom_w),               NULL, NULL, mmc3_irq },   // this is MMC3 + possibly additional WRAM added in 0x5000-0x5fff
11868   { WAIXING_TYPE_J,       NES_NOACCESS, NES_NOACCESS, NES_WRITEONLY(txrom_w),               NULL, NULL, mmc3_irq },   // this is MMC3 + possibly additional WRAM added in 0x5000-0x5fff
11869   { WAIXING_SGZ,          NES_NOACCESS, NES_NOACCESS, NES_WRITEONLY(waixing_sgz_w),         NULL, NULL, konami_irq },
11870   { WAIXING_SGZLZ,        NES_WRITEONLY(waixing_sgzlz_l_w), NES_NOACCESS, NES_NOACCESS,     NULL, NULL, NULL },
11871   { WAIXING_FFV,          NES_WRITEONLY(waixing_ffv_l_w), NES_NOACCESS, NES_NOACCESS,       NULL, NULL, NULL },
11872   { WAIXING_ZS,           NES_NOACCESS, NES_NOACCESS, NES_WRITEONLY(waixing_zs_w),          NULL, NULL, NULL },
11873   { WAIXING_DQ8,          NES_NOACCESS, NES_NOACCESS, NES_WRITEONLY(waixing_dq8_w),         NULL, NULL, NULL },
11874   { WAIXING_SECURITY,     NES_WRITEONLY(waixing_sec_l_w), NES_NOACCESS, NES_WRITEONLY(txrom_w), NULL, NULL, mmc3_irq },
11875   { WAIXING_SH2,          NES_NOACCESS, NES_NOACCESS, NES_WRITEONLY(txrom_w),               NULL, NULL, mmc3_irq },   // this is MMC3 + possibly additional WRAM added in 0x5000-0x5fff
11876   { WAIXING_PS2,          NES_NOACCESS, NES_NOACCESS, NES_WRITEONLY(waixing_ps2_w),         NULL, NULL, NULL },
11877   { UNL_8237,             NES_WRITEONLY(unl_8237_l_w), NES_NOACCESS, NES_WRITEONLY(unl_8237_w),      NULL, NULL, mmc3_irq },
11878   { UNL_AX5705,           NES_NOACCESS, NES_NOACCESS, NES_WRITEONLY(unl_ax5705_w),          NULL, NULL, NULL },
11879   { UNL_CC21,             NES_NOACCESS, NES_NOACCESS, NES_WRITEONLY(unl_cc21_w),            NULL, NULL, NULL },
11880   { UNL_KOF97,            NES_NOACCESS, NES_NOACCESS, NES_WRITEONLY(unl_kof97_w),           NULL, NULL, mmc3_irq },
11881   { UNL_T230,             NES_NOACCESS, NES_NOACCESS, NES_WRITEONLY(unl_t230_w),            NULL, NULL, konami_irq },
11882   { UNL_KOF96,            {FUNC(kof96_l_w), FUNC(kof96_l_r)}, NES_NOACCESS, NES_WRITEONLY(kof96_w),     NULL, NULL, mmc3_irq },
11883   { UNL_MK2,              NES_NOACCESS, NES_WRITEONLY(mk2_m_w), NES_NOACCESS,               NULL, NULL, mmc3_irq },
11884   { UNL_N625092,          NES_NOACCESS, NES_NOACCESS, NES_WRITEONLY(n625092_w),             NULL, NULL, NULL },
11885   { UNL_SC127,            NES_NOACCESS, NES_NOACCESS, NES_WRITEONLY(sc127_w),               NULL, NULL, sc127_irq },
11886   { UNL_SMB2J,            NES_NOACCESS, NES_NOACCESS, NES_WRITEONLY(smb2j_w),               NULL, NULL, NULL },
11887   { UNL_SUPERFIGHTER3,    NES_NOACCESS, NES_NOACCESS, NES_WRITEONLY(unl_sf3_w),             NULL, NULL, mmc3_irq },
11888   { UNL_XZY,              NES_WRITEONLY(unl_xzy_l_w), NES_NOACCESS, NES_NOACCESS,           NULL, NULL, NULL },
11889   { UNL_RACERMATE,        NES_NOACCESS, NES_NOACCESS, NES_WRITEONLY(unl_racmate_w),         NULL, NULL, NULL },
11890   { UNL_STUDYNGAME,       NES_NOACCESS, NES_NOACCESS, NES_WRITEONLY(sng32_w),               NULL, NULL, NULL },
11891   { UNL_603_5052,         {FUNC(unl_6035052_extra_w), FUNC(unl_6035052_extra_r)}, {FUNC(unl_6035052_extra_w), FUNC(unl_6035052_extra_r)}, NES_WRITEONLY(txrom_w), NULL, NULL, mmc3_irq },
11892   { UNL_EDU2K,            NES_NOACCESS, NES_NOACCESS, NES_WRITEONLY(edu2k_w),               NULL, NULL, NULL },
11893   { UNL_SHJY3,            NES_NOACCESS, NES_NOACCESS, NES_WRITEONLY(shjy3_w),               NULL, NULL, shjy3_irq },
11894   { UNL_H2288,            {FUNC(h2288_l_w), FUNC(h2288_l_r)}, NES_NOACCESS, NES_WRITEONLY(h2288_w),     NULL, NULL, mmc3_irq },
11895   //
11896   { BTL_AISENSHINICOL,    NES_NOACCESS, NES_NOACCESS, NES_WRITEONLY(btl_mariobaby_w),       NULL, NULL, NULL },
11897   { BTL_DRAGONNINJA,      NES_NOACCESS, NES_NOACCESS, NES_WRITEONLY(btl_dn_w),              NULL, NULL, btl_dn_irq },
11898   { BTL_MARIOBABY,        NES_NOACCESS, NES_NOACCESS, NES_WRITEONLY(btl_mariobaby_w),       NULL, NULL, NULL },
11899   { BTL_SMB2A,            NES_NOACCESS, NES_NOACCESS, NES_WRITEONLY(btl_smb2a_w),           NULL, NULL, btl_smb2a_irq },
11900   { BTL_SMB2B,            NES_WRITEONLY(smb2jb_l_w), NES_NOACCESS, NES_NOACCESS,            NULL, NULL, smb2jb_irq },
11901   { BTL_SMB3,             NES_NOACCESS, NES_NOACCESS, NES_WRITEONLY(btl_smb3_w),            NULL, NULL, btl_smb3_irq },
11902   { BTL_SUPERBROS11,      NES_NOACCESS, NES_NOACCESS, NES_WRITEONLY(btl_smb11_w),           NULL, NULL, mmc3_irq },
11903   { BTL_TOBIDASE,         NES_WRITEONLY(btl_tobi_l_w), NES_NOACCESS, NES_NOACCESS,          NULL, NULL, NULL },
11904   { BTL_PIKACHUY2K,       NES_NOACCESS, {FUNC(btl_pika_y2k_m_w), FUNC(btl_pika_y2k_m_r)}, NES_WRITEONLY(btl_pika_y2k_w),  NULL, NULL, mmc3_irq },
11905   { WHIRLWIND_2706,       NES_NOACCESS, NES_NOACCESS, NES_WRITEONLY(whirl2706_w),           NULL, NULL, NULL },
11906   //
11907   { BMC_190IN1,           NES_NOACCESS, NES_NOACCESS, NES_WRITEONLY(bmc_190in1_w),          NULL, NULL, NULL },
11908   { BMC_A65AS,            NES_NOACCESS, NES_NOACCESS, NES_WRITEONLY(bmc_a65as_w),           NULL, NULL, NULL },
11909   { BMC_GS2004,           NES_NOACCESS, NES_NOACCESS, NES_WRITEONLY(bmc_gs2004_w),          NULL, NULL, NULL },
11910   { BMC_GS2013,           NES_NOACCESS, NES_NOACCESS, NES_WRITEONLY(bmc_gs2013_w),          NULL, NULL, NULL },
11911   { BMC_NOVELDIAMOND,     NES_NOACCESS, NES_NOACCESS, NES_WRITEONLY(novel1_w),              NULL, NULL, NULL },
11912   { BMC_9999999IN1,       NES_NOACCESS, NES_NOACCESS, NES_WRITEONLY(novel2_w),              NULL, NULL, NULL },
11913   { BMC_T262,             NES_NOACCESS, NES_NOACCESS, NES_WRITEONLY(bmc_t262_w),            NULL, NULL, NULL },
11914   { BMC_WS,               NES_NOACCESS, NES_WRITEONLY(bmc_ws_m_w), NES_NOACCESS,            NULL, NULL, NULL },
11915   { BMC_GKA,              NES_NOACCESS, NES_NOACCESS, NES_WRITEONLY(bmc_gka_w),             NULL, NULL, NULL },
11916   { BMC_GKB,              NES_NOACCESS, NES_NOACCESS, NES_WRITEONLY(bmc_gkb_w),             NULL, NULL, NULL },
11917   { BMC_SUPER_700IN1,     NES_NOACCESS, NES_NOACCESS, NES_WRITEONLY(bmc_super700in1_w),     NULL, NULL, NULL },
11918   { BMC_36IN1,            NES_NOACCESS, NES_NOACCESS, NES_WRITEONLY(bmc_36in1_w),           NULL, NULL, NULL },
11919   { BMC_21IN1,            NES_NOACCESS, NES_NOACCESS, NES_WRITEONLY(bmc_21in1_w),           NULL, NULL, NULL },
11920   { BMC_150IN1,           NES_NOACCESS, NES_NOACCESS, NES_WRITEONLY(bmc_150in1_w),          NULL, NULL, NULL },
11921   { BMC_35IN1,            NES_NOACCESS, NES_NOACCESS, NES_WRITEONLY(bmc_35in1_w),           NULL, NULL, NULL },
11922   { BMC_64IN1,            NES_NOACCESS, NES_NOACCESS, NES_WRITEONLY(bmc_64in1_w),           NULL, NULL, NULL },
11923   { BMC_SUPERHIK_300IN1,  NES_NOACCESS, NES_NOACCESS, NES_WRITEONLY(bmc_hik300_w),          NULL, NULL, NULL },
11924   { BMC_SUPERGUN_20IN1,   NES_NOACCESS, NES_NOACCESS, NES_WRITEONLY(supergun20in1_w),       NULL, NULL, NULL },
11925   { BMC_72IN1,            NES_NOACCESS, NES_NOACCESS, NES_WRITEONLY(bmc_72in1_w),           NULL, NULL, NULL },
11926   { BMC_76IN1,            NES_NOACCESS, NES_NOACCESS, NES_WRITEONLY(bmc_76in1_w),           NULL, NULL, NULL },
11927   { BMC_SUPER_42IN1,      NES_NOACCESS, NES_NOACCESS, NES_WRITEONLY(bmc_76in1_w),           NULL, NULL, NULL },
11928   { BMC_1200IN1,          NES_NOACCESS, NES_NOACCESS, NES_WRITEONLY(bmc_1200in1_w),         NULL, NULL, NULL },
11929   { BMC_31IN1,            NES_NOACCESS, NES_NOACCESS, NES_WRITEONLY(bmc_31in1_w),           NULL, NULL, NULL },
11930   { BMC_22GAMES,          NES_NOACCESS, NES_NOACCESS, NES_WRITEONLY(bmc_22g_w),             NULL, NULL, NULL },
11931   { BMC_20IN1,            NES_NOACCESS, NES_NOACCESS, NES_WRITEONLY(bmc_20in1_w),           NULL, NULL, NULL },
11932   { BMC_110IN1,           NES_NOACCESS, NES_NOACCESS, NES_WRITEONLY(bmc_110in1_w),          NULL, NULL, NULL },
11933   { BMC_64IN1NR,          NES_WRITEONLY(bmc_64in1nr_l_w), NES_NOACCESS, NES_WRITEONLY(bmc_64in1nr_w), NULL, NULL, NULL },
11934   { BMC_S24IN1SC03,       NES_WRITEONLY(bmc_s24in1sc03_l_w), NES_NOACCESS, NES_WRITEONLY(txrom_w), NULL, NULL, mmc3_irq },
11935   { BMC_HIK8IN1,          NES_NOACCESS, NES_WRITEONLY(bmc_hik8_m_w), NES_WRITEONLY(txrom_w), NULL, NULL, mmc3_irq },
11936   { BMC_SUPERHIK_4IN1,    NES_NOACCESS, NES_WRITEONLY(bmc_hik4in1_m_w), NES_WRITEONLY(txrom_w), NULL, NULL, mmc3_irq },
11937   { BMC_SUPERBIG_7IN1,    NES_NOACCESS, NES_NOACCESS, NES_WRITEONLY(bmc_sbig7_w),           NULL, NULL, mmc3_irq },
11938   { BMC_MARIOPARTY_7IN1,  NES_NOACCESS, NES_WRITEONLY(bmc_mario7in1_m_w), NES_WRITEONLY(txrom_w), NULL, NULL, mmc3_irq },
11939   { BMC_FAMILY_4646B,     NES_NOACCESS, NES_WRITEONLY(bmc_family4646_m_w), NES_WRITEONLY(txrom_w), NULL, NULL, mmc3_irq },
11940   { BMC_15IN1,            NES_NOACCESS, NES_WRITEONLY(bmc_15in1_m_w), NES_WRITEONLY(txrom_w), NULL, NULL, mmc3_irq },
11941   { BMC_BALLGAMES_11IN1,  NES_NOACCESS, NES_WRITEONLY(bmc_ball11_m_w), NES_WRITEONLY(bmc_ball11_w), NULL, NULL, NULL },
11942   { BMC_GOLDENCARD_6IN1,  NES_WRITEONLY(bmc_gc6in1_l_w), NES_NOACCESS, NES_WRITEONLY(bmc_gc6in1_w), NULL, NULL, mmc3_irq },
11943   { BMC_VT5201,           NES_NOACCESS, NES_NOACCESS, {FUNC(bmc_vt5201_w), FUNC(bmc_vt5201_r)},         NULL, NULL, NULL },
11944   { BMC_BENSHENG_BS5,     NES_NOACCESS, NES_NOACCESS, NES_WRITEONLY(bmc_bs5_w),             NULL, NULL, NULL },
11945   { BMC_810544,           NES_NOACCESS, NES_NOACCESS, NES_WRITEONLY(bmc_810544_w),          NULL, NULL, NULL },
11946   { BMC_NTD_03,           NES_NOACCESS, NES_NOACCESS, NES_WRITEONLY(bmc_ntd03_w),           NULL, NULL, NULL },
11947   { BMC_G63IN1,           NES_NOACCESS, NES_NOACCESS, {FUNC(bmc_gb63_w), FUNC(bmc_gb63_r)},             NULL, NULL, NULL },
11948   { BMC_FK23C,            NES_WRITEONLY(fk23c_l_w), NES_NOACCESS, NES_WRITEONLY(fk23c_w),   NULL, NULL, mmc3_irq },
11949   { BMC_FK23CA,           NES_WRITEONLY(fk23c_l_w), NES_NOACCESS, NES_WRITEONLY(fk23c_w),   NULL, NULL, mmc3_irq },
11950   { BMC_PJOY84,           NES_NOACCESS, NES_WRITEONLY(pjoy84_m_w), NES_WRITEONLY(txrom_w),  NULL, NULL, mmc3_irq },
11951   //
11952   { FFE_MAPPER6,          NES_WRITEONLY(mapper6_l_w), NES_NOACCESS, NES_WRITEONLY(mapper6_w), NULL, NULL, ffe_irq },
11953   { FFE_MAPPER8,          NES_NOACCESS, NES_NOACCESS, NES_WRITEONLY(mapper8_w),             NULL, NULL, NULL },
11954   { FFE_MAPPER17,         NES_WRITEONLY(mapper17_l_w), NES_NOACCESS, NES_NOACCESS,          NULL, NULL, ffe_irq },
11955   // for debug and development
11956   { UNKNOWN_BOARD,        {FUNC(dummy_l_w), FUNC(dummy_l_r)}, {FUNC(dummy_m_w), FUNC(dummy_m_r)}, {FUNC(dummy_w), FUNC(dummy_r)}, NULL, NULL, NULL },
11957   //
11958   { UNSUPPORTED_BOARD,    NES_NOACCESS, NES_NOACCESS, NES_NOACCESS,                         NULL, NULL, NULL },
11959   //
11960};
11961
11962const nes_pcb_intf *nes_pcb_intf_lookup( int pcb_id )
11963{
11964   int i;
11965   for (i = 0; i < ARRAY_LENGTH(nes_intf_list); i++)
11966   {
11967      if (nes_intf_list[i].mmc_pcb == pcb_id)
11968         return &nes_intf_list[i];
11969   }
11970   return NULL;
11971}
11972
11973void pcb_handlers_setup( running_machine &machine )
11974{
11975   nes_state *state = machine.driver_data<nes_state>();
11976   const nes_pcb_intf *intf = nes_pcb_intf_lookup(state->m_pcb_id);
11977   device_t *ppu = machine.device("ppu");
11978
11979   if (intf == NULL)
11980      fatalerror("Missing PCB interface\n");
11981
11982   if (intf)
11983   {
11984      state->m_mmc_write_low = intf->mmc_l.write;
11985      state->m_mmc_write_low_name = intf->mmc_l.write_name;
11986      state->m_mmc_write_mid = intf->mmc_m.write;
11987      state->m_mmc_write_mid_name = intf->mmc_m.write_name;
11988      state->m_mmc_write = intf->mmc_h.write;
11989      state->m_mmc_write_name = intf->mmc_h.write_name;
11990      state->m_mmc_read_low = intf->mmc_l.read;
11991      state->m_mmc_read_low_name = intf->mmc_l.read_name;
11992      state->m_mmc_read_mid = intf->mmc_m.read;   // in progress
11993      state->m_mmc_read_mid_name = intf->mmc_m.read_name;
11994      state->m_mmc_read = intf->mmc_h.read;   // in progress
11995      state->m_mmc_read_name = intf->mmc_h.read_name;
11996      ppu2c0x_set_latch(ppu, intf->mmc_ppu_latch);
11997   }
11998   else
11999   {
12000      logerror("PCB %d is not yet supported, defaulting to no mapper.\n", state->m_pcb_id);
12001      state->m_mmc_write_low = NULL;
12002      state->m_mmc_write_mid = NULL;
12003      state->m_mmc_write = NULL;
12004      state->m_mmc_read_low = NULL;
12005      state->m_mmc_read_mid = NULL;   // in progress
12006      state->m_mmc_read = NULL;   // in progress
12007      ppu2c0x_set_latch(ppu, NULL);
12008   }
12009
12010   state->m_mmc3_prg_cb = prg8_x;
12011   state->m_mmc3_chr_cb = chr1_x;
12012
12013   switch (state->m_pcb_id)
12014   {
12015      case STD_TXSROM:
12016         state->m_mmc3_chr_cb = txsrom_chr_cb;
12017         break;
12018      case GOUDER_37017:
12019         state->m_mmc3_prg_cb = gouder_sf4_prg_cb;
12020         break;
12021      case KASING_BOARD:
12022         state->m_mmc3_prg_cb = kasing_prg_cb;
12023         break;
12024      case REXSOFT_DBZ5:
12025         state->m_mmc3_chr_cb = rex_dbz_chr_cb;
12026         break;
12027      case TXC_TW:
12028         state->m_mmc3_prg_cb = txc_tw_prg_cb;
12029         break;
12030      case WAIXING_TYPE_A:
12031         state->m_mmc3_chr_cb = waixing_a_chr_cb;
12032         break;
12033      case WAIXING_TYPE_A_1:
12034         state->m_mmc3_chr_cb = waixing_a1_chr_cb;
12035         break;
12036      case WAIXING_TYPE_B:
12037         state->m_mmc3_chr_cb = waixing_b_chr_cb;
12038         break;
12039      case WAIXING_TYPE_C:
12040         state->m_mmc3_chr_cb = waixing_c_chr_cb;
12041         break;
12042      case WAIXING_TYPE_D:
12043         state->m_mmc3_chr_cb = waixing_d_chr_cb;
12044         break;
12045      case WAIXING_TYPE_E:
12046         state->m_mmc3_chr_cb = waixing_e_chr_cb;
12047         break;
12048      case WAIXING_TYPE_G:
12049         state->m_mmc3_chr_cb = waixing_g_chr_cb;
12050         break;
12051      case WAIXING_TYPE_H:
12052         state->m_mmc3_chr_cb = waixing_h_chr_cb;
12053         break;
12054      case WAIXING_SECURITY:
12055         state->m_mmc3_prg_cb = waixing_sec_prg_cb;
12056         state->m_mmc3_chr_cb = waixing_sec_chr_cb;
12057         break;
12058      case WAIXING_SH2:
12059         state->m_mmc3_chr_cb = waixing_sh2_chr_cb;
12060         break;
12061      case UNL_8237:
12062         state->m_mmc3_prg_cb = unl_8237_prg_cb;
12063         state->m_mmc3_chr_cb = unl_8237_chr_cb;
12064         break;
12065      case UNL_H2288:
12066         state->m_mmc3_prg_cb = h2288_prg_cb;
12067         break;
12068      case SUPERGAME_BOOGERMAN:
12069         state->m_mmc3_prg_cb = sgame_boog_prg_cb;
12070         state->m_mmc3_chr_cb = sgame_boog_chr_cb;
12071         break;
12072      case UNL_KOF96:
12073         state->m_mmc3_prg_cb = kof96_prg_cb;
12074         state->m_mmc3_chr_cb = kof96_chr_cb;
12075         break;
12076      case KAY_PANDAPRINCE:
12077         state->m_mmc3_prg_cb = kay_pp_prg_cb;
12078         state->m_mmc3_chr_cb = kay_pp_chr_cb;
12079         break;
12080      case BMC_FK23C:
12081         state->m_mmc3_prg_cb = fk23c_prg_cb;
12082         state->m_mmc3_chr_cb = fk23c_chr_cb;
12083         break;
12084      case BMC_S24IN1SC03:
12085         state->m_mmc3_prg_cb = bmc_s24in1sc03_prg_cb;
12086         state->m_mmc3_chr_cb = bmc_s24in1sc03_chr_cb;
12087         break;
12088      case BMC_PJOY84:
12089         state->m_mmc3_prg_cb = pjoy84_prg_cb;
12090         state->m_mmc3_chr_cb = pjoy84_chr_cb;
12091         break;
12092   }
12093}
12094
12095/*************************************************************
12096
12097 pcb_initialize
12098
12099 Initialize all the necessary registers and quantities for
12100 emulation of each board
12101
12102 *************************************************************/
12103
12104/* this is used by many boards (MMC3, MMC6 + most MMC3 pirate clone boards) */
12105static void mmc3_common_initialize( running_machine &machine, int prg_mask, int chr_mask, int IRQ_type )
12106{
12107   nes_state *state = machine.driver_data<nes_state>();
12108
12109   state->m_mmc3_alt_irq = IRQ_type;      // later MMC3 boards seem to use MMC6-type IRQ... more investigations are in progress at NESDev...
12110   state->m_mmc_prg_bank[0] = state->m_mmc_prg_bank[2] = 0xfe;   // prg_bank[2] & prg_bank[3] remain always the same in most MMC3 variants
12111   state->m_mmc_prg_bank[1] = state->m_mmc_prg_bank[3] = 0xff;   // but some pirate clone mappers change them after writing certain registers
12112   state->m_mmc3_latch = 0;
12113   state->m_mmc3_wram_protect = 0x80;
12114   state->m_mmc_prg_base = state->m_mmc_chr_base = 0;
12115   state->m_mmc_prg_mask = prg_mask;
12116   state->m_mmc_chr_mask = chr_mask;
12117   mmc3_set_prg(machine, state->m_mmc_prg_base, state->m_mmc_prg_mask);
12118   mmc3_set_chr(machine, state->m_mmc_chr_source, state->m_mmc_chr_base, state->m_mmc_chr_mask);
12119}
12120
12121// WIP code
12122static int pcb_initialize( running_machine &machine, int idx )
12123{
12124   nes_state *state = machine.driver_data<nes_state>();
12125   int err = 0, i;
12126
12127   /* basic PRG config */
12128   prg32(machine, 0);
12129
12130   /* some boards will not use this, but directly CHRROM (resp. CHRRAM) if the board only has VROM (resp. VRAM) */
12131   state->m_mmc_chr_source = state->m_chr_chunks ? CHRROM : CHRRAM;
12132   chr8(machine, 0, state->m_mmc_chr_source);
12133
12134   /* Here, we init a few helpers: 4 prg banks and 16 chr banks - some mappers use them */
12135   for (i = 0; i < 4; i++)
12136      state->m_mmc_prg_bank[i] = 0;
12137   for (i = 0; i < 16; i++)
12138      state->m_mmc_vrom_bank[i] = 0;
12139   for (i = 0; i < 16; i++)
12140      state->m_mmc_extra_bank[i] = 0;
12141
12142   state->m_mmc_latch1 = 0;
12143   state->m_mmc_latch2 = 0;
12144
12145   /* Finally, we init IRQ-related quantities. */
12146   state->m_IRQ_enable = state->m_IRQ_enable_latch = 0;
12147   state->m_IRQ_count = state->m_IRQ_count_latch = 0;
12148   state->m_IRQ_toggle = 0;
12149
12150   switch (idx)
12151   {
12152         /* many boards only needs PRG to point at first 32k and CHR at first 8k */
12153      case STD_NROM:   // mapper 0
12154      case HVC_FAMBASIC:
12155      case GG_NROM:
12156      case UXROM_CC:   // mapper 180
12157      case STD_CNROM:   // mapper 3, 185
12158      case BANDAI_PT554:
12159      case TENGEN_800008:
12160      case STD_BXROM:   // mapper 34
12161      case STD_GXROM:   // mapper 66
12162      case STD_MXROM:
12163      case BANDAI_OEKAKIDS:   // mapper 96
12164      case JALECO_JF11:   // mapper 140
12165      case JALECO_JF13:   // mapper 86
12166      case JALECO_JF19:   // mapper 92
12167      case DIS_74X377:   // mapper 11
12168      case DIS_74X161X138:   // mapper 38
12169      case CALTRON_6IN1:   // mapper 41
12170      case TXC_STRIKEWOLF:   // mapper 36
12171      case UNL_STUDYNGAME:   // mapper 39
12172      case RUMBLESTATION_BOARD:   // mapper 46
12173      case BMC_GKB:   // mapper 58
12174      case RCM_TETRISFAMILY:   // mapper 61
12175      case BMC_SUPER_700IN1:   // mapper 62
12176      case MAGICSERIES_MD:   // mapper 107
12177      case HES_BOARD:   // mapper 113
12178      case HES6IN1_BOARD:   // mapper 113
12179      case SACHEN_SA72008:   // mapper 133
12180      case SACHEN_TCU02:   // mapper 136
12181      case SACHEN_SA72007:   // mapper 145
12182      case SACHEN_TCU01:   // mapper 147
12183      case SACHEN_SA009:   // mapper 160
12184      case SACHEN_SA0037:   // mapper 148
12185      case SACHEN_SA0036:   // mapper 149
12186      case AGCI_50282:   // mapper 144
12187      case KAISER_KS7058:   // mapper 171
12188      case HENGEDIANZI_BOARD:   // mapper 177
12189      case WAIXING_SGZLZ:   // mapper 178
12190      case HENGEDIANZI_XJZB:   // mapper 179
12191      case BMC_21IN1:   // mapper 201
12192      case BMC_9999999IN1:   // mapper 213
12193      case RCM_GS2015:   // mapper 216
12194      case BMC_72IN1:   // mapper 225
12195      case BMC_76IN1:   // mapper 226
12196      case BMC_SUPER_42IN1:   // mapper 226
12197      case ACTENT_ACT52:   // mapper 228
12198      case CNE_SHLZ:   // mapper 240
12199      case TXC_MXMDHTWO:   // mapper 241
12200      case WAIXING_ZS:   // mapper 242
12201      case WAIXING_DQ8:   // mapper 242
12202      case CNE_DECATHLON:   // mapper 244
12203      case UNL_CC21:
12204      case BMC_VT5201:
12205      case BMC_WS:
12206      case UNL_EDU2K:
12207         break;
12208
12209         /* other boards need additional initialization */
12210      case STD_UXROM:   // mapper 2
12211      case STD_UN1ROM:   // mapper 94
12212      case STD_JXROM:      // mapper 69
12213      case SUNSOFT_5B:
12214      case SUNSOFT_FME7:
12215      case NAMCOT_3425:   // mapper 95
12216      case DIS_74X139X74:   // mapper 87
12217      case DIS_74X161X161X32:   // mapper 152 & 70
12218      case BANDAI_LZ93:   // mapper 16, 157
12219      case BANDAI_LZ93EX:   // same + EEPROM
12220      case BANDAI_DATACH:
12221      case BANDAI_FCG:
12222      case IREM_HOLYDIV:   // mapper 78
12223      case IREM_G101:   // mapper 32
12224      case IREM_H3001:   // mapper 65
12225      case JALECO_SS88006:   // mapper 18
12226      case JALECO_JF16:   // mapper 78
12227      case JALECO_JF17:   // mapper 72
12228      case KONAMI_VRC1:   // mapper 75
12229      case KONAMI_VRC2:
12230      case KONAMI_VRC3:   // mapper 73
12231      case KONAMI_VRC4:
12232      case KONAMI_VRC6:
12233      case SUNSOFT_3:   // mapper 67
12234      case TAITO_TC0190FMC:   // mapper 33
12235      case TAITO_TC0190FMCP:   // mapper 48
12236      case TAITO_X1_005:   // mapper 80
12237      case TAITO_X1_005_A:   // mapper 207
12238      case TAITO_X1_017:   // mapper 82
12239      case NTDEC_ASDER:   // mapper 112
12240      case FUTUREMEDIA_BOARD:   // mapper 117
12241      case BTL_DRAGONNINJA:   // mapper 222
12242      case WAIXING_SGZ:   // mapper 252
12243      case UNL_T230:
12244      case BMC_NTD_03:
12245      case KAISER_KS7022:
12246      case UNL_SHJY3:
12247      case KAISER_KS7017:
12248      case KAISER_KS7032:
12249      case KAISER_KS202:
12250         prg16_89ab(machine, 0);
12251         prg16_cdef(machine, state->m_prg_chunks - 1);
12252         break;
12253
12254      case STD_CPROM:   // mapper 13
12255         chr4_0(machine, 0, CHRRAM);
12256         chr4_4(machine, 0, CHRRAM);
12257         break;
12258      case STD_AXROM:   // mapper 7
12259         set_nt_mirroring(machine, PPU_MIRROR_LOW);
12260         break;
12261      case STD_SXROM:   // mapper 1, 155
12262      case STD_SOROM:
12263      case STD_SXROM_A:
12264      case STD_SOROM_A:
12265         state->m_mmc1_latch = 0;
12266         state->m_mmc1_count = 0;
12267         state->m_mmc_reg[0] = 0x0f;
12268         state->m_mmc_reg[1] = state->m_mmc_reg[2] = state->m_mmc_reg[3] = 0;
12269         state->m_mmc1_reg_write_enable = 1;
12270         set_nt_mirroring(machine, PPU_MIRROR_HORZ);
12271         mmc1_set_chr(machine);
12272         mmc1_set_prg(machine);
12273         if (state->m_battery || state->m_wram)
12274            wram_bank(machine, 0, (idx == STD_SOROM) ? NES_WRAM : NES_BATTERY);
12275         break;
12276      case STD_PXROM:   // mapper 9
12277         state->m_mmc_reg[0] = state->m_mmc_reg[2] = 0;
12278         state->m_mmc_reg[1] = state->m_mmc_reg[3] = 0;
12279         state->m_mmc_latch1 = state->m_mmc_latch2 = 0xfe;
12280         prg8_89(machine, 0);
12281         prg8_ab(machine, (state->m_prg_chunks << 1) - 3);
12282         prg8_cd(machine, (state->m_prg_chunks << 1) - 2);
12283         prg8_ef(machine, (state->m_prg_chunks << 1) - 1);
12284         break;
12285      case STD_FXROM: // mapper 10
12286         state->m_mmc_reg[0] = state->m_mmc_reg[2] = 0;
12287         state->m_mmc_reg[1] = state->m_mmc_reg[3] = 0;
12288         state->m_mmc_latch1 = state->m_mmc_latch2 = 0xfe;
12289         prg16_89ab(machine, 0);
12290         prg16_cdef(machine, state->m_prg_chunks - 1);
12291         break;
12292      case STD_TXROM:   // mapper 4
12293      case STD_TVROM:
12294      case STD_TKROM:
12295      case REXSOFT_DBZ5:   // mapper 12
12296      case WAIXING_TYPE_A:   // mapper 74
12297      case WAIXING_TYPE_A_1:
12298      case STD_TXSROM:   // mapper 118
12299      case STD_TQROM:   // mapper 119
12300      case WAIXING_SH2:   // mapper 165
12301      case WAIXING_TYPE_B:   // mapper 191
12302      case WAIXING_TYPE_C:   // mapper 192
12303      case WAIXING_TYPE_D:   // mapper 194
12304      case WAIXING_TYPE_E:   // mapper 195
12305      case WAIXING_TYPE_H:   // mapper 245
12306      case BTL_SUPERBROS11:   // mapper 196
12307      case UNL_H2288:      // mapper 123
12308      case UNL_KOF97:
12309      case UNL_603_5052:
12310      case NITRA_TDA:   // mapper 250
12311         if (state->m_four_screen_vram)   // only TXROM and DXROM have 4-screen mirroring
12312         {
12313            set_nt_page(machine, 0, CART_NTRAM, 0, 1);
12314            set_nt_page(machine, 1, CART_NTRAM, 1, 1);
12315            set_nt_page(machine, 2, CART_NTRAM, 2, 1);
12316            set_nt_page(machine, 3, CART_NTRAM, 3, 1);
12317         }
12318         mmc3_common_initialize(machine, 0xff, 0xff, 0);
12319         break;
12320      case STD_HKROM:   // MMC6 (basically the same as TxROM, but alt IRQ behaviour)
12321         mmc3_common_initialize(machine, 0xff, 0xff, 1);
12322         state->m_mmc6_reg = 0xf0;
12323         state->m_mmc_latch2 = 0;   // this is used differently here compared to MMC3
12324         break;
12325      case PAL_ZZ:   // mapper 37
12326         mmc3_common_initialize(machine, 0x07, 0x7f, 0);
12327         break;
12328      case NES_QJ:   // mapper 47
12329         mmc3_common_initialize(machine, 0x0f, 0x7f, 0);
12330         break;
12331      case STD_EXROM:   // mapper 5
12332         state->m_MMC5_rom_bank_mode = 3;
12333         state->m_MMC5_vrom_bank_mode = 0;
12334         state->m_MMC5_vram_protect = 0;
12335         state->m_mmc5_high_chr = 0;
12336         state->m_mmc5_vram_control = 0;
12337         state->m_mmc5_split_scr = 0;
12338         memset(state->m_MMC5_vrom_bank, 0, ARRAY_LENGTH(state->m_MMC5_vrom_bank));
12339         state->m_mmc5_prg_mode = 3;
12340         state->m_mmc5_last_chr_a = 1;
12341         state->m_mmc5_prg_regs[0] = 0xfc;
12342         state->m_mmc5_prg_regs[1] = 0xfd;
12343         state->m_mmc5_prg_regs[2] = 0xfe;
12344         state->m_mmc5_prg_regs[3] = 0xff;
12345         memset(state->m_mmc5_vrom_regA, ~0, ARRAY_LENGTH(state->m_mmc5_vrom_regA));
12346         memset(state->m_mmc5_vrom_regB, ~0, ARRAY_LENGTH(state->m_mmc5_vrom_regB));
12347         prg16_89ab(machine, state->m_prg_chunks - 2);
12348         prg16_cdef(machine, state->m_prg_chunks - 1);
12349         break;
12350      case STD_NXROM:      // mapper 68
12351      case SUNSOFT_DCS:      // mapper 68
12352         state->m_mmc_reg[0] = 0;
12353         prg16_89ab(machine, 0);
12354         prg16_cdef(machine, state->m_prg_chunks - 1);
12355         break;
12356      case NAMCOT_34X3:   // mapper 88
12357      case STD_DXROM:   // mapper 206
12358      case STD_DRROM:
12359         if (state->m_four_screen_vram)   // only TXROM and DXROM have 4-screen mirroring
12360         {
12361            set_nt_page(machine, 0, CART_NTRAM, 0, 1);
12362            set_nt_page(machine, 1, CART_NTRAM, 1, 1);
12363            set_nt_page(machine, 2, CART_NTRAM, 2, 1);
12364            set_nt_page(machine, 3, CART_NTRAM, 3, 1);
12365         }
12366      case NAMCOT_3453:   // mapper 154
12367         prg16_89ab(machine, state->m_prg_chunks - 2);
12368         prg16_cdef(machine, state->m_prg_chunks - 1);
12369         break;
12370      case NAMCOT_3446:   // mapper 76
12371         prg8_89(machine, 0);
12372         prg8_ab(machine, 1);
12373         prg16_cdef(machine, state->m_prg_chunks - 1);
12374         chr2_0(machine, 0, CHRROM);
12375         chr2_2(machine, 1, CHRROM);
12376         chr2_4(machine, 2, CHRROM);
12377         chr2_6(machine, 3, CHRROM);
12378         break;
12379      case BANDAI_JUMP2:   // mapper 153
12380         for (i = 0; i < 8; i++)
12381            state->m_mmc_reg[i] = 0;
12382         prg16_89ab(machine, 0);
12383         prg16_cdef(machine, state->m_prg_chunks - 1);
12384         fjump2_set_prg(machine);
12385         break;
12386      case BANDAI_KARAOKE:   // mapper 188
12387         prg16_89ab(machine, 0);
12388         prg16_cdef(machine, (state->m_prg_chunks - 1) ^ 0x08);
12389         break;
12390      case IREM_LROG017:   // mapper 77
12391         chr2_2(machine, 0, CHRROM);
12392         chr2_4(machine, 1, CHRROM);
12393         chr2_6(machine, 2, CHRROM);
12394         break;
12395      case IREM_TAM_S1:   // mapper 97
12396         prg16_89ab(machine, state->m_prg_chunks - 1);
12397         prg16_cdef(machine, 0);
12398         break;
12399      case KONAMI_VRC7:   // mapper 85
12400         prg8_89(machine, 0);
12401         prg8_ab(machine, 0);
12402         prg8_cd(machine, 0);
12403         prg8_ef(machine, 0xff);
12404         break;
12405      case NAMCOT_163:   // mapper 19
12406         prg16_89ab(machine, 0);
12407         prg16_cdef(machine, state->m_prg_chunks - 1);
12408         set_nt_mirroring(machine, PPU_MIRROR_VERT);
12409         break;
12410      case SUNSOFT_1:   // mapper 184
12411      case SUNSOFT_2:   // mapper 89 & 93
12412         prg16_89ab(machine, 0);
12413         prg16_cdef(machine, state->m_prg_chunks - 1);
12414         if (!state->m_hard_mirroring)
12415            set_nt_mirroring(machine, PPU_MIRROR_LOW);
12416         break;
12417
12418         // mapper 14
12419      case REXSOFT_SL1632:
12420         state->m_mmc_extra_bank[2] = 0xfe;
12421         state->m_mmc_extra_bank[3] = 0xff;
12422         state->m_mmc_extra_bank[0] = state->m_mmc_extra_bank[1] = state->m_mmc_extra_bank[4] = state->m_mmc_extra_bank[5] = state->m_mmc_extra_bank[6] = 0;
12423         state->m_mmc_extra_bank[7] = state->m_mmc_extra_bank[8] = state->m_mmc_extra_bank[9] = state->m_mmc_extra_bank[0xa] = state->m_mmc_extra_bank[0xb] = 0;
12424         state->m_mmc_reg[0] = state->m_mmc_reg[1] = 0;
12425         mmc3_common_initialize(machine, 0xff, 0xff, 0);
12426         break;
12427         // mapper 15
12428      case WAIXING_PS2:
12429         set_nt_mirroring(machine, PPU_MIRROR_VERT);
12430         break;
12431
12432         // mapper 35
12433      case UNL_SC127:
12434         // mapper 42
12435      case BTL_MARIOBABY:
12436      case BTL_AISENSHINICOL:
12437         prg32(machine, 0xff);
12438         break;
12439
12440         // mapper 40
12441      case BTL_SMB2A:
12442         prg8_67(machine, 0xfe);
12443         prg8_89(machine, 0xfc);
12444         prg8_ab(machine, 0xfd);
12445         prg8_cd(machine, 0xfe);
12446         prg8_ef(machine, 0xff);
12447         break;
12448
12449         // mapper 43
12450      case UNL_SMB2J:
12451         if (state->m_battery)
12452            memset(state->m_battery_ram, 0x2000, 0xff);
12453         else if (state->m_prg_ram)
12454            memset(state->m_wram, 0x2000, 0xff);
12455         break;
12456         // mapper 44
12457      case BMC_SUPERBIG_7IN1:
12458         // mapper 49
12459      case BMC_SUPERHIK_4IN1:
12460         mmc3_common_initialize(machine, 0x0f, 0x7f, 0);
12461         break;
12462         // mapper 45
12463      case BMC_HIK8IN1:
12464         state->m_mmc_reg[0] = state->m_mmc_reg[1] = state->m_mmc_reg[2] = state->m_mmc_reg[3] = 0;
12465         mmc3_common_initialize(machine, 0x3f, 0xff, 0);
12466         break;
12467
12468         // mapper 50
12469      case BTL_SMB2B:
12470         prg8_67(machine, 0x0f);
12471         prg8_89(machine, 0x08);
12472         prg8_ab(machine, 0x09);
12473         prg8_cd(machine, 0);
12474         prg8_ef(machine, 0x0b);
12475         break;
12476         // mapper 51
12477      case BMC_BALLGAMES_11IN1:
12478         state->m_mmc_reg[0] = 0x01;
12479         state->m_mmc_reg[1] = 0x00;
12480         bmc_ball11_set_banks(machine);
12481         break;
12482         // mapper 52
12483      case BMC_MARIOPARTY_7IN1:
12484         state->m_map52_reg_written = 0;
12485         mmc3_common_initialize(machine, 0x1f, 0xff, 0);
12486         break;
12487         // mapper 54
12488      case BMC_NOVELDIAMOND:
12489         set_nt_mirroring(machine, PPU_MIRROR_VERT);
12490         break;
12491         // mapper 57
12492      case BMC_GKA:
12493         prg16_89ab(machine, 0);
12494         prg16_cdef(machine, 0);
12495         break;
12496
12497         // mapper 64
12498      case TENGEN_800032:
12499         // mapper 158
12500      case TENGEN_800037:
12501         prg16_89ab(machine, state->m_prg_chunks - 1);
12502         prg16_cdef(machine, state->m_prg_chunks - 1);
12503         break;
12504         // mapper 71
12505      case CAMERICA_BF9097:
12506         set_nt_mirroring(machine, PPU_MIRROR_HORZ);
12507      case CAMERICA_BF9093:
12508         prg32(machine, 0xff);
12509         break;
12510
12511         // mapper 79 (& 146)
12512      case AVE_NINA06:
12513         set_nt_mirroring(machine, PPU_MIRROR_HORZ);
12514         break;
12515
12516         // mapper 83
12517      case CONY_BOARD:
12518         state->m_mapper83_reg[9] = 0x0f;
12519         prg8_cd(machine, 0x1e);
12520         prg8_ef(machine, 0x1f);
12521         break;
12522
12523         // mapper 91
12524      case UNL_MK2:
12525         set_nt_mirroring(machine, PPU_MIRROR_VERT);
12526         prg16_89ab(machine, state->m_prg_chunks - 1);
12527         prg16_cdef(machine, state->m_prg_chunks - 1);
12528         break;
12529
12530         // mapper 104
12531      case CAMERICA_GOLDENFIVE:
12532         prg16_89ab(machine, 0x00);
12533         prg16_cdef(machine, 0x0f);
12534         break;
12535         // mapper 106
12536      case BTL_SMB3:
12537         prg8_89(machine, (state->m_prg_chunks << 1) - 1);
12538         prg8_ab(machine, 0);
12539         prg8_cd(machine, 0);
12540         prg8_ef(machine, (state->m_prg_chunks << 1) - 1);
12541         break;
12542
12543         // mapper 108
12544      case WHIRLWIND_2706:
12545         prg32(machine, 0xff);
12546         break;
12547
12548         // mapper 114
12549      case SUPERGAME_LIONKING:
12550         state->m_map114_reg = state->m_map114_reg_enabled = 0;
12551         mmc3_common_initialize(machine, 0xff, 0xff, 0);
12552         break;
12553         // mapper 115
12554      case KASING_BOARD:
12555         state->m_mmc_reg[0] = 0;
12556         mmc3_common_initialize(machine, 0xff, 0xff, 0);
12557         break;
12558         // mapper 116
12559      case SOMERI_SL12:
12560         state->m_mmc_prg_base = state->m_mmc_chr_base = 0;
12561         state->m_mmc_prg_mask = 0xff;
12562         state->m_mmc_chr_mask = 0xff;
12563         state->m_mmc_cmd1 = 2; // mode
12564         state->m_mmc3_latch = 0;
12565         state->m_mmc3_wram_protect = 0;
12566         // MMC1 regs
12567         state->m_mmc1_count = 0;
12568         state->m_mmc_reg[0] = 0x0c;
12569         state->m_mmc_reg[1] = 0x00;
12570         state->m_mmc_reg[2] = 0x00;
12571         state->m_mmc_reg[3] = 0x00;
12572         // MMC3 regs
12573         state->m_mmc_prg_bank[0] = 0x3c;
12574         state->m_mmc_prg_bank[1] = 0x3d;
12575         state->m_mmc_prg_bank[2] = 0xfe;
12576         state->m_mmc_prg_bank[3] = 0xff;
12577         state->m_mmc_vrom_bank[0] = 0x00;
12578         state->m_mmc_vrom_bank[1] = 0x01;
12579         state->m_mmc_vrom_bank[2] = 0x04;
12580         state->m_mmc_vrom_bank[3] = 0x05;
12581         state->m_mmc_vrom_bank[4] = 0x06;
12582         state->m_mmc_vrom_bank[5] = 0x07;
12583         // VRC2 regs
12584         state->m_mmc_prg_bank[4] = 0x00;
12585         state->m_mmc_prg_bank[5] = 0x01;
12586         for (i = 0; i < 8; ++i)
12587            state->m_mmc_vrom_bank[6 + i] = i;
12588         someri_mode_update(machine);
12589         break;
12590
12591         // mapper 120
12592      case BTL_TOBIDASE:
12593         prg32(machine, 2);
12594         break;
12595
12596         // mapper 121
12597      case KAY_PANDAPRINCE:
12598         state->m_mmc_reg[5] = state->m_mmc_reg[6] = state->m_mmc_reg[7] = 0;
12599         mmc3_common_initialize(machine, 0xff, 0xff, 0);
12600         break;
12601
12602         // mapper 126
12603      case BMC_PJOY84:
12604         mmc3_common_initialize(machine, 0xff, 0xff, 0);
12605         state->m_mmc_reg[0] = state->m_mmc_reg[1] = state->m_mmc_reg[2] = state->m_mmc_reg[3] = 0;
12606         pjoy84_set_base_mask(machine);
12607         mmc3_set_chr(machine, state->m_mmc_chr_source, state->m_mmc_chr_base, state->m_mmc_chr_mask);
12608         mmc3_set_prg(machine, state->m_mmc_prg_base, state->m_mmc_prg_mask);
12609         break;
12610
12611         // mapper 132
12612      case TXC_22211A:
12613         // mapper 172
12614      case TXC_22211B:
12615         // mapper 173
12616      case TXC_22211C:
12617         state->m_txc_reg[0] = state->m_txc_reg[1] = state->m_txc_reg[2] = state->m_txc_reg[3] = 0;
12618         break;
12619
12620         // mapper 134
12621      case BMC_FAMILY_4646B:
12622         mmc3_common_initialize(machine, 0x1f, 0xff, 0);
12623         break;
12624
12625         // mapper 137
12626      case SACHEN_8259D:
12627         chr8(machine, state->m_chr_chunks - 1, CHRROM);
12628         set_nt_mirroring(machine, PPU_MIRROR_VERT);
12629         break;
12630         // mapper 138
12631      case SACHEN_8259B:
12632         // mapper 139
12633      case SACHEN_8259C:
12634         // mapper 141
12635      case SACHEN_8259A:
12636         // mapper 150
12637      case SACHEN_74LS374:
12638         set_nt_mirroring(machine, PPU_MIRROR_VERT);
12639         break;
12640         // mapper 143
12641      case SACHEN_TCA01:
12642         prg16_89ab(machine, 0);
12643         prg16_cdef(machine, 1);
12644         break;
12645
12646         // mapper 156
12647      case OPENCORP_DAOU306:
12648         prg16_89ab(machine, state->m_prg_chunks - 2);
12649         prg16_cdef(machine, state->m_prg_chunks - 1);
12650         set_nt_mirroring(machine, PPU_MIRROR_LOW);
12651         break;
12652         // mapper 163
12653      case NANJING_BOARD:
12654         state->m_mmc_count = 0xff;
12655         state->m_mmc_reg[0] = 0xff;
12656         state->m_mmc_reg[1] = 0;
12657         prg16_89ab(machine, state->m_prg_chunks - 2);
12658         prg16_cdef(machine, state->m_prg_chunks - 1);
12659         break;
12660         // mapper 164
12661      case WAIXING_FFV:
12662         prg16_89ab(machine, 0);
12663         prg16_cdef(machine, 0x1f);
12664         break;
12665         // mapper 166
12666      case SUBOR_TYPE1:
12667         state->m_subor_reg[0] = state->m_subor_reg[1] = state->m_subor_reg[2] = state->m_subor_reg[3] = 0;
12668         prg16_89ab(machine, 0);
12669         prg16_cdef(machine, 0x07);
12670         break;
12671         // mapper 167
12672      case SUBOR_TYPE0:
12673         state->m_subor_reg[0] = state->m_subor_reg[1] = state->m_subor_reg[2] = state->m_subor_reg[3] = 0;
12674         prg16_89ab(machine, 0);
12675         prg16_cdef(machine, 0x20);
12676         break;
12677
12678         // mapper 176
12679      case UNL_XZY:
12680         // mapper 182
12681      case HOSENKAN_BOARD:
12682         prg32(machine, (state->m_prg_chunks - 1) >> 1);
12683         break;
12684
12685      case FUKUTAKE_BOARD:   // mapper 186
12686         prg16_89ab(machine, 0);
12687         prg16_cdef(machine, 0);
12688         break;
12689
12690         // mapper 187
12691      case UNL_KOF96:
12692         state->m_mmc_reg[0] = state->m_mmc_reg[1] = state->m_mmc_reg[2] = state->m_mmc_reg[3] = 0;
12693         mmc3_common_initialize(machine, 0xff, 0xff, 0);
12694         break;
12695         // mapper 189
12696      case TXC_TW:
12697         state->m_mmc_latch1 = 0;
12698         state->m_mmc_latch2 = 0x80;
12699         state->m_mmc_chr_base = 0;
12700         state->m_mmc_chr_mask = 0xff;
12701         mmc3_set_chr(machine, state->m_mmc_chr_source, state->m_mmc_chr_base, state->m_mmc_chr_mask);
12702         break;
12703         // mapper 193
12704      case NTDEC_FIGHTINGHERO:
12705         prg32(machine, (state->m_prg_chunks - 1) >> 1);
12706         set_nt_mirroring(machine, PPU_MIRROR_VERT);
12707         break;
12708         // mapper 197
12709      case UNL_SUPERFIGHTER3:
12710         mmc3_common_initialize(machine, 0xff, 0xff, 0);
12711         unl_sf3_set_chr(machine, state->m_mmc_chr_source, state->m_mmc_chr_base, state->m_mmc_chr_mask);
12712         break;
12713         // mapper 198
12714      case WAIXING_TYPE_F:
12715         mmc3_common_initialize(machine, 0xff, 0xff, 0);
12716         state->m_mmc_prg_bank[0] = 0x00;
12717         state->m_mmc_prg_bank[1] = 0x01;
12718         state->m_mmc_prg_bank[2] = 0x4e;
12719         state->m_mmc_prg_bank[3] = 0x4f;
12720         mmc3_set_prg(machine, state->m_mmc_prg_base, state->m_mmc_prg_mask);
12721         break;
12722         // mapper 199
12723      case WAIXING_TYPE_G:
12724         mmc3_common_initialize(machine, 0xff, 0xff, 0);
12725         state->m_mmc_prg_bank[0] = 0x00;
12726         state->m_mmc_prg_bank[1] = 0x01;
12727         state->m_mmc_prg_bank[2] = 0x3e;
12728         state->m_mmc_prg_bank[3] = 0x3f;
12729         mmc3_set_prg(machine, state->m_mmc_prg_base, state->m_mmc_prg_mask);
12730         state->m_mmc_vrom_bank[0] = 0x00;
12731         state->m_mmc_vrom_bank[1] = 0x02;
12732         state->m_mmc_vrom_bank[2] = 0x04;
12733         state->m_mmc_vrom_bank[3] = 0x05;
12734         state->m_mmc_vrom_bank[4] = 0x06;
12735         state->m_mmc_vrom_bank[5] = 0x07;
12736         state->m_mmc_vrom_bank[6] = 0x01;
12737         state->m_mmc_vrom_bank[7] = 0x03;
12738         waixing_g_set_chr(machine, state->m_mmc_chr_base, state->m_mmc_chr_mask);
12739         break;
12740
12741         // mapper 200
12742      case BMC_36IN1:
12743         prg16_89ab(machine, state->m_prg_chunks - 1);
12744         prg16_cdef(machine, state->m_prg_chunks - 1);
12745         break;
12746
12747         // mapper 202
12748      case BMC_150IN1:
12749         // mapper 203
12750      case BMC_35IN1:
12751         // mapper 204
12752      case BMC_64IN1:
12753         // mapper 214
12754      case BMC_SUPERGUN_20IN1:
12755         prg16_89ab(machine, 0);
12756         prg16_cdef(machine, 0);
12757         break;
12758         // mapper 205
12759      case BMC_15IN1:
12760         mmc3_common_initialize(machine, 0x1f, 0xff, 0);
12761         state->m_mmc_prg_base = 0x10;   // this board has a diff prg_base
12762         mmc3_set_prg(machine, state->m_mmc_prg_base, state->m_mmc_prg_mask);
12763         break;
12764
12765         // mapper 208
12766      case GOUDER_37017:
12767         state->m_mmc_reg[0] = state->m_mmc_reg[1] = state->m_mmc_reg[2] = state->m_mmc_reg[3] = state->m_mmc_reg[4] = 0;
12768         mmc3_common_initialize(machine, 0xff, 0xff, 0);
12769         break;
12770         // mapper 212
12771      case BMC_SUPERHIK_300IN1:
12772         chr8(machine, 0xff, CHRROM);
12773         prg32(machine, 0xff);
12774         break;
12775
12776         // mapper 215
12777      case SUPERGAME_BOOGERMAN:
12778         state->m_mmc_reg[0] = 0x00;
12779         state->m_mmc_reg[1] = 0xff;
12780         state->m_mmc_reg[2] = 0x04;
12781         state->m_mmc_reg[3] = 0;
12782         mmc3_common_initialize(machine, 0x1f, 0xff, 0);
12783         sgame_boog_set_prg(machine);
12784         mmc3_set_chr(machine, state->m_mmc_chr_source, state->m_mmc_chr_base, state->m_mmc_chr_mask);
12785         break;
12786
12787         // mapper 217
12788      case BMC_GOLDENCARD_6IN1:
12789         mmc3_common_initialize(machine, 0xff, 0xff, 0);
12790         state->m_mmc_reg[0] = 0x00;
12791         state->m_mmc_reg[1] = 0xff;
12792         state->m_mmc_reg[2] = 0x03;
12793         state->m_mmc_reg[3] = 0;
12794         bmc_gc6in1_set_prg(machine, state->m_mmc_prg_base, state->m_mmc_prg_mask);
12795         bmc_gc6in1_set_chr(machine, state->m_mmc_chr_source);
12796         break;
12797         // mapper 221
12798      case UNL_N625092:
12799         prg16_89ab(machine, 0);
12800         prg16_cdef(machine, 0);
12801         break;
12802
12803         // mapper 223?
12804      case WAIXING_TYPE_I:
12805         mmc3_common_initialize(machine, 0xff, 0xff, 0);
12806         state->m_mmc3_wram_protect = 0;
12807         break;
12808
12809         // mapper 224?
12810      case WAIXING_TYPE_J:
12811         mmc3_common_initialize(machine, 0xff, 0xff, 0);
12812         state->m_mmc_prg_bank[0] = 0x01;
12813         state->m_mmc_prg_bank[1] = 0x02;
12814         state->m_mmc_prg_bank[2] = 0x7e;
12815         state->m_mmc_prg_bank[3] = 0x7f;
12816         mmc3_set_prg(machine, state->m_mmc_prg_base, state->m_mmc_prg_mask);
12817         break;
12818
12819         // mapper 227
12820      case BMC_1200IN1:
12821         prg16_89ab(machine, 0);
12822         prg16_cdef(machine, 0);
12823         break;
12824
12825         // mapper 229
12826      case BMC_31IN1:
12827         prg16_89ab(machine, 0);
12828         prg16_cdef(machine, 1);
12829         set_nt_mirroring(machine, PPU_MIRROR_VERT);
12830         break;
12831         // mapper 230
12832      case BMC_22GAMES:
12833         prg16_89ab(machine, 0);
12834         prg16_cdef(machine, 7);
12835         break;
12836         // mapper 231
12837      case BMC_20IN1:
12838         prg16_89ab(machine, 0);
12839         prg16_cdef(machine, state->m_prg_chunks - 1);
12840         set_nt_mirroring(machine, PPU_MIRROR_VERT);
12841         break;
12842         // mapper 232
12843      case CAMERICA_BF9096:
12844         state->m_mmc_latch1 = 0x18;
12845         state->m_mmc_latch2 = 0x00;
12846         bf9096_set_prg(machine);
12847         break;
12848
12849         // mapper 243
12850      case SACHEN_74LS374_A:
12851         state->m_mmc_vrom_bank[0] = 3;
12852         chr8(machine, 3, CHRROM);
12853         set_nt_mirroring(machine, PPU_MIRROR_VERT);
12854         break;
12855
12856         // mapper 246
12857      case CNE_FSB:
12858         prg32(machine, 0xff);
12859         break;
12860         // mapper 249
12861      case WAIXING_SECURITY:
12862         state->m_mmc_reg[0] = 0;
12863         mmc3_common_initialize(machine, 0xff, 0xff, 0);
12864         break;
12865
12866         // mapper 254
12867      case BTL_PIKACHUY2K:
12868         state->m_mmc_reg[0] = 0xff;
12869         mmc3_common_initialize(machine, 0xff, 0xff, 0);
12870         break;
12871
12872         // mapper 255
12873      case BMC_110IN1:
12874         prg16_89ab(machine, 0);
12875         prg16_cdef(machine, 1);
12876         set_nt_mirroring(machine, PPU_MIRROR_VERT);
12877         break;
12878
12879         // UNIF only
12880      case BMC_64IN1NR:
12881         state->m_mmc_reg[0] = 0x80;
12882         state->m_mmc_reg[1] = 0x43;
12883         state->m_mmc_reg[2] = state->m_mmc_reg[3] = 0;
12884         bmc_64in1nr_set_prg(machine);
12885         set_nt_mirroring(machine, PPU_MIRROR_VERT);
12886         break;
12887      case BMC_190IN1:
12888         prg16_89ab(machine, 0);
12889         prg16_cdef(machine, 0);
12890         break;
12891      case BMC_A65AS:
12892         prg16_89ab(machine, 0);
12893         prg16_cdef(machine, 7);
12894         set_nt_mirroring(machine, PPU_MIRROR_VERT);
12895         break;
12896      case BMC_GS2004:
12897      case BMC_GS2013:
12898         prg32(machine, 0xff);
12899         break;
12900      case BMC_S24IN1SC03:
12901         state->m_mmc_reg[0] = 0x24;
12902         state->m_mmc_reg[1] = 0x9f;
12903         state->m_mmc_reg[2] = 0;
12904         mmc3_common_initialize(machine, 0xff, 0xff, 0);
12905         break;
12906      case BMC_T262:
12907         state->m_mmc_latch1 = 0;
12908         state->m_mmc_latch2 = 0;
12909         prg16_89ab(machine, 0);
12910         prg16_cdef(machine, 7);
12911         break;
12912      case DREAMTECH_BOARD:
12913         prg16_89ab(machine, 0);
12914         prg16_cdef(machine, 8);
12915         break;
12916      case UNL_8237:
12917         state->m_mmc_reg[0] = state->m_mmc_reg[1] = state->m_mmc_reg[2] = 0;
12918         mmc3_common_initialize(machine, 0xff, 0xff, 0);
12919         break;
12920      case UNL_AX5705:
12921         state->m_mmc_prg_bank[0] = 0;
12922         state->m_mmc_prg_bank[1] = 1;
12923         prg8_89(machine, state->m_mmc_prg_bank[0]);
12924         prg8_ab(machine, state->m_mmc_prg_bank[1]);
12925         prg8_cd(machine, 0xfe);
12926         prg8_ef(machine, 0xff);
12927         break;
12928      case UNL_RACERMATE:
12929         chr4_0(machine, 0, state->m_mmc_chr_source);
12930         chr4_4(machine, 0, state->m_mmc_chr_source);
12931         prg16_89ab(machine, 0);
12932         prg16_cdef(machine, state->m_prg_chunks - 1);
12933         break;
12934
12935      case BMC_BENSHENG_BS5:
12936         state->m_mmc_prg_bank[0] = 0xff;
12937         state->m_mmc_prg_bank[1] = 0xff;
12938         state->m_mmc_prg_bank[2] = 0xff;
12939         state->m_mmc_prg_bank[3] = 0xff;
12940         bmc_bs5_update_banks(machine);
12941         break;
12942
12943      case BMC_810544:
12944         prg16_89ab(machine, 0);
12945         prg16_cdef(machine, 0);
12946         set_nt_mirroring(machine, PPU_MIRROR_VERT);
12947         break;
12948
12949      case BMC_G63IN1:
12950         bmc_gb63_update(machine);
12951         break;
12952
12953      case BMC_FK23C:
12954         state->m_mmc_reg[0] = 4;
12955         state->m_mmc_reg[1] = 0xff;
12956         state->m_mmc_reg[2] = state->m_mmc_reg[3] = 0;
12957         state->m_mmc_reg[4] = state->m_mmc_reg[5] = state->m_mmc_reg[6] = state->m_mmc_reg[7] = 0xff;
12958         mmc3_common_initialize(machine, 0xff, 0xff, 0);
12959         fk23c_set_prg(machine);
12960         fk23c_set_chr(machine);
12961         break;
12962
12963      case BMC_FK23CA:
12964         state->m_mmc_reg[0] = state->m_mmc_reg[1] = state->m_mmc_reg[2] = state->m_mmc_reg[3] = 0;
12965         state->m_mmc_reg[4] = state->m_mmc_reg[5] = state->m_mmc_reg[6] = state->m_mmc_reg[7] = 0xff;
12966         mmc3_common_initialize(machine, 0xff, 0xff, 0);
12967         fk23c_set_prg(machine);
12968         fk23c_set_chr(machine);
12969         break;
12970
12971
12972      case FFE_MAPPER6:
12973         prg16_89ab(machine, 0);
12974         prg16_cdef(machine, 7);
12975         break;
12976      case FFE_MAPPER8:
12977         prg32(machine, 0);
12978         break;
12979      case FFE_MAPPER17:
12980         prg16_89ab(machine, 0);
12981         prg16_cdef(machine, state->m_prg_chunks - 1);
12982         break;
12983
12984      case UNSUPPORTED_BOARD:
12985      default:
12986         /* Mapper not supported */
12987         err = 2;
12988         break;
12989   }
12990
12991   return err;
12992}
12993
12994/*************************************************************
12995
12996 nes_pcb_reset
12997
12998 Resets the mmc bankswitch areas to their defaults.
12999 It returns a value "err" that indicates if it was
13000 successful. Possible values for err are:
13001
13002 0 = success
13003 1 = no pcb found
13004 2 = pcb not supported
13005
13006 *************************************************************/
13007
13008int nes_pcb_reset( running_machine &machine )
13009{
13010   nes_state *state = machine.driver_data<nes_state>();
13011   int err = 0;
13012   const nes_pcb_intf *intf = nes_pcb_intf_lookup(state->m_pcb_id);
13013
13014   if (intf == NULL)
13015      fatalerror("Missing PCB interface\n");
13016
13017   /* Set the mapper irq callback */
13018   ppu2c0x_set_scanline_callback(state->m_ppu, intf ? intf->mmc_scanline : NULL);
13019   ppu2c0x_set_hblank_callback(state->m_ppu, intf ? intf->mmc_hblank : NULL);
13020
13021   err = pcb_initialize(machine, state->m_pcb_id);
13022
13023   return err;
13024}
src/mess/machine/amigacd.c
r0r11532
1/***************************************************************************
2
3    Amiga CD-ROM controller emulation
4
5Notes:
6Many thanks to Toni Wilen for all the help and information about the
7DMAC controller.
8
9***************************************************************************/
10
11
12#include "emu.h"
13#include "includes/amiga.h"
14#include "amigacd.h"
15#include "machine/6525tpi.h"
16#include "machine/6526cia.h"
17#include "machine/wd33c93.h"
18#include "imagedev/chd_cd.h"
19#include "machine/matsucd.h"
20
21
22#define VERBOSE_DMAC 0
23
24#define LOG(x) do { if (VERBOSE_DMAC) logerror x; } while (0)
25
26/* constants */
27#define CD_SECTOR_TIME      (1000/((300*1024)/2048))   /* 2X CDROM sector time in msec (300KBps) */
28
29/***************************************************************************
30
31    DMAC
32
33***************************************************************************/
34
35/*
36 * value to go into DAWR
37 */
38#define DAWR_ATZSC      3       /* according to A3000T service-manual */
39
40/*
41 * bits defined for CNTR
42 */
43#define CNTR_TCEN       (1<<7)  /* Terminal Count Enable */
44#define CNTR_PREST      (1<<6)  /* Perp Reset (not implemented :-((( ) */
45#define CNTR_PDMD       (1<<5)  /* Perp Device Mode Select (1=SCSI,0=XT/AT) */
46#define CNTR_INTEN      (1<<4)  /* Interrupt Enable */
47#define CNTR_DDIR       (1<<3)  /* Device Direction. 1==rd host, wr to perp */
48
49/*
50 * bits defined for ISTR
51 */
52#define ISTR_INTX       (1<<8)  /* XT/AT Interrupt pending */
53#define ISTR_INT_F      (1<<7)  /* Interrupt Follow */
54#define ISTR_INTS       (1<<6)  /* SCSI Peripheral Interrupt */
55#define ISTR_E_INT      (1<<5)  /* End-Of-Process Interrupt */
56#define ISTR_INT_P      (1<<4)  /* Interrupt Pending */
57#define ISTR_UE_INT     (1<<3)  /* Under-Run FIFO Error Interrupt */
58#define ISTR_OE_INT     (1<<2)  /* Over-Run FIFO Error Interrupt */
59#define ISTR_FF_FLG     (1<<1)  /* FIFO-Full Flag */
60#define ISTR_FE_FLG     (1<<0)  /* FIFO-Empty Flag */
61
62typedef struct
63{
64   UINT16      istr;      /* Interrupt Status Register (R) */
65   UINT16      cntr;      /* Control Register (RW) */
66   UINT32      wtc;      /* Word Transfer Count Register (RW) */
67   UINT32      acr;      /* Address Count Register (RW) */
68   UINT16      dawr;      /* DACK Width Register (W) */
69   emu_timer *dma_timer;
70} _dmac_data;
71
72static _dmac_data dmac_data;
73
74static void check_interrupts( running_machine &machine )
75{
76   /* if interrupts are disabled, bail */
77   if ( (dmac_data.cntr & CNTR_INTEN) == 0 )
78      return;
79
80   /* if no interrupts are pending, bail */
81   if ( (dmac_data.istr & ISTR_INT_P) == 0 )
82      return;
83
84   /* otherwise, generate the IRQ */
85   amiga_custom_w(machine.device("maincpu")->memory().space(AS_PROGRAM), REG_INTREQ, 0x8000 | INTENA_PORTS, 0xffff);
86}
87
88static TIMER_CALLBACK(dmac_dma_proc)
89{
90   amiga_state *state = machine.driver_data<amiga_state>();
91   while( dmac_data.wtc > 0 )
92   {
93      UINT16   dat16;
94      UINT8   dat8;
95
96      if ( matsucd_get_next_byte( &dat8 ) < 0 )
97         break;
98
99      dat16 = dat8;
100
101      if ( matsucd_get_next_byte( &dat8 ) < 0 )
102         break;
103
104      dat16 <<= 8;
105      dat16 |= dat8;
106
107      (*state->m_chip_ram_w)(state, dmac_data.acr, dat16);
108
109      dmac_data.acr += 2;
110      dmac_data.wtc--;
111   }
112
113   if ( dmac_data.wtc > 0 )
114   {
115      matsucd_read_next_block();
116      dmac_data.dma_timer->adjust(attotime::from_msec( CD_SECTOR_TIME ));
117   }
118   else
119   {
120      dmac_data.istr |= ISTR_INT_P | ISTR_E_INT;
121      check_interrupts( machine );
122   }
123}
124
125static READ16_HANDLER( amiga_dmac_r )
126{
127   offset &= 0xff;
128
129   switch( offset )
130   {
131      case 0x20:
132      {
133         UINT8   v = dmac_data.istr;
134         LOG(( "DMAC: PC=%08x - ISTR Read(%04x)\n", cpu_get_pc(&space->device()), dmac_data.istr ));
135
136         dmac_data.istr &= ~0x0f;
137         return v;
138      }
139      break;
140
141      case 0x21:
142      {
143         LOG(( "DMAC: PC=%08x - CNTR Read(%04x)\n", cpu_get_pc(&space->device()), dmac_data.cntr ));
144         return dmac_data.cntr;
145      }
146      break;
147
148      case 0x40:   /* wtc hi */
149      {
150         LOG(( "DMAC: PC=%08x - WTC HI Read\n", cpu_get_pc(&space->device()) ));
151         return (dmac_data.wtc >> 16);
152      }
153      break;
154
155      case 0x41:   /* wtc lo */
156      {
157         LOG(( "DMAC: PC=%08x - WTC LO Read\n", cpu_get_pc(&space->device()) ));
158         return dmac_data.wtc;
159      }
160      break;
161
162      case 0x42:   /* acr hi */
163      {
164         LOG(( "DMAC: PC=%08x - ACR HI Read\n", cpu_get_pc(&space->device()) ));
165         return (dmac_data.acr >> 16);
166      }
167      break;
168
169      case 0x43:   /* acr lo */
170      {
171         LOG(( "DMAC: PC=%08x - ACR LO Read\n", cpu_get_pc(&space->device()) ));
172         return dmac_data.acr;
173      }
174      break;
175
176      case 0x48:   /* wd33c93 SCSI expansion */
177      case 0x49:
178      {
179         LOG(( "DMAC: PC=%08x - WD33C93 Read(%d)\n", cpu_get_pc(&space->device()), offset & 1 ));
180         return 0x00;   /* Not available without SCSI expansion */
181      }
182      break;
183
184      case 0x50:
185      {
186         LOG(( "DMAC: PC=%08x - CDROM RESP Read\n", cpu_get_pc(&space->device()) ));
187         return matsucd_response_r(space->machine());
188      }
189      break;
190
191      case 0x51:   /* XT IO */
192      case 0x52:
193      case 0x53:
194      {
195         LOG(( "DMAC: PC=%08x - XT IO Read(%d)\n", cpu_get_pc(&space->device()), (offset & 3)-1 ));
196         return 0xff;
197      }
198      break;
199
200      case 0x58:   /* TPI6525 */
201      case 0x59:
202      case 0x5A:
203      case 0x5B:
204      case 0x5C:
205      case 0x5D:
206      case 0x5E:
207      case 0x5F:
208      case 0x60:
209      case 0x61:
210      case 0x62:
211      case 0x63:
212      case 0x64:
213      case 0x65:
214      case 0x66:
215      case 0x67:
216      {
217         device_t *tpi = space->machine().device("tpi6525");
218         LOG(( "DMAC: PC=%08x - TPI6525 Read(%d)\n", cpu_get_pc(&space->device()), (offset - 0x58) ));
219         return tpi6525_r(tpi, offset - 0x58);
220      }
221      break;
222
223      case 0x70:   /* DMA start strobe */
224      {
225         LOG(( "DMAC: PC=%08x - DMA Start Strobe\n", cpu_get_pc(&space->device()) ));
226         dmac_data.dma_timer->adjust(attotime::from_msec( CD_SECTOR_TIME ));
227      }
228      break;
229
230      case 0x71:   /* DMA stop strobe */
231      {
232         LOG(( "DMAC: PC=%08x - DMA Stop Strobe\n", cpu_get_pc(&space->device()) ));
233         dmac_data.dma_timer->reset(  );
234      }
235      break;
236
237      case 0x72:   /* Clear IRQ strobe */
238      {
239         LOG(( "DMAC: PC=%08x - IRQ Clear Strobe\n", cpu_get_pc(&space->device()) ));
240         dmac_data.istr &= ~ISTR_INT_P;
241      }
242      break;
243
244      case 0x74:   /* Flush strobe */
245      {
246         LOG(( "DMAC: PC=%08x - Flush Strobe\n", cpu_get_pc(&space->device()) ));
247         dmac_data.istr |= ISTR_FE_FLG;
248      }
249      break;
250
251      default:
252         logerror( "DMAC-READ: PC=%08x, offset = %02x\n", cpu_get_pc(&space->device()), offset );
253      break;
254   }
255
256   return 0;
257}
258
259static WRITE16_HANDLER( amiga_dmac_w )
260{
261   offset &= 0xff;
262
263   switch( offset )
264   {
265      case 0x21:   /* control write */
266      {
267         LOG(( "DMAC: PC=%08x - CNTR Write(%04x)\n", cpu_get_pc(&space->device()), data ));
268         dmac_data.cntr = data;
269         check_interrupts(space->machine());
270      }
271      break;
272
273      case 0x40:   /* wtc hi */
274      {
275         LOG(( "DMAC: PC=%08x - WTC HI Write - data = %04x\n", cpu_get_pc(&space->device()), data ));
276         dmac_data.wtc &= 0x0000ffff;
277         dmac_data.wtc |= ((UINT32)data) << 16;
278      }
279      break;
280
281      case 0x41:   /* wtc lo */
282      {
283         LOG(( "DMAC: PC=%08x - WTC LO Write - data = %04x\n", cpu_get_pc(&space->device()), data ));
284         dmac_data.wtc &= 0xffff0000;
285         dmac_data.wtc |= data;
286      }
287      break;
288
289      case 0x42:   /* acr hi */
290      {
291         LOG(( "DMAC: PC=%08x - ACR HI Write - data = %04x\n", cpu_get_pc(&space->device()), data ));
292         dmac_data.acr &= 0x0000ffff;
293         dmac_data.acr |= ((UINT32)data) << 16;
294      }
295      break;
296
297      case 0x43:   /* acr lo */
298      {
299         LOG(( "DMAC: PC=%08x - ACR LO Write - data = %04x\n", cpu_get_pc(&space->device()), data ));
300         dmac_data.acr &= 0xffff0000;
301         dmac_data.acr |= data;
302      }
303      break;
304
305      case 0x47:   /* dawr */
306      {
307         LOG(( "DMAC: PC=%08x - DAWR Write - data = %04x\n", cpu_get_pc(&space->device()), data ));
308         dmac_data.dawr = data;
309      }
310      break;
311
312      case 0x48:   /* wd33c93 SCSI expansion */
313      case 0x49:
314      {
315         LOG(( "DMAC: PC=%08x - WD33C93 Write(%d) - data = %04x\n", cpu_get_pc(&space->device()), offset & 1, data ));
316         /* Not available without SCSI expansion */
317      }
318      break;
319
320      case 0x50:
321      {
322         LOG(( "DMAC: PC=%08x - CDROM CMD Write - data = %04x\n", cpu_get_pc(&space->device()), data ));
323         matsucd_command_w(space->machine(), data );
324      }
325      break;
326
327      case 0x58:   /* TPI6525 */
328      case 0x59:
329      case 0x5A:
330      case 0x5B:
331      case 0x5C:
332      case 0x5D:
333      case 0x5E:
334      case 0x5F:
335      case 0x60:
336      case 0x61:
337      case 0x62:
338      case 0x63:
339      case 0x64:
340      case 0x65:
341      case 0x66:
342      case 0x67:
343      {
344         device_t *tpi = space->machine().device("tpi6525");
345         LOG(( "DMAC: PC=%08x - TPI6525 Write(%d) - data = %04x\n", cpu_get_pc(&space->device()), (offset - 0x58), data ));
346         tpi6525_w(tpi, offset - 0x58, data);
347      }
348      break;
349
350      case 0x70:   /* DMA start strobe */
351      {
352         LOG(( "DMAC: PC=%08x - DMA Start Strobe\n", cpu_get_pc(&space->device()) ));
353         dmac_data.dma_timer->adjust(attotime::from_msec( CD_SECTOR_TIME ));
354      }
355      break;
356
357      case 0x71:   /* DMA stop strobe */
358      {
359         LOG(( "DMAC: PC=%08x - DMA Stop Strobe\n", cpu_get_pc(&space->device()) ));
360         dmac_data.dma_timer->reset(  );
361      }
362      break;
363
364      case 0x72:   /* Clear IRQ strobe */
365      {
366         LOG(( "DMAC: PC=%08x - IRQ Clear Strobe\n", cpu_get_pc(&space->device()) ));
367         dmac_data.istr &= ~ISTR_INT_P;
368      }
369      break;
370
371      case 0x74:   /* Flush Strobe */
372      {
373         LOG(( "DMAC: PC=%08x - Flush Strobe\n", cpu_get_pc(&space->device()) ));
374         dmac_data.istr |= ISTR_FE_FLG;
375      }
376      break;
377
378      default:
379         logerror( "DMAC-WRITE: PC=%08x, offset = %02x, data = %04x\n", cpu_get_pc(&space->device()), offset, data );
380      break;
381   }
382}
383
384/***************************************************************************
385
386    Autoconfig
387
388***************************************************************************/
389
390static void   dmac_install(running_machine &machine, offs_t base)
391{
392   address_space *space = machine.device("maincpu")->memory().space(AS_PROGRAM);
393   space->install_legacy_read_handler(base, base + 0xFFFF, FUNC(amiga_dmac_r));
394   space->install_legacy_write_handler(base, base + 0xFFFF, FUNC(amiga_dmac_w));
395}
396
397static void   dmac_uninstall(running_machine &machine, offs_t base)
398{
399   address_space *space = machine.device("maincpu")->memory().space(AS_PROGRAM);
400   space->unmap_readwrite(base, base + 0xFFFF);
401}
402
403static const amiga_autoconfig_device dmac_device =
404{
405   0,            /* link into free memory list */
406   0,            /* ROM vector offset valid */
407   0,            /* multiple devices on card */
408   1,            /* number of 64k pages */
409   3,            /* product number (DMAC) */
410   0,            /* prefer 8MB address space */
411   0,            /* can be shut up */
412   0x0202,         /* manufacturers number (Commodore) */
413   0,            /* serial number */
414   0,            /* ROM vector offset */
415   NULL,         /* interrupt control read */
416   NULL,         /* interrupt control write */
417   dmac_install,   /* memory installation */
418   dmac_uninstall   /* memory uninstallation */
419};
420
421/***************************************************************************
422
423    TPI6525
424
425***************************************************************************/
426
427READ8_DEVICE_HANDLER( amigacd_tpi6525_portc_r )
428{
429   int   ret = 0;
430
431   if ( (tpi6525_get_ddr_c(device) & 0x04) == 0 ) /* if pin 2 is set to input */
432   {
433      ret |= matsucd_stch_r() ? 0x00 : 0x04;   /* read status change signal */
434   }
435
436   if ( (tpi6525_get_ddr_c(device) & 0x08) == 0 ) /* if pin 3 is set to input */
437      ret |= matsucd_sten_r() ? 0x08 : 0x00;   /* read enable signal */
438
439   return ret;
440}
441
442WRITE8_DEVICE_HANDLER( amigacd_tpi6525_portb_w )
443{
444   if ( tpi6525_get_ddr_b(device) & 0x01 ) /* if pin 0 is set to output */
445      matsucd_cmd_w( data & 1 ); /* write to the /CMD signal */
446
447   if ( tpi6525_get_ddr_b(device) & 0x02 ) /* if pin 1 is set to output */
448      matsucd_enable_w( data & 2 ); /* write to the /ENABLE signal */
449}
450
451static emu_timer *tp6525_delayed_timer;
452
453static TIMER_CALLBACK(tp6525_delayed_irq)
454{
455   amiga_state *state = machine.driver_data<amiga_state>();
456   (void)param;
457
458   if ( (CUSTOM_REG(REG_INTREQ) & INTENA_PORTS) == 0 )
459   {
460      amiga_custom_w(machine.device("maincpu")->memory().space(AS_PROGRAM), REG_INTREQ, 0x8000 | INTENA_PORTS, 0xffff);
461   }
462   else
463   {
464      tp6525_delayed_timer->adjust(attotime::from_msec(1));
465   }
466}
467
468static void amigacd_tpi6525_irq_trampoline(device_t *device, int level)
469{
470   amiga_state *state = device->machine().driver_data<amiga_state>();
471   LOG(( "TPI6525 Interrupt: level = %d\n", level ));
472
473   if ( level )
474   {
475      if ( (CUSTOM_REG(REG_INTREQ) & INTENA_PORTS) == 0 )
476      {
477         amiga_custom_w(device->machine().device("maincpu")->memory().space(AS_PROGRAM), REG_INTREQ, 0x8000 | INTENA_PORTS, 0xffff);
478      }
479      else
480      {
481         /* we *have to* deliver the irq, so if we can't, delay it and try again later */
482         tp6525_delayed_timer->adjust(attotime::from_msec(1));
483      }
484   }
485}
486
487WRITE_LINE_DEVICE_HANDLER( amigacd_tpi6525_irq )
488{
489   amigacd_tpi6525_irq_trampoline(device, state);
490}
491
492static void cdrom_status_enabled( running_machine &machine, int level )
493{
494   device_t *tpi = machine.device("tpi6525");
495
496   /* PC3 on the 6525 */
497   tpi6525_i3_w(tpi, level);
498}
499
500static void cdrom_status_change( running_machine &machine, int level )
501{
502   device_t *tpi = machine.device("tpi6525");
503
504   /* invert */
505   level = level ? 0 : 1;
506
507   /* PC2 on the 6525 */
508   tpi6525_i2_w(tpi, level);
509}
510
511static void cdrom_subcode_ready( running_machine &machine, int level )
512{
513   device_t *tpi = machine.device("tpi6525");
514
515   /* PC1 on the 6525 */
516   tpi6525_i1_w(tpi, level);
517}
518
519MACHINE_START( amigacd )
520{
521   /* initialize the dmac */
522   memset( &dmac_data, 0, sizeof( dmac_data ) );
523
524   dmac_data.dma_timer = machine.scheduler().timer_alloc(FUNC(dmac_dma_proc));
525   tp6525_delayed_timer = machine.scheduler().timer_alloc(FUNC(tp6525_delayed_irq));
526
527   /* set up DMAC with autoconfig */
528   amiga_add_autoconfig( machine, &dmac_device );
529
530   matsucd_init( machine.device("cdrom"), "cdda" );
531}
532
533MACHINE_RESET( amigacd )
534{
535   /* initialize the cdrom */
536   matsucd_set_status_enabled_callback( cdrom_status_enabled );
537   matsucd_set_status_changed_callback( cdrom_status_change );
538   matsucd_set_subcode_ready_callback( cdrom_subcode_ready );
539}
src/mess/machine/nes.c
r0r11532
1#include "emu.h"
2#include "crsshair.h"
3#include "hash.h"
4#include "cpu/m6502/m6502.h"
5#include "video/ppu2c0x.h"
6#include "includes/nes.h"
7#include "machine/nes_mmc.h"
8#include "imagedev/cartslot.h"
9#include "imagedev/flopdrv.h"
10#include "hashfile.h"
11
12/***************************************************************************
13    CONSTANTS
14***************************************************************************/
15
16/* Set to dump info about the inputs to the errorlog */
17#define LOG_JOY      0
18
19/* Set to generate prg & chr files when the cart is loaded */
20#define SPLIT_PRG   0
21#define SPLIT_CHR   0
22
23/***************************************************************************
24    FUNCTION PROTOTYPES
25***************************************************************************/
26
27static void init_nes_core(running_machine &machine);
28static void nes_machine_stop(running_machine &machine);
29static READ8_HANDLER(nes_fds_r);
30static WRITE8_HANDLER(nes_fds_w);
31static void fds_irq(device_t *device, int scanline, int vblank, int blanked);
32
33/***************************************************************************
34    FUNCTIONS
35***************************************************************************/
36
37static void init_nes_core( running_machine &machine )
38{
39   nes_state *state = machine.driver_data<nes_state>();
40   address_space *space = machine.device("maincpu")->memory().space(AS_PROGRAM);
41   static const char *const bank_names[] = { "bank1", "bank2", "bank3", "bank4" };
42   int prg_banks = (state->m_prg_chunks == 1) ? (2 * 2) : (state->m_prg_chunks * 2);
43   int i;
44
45   /* We set these here in case they weren't set in the cart loader */
46   state->m_rom = machine.region("maincpu")->base();
47   state->m_vrom = machine.region("gfx1")->base();
48   state->m_vram = machine.region("gfx2")->base();
49   state->m_ciram = machine.region("gfx3")->base();
50
51   /* Brutal hack put in as a consequence of the new memory system; we really need to fix the NES code */
52   space->install_readwrite_bank(0x0000, 0x07ff, 0, 0x1800, "bank10");
53
54   machine.device("ppu")->memory().space(AS_PROGRAM)->install_legacy_readwrite_handler(0, 0x1fff, FUNC(nes_chr_r), FUNC(nes_chr_w));
55   machine.device("ppu")->memory().space(AS_PROGRAM)->install_legacy_readwrite_handler(0x2000, 0x3eff, FUNC(nes_nt_r), FUNC(nes_nt_w));
56
57   memory_set_bankptr(machine, "bank10", state->m_rom);
58
59   /* If there is Disk Expansion and no cart has been loaded, setup memory accordingly */
60   if (state->m_disk_expansion && state->m_pcb_id == NO_BOARD)
61   {
62      /* If we are loading a disk we have already filled state->m_fds_data and we don't want to overwrite it,
63         if we are loading a cart image identified as mapper 20 (probably wrong mapper...) we need to alloc
64         memory for use in nes_fds_r/nes_fds_w. Same goes for allocation of fds_ram (used for bank2)  */
65      if (state->m_fds_data == NULL)
66      {
67         UINT32 size = machine.region("maincpu")->bytes() - 0x10000;
68         state->m_fds_data = auto_alloc_array_clear(machine, UINT8, size);
69         memcpy(state->m_fds_data, state->m_rom, size);   // copy in fds_data the cart PRG
70      }
71      if (state->m_fds_ram == NULL)
72         state->m_fds_ram = auto_alloc_array(machine, UINT8, 0x8000);
73
74      space->install_legacy_read_handler(0x4030, 0x403f, FUNC(nes_fds_r));
75      space->install_read_bank(0x6000, 0xdfff, "bank2");
76      space->install_read_bank(0xe000, 0xffff, "bank1");
77
78      space->install_legacy_write_handler(0x4020, 0x402f, FUNC(nes_fds_w));
79      space->install_write_bank(0x6000, 0xdfff, "bank2");
80
81      memory_set_bankptr(machine, "bank1", &state->m_rom[0xe000]);
82      memory_set_bankptr(machine, "bank2", state->m_fds_ram);
83      return;
84   }
85
86   /* Set up the mapper callbacks */
87   pcb_handlers_setup(machine);
88
89   /* Set up the memory handlers for the mapper */
90   space->install_read_bank(0x8000, 0x9fff, "bank1");
91   space->install_read_bank(0xa000, 0xbfff, "bank2");
92   space->install_read_bank(0xc000, 0xdfff, "bank3");
93   space->install_read_bank(0xe000, 0xffff, "bank4");
94   space->install_readwrite_bank(0x6000, 0x7fff, "bank5");
95
96   /* configure banks 1-4 */
97   for (i = 0; i < 4; i++)
98   {
99      memory_configure_bank(machine, bank_names[i], 0, prg_banks, machine.region("maincpu")->base() + 0x10000, 0x2000);
100      // some mappers (e.g. MMC5) can map PRG RAM in  0x8000-0xffff as well
101      if (state->m_prg_ram)
102         memory_configure_bank(machine, bank_names[i], prg_banks, state->m_wram_size / 0x2000, state->m_wram, 0x2000);
103      // however, at start we point to PRG ROM
104      memory_set_bank(machine, bank_names[i], i);
105      state->m_prg_bank[i] = i;
106   }
107
108   /* bank 5 configuration is more delicate, since it can have PRG RAM, PRG ROM or SRAM mapped to it */
109   /* we first map PRG ROM banks, then the battery bank (if a battery is present), and finally PRG RAM (state->m_wram) */
110   memory_configure_bank(machine, "bank5", 0, prg_banks, machine.region("maincpu")->base() + 0x10000, 0x2000);
111   state->m_battery_bank5_start = prg_banks;
112   state->m_prgram_bank5_start = prg_banks;
113   state->m_empty_bank5_start = prg_banks;
114
115   /* add battery ram, but only if there's no trainer since they share overlapping memory. */
116   if (state->m_battery && !state->m_trainer)
117   {
118      UINT32 bank_size = (state->m_battery_size > 0x2000) ? 0x2000 : state->m_battery_size;
119      int bank_num = (state->m_battery_size > 0x2000) ? state->m_battery_size / 0x2000 : 1;
120      memory_configure_bank(machine, "bank5", prg_banks, bank_num, state->m_battery_ram, bank_size);
121      state->m_prgram_bank5_start += bank_num;
122      state->m_empty_bank5_start += bank_num;
123   }
124   /* add prg ram. */
125   if (state->m_prg_ram)
126   {
127      memory_configure_bank(machine, "bank5", state->m_prgram_bank5_start, state->m_wram_size / 0x2000, state->m_wram, 0x2000);
128      state->m_empty_bank5_start += state->m_wram_size / 0x2000;
129   }
130
131   memory_configure_bank(machine, "bank5", state->m_empty_bank5_start, 1, state->m_rom + 0x6000, 0x2000);
132
133   /* if we have any additional PRG RAM, point bank5 to its first bank */
134   if (state->m_battery || state->m_prg_ram)
135      state->m_prg_bank[4] = state->m_battery_bank5_start;
136   else
137      state->m_prg_bank[4] = state->m_empty_bank5_start; // or shall we point to "maincpu" region at 0x6000? point is that we should never access this region if no sram or wram is present!
138
139   memory_set_bank(machine, "bank5", state->m_prg_bank[4]);
140
141   if (state->m_four_screen_vram)
142   {
143      state->m_extended_ntram = auto_alloc_array(machine, UINT8, 0x2000);
144      state->save_pointer(NAME(state->m_extended_ntram), 0x2000);
145   }
146
147   // there are still some quirk about writes to bank5... I hope to fix them soon. (mappers 34,45,52,246 have both mid_w and WRAM-->check)
148   if (state->m_mmc_write_mid)
149      space->install_legacy_write_handler(0x6000, 0x7fff, state->m_mmc_write_mid,state->m_mmc_write_mid_name);
150   if (state->m_mmc_write)
151      space->install_legacy_write_handler(0x8000, 0xffff, state->m_mmc_write, state->m_mmc_write_name);
152
153   // In fact, we also allow single pcbs to overwrite the bank read handlers defined above,
154   // because some pcbs (mainly pirate ones) require protection values to be read instead of
155   // the expected ROM banks: these handlers, though, must take care of the ROM access as well
156   if (state->m_mmc_read_mid)
157      space->install_legacy_read_handler(0x6000, 0x7fff, state->m_mmc_read_mid,state->m_mmc_read_mid_name);
158   if (state->m_mmc_read)
159      space->install_legacy_read_handler(0x8000, 0xffff, state->m_mmc_read,state->m_mmc_read_name);
160
161   // install additional handlers
162   if (state->m_pcb_id == BTL_SMB2B || state->m_mapper == 50)
163   {
164      space->install_legacy_write_handler(0x4020, 0x403f, FUNC(smb2jb_extra_w));
165      space->install_legacy_write_handler(0x40a0, 0x40bf, FUNC(smb2jb_extra_w));
166   }
167
168   if (state->m_pcb_id == KAISER_KS7017)
169   {
170      space->install_legacy_read_handler(0x4030, 0x4030, FUNC(ks7017_extra_r));
171      space->install_legacy_write_handler(0x4020, 0x40ff, FUNC(ks7017_extra_w));
172   }
173
174   if (state->m_pcb_id == UNL_603_5052)
175   {
176      space->install_legacy_read_handler(0x4020, 0x40ff, FUNC(unl_6035052_extra_r));
177      space->install_legacy_write_handler(0x4020, 0x40ff, FUNC(unl_6035052_extra_w));
178   }
179
180   if (state->m_pcb_id == WAIXING_SH2)
181      machine.device("ppu")->memory().space(AS_PROGRAM)->install_legacy_read_handler(0, 0x1fff, FUNC(waixing_sh2_chr_r));
182}
183
184// to be probably removed (it does nothing since a long time)
185int nes_ppu_vidaccess( device_t *device, int address, int data )
186{
187   return data;
188}
189
190MACHINE_RESET( nes )
191{
192   nes_state *state = machine.driver_data<nes_state>();
193
194   /* Reset the mapper variables. Will also mark the char-gen ram as dirty */
195   if (state->m_disk_expansion && state->m_pcb_id == NO_BOARD)
196      ppu2c0x_set_hblank_callback(state->m_ppu, fds_irq);
197   else
198      nes_pcb_reset(machine);
199
200   /* Reset the serial input ports */
201   state->m_in_0.shift = 0;
202   state->m_in_1.shift = 0;
203
204   machine.device("maincpu")->reset();
205}
206
207static TIMER_CALLBACK( nes_irq_callback )
208{
209   nes_state *state = machine.driver_data<nes_state>();
210   device_set_input_line(state->m_maincpu, M6502_IRQ_LINE, HOLD_LINE);
211   state->m_irq_timer->adjust(attotime::never);
212}
213
214static void nes_banks_restore(nes_state *state)
215{
216   memory_set_bank(state->machine(), "bank1", state->m_prg_bank[0]);
217   memory_set_bank(state->machine(), "bank2", state->m_prg_bank[1]);
218   memory_set_bank(state->machine(), "bank3", state->m_prg_bank[2]);
219   memory_set_bank(state->machine(), "bank4", state->m_prg_bank[3]);
220   memory_set_bank(state->machine(), "bank5", state->m_prg_bank[4]);
221}
222
223static void nes_state_register( running_machine &machine )
224{
225   nes_state *state = machine.driver_data<nes_state>();
226
227   state->save_item(NAME(state->m_prg_bank));
228
229   state->save_item(NAME(state->m_MMC5_floodtile));
230   state->save_item(NAME(state->m_MMC5_floodattr));
231   state->save_item(NAME(state->m_mmc5_vram_control));
232
233   state->save_item(NAME(state->m_nes_vram_sprite));
234   state->save_item(NAME(state->m_last_frame_flip));
235
236   // shared mapper variables
237   state->save_item(NAME(state->m_IRQ_enable));
238   state->save_item(NAME(state->m_IRQ_enable_latch));
239   state->save_item(NAME(state->m_IRQ_count));
240   state->save_item(NAME(state->m_IRQ_count_latch));
241   state->save_item(NAME(state->m_IRQ_toggle));
242   state->save_item(NAME(state->m_IRQ_reset));
243   state->save_item(NAME(state->m_IRQ_status));
244   state->save_item(NAME(state->m_IRQ_mode));
245   state->save_item(NAME(state->m_mult1));
246   state->save_item(NAME(state->m_mult2));
247   state->save_item(NAME(state->m_mmc_chr_source));
248   state->save_item(NAME(state->m_mmc_cmd1));
249   state->save_item(NAME(state->m_mmc_cmd2));
250   state->save_item(NAME(state->m_mmc_count));
251   state->save_item(NAME(state->m_mmc_prg_base));
252   state->save_item(NAME(state->m_mmc_prg_mask));
253   state->save_item(NAME(state->m_mmc_chr_base));
254   state->save_item(NAME(state->m_mmc_chr_mask));
255   state->save_item(NAME(state->m_mmc_prg_bank));
256   state->save_item(NAME(state->m_mmc_vrom_bank));
257   state->save_item(NAME(state->m_mmc_extra_bank));
258
259   state->save_item(NAME(state->m_fds_motor_on));
260   state->save_item(NAME(state->m_fds_door_closed));
261   state->save_item(NAME(state->m_fds_current_side));
262   state->save_item(NAME(state->m_fds_head_position));
263   state->save_item(NAME(state->m_fds_status0));
264   state->save_item(NAME(state->m_fds_read_mode));
265   state->save_item(NAME(state->m_fds_write_reg));
266   state->save_item(NAME(state->m_fds_last_side));
267   state->save_item(NAME(state->m_fds_count));
268
269   state->save_pointer(NAME(state->m_wram), state->m_wram_size);
270   if (state->m_battery)
271      state->save_pointer(NAME(state->m_battery_ram), state->m_battery_size);
272
273   machine.save().register_postload(save_prepost_delegate(FUNC(nes_banks_restore), state));
274}
275
276MACHINE_START( nes )
277{
278   nes_state *state = machine.driver_data<nes_state>();
279
280   init_nes_core(machine);
281   machine.add_notifier(MACHINE_NOTIFY_EXIT, machine_notify_delegate(FUNC(nes_machine_stop),&machine));
282
283   state->m_maincpu = machine.device("maincpu");
284   state->m_ppu = machine.device("ppu");
285   state->m_sound = machine.device("nessound");
286   state->m_cart = machine.device("cart");
287
288   state->m_irq_timer = machine.scheduler().timer_alloc(FUNC(nes_irq_callback));
289   nes_state_register(machine);
290}
291
292static void nes_machine_stop( running_machine &machine )
293{
294   nes_state *state = machine.driver_data<nes_state>();
295   device_image_interface *image = dynamic_cast<device_image_interface *>(state->m_cart);
296   /* Write out the battery file if necessary */
297   if (state->m_battery)
298      image->battery_save(state->m_battery_ram, state->m_battery_size);
299
300   if (state->m_mapper_bram_size)
301      image->battery_save(state->m_mapper_bram, state->m_mapper_bram_size);
302}
303
304
305
306READ8_HANDLER( nes_IN0_r )
307{
308   nes_state *state = space->machine().driver_data<nes_state>();
309   int cfg = input_port_read(space->machine(), "CTRLSEL");
310   int ret;
311
312   if ((cfg & 0x000f) >= 0x07)   // for now we treat the FC keyboard separately from other inputs!
313   {
314      // here we should have the tape input
315      ret = 0;
316   }
317   else
318   {
319      /* Some games expect bit 6 to be set because the last entry on the data bus shows up */
320      /* in the unused upper 3 bits, so typically a read from $4016 leaves 0x40 there. */
321      ret = 0x40;
322
323      ret |= ((state->m_in_0.i0 >> state->m_in_0.shift) & 0x01);
324
325      /* zapper */
326      if ((cfg & 0x000f) == 0x0002)
327      {
328         int x = state->m_in_0.i1;   /* read Zapper x-position */
329         int y = state->m_in_0.i2;   /* read Zapper y-position */
330         UINT32 pix, color_base;
331
332         /* get the pixel at the gun position */
333         pix = ppu2c0x_get_pixel(state->m_ppu, x, y);
334
335         /* get the color base from the ppu */
336         color_base = ppu2c0x_get_colorbase(state->m_ppu);
337
338         /* look at the screen and see if the cursor is over a bright pixel */
339         if ((pix == color_base + 0x20) || (pix == color_base + 0x30) ||
340            (pix == color_base + 0x33) || (pix == color_base + 0x34))
341         {
342            ret &= ~0x08; /* sprite hit */
343         }
344         else
345            ret |= 0x08;  /* no sprite hit */
346
347         /* If button 1 is pressed, indicate the light gun trigger is pressed */
348         ret |= ((state->m_in_0.i0 & 0x01) << 4);
349      }
350
351      if (LOG_JOY)
352         logerror("joy 0 read, val: %02x, pc: %04x, bits read: %d, chan0: %08x\n", ret, cpu_get_pc(&space->device()), state->m_in_0.shift, state->m_in_0.i0);
353
354      state->m_in_0.shift++;
355   }
356
357   return ret;
358}
359
360// row of the keyboard matrix are read 4-bits at time, and gets returned as bit1->bit4
361static UINT8 nes_read_fc_keyboard_line( running_machine &machine, UINT8 scan, UINT8 mode )
362{
363   static const char *const fc_keyport_names[] = { "FCKEY0", "FCKEY1", "FCKEY2", "FCKEY3", "FCKEY4", "FCKEY5", "FCKEY6", "FCKEY7", "FCKEY8" };
364   return ((input_port_read(machine, fc_keyport_names[scan]) >> (mode * 4)) & 0x0f) << 1;
365}
366
367static UINT8 nes_read_subor_keyboard_line( running_machine &machine, UINT8 scan, UINT8 mode )
368{
369   static const char *const sub_keyport_names[] = { "SUBKEY0", "SUBKEY1", "SUBKEY2", "SUBKEY3", "SUBKEY4",
370      "SUBKEY5", "SUBKEY6", "SUBKEY7", "SUBKEY8", "SUBKEY9", "SUBKEY10", "SUBKEY11", "SUBKEY12" };
371   return ((input_port_read(machine, sub_keyport_names[scan]) >> (mode * 4)) & 0x0f) << 1;
372}
373
374READ8_HANDLER( nes_IN1_r )
375{
376   nes_state *state = space->machine().driver_data<nes_state>();
377   int cfg = input_port_read(space->machine(), "CTRLSEL");
378   int ret;
379
380   if ((cfg & 0x000f) == 0x07)   // for now we treat the FC keyboard separately from other inputs!
381   {
382      if (state->m_fck_scan < 9)
383         ret = ~nes_read_fc_keyboard_line(space->machine(), state->m_fck_scan, state->m_fck_mode) & 0x1e;
384      else
385         ret = 0x1e;
386   }
387   else if ((cfg & 0x000f) == 0x08)   // for now we treat the Subor keyboard separately from other inputs!
388   {
389      if (state->m_fck_scan < 12)
390         ret = ~nes_read_subor_keyboard_line(space->machine(), state->m_fck_scan, state->m_fck_mode) & 0x1e;
391      else
392         ret = 0x1e;
393   }
394   else
395   {
396      /* Some games expect bit 6 to be set because the last entry on the data bus shows up */
397      /* in the unused upper 3 bits, so typically a read from $4017 leaves 0x40 there. */
398      ret = 0x40;
399
400      /* Handle data line 0's serial output */
401      ret |= ((state->m_in_1.i0 >> state->m_in_1.shift) & 0x01);
402
403      /* zapper */
404      if ((cfg & 0x00f0) == 0x0030)
405      {
406         int x = state->m_in_1.i1;   /* read Zapper x-position */
407         int y = state->m_in_1.i2;   /* read Zapper y-position */
408         UINT32 pix, color_base;
409
410         /* get the pixel at the gun position */
411         pix = ppu2c0x_get_pixel(state->m_ppu, x, y);
412
413         /* get the color base from the ppu */
414         color_base = ppu2c0x_get_colorbase(state->m_ppu);
415
416         /* look at the screen and see if the cursor is over a bright pixel */
417         if ((pix == color_base + 0x20) || (pix == color_base + 0x30) ||
418            (pix == color_base + 0x33) || (pix == color_base + 0x34))
419         {
420            ret &= ~0x08; /* sprite hit */
421         }
422         else
423            ret |= 0x08;  /* no sprite hit */
424
425         /* If button 1 is pressed, indicate the light gun trigger is pressed */
426         ret |= ((state->m_in_1.i0 & 0x01) << 4);
427      }
428
429      /* arkanoid dial */
430      else if ((cfg & 0x00f0) == 0x0040)
431      {
432         /* Handle data line 2's serial output */
433         ret |= ((state->m_in_1.i2 >> state->m_in_1.shift) & 0x01) << 3;
434
435         /* Handle data line 3's serial output - bits are reversed */
436         /* NPW 27-Nov-2007 - there is no third subscript! commenting out */
437         /* ret |= ((state->m_in_1[3] >> state->m_in_1.shift) & 0x01) << 4; */
438         /* ret |= ((state->m_in_1[3] << state->m_in_1.shift) & 0x80) >> 3; */
439      }
440
441      if (LOG_JOY)
442         logerror("joy 1 read, val: %02x, pc: %04x, bits read: %d, chan0: %08x\n", ret, cpu_get_pc(&space->device()), state->m_in_1.shift, state->m_in_1.i0);
443
444      state->m_in_1.shift++;
445   }
446
447   return ret;
448}
449
450
451// FIXME: this is getting messier and messier (no pun intended). inputs reading should be simplified and port_categories cleaned up
452// to also emulate the fact that nothing should be in Port 2 if there is a Crazy Climber pad, etc.
453static void nes_read_input_device( running_machine &machine, int cfg, nes_input *vals, int pad_port, int supports_zapper )
454{
455   nes_state *state = machine.driver_data<nes_state>();
456   static const char *const padnames[] = { "PAD1", "PAD2", "PAD3", "PAD4", "CC_LEFT", "CC_RIGHT" };
457
458   vals->i0 = 0;
459   vals->i1 = 0;
460   vals->i2 = 0;
461
462   switch (cfg & 0x0f)
463   {
464      case 0x01:   /* gamepad */
465         if (pad_port >= 0)
466            vals->i0 = input_port_read(machine, padnames[pad_port]);
467         break;
468
469      case 0x02:   /* zapper 1 */
470         if (supports_zapper)
471         {
472            vals->i0 = input_port_read(machine, "ZAPPER1_T");
473            vals->i1 = input_port_read(machine, "ZAPPER1_X");
474            vals->i2 = input_port_read(machine, "ZAPPER1_Y");
475         }
476         break;
477
478      case 0x03:   /* zapper 2 */
479         if (supports_zapper)
480         {
481            vals->i0 = input_port_read(machine, "ZAPPER2_T");
482            vals->i1 = input_port_read(machine, "ZAPPER2_X");
483            vals->i2 = input_port_read(machine, "ZAPPER2_Y");
484         }
485         break;
486
487      case 0x04:   /* arkanoid paddle */
488         if (pad_port == 1)
489            vals->i0 = (UINT8) ((UINT8) input_port_read(machine, "PADDLE") + (UINT8)0x52) ^ 0xff;
490         break;
491
492      case 0x05:   /* crazy climber controller */
493         if (pad_port == 0)
494         {
495            state->m_in_0.i0 = input_port_read(machine, padnames[4]);
496            state->m_in_1.i0 = input_port_read(machine, padnames[5]);
497         }
498         break;
499   }
500}
501
502
503static TIMER_CALLBACK( lightgun_tick )
504{
505   if ((input_port_read(machine, "CTRLSEL") & 0x000f) == 0x0002)
506   {
507      /* enable lightpen crosshair */
508      crosshair_set_screen(machine, 0, CROSSHAIR_SCREEN_ALL);
509   }
510   else
511   {
512      /* disable lightpen crosshair */
513      crosshair_set_screen(machine, 0, CROSSHAIR_SCREEN_NONE);
514   }
515
516   if ((input_port_read(machine, "CTRLSEL") & 0x00f0) == 0x0030)
517   {
518      /* enable lightpen crosshair */
519      crosshair_set_screen(machine, 1, CROSSHAIR_SCREEN_ALL);
520   }
521   else
522   {
523      /* disable lightpen crosshair */
524      crosshair_set_screen(machine, 1, CROSSHAIR_SCREEN_NONE);
525   }
526}
527
528WRITE8_HANDLER( nes_IN0_w )
529{
530   nes_state *state = space->machine().driver_data<nes_state>();
531   int cfg = input_port_read(space->machine(), "CTRLSEL");
532
533   /* Check if lightgun has been chosen as input: if so, enable crosshair */
534   space->machine().scheduler().timer_set(attotime::zero, FUNC(lightgun_tick));
535
536   if ((cfg & 0x000f) >= 0x07)   // for now we treat the FC keyboard separately from other inputs!
537   {
538      // here we should also have the tape output
539
540      if (BIT(data, 2))   // keyboard active
541      {
542         int lines = ((cfg & 0x000f) == 0x04) ? 9 : 12;
543         UINT8 out = BIT(data, 1);   // scan
544
545         if (state->m_fck_mode && !out && ++state->m_fck_scan > lines)
546            state->m_fck_scan = 0;
547
548         state->m_fck_mode = out;   // access lower or upper 4 bits
549
550         if (BIT(data, 0))   // reset
551            state->m_fck_scan = 0;
552      }
553   }
554   else
555   {
556      if (data & 0x01)
557         return;
558
559      if (LOG_JOY)
560         logerror("joy 0 bits read: %d\n", state->m_in_0.shift);
561
562      /* Toggling bit 0 high then low resets both controllers */
563      state->m_in_0.shift = 0;
564      state->m_in_1.shift = 0;
565
566      /* Read the input devices */
567      if ((cfg & 0x000f) != 0x06)
568      {
569         nes_read_input_device(space->machine(), cfg >>  0, &state->m_in_0, 0,  TRUE);
570         nes_read_input_device(space->machine(), cfg >>  4, &state->m_in_1, 1,  TRUE);
571         nes_read_input_device(space->machine(), cfg >>  8, &state->m_in_2, 2, FALSE);
572         nes_read_input_device(space->machine(), cfg >> 12, &state->m_in_3, 3, FALSE);
573      }
574      else // crazy climber pad
575      {
576         nes_read_input_device(space->machine(), 0, &state->m_in_1, 1,  TRUE);
577         nes_read_input_device(space->machine(), 0, &state->m_in_2, 2, FALSE);
578         nes_read_input_device(space->machine(), 0, &state->m_in_3, 3, FALSE);
579         nes_read_input_device(space->machine(), cfg >>  0, &state->m_in_0, 0,  TRUE);
580      }
581
582      if (cfg & 0x0f00)
583         state->m_in_0.i0 |= (state->m_in_2.i0 << 8) | (0x08 << 16);
584
585      if (cfg & 0xf000)
586         state->m_in_1.i0 |= (state->m_in_3.i0 << 8) | (0x04 << 16);
587   }
588}
589
590
591WRITE8_HANDLER( nes_IN1_w )
592{
593}
594
595struct nes_cart_lines
596{
597   const char *tag;
598   int line;
599};
600
601static const struct nes_cart_lines nes_cart_lines_table[] =
602{
603   { "PRG A0",    0 },
604   { "PRG A1",    1 },
605   { "PRG A2",    2 },
606   { "PRG A3",    3 },
607   { "PRG A4",    4 },
608   { "PRG A5",    5 },
609   { "PRG A6",    6 },
610   { "PRG A7",    7 },
611   { "CHR A10",  10 },
612   { "CHR A11",  11 },
613   { "CHR A12",  12 },
614   { "CHR A13",  13 },
615   { "CHR A14",  14 },
616   { "CHR A15",  15 },
617   { "CHR A16",  16 },
618   { "CHR A17",  17 },
619   { "NC",      127 },
620   { 0 }
621};
622
623static int nes_cart_get_line( const char *feature )
624{
625   const struct nes_cart_lines *nes_line = &nes_cart_lines_table[0];
626
627   if (feature == NULL)
628      return 128;
629
630   while (nes_line->tag)
631   {
632      if (strcmp(nes_line->tag, feature) == 0)
633         break;
634
635      nes_line++;
636   }
637
638   return nes_line->line;
639}
640
641DEVICE_IMAGE_LOAD( nes_cart )
642{
643   nes_state *state = image.device().machine().driver_data<nes_state>();
644   state->m_pcb_id = NO_BOARD;   // initialization
645
646   if (image.software_entry() == NULL)
647   {
648      const char *mapinfo = NULL;
649      int mapint1 = 0, mapint2 = 0, mapint3 = 0, mapint4 = 0, goodcrcinfo = 0;
650      char magic[4], extend[5];
651      int local_options = 0;
652      char m;
653
654      /* Check first 4 bytes of the image to decide if it is UNIF or iNES */
655      /* Unfortunately, many .unf files have been released as .nes, so we cannot rely on extensions only */
656      memset(magic, '\0', sizeof(magic));
657      image.fread(magic, 4);
658
659      if ((magic[0] == 'N') && (magic[1] == 'E') && (magic[2] == 'S'))   /* If header starts with 'NES' it is iNES */
660      {
661         UINT32 prg_size;
662         state->m_ines20 = 0;
663         state->m_battery_size = NES_BATTERY_SIZE; // with iNES we can only support 8K WRAM battery (iNES 2.0 might fix this)
664         state->m_prg_ram = 1;   // always map state->m_wram in bank5 (eventually, this should be enabled only for some mappers)
665
666         // check if the image is recognized by nes.hsi
667         mapinfo = hashfile_extrainfo(image);
668
669         // image_extrainfo() resets the file position back to start.
670         // Let's skip past the magic header once again.
671         image.fseek(4, SEEK_SET);
672
673         image.fread(&state->m_prg_chunks, 1);
674         image.fread(&state->m_chr_chunks, 1);
675         /* Read the first ROM option byte (offset 6) */
676         image.fread(&m, 1);
677
678         /* Interpret the iNES header flags */
679         state->m_mapper = (m & 0xf0) >> 4;
680         local_options = m & 0x0f;
681
682         /* Read the second ROM option byte (offset 7) */
683         image.fread(&m, 1);
684
685         switch (m & 0xc)
686         {
687            case 0x4:
688            case 0xc:
689               // probably the header got corrupted: don't trust upper bits for mapper
690               break;
691
692            case 0x8:   // it's iNES 2.0 format
693               state->m_ines20 = 1;
694            case 0x0:
695            default:
696               state->m_mapper = state->m_mapper | (m & 0xf0);
697               break;
698         }
699
700         if (mapinfo /* && !state->m_ines20 */)
701         {
702            if (4 == sscanf(mapinfo,"%d %d %d %d", &mapint1, &mapint2, &mapint3, &mapint4))
703            {
704               /* image is present in nes.hsi: overwrite the header settings with these */
705               state->m_mapper = mapint1;
706               local_options = mapint2 & 0x0f;
707               state->m_crc_hack = (mapint2 & 0xf0) >> 4;   // this is used to differentiate among variants of the same Mapper (see below)
708               state->m_prg_chunks = mapint3;
709               state->m_chr_chunks = mapint4;
710               logerror("NES.HSI info: %d %d %d %d\n", mapint1, mapint2, mapint3, mapint4);
711//                  mame_printf_error("NES.HSI info: %d %d %d %d\n", mapint1, mapint2, mapint3, mapint4);
712               goodcrcinfo = 1;
713               state->m_ines20 = 0;
714            }
715            else
716            {
717               logerror("NES: [%s], Invalid mapinfo found\n", mapinfo);
718            }
719         }
720         else
721         {
722            logerror("NES: No extrainfo found\n");
723         }
724
725         state->m_hard_mirroring = (local_options & 0x01) ? PPU_MIRROR_VERT : PPU_MIRROR_HORZ;
726//          mame_printf_error("%s\n", state->m_hard_mirroring & 0x01 ? "Vertical" : "Horizontal");
727         state->m_battery = local_options & 0x02;
728         state->m_trainer = local_options & 0x04;
729         state->m_four_screen_vram = local_options & 0x08;
730
731         if (state->m_battery)
732            logerror("-- Battery found\n");
733
734         if (state->m_trainer)
735            logerror("-- Trainer found\n");
736
737         if (state->m_four_screen_vram)
738            logerror("-- 4-screen VRAM\n");
739
740         if (state->m_ines20)
741         {
742            logerror("Extended iNES format:\n");
743            image.fread(&extend, 5);
744            state->m_mapper |= (extend[0] & 0x0f) << 8;
745            logerror("-- mapper: %d\n", state->m_mapper);
746            logerror("-- submapper: %d\n", (extend[0] & 0xf0) >> 4);
747            state->m_prg_chunks |= ((extend[1] & 0x0f) << 8);
748            state->m_chr_chunks |= ((extend[1] & 0xf0) << 4);
749            logerror("-- PRG chunks: %d\n", state->m_prg_chunks);
750            logerror("-- CHR chunks: %d\n", state->m_chr_chunks);
751            logerror("-- PRG NVWRAM: %d\n", extend[2] & 0x0f);
752            logerror("-- PRG WRAM: %d\n", (extend[2] & 0xf0) >> 4);
753            logerror("-- CHR NVWRAM: %d\n", extend[3] & 0x0f);
754            logerror("-- CHR WRAM: %d\n", (extend[3] & 0xf0) >> 4);
755            logerror("-- TV System: %d\n", extend[4] & 3);
756         }
757
758         /* Free the regions that were allocated by the ROM loader */
759         image.device().machine().region_free("maincpu");
760         image.device().machine().region_free("gfx1");
761
762         /* Allocate them again with the proper size */
763         prg_size = (state->m_prg_chunks == 1) ? 2 * 0x4000 : state->m_prg_chunks * 0x4000;
764         image.device().machine().region_alloc("maincpu", 0x10000 + prg_size, 1, ENDIANNESS_LITTLE);
765         if (state->m_chr_chunks)
766            image.device().machine().region_alloc("gfx1", state->m_chr_chunks * 0x2000, 1, ENDIANNESS_LITTLE);
767
768         state->m_rom = image.device().machine().region("maincpu")->base();
769         state->m_vrom = image.device().machine().region("gfx1")->base();
770
771         state->m_vram_chunks = image.device().machine().region("gfx2")->bytes() / 0x2000;
772         state->m_vram = image.device().machine().region("gfx2")->base();
773         // FIXME: this should only be allocated if there is actual wram in the cart (i.e. if state->m_prg_ram = 1)!
774         // or if there is a trainer, I think
775         state->m_wram_size = 0x10000;
776         state->m_wram = auto_alloc_array(image.device().machine(), UINT8, state->m_wram_size);
777
778         /* Setup PCB type (needed to add proper handlers later) */
779         state->m_pcb_id = nes_get_mmc_id(image.device().machine(), state->m_mapper);
780
781         // a few mappers correspond to multiple PCBs, so we need a few additional checks
782         switch (state->m_pcb_id)
783         {
784            case STD_CNROM:
785               if (state->m_mapper == 185)
786               {
787                  switch (state->m_crc_hack)
788                  {
789                     case 0x0: // pin26: CE, pin27: CE (B-Wings, Bird Week)
790                        state->m_ce_mask = 0x03;
791                        state->m_ce_state = 0x03;
792                        break;
793                     case 0x4: // pin26: CE, pin27: /CE (Mighty Bomb Jack, Spy Vs. Spy)
794                        state->m_ce_mask = 0x03;
795                        state->m_ce_state = 0x01;
796                        break;
797                     case 0x8: // pin26: /CE, pin27: CE (Sansu 1, 2, 3 Nen)
798                        state->m_ce_mask = 0x03;
799                        state->m_ce_state = 0x02;
800                        break;
801                     case 0xc: // pin26: /CE, pin27: /CE (Seicross v2.0)
802                        state->m_ce_mask = 0x03;
803                        state->m_ce_state = 0x00;
804                        break;
805                  }
806               }
807               break;
808            case KONAMI_VRC2:
809               if (state->m_mapper == 22)
810               {
811                  state->m_vrc_ls_prg_a = 0;
812                  state->m_vrc_ls_prg_b = 1;
813                  state->m_vrc_ls_chr = 1;
814               }
815               if (state->m_mapper == 23 && !state->m_crc_hack)
816               {
817                  state->m_vrc_ls_prg_a = 1;
818                  state->m_vrc_ls_prg_b = 0;
819                  state->m_vrc_ls_chr = 0;
820               }
821               if (state->m_mapper == 23 && state->m_crc_hack)
822               {
823                  // here there are also Akumajou Special, Crisis Force, Parodius da!, Tiny Toons which are VRC-4
824                  state->m_vrc_ls_prg_a = 3;
825                  state->m_vrc_ls_prg_b = 2;
826                  state->m_pcb_id = KONAMI_VRC4; // this allows for konami_irq to be installed at reset
827               }
828               break;
829            case KONAMI_VRC4:
830               if (state->m_mapper == 21)
831               {
832                  // Wai Wai World 2 & Ganbare Goemon Gaiden 2 (the latter with crc_hack)
833                  state->m_vrc_ls_prg_a = state->m_crc_hack ? 7 : 2;
834                  state->m_vrc_ls_prg_b = state->m_crc_hack ? 6 : 1;
835               }
836               if (state->m_mapper == 25)   // here there is also Ganbare Goemon Gaiden which is VRC-2
837               {
838                  state->m_vrc_ls_prg_a = state->m_crc_hack ? 2 : 0;
839                  state->m_vrc_ls_prg_b = state->m_crc_hack ? 3 : 1;
840               }
841               break;
842            case KONAMI_VRC6:
843               if (state->m_mapper == 24)
844               {
845                  state->m_vrc_ls_prg_a = 1;
846                  state->m_vrc_ls_prg_b = 0;
847               }
848               if (state->m_mapper == 26)
849               {
850                  state->m_vrc_ls_prg_a = 0;
851                  state->m_vrc_ls_prg_b = 1;
852               }
853               break;
854            case IREM_G101:
855               if (state->m_crc_hack)
856                  state->m_hard_mirroring = PPU_MIRROR_HIGH;   // Major League has hardwired mirroring
857               break;
858            case DIS_74X161X161X32:
859               if (state->m_mapper == 70)
860                  state->m_hard_mirroring = PPU_MIRROR_VERT;   // only hardwired mirroring makes different mappers 70 & 152
861               break;
862            case SUNSOFT_2:
863               if (state->m_mapper == 93)
864                  state->m_hard_mirroring = PPU_MIRROR_VERT;   // only hardwired mirroring makes different mappers 89 & 93
865               break;
866            case STD_BXROM:
867               if (state->m_crc_hack)
868                  state->m_pcb_id = AVE_NINA01;   // Mapper 34 is used for 2 diff boards
869               break;
870            case BANDAI_LZ93:
871               if (state->m_crc_hack)
872                  state->m_pcb_id = BANDAI_JUMP2;   // Mapper 153 is used for 2 diff boards
873               break;
874            case IREM_HOLYDIV:
875               if (state->m_crc_hack)
876                  state->m_pcb_id = JALECO_JF16;   // Mapper 78 is used for 2 diff boards
877               break;
878            case CAMERICA_BF9093:
879               if (state->m_crc_hack)
880                  state->m_pcb_id = CAMERICA_BF9097;   // Mapper 71 is used for 2 diff boards
881               break;
882            case HES_BOARD:
883               if (state->m_crc_hack)
884                  state->m_pcb_id = HES6IN1_BOARD;   // Mapper 113 is used for 2 diff boards
885               break;
886            case WAIXING_ZS:
887               if (state->m_crc_hack)
888                  state->m_pcb_id = WAIXING_DQ8;   // Mapper 242 is used for 2 diff boards
889               break;
890            //FIXME: we also have to fix Action 52 PRG loading somewhere...
891         }
892
893         /* Allocate internal Mapper RAM for boards which require it */
894         if (state->m_pcb_id == STD_EXROM)
895            state->m_mapper_ram = auto_alloc_array(image.device().machine(), UINT8, 0x400);
896
897         if (state->m_pcb_id == TAITO_X1_005 || state->m_pcb_id == TAITO_X1_005_A)
898            state->m_mapper_bram = auto_alloc_array(image.device().machine(), UINT8, 0x80);
899
900         if (state->m_pcb_id == TAITO_X1_017)
901            state->m_mapper_bram = auto_alloc_array(image.device().machine(), UINT8, 0x1400);
902
903         if (state->m_pcb_id == NAMCOT_163)
904            state->m_mapper_ram = auto_alloc_array(image.device().machine(), UINT8, 0x2000);
905
906         if (state->m_pcb_id == FUKUTAKE_BOARD)
907            state->m_mapper_ram = auto_alloc_array(image.device().machine(), UINT8, 2816);
908
909         /* Position past the header */
910         image.fseek(16, SEEK_SET);
911
912         /* Load the 0x200 byte trainer at 0x7000 if it exists */
913         if (state->m_trainer)
914            image.fread(&state->m_wram[0x1000], 0x200);
915
916         /* Read in the program chunks */
917         image.fread(&state->m_rom[0x10000], 0x4000 * state->m_prg_chunks);
918         if (state->m_prg_chunks == 1)
919            memcpy(&state->m_rom[0x14000], &state->m_rom[0x10000], 0x4000);
920
921#if SPLIT_PRG
922         {
923            FILE *prgout;
924            char outname[255];
925
926            sprintf(outname, "%s.prg", image.filename());
927            prgout = fopen(outname, "wb");
928            if (prgout)
929            {
930               fwrite(&state->m_rom[0x10000], 1, 0x4000 * state->m_prg_chunks, prgout);
931               mame_printf_error("Created PRG chunk\n");
932            }
933
934            fclose(prgout);
935         }
936#endif
937
938         logerror("**\n");
939         logerror("Mapper: %d\n", state->m_mapper);
940         logerror("PRG chunks: %02x, size: %06x\n", state->m_prg_chunks, 0x4000 * state->m_prg_chunks);
941         // mame_printf_error("Mapper: %d\n", state->m_mapper);
942         // mame_printf_error("PRG chunks: %02x, size: %06x\n", state->m_prg_chunks, 0x4000 * state->m_prg_chunks);
943
944         /* Read in any chr chunks */
945         if (state->m_chr_chunks > 0)
946         {
947            image.fread(state->m_vrom, state->m_chr_chunks * 0x2000);
948            if (state->m_mapper == 2)
949               logerror("Warning: VROM has been found in VRAM-based mapper. Either the mapper is set wrong or the ROM image is incorrect.\n");
950         }
951
952#if SPLIT_CHR
953         if (state->m_chr_chunks > 0)
954         {
955            FILE *chrout;
956            char outname[255];
957
958            sprintf(outname, "%s.chr", image.filename());
959            chrout= fopen(outname, "wb");
960            if (chrout)
961            {
962               fwrite(state->m_vrom, 1, 0x2000 * state->m_chr_chunks, chrout);
963               mame_printf_error("Created CHR chunk\n");
964            }
965            fclose(chrout);
966         }
967#endif
968
969         logerror("CHR chunks: %02x, size: %06x\n", state->m_chr_chunks, 0x2000 * state->m_chr_chunks);
970         logerror("**\n");
971         // mame_printf_error("CHR chunks: %02x, size: %06x\n", state->m_chr_chunks, 0x2000 * state->m_chr_chunks);
972         // mame_printf_error("**\n");
973      }
974      else if ((magic[0] == 'U') && (magic[1] == 'N') && (magic[2] == 'I') && (magic[3] == 'F')) /* If header starts with 'UNIF' it is UNIF */
975      {
976         UINT32 unif_ver = 0;
977         char magic2[4];
978         UINT8 buffer[4];
979         UINT32 chunk_length = 0, read_length = 0x20;
980         UINT32 prg_start = 0, chr_start = 0, prg_size;
981         char unif_mapr[32];   // here we should store MAPR chunks
982         UINT32 size = image.length();
983         int mapr_chunk_found = 0;
984         // allocate space to temporarily store PRG & CHR banks
985         UINT8 *temp_prg = auto_alloc_array(image.device().machine(), UINT8, 256 * 0x4000);
986         UINT8 *temp_chr = auto_alloc_array(image.device().machine(), UINT8, 256 * 0x2000);
987         UINT8 temp_byte = 0;
988
989         /* init prg/chr chunks to 0: the exact number of chunks will be determined while reading the file */
990         state->m_prg_chunks = 0;
991         state->m_chr_chunks = 0;
992
993         image.fread(&buffer, 4);
994         unif_ver = buffer[0] | (buffer[1] << 8) | (buffer[2] << 16) | (buffer[3] << 24);
995         logerror("UNIF file found, version %d\n", unif_ver);
996
997         if (size <= 0x20)
998         {
999            logerror("%s only contains the UNIF header and no data.\n", image.filename());
1000            return IMAGE_INIT_FAIL;
1001         }
1002
1003         do
1004         {
1005            image.fseek(read_length, SEEK_SET);
1006
1007            memset(magic2, '\0', sizeof(magic2));
1008            image.fread(&magic2, 4);
1009
1010            /* We first run through the whole image to find a [MAPR] chunk. This is needed
1011                 because, unfortunately, the MAPR chunk is not always the first chunk (see
1012                 Super 24-in-1). When such a chunk is found, we set mapr_chunk_found=1 and
1013                 we go back to load other chunks! */
1014            if (!mapr_chunk_found)
1015            {
1016               if ((magic2[0] == 'M') && (magic2[1] == 'A') && (magic2[2] == 'P') && (magic2[3] == 'R'))
1017               {
1018                  mapr_chunk_found = 1;
1019                  logerror("[MAPR] chunk found: ");
1020                  image.fread(&buffer, 4);
1021                  chunk_length = buffer[0] | (buffer[1] << 8) | (buffer[2] << 16) | (buffer[3] << 24);
1022
1023                  if (chunk_length <= 0x20)
1024                     image.fread(&unif_mapr, chunk_length);
1025
1026                  // find out prg/chr size, battery, wram, etc.
1027                  unif_mapr_setup(image.device().machine(), unif_mapr);
1028
1029                  /* now that we found the MAPR chunk, we can go back to load other chunks */
1030                  image.fseek(0x20, SEEK_SET);
1031                  read_length = 0x20;
1032               }
1033               else
1034               {
1035                  logerror("Skip this chunk. We need a [MAPR] chunk before anything else.\n");
1036                  image.fread(&buffer, 4);
1037                  chunk_length = buffer[0] | (buffer[1] << 8) | (buffer[2] << 16) | (buffer[3] << 24);
1038
1039                  read_length += (chunk_length + 8);
1040               }
1041            }
1042            else
1043            {
1044               /* What kind of chunk do we have here? */
1045               if ((magic2[0] == 'M') && (magic2[1] == 'A') && (magic2[2] == 'P') && (magic2[3] == 'R'))
1046               {
1047                  /* The [MAPR] chunk has already been read, so we skip it */
1048                  /* TO DO: it would be nice to check if more than one MAPR chunk is present */
1049                  logerror("[MAPR] chunk found (in the 2nd run). Already loaded.\n");
1050                  image.fread(&buffer, 4);
1051                  chunk_length = buffer[0] | (buffer[1] << 8) | (buffer[2] << 16) | (buffer[3] << 24);
1052
1053                  read_length += (chunk_length + 8);
1054               }
1055               else if ((magic2[0] == 'R') && (magic2[1] == 'E') && (magic2[2] == 'A') && (magic2[3] == 'D'))
1056               {
1057                  logerror("[READ] chunk found. No support yet.\n");
1058                  image.fread(&buffer, 4);
1059                  chunk_length = buffer[0] | (buffer[1] << 8) | (buffer[2] << 16) | (buffer[3] << 24);
1060
1061                  read_length += (chunk_length + 8);
1062               }
1063               else if ((magic2[0] == 'N') && (magic2[1] == 'A') && (magic2[2] == 'M') && (magic2[3] == 'E'))
1064               {
1065                  logerror("[NAME] chunk found. No support yet.\n");
1066                  image.fread(&buffer, 4);
1067                  chunk_length = buffer[0] | (buffer[1] << 8) | (buffer[2] << 16) | (buffer[3] << 24);
1068
1069                  read_length += (chunk_length + 8);
1070               }
1071               else if ((magic2[0] == 'W') && (magic2[1] == 'R') && (magic2[2] == 'T') && (magic2[3] == 'R'))
1072               {
1073                  logerror("[WRTR] chunk found. No support yet.\n");
1074                  image.fread(&buffer, 4);
1075                  chunk_length = buffer[0] | (buffer[1] << 8) | (buffer[2] << 16) | (buffer[3] << 24);
1076
1077                  read_length += (chunk_length + 8);
1078               }
1079               else if ((magic2[0] == 'T') && (magic2[1] == 'V') && (magic2[2] == 'C') && (magic2[3] == 'I'))
1080               {
1081                  logerror("[TVCI] chunk found.\n");
1082                  image.fread(&buffer, 4);
1083                  chunk_length = buffer[0] | (buffer[1] << 8) | (buffer[2] << 16) | (buffer[3] << 24);
1084
1085                  image.fread(&temp_byte, 1);
1086                  logerror("Television Standard : %s\n", (temp_byte == 0) ? "NTSC" : (temp_byte == 1) ? "PAL" : "Does not matter");
1087
1088                  read_length += (chunk_length + 8);
1089               }
1090               else if ((magic2[0] == 'T') && (magic2[1] == 'V') && (magic2[2] == 'S') && (magic2[3] == 'C')) // is this the same as TVCI??
1091               {
1092                  logerror("[TVSC] chunk found. No support yet.\n");
1093                  image.fread(&buffer, 4);
1094                  chunk_length = buffer[0] | (buffer[1] << 8) | (buffer[2] << 16) | (buffer[3] << 24);
1095
1096                  read_length += (chunk_length + 8);
1097               }
1098               else if ((magic2[0] == 'D') && (magic2[1] == 'I') && (magic2[2] == 'N') && (magic2[3] == 'F'))
1099               {
1100                  logerror("[DINF] chunk found. No support yet.\n");
1101                  image.fread(&buffer, 4);
1102                  chunk_length = buffer[0] | (buffer[1] << 8) | (buffer[2] << 16) | (buffer[3] << 24);
1103
1104                  read_length += (chunk_length + 8);
1105               }
1106               else if ((magic2[0] == 'C') && (magic2[1] == 'T') && (magic2[2] == 'R') && (magic2[3] == 'L'))
1107               {
1108                  logerror("[CTRL] chunk found. No support yet.\n");
1109                  image.fread(&buffer, 4);
1110                  chunk_length = buffer[0] | (buffer[1] << 8) | (buffer[2] << 16) | (buffer[3] << 24);
1111
1112                  read_length += (chunk_length + 8);
1113               }
1114               else if ((magic2[0] == 'B') && (magic2[1] == 'A') && (magic2[2] == 'T') && (magic2[3] == 'R'))
1115               {
1116                  logerror("[BATR] chunk found. No support yet.\n");
1117                  image.fread(&buffer, 4);
1118                  chunk_length = buffer[0] | (buffer[1] << 8) | (buffer[2] << 16) | (buffer[3] << 24);
1119
1120                  read_length += (chunk_length + 8);
1121               }
1122               else if ((magic2[0] == 'V') && (magic2[1] == 'R') && (magic2[2] == 'O') && (magic2[3] == 'R'))
1123               {
1124                  logerror("[VROR] chunk found. No support yet.\n");
1125                  image.fread(&buffer, 4);
1126                  chunk_length = buffer[0] | (buffer[1] << 8) | (buffer[2] << 16) | (buffer[3] << 24);
1127
1128                  read_length += (chunk_length + 8);
1129               }
1130               else if ((magic2[0] == 'M') && (magic2[1] == 'I') && (magic2[2] == 'R') && (magic2[3] == 'R'))
1131               {
1132                  logerror("[MIRR] chunk found.\n");
1133                  image.fread(&buffer, 4);
1134                  chunk_length = buffer[0] | (buffer[1] << 8) | (buffer[2] << 16) | (buffer[3] << 24);
1135
1136                  image.fread(&temp_byte, 1);
1137                  switch (temp_byte)
1138                  {
1139                     case 0:   // Horizontal Mirroring (Hard Wired)
1140                        state->m_hard_mirroring = PPU_MIRROR_HORZ;
1141                        break;
1142                     case 1:   // Vertical Mirroring (Hard Wired)
1143                        state->m_hard_mirroring = PPU_MIRROR_VERT;
1144                        break;
1145                     case 2:   // Mirror All Pages From $2000 (Hard Wired)
1146                        state->m_hard_mirroring = PPU_MIRROR_LOW;
1147                        break;
1148                     case 3:   // Mirror All Pages From $2400 (Hard Wired)
1149                        state->m_hard_mirroring = PPU_MIRROR_HIGH;
1150                        break;
1151                     case 4:   // Four Screens of VRAM (Hard Wired)
1152                        state->m_four_screen_vram = 1;
1153                        break;
1154                     case 5:   // Mirroring Controlled By Mapper Hardware
1155                        logerror("Mirroring handled by the board hardware.\n");
1156                        // default to horizontal at start
1157                        state->m_hard_mirroring = PPU_MIRROR_HORZ;
1158                        break;
1159                     default:
1160                        logerror("Undocumented mirroring value.\n");
1161                        // default to horizontal
1162                        state->m_hard_mirroring = PPU_MIRROR_HORZ;
1163                        break;
1164                  }
1165
1166                  read_length += (chunk_length + 8);
1167               }
1168               else if ((magic2[0] == 'P') && (magic2[1] == 'C') && (magic2[2] == 'K'))
1169               {
1170                  logerror("[PCK%c] chunk found. No support yet.\n", magic2[3]);
1171                  image.fread(&buffer, 4);
1172                  chunk_length = buffer[0] | (buffer[1] << 8) | (buffer[2] << 16) | (buffer[3] << 24);
1173
1174                  read_length += (chunk_length + 8);
1175               }
1176               else if ((magic2[0] == 'C') && (magic2[1] == 'C') && (magic2[2] == 'K'))
1177               {
1178                  logerror("[CCK%c] chunk found. No support yet.\n", magic2[3]);
1179                  image.fread(&buffer, 4);
1180                  chunk_length = buffer[0] | (buffer[1] << 8) | (buffer[2] << 16) | (buffer[3] << 24);
1181
1182                  read_length += (chunk_length + 8);
1183               }
1184               else if ((magic2[0] == 'P') && (magic2[1] == 'R') && (magic2[2] == 'G'))
1185               {
1186                  logerror("[PRG%c] chunk found. ", magic2[3]);
1187                  image.fread(&buffer, 4);
1188                  chunk_length = buffer[0] | (buffer[1] << 8) | (buffer[2] << 16) | (buffer[3] << 24);
1189
1190                  // FIXME: we currently don't support PRG chunks smaller than 16K!
1191                  state->m_prg_chunks += (chunk_length / 0x4000);
1192
1193                  if (chunk_length / 0x4000)
1194                     logerror("It consists of %d 16K-blocks.\n", chunk_length / 0x4000);
1195                  else
1196                     logerror("This chunk is smaller than 16K: the emulation might have issues. Please report this file to the MESS forums.\n");
1197
1198                  /* Read in the program chunks */
1199                  image.fread(&temp_prg[prg_start], chunk_length);
1200
1201                  prg_start += chunk_length;
1202                  read_length += (chunk_length + 8);
1203               }
1204               else if ((magic2[0] == 'C') && (magic2[1] == 'H') && (magic2[2] == 'R'))
1205               {
1206                  logerror("[CHR%c] chunk found. ", magic2[3]);
1207                  image.fread(&buffer, 4);
1208                  chunk_length = buffer[0] | (buffer[1] << 8) | (buffer[2] << 16) | (buffer[3] << 24);
1209
1210                  state->m_chr_chunks += (chunk_length / 0x2000);
1211
1212                  logerror("It consists of %d 8K-blocks.\n", chunk_length / 0x2000);
1213
1214                  /* Read in the vrom chunks */
1215                  image.fread(&temp_chr[chr_start], chunk_length);
1216
1217                  chr_start += chunk_length;
1218                  read_length += (chunk_length + 8);
1219               }
1220               else
1221               {
1222                  logerror("Unsupported UNIF chunk or corrupted header. Please report the problem at MESS Board.\n");
1223                  read_length = size;
1224               }
1225            }
1226         } while (size > read_length);
1227
1228         if (!mapr_chunk_found)
1229         {
1230            auto_free(image.device().machine(), temp_prg);
1231            auto_free(image.device().machine(), temp_chr);
1232            fatalerror("UNIF should have a [MAPR] chunk to work. Check if your image has been corrupted");
1233         }
1234
1235         if (!prg_start)
1236         {
1237            auto_free(image.device().machine(), temp_prg);
1238            auto_free(image.device().machine(), temp_chr);
1239            fatalerror("Unsupported UNIF chunk or corrupted header. Please report the problem at MESS Board.\n");
1240         }
1241
1242         /* Free the regions that were allocated by the ROM loader */
1243         image.device().machine().region_free("maincpu");
1244         image.device().machine().region_free("gfx1");
1245         image.device().machine().region_free("gfx2");
1246
1247         /* Allocate them again, and copy PRG/CHR from temp buffers */
1248         /* Take care of PRG */
1249         prg_size = (state->m_prg_chunks == 1) ? 2 * 0x4000 : state->m_prg_chunks * 0x4000;
1250         image.device().machine().region_alloc("maincpu", 0x10000 + prg_size, 1, ENDIANNESS_LITTLE);
1251         state->m_rom = image.device().machine().region("maincpu")->base();
1252         memcpy(&state->m_rom[0x10000], &temp_prg[0x00000], state->m_prg_chunks * 0x4000);
1253         /* If only a single 16K PRG chunk is present, mirror it! */
1254         if (state->m_prg_chunks == 1)
1255            memcpy(&state->m_rom[0x14000], &state->m_rom[0x10000], 0x4000);
1256
1257         /* Take care of CHR ROM */
1258         if (state->m_chr_chunks)
1259         {
1260            image.device().machine().region_alloc("gfx1", state->m_chr_chunks * 0x2000, 1, ENDIANNESS_LITTLE);
1261            state->m_vrom = image.device().machine().region("gfx1")->base();
1262            memcpy(&state->m_vrom[0x00000], &temp_chr[0x00000], state->m_chr_chunks * 0x2000);
1263         }
1264
1265         /* Take care of CHR RAM */
1266         if (state->m_vram_chunks)
1267         {
1268            image.device().machine().region_alloc("gfx2", state->m_vram_chunks * 0x2000, 1, ENDIANNESS_LITTLE);
1269            state->m_vram = image.device().machine().region("gfx2")->base();
1270         }
1271
1272         // FIXME: this should only be allocated if there is actual wram in the cart (i.e. if state->m_prg_ram = 1)!
1273         state->m_wram_size = 0x10000;
1274         state->m_wram = auto_alloc_array(image.device().machine(), UINT8, state->m_wram_size);
1275
1276#if SPLIT_PRG
1277         {
1278            FILE *prgout;
1279            char outname[255];
1280
1281            sprintf(outname, "%s.prg", image.filename());
1282            prgout = fopen(outname, "wb");
1283            if (prgout)
1284            {
1285               fwrite(&state->m_rom[0x10000], 1, 0x4000 * state->m_prg_chunks, prgout);
1286               mame_printf_error("Created PRG chunk\n");
1287            }
1288
1289            fclose(prgout);
1290         }
1291#endif
1292
1293#if SPLIT_CHR
1294         if (state->m_chr_chunks > 0)
1295         {
1296            FILE *chrout;
1297            char outname[255];
1298
1299            sprintf(outname, "%s.chr", image.filename());
1300            chrout= fopen(outname, "wb");
1301            if (chrout)
1302            {
1303               fwrite(state->m_vrom, 1, 0x2000 * state->m_chr_chunks, chrout);
1304               mame_printf_error("Created CHR chunk\n");
1305            }
1306            fclose(chrout);
1307         }
1308#endif
1309         // free the temporary copy of PRG/CHR
1310         auto_free(image.device().machine(), temp_prg);
1311         auto_free(image.device().machine(), temp_chr);
1312         logerror("UNIF support is only very preliminary.\n");
1313      }
1314      else
1315      {
1316         logerror("%s is NOT a file in either iNES or UNIF format.\n", image.filename());
1317         return IMAGE_INIT_FAIL;
1318      }
1319   }
1320   else
1321   {
1322      UINT32 prg_size = image.get_software_region_length("prg");
1323      UINT32 chr_size = image.get_software_region_length("chr");
1324      UINT32 vram_size = image.get_software_region_length("vram");
1325      vram_size += image.get_software_region_length("vram2");
1326
1327      /* Free the regions that were allocated by the ROM loader */
1328      image.device().machine().region_free("maincpu");
1329      image.device().machine().region_free("gfx1");
1330      image.device().machine().region_free("gfx2");
1331
1332      /* Allocate them again with the proper size */
1333      image.device().machine().region_alloc("maincpu", 0x10000 + prg_size, 1, ENDIANNESS_LITTLE);
1334
1335      // validate the xml fields
1336      if (!prg_size)
1337         fatalerror("No PRG entry for this software! Please check if the xml list got corrupted");
1338      if (prg_size < 0x8000)
1339         fatalerror("PRG entry is too small! Please check if the xml list got corrupted");
1340
1341      if (chr_size)
1342         image.device().machine().region_alloc("gfx1", chr_size, 1, ENDIANNESS_LITTLE);
1343
1344      if (vram_size)
1345         image.device().machine().region_alloc("gfx2", vram_size, 1, ENDIANNESS_LITTLE);
1346
1347      state->m_rom = image.device().machine().region("maincpu")->base();
1348      state->m_vrom = image.device().machine().region("gfx1")->base();
1349      state->m_vram = image.device().machine().region("gfx2")->base();
1350
1351      memcpy(state->m_rom + 0x10000, image.get_software_region("prg"), prg_size);
1352
1353      if (chr_size)
1354         memcpy(state->m_vrom, image.get_software_region("chr"), chr_size);
1355
1356      state->m_prg_chunks = prg_size / 0x4000;
1357      state->m_chr_chunks = chr_size / 0x2000;
1358      state->m_vram_chunks = vram_size / 0x2000;
1359
1360      state->m_pcb_id = nes_get_pcb_id(image.device().machine(), image.get_feature("pcb"));
1361
1362      if (state->m_pcb_id == STD_TVROM || state->m_pcb_id == STD_DRROM || state->m_pcb_id == IREM_LROG017)
1363         state->m_four_screen_vram = 1;
1364      else
1365         state->m_four_screen_vram = 0;
1366
1367      state->m_battery = (image.get_software_region("bwram") != NULL) ? 1 : 0;
1368      state->m_battery_size = image.get_software_region_length("bwram");
1369
1370      if (state->m_pcb_id == BANDAI_LZ93EX)
1371      {
1372         // allocate the 24C01 or 24C02 EEPROM
1373         state->m_battery = 1;
1374         state->m_battery_size += 0x2000;
1375      }
1376
1377      if (state->m_pcb_id == BANDAI_DATACH)
1378      {
1379         // allocate the 24C01 and 24C02 EEPROM
1380         state->m_battery = 1;
1381         state->m_battery_size += 0x4000;
1382      }
1383
1384      state->m_prg_ram = (image.get_software_region("wram") != NULL) ? 1 : 0;
1385      state->m_wram_size = image.get_software_region_length("wram");
1386      state->m_mapper_ram_size = image.get_software_region_length("mapper_ram");
1387      state->m_mapper_bram_size = image.get_software_region_length("mapper_bram");
1388
1389      if (state->m_prg_ram)
1390         state->m_wram = auto_alloc_array(image.device().machine(), UINT8, state->m_wram_size);
1391      if (state->m_mapper_ram_size)
1392         state->m_mapper_ram = auto_alloc_array(image.device().machine(), UINT8, state->m_mapper_ram_size);
1393      if (state->m_mapper_bram_size)
1394         state->m_mapper_bram = auto_alloc_array(image.device().machine(), UINT8, state->m_mapper_bram_size);
1395
1396      /* Check for mirroring */
1397      if (image.get_feature("mirroring") != NULL)
1398      {
1399         const char *mirroring = image.get_feature("mirroring");
1400         if (!strcmp(mirroring, "horizontal"))
1401            state->m_hard_mirroring = PPU_MIRROR_HORZ;
1402         if (!strcmp(mirroring, "vertical"))
1403            state->m_hard_mirroring = PPU_MIRROR_VERT;
1404         if (!strcmp(mirroring, "high"))
1405            state->m_hard_mirroring = PPU_MIRROR_HIGH;
1406         if (!strcmp(mirroring, "low"))
1407            state->m_hard_mirroring = PPU_MIRROR_LOW;
1408      }
1409
1410      state->m_chr_open_bus = 0;
1411      state->m_ce_mask = 0;
1412      state->m_ce_state = 0;
1413      state->m_vrc_ls_prg_a = 0;
1414      state->m_vrc_ls_prg_b = 0;
1415      state->m_vrc_ls_chr = 0;
1416
1417      /* Check for pins in specific boards which require them */
1418      if (state->m_pcb_id == STD_CNROM)
1419      {
1420         if (image.get_feature("chr-pin26") != NULL)
1421         {
1422            state->m_ce_mask |= 0x01;
1423            state->m_ce_state |= !strcmp(image.get_feature("chr-pin26"), "CE") ? 0x01 : 0;
1424         }
1425         if (image.get_feature("chr-pin27") != NULL)
1426         {
1427            state->m_ce_mask |= 0x02;
1428            state->m_ce_state |= !strcmp(image.get_feature("chr-pin27"), "CE") ? 0x02 : 0;
1429         }
1430      }
1431
1432      if (state->m_pcb_id == TAITO_X1_005 && image.get_feature("x1-pin17") != NULL && image.get_feature("x1-pin31") != NULL)
1433      {
1434         if (!strcmp(image.get_feature("x1-pin17"), "CIRAM A10") && !strcmp(image.get_feature("x1-pin31"), "NC"))
1435            state->m_pcb_id = TAITO_X1_005_A;
1436      }
1437
1438      if (state->m_pcb_id == KONAMI_VRC2)
1439      {
1440         state->m_vrc_ls_prg_a = nes_cart_get_line(image.get_feature("vrc2-pin3"));
1441         state->m_vrc_ls_prg_b = nes_cart_get_line(image.get_feature("vrc2-pin4"));
1442         state->m_vrc_ls_chr = (nes_cart_get_line(image.get_feature("vrc2-pin21")) != 10) ? 1 : 0;
1443//          mame_printf_error("VRC-2, pin3: A%d, pin4: A%d, pin21: %s\n", state->m_vrc_ls_prg_a, state->m_vrc_ls_prg_b, state->m_vrc_ls_chr ? "NC" : "A10");
1444      }
1445
1446      if (state->m_pcb_id == KONAMI_VRC4)
1447      {
1448         state->m_vrc_ls_prg_a = nes_cart_get_line(image.get_feature("vrc4-pin3"));
1449         state->m_vrc_ls_prg_b = nes_cart_get_line(image.get_feature("vrc4-pin4"));
1450//          mame_printf_error("VRC-4, pin3: A%d, pin4: A%d\n", state->m_vrc_ls_prg_a, state->m_vrc_ls_prg_b);
1451      }
1452
1453      if (state->m_pcb_id == KONAMI_VRC6)
1454      {
1455         state->m_vrc_ls_prg_a = nes_cart_get_line(image.get_feature("vrc6-pin9"));
1456         state->m_vrc_ls_prg_b = nes_cart_get_line(image.get_feature("vrc6-pin10"));
1457//          mame_printf_error("VRC-6, pin9: A%d, pin10: A%d\n", state->m_vrc_ls_prg_a, state->m_vrc_ls_prg_b);
1458      }
1459
1460      /* Check for other misc board variants */
1461      if (state->m_pcb_id == STD_SOROM)
1462      {
1463         if (image.get_feature("mmc1_type") != NULL && !strcmp(image.get_feature("mmc1_type"), "MMC1A"))
1464            state->m_pcb_id = STD_SOROM_A;   // in MMC1-A PRG RAM is always enabled
1465      }
1466
1467      if (state->m_pcb_id == STD_SXROM)
1468      {
1469         if (image.get_feature("mmc1_type") != NULL && !strcmp(image.get_feature("mmc1_type"), "MMC1A"))
1470            state->m_pcb_id = STD_SXROM_A;   // in MMC1-A PRG RAM is always enabled
1471      }
1472
1473      if (state->m_pcb_id == STD_NXROM || state->m_pcb_id == SUNSOFT_DCS)
1474      {
1475         if (image.get_software_region("minicart") != NULL)   // check for dual minicart
1476         {
1477            state->m_pcb_id = SUNSOFT_DCS;
1478            // we shall load somewhere the minicart, but we still do not support this
1479         }
1480      }
1481
1482#if 0
1483      if (state->m_pcb_id == UNSUPPORTED_BOARD)
1484         mame_printf_error("This board (%s) is currently not supported by MESS\n", image.get_feature("pcb"));
1485      mame_printf_error("PCB Feature: %s\n", image.get_feature("pcb"));
1486      mame_printf_error("PRG chunks: %d\n", state->m_prg_chunks);
1487      mame_printf_error("CHR chunks: %d\n", state->m_chr_chunks);
1488      mame_printf_error("VRAM: Present %s, size: %d\n", state->m_vram_chunks ? "Yes" : "No", vram_size);
1489      mame_printf_error("NVWRAM: Present %s, size: %d\n", state->m_battery ? "Yes" : "No", state->m_battery_size);
1490      mame_printf_error("WRAM:   Present %s, size: %d\n", state->m_prg_ram ? "Yes" : "No", state->m_wram_size);
1491#endif
1492   }
1493
1494   // Attempt to load a battery file for this ROM
1495   // A few boards have internal RAM with a battery (MMC6, Taito X1-005 & X1-017, etc.)
1496   if (state->m_battery || state->m_mapper_bram_size)
1497   {
1498      UINT8 *temp_nvram = auto_alloc_array(image.device().machine(), UINT8, state->m_battery_size + state->m_mapper_bram_size);
1499      image.battery_load(temp_nvram, state->m_battery_size + state->m_mapper_bram_size, 0x00);
1500      if (state->m_battery)
1501      {
1502         state->m_battery_ram = auto_alloc_array(image.device().machine(), UINT8, state->m_battery_size);
1503         memcpy(state->m_battery_ram, temp_nvram, state->m_battery_size);
1504      }
1505      if (state->m_mapper_bram_size)
1506         memcpy(state->m_mapper_bram, temp_nvram + state->m_battery_size, state->m_mapper_bram_size);
1507
1508      auto_free(image.device().machine(), temp_nvram);
1509   }
1510
1511   return IMAGE_INIT_PASS;
1512}
1513
1514
1515
1516void nes_partialhash(hash_collection &dest, const unsigned char *data,
1517   unsigned long length, const char *functions)
1518{
1519   if (length <= 16)
1520      return;
1521   dest.compute(&data[16], length - 16, functions);
1522}
1523
1524/**************************
1525
1526 Disk System emulation
1527
1528**************************/
1529
1530static void fds_irq( device_t *device, int scanline, int vblank, int blanked )
1531{
1532   nes_state *state = device->machine().driver_data<nes_state>();
1533
1534   if (state->m_IRQ_enable_latch)
1535      device_set_input_line(state->m_maincpu, M6502_IRQ_LINE, HOLD_LINE);
1536
1537   if (state->m_IRQ_enable)
1538   {
1539      if (state->m_IRQ_count <= 114)
1540      {
1541         device_set_input_line(state->m_maincpu, M6502_IRQ_LINE, HOLD_LINE);
1542         state->m_IRQ_enable = 0;
1543         state->m_fds_status0 |= 0x01;
1544      }
1545      else
1546         state->m_IRQ_count -= 114;
1547   }
1548}
1549
1550static READ8_HANDLER( nes_fds_r )
1551{
1552   nes_state *state = space->machine().driver_data<nes_state>();
1553   UINT8 ret = 0x00;
1554
1555   switch (offset)
1556   {
1557      case 0x00: /* $4030 - disk status 0 */
1558         ret = state->m_fds_status0;
1559         /* clear the disk IRQ detect flag */
1560         state->m_fds_status0 &= ~0x01;
1561         break;
1562      case 0x01: /* $4031 - data latch */
1563         /* don't read data if disk is unloaded */
1564         if (state->m_fds_data == NULL)
1565            ret = 0;
1566         else if (state->m_fds_current_side)
1567            ret = state->m_fds_data[(state->m_fds_current_side - 1) * 65500 + state->m_fds_head_position++];
1568         else
1569            ret = 0;
1570         break;
1571      case 0x02: /* $4032 - disk status 1 */
1572         /* return "no disk" status if disk is unloaded */
1573         if (state->m_fds_data == NULL)
1574            ret = 1;
1575         else if (state->m_fds_last_side != state->m_fds_current_side)
1576         {
1577            /* If we've switched disks, report "no disk" for a few reads */
1578            ret = 1;
1579            state->m_fds_count++;
1580            if (state->m_fds_count == 50)
1581            {
1582               state->m_fds_last_side = state->m_fds_current_side;
1583               state->m_fds_count = 0;
1584            }
1585         }
1586         else
1587            ret = (state->m_fds_current_side == 0); /* 0 if a disk is inserted */
1588         break;
1589      case 0x03: /* $4033 */
1590         ret = 0x80;
1591         break;
1592      default:
1593         ret = 0x00;
1594         break;
1595   }
1596
1597   return ret;
1598}
1599
1600static WRITE8_HANDLER( nes_fds_w )
1601{
1602   nes_state *state = space->machine().driver_data<nes_state>();
1603
1604   switch (offset)
1605   {
1606      case 0x00:
1607         state->m_IRQ_count_latch = (state->m_IRQ_count_latch & 0xff00) | data;
1608         break;
1609      case 0x01:
1610         state->m_IRQ_count_latch = (state->m_IRQ_count_latch & 0x00ff) | (data << 8);
1611         break;
1612      case 0x02:
1613         state->m_IRQ_count = state->m_IRQ_count_latch;
1614         state->m_IRQ_enable = data;
1615         break;
1616      case 0x03:
1617         // d0 = sound io (1 = enable)
1618         // d1 = disk io (1 = enable)
1619         break;
1620      case 0x04:
1621         /* write data out to disk */
1622         break;
1623      case 0x05:
1624         state->m_fds_motor_on = BIT(data, 0);
1625
1626         if (BIT(data, 1))
1627            state->m_fds_head_position = 0;
1628
1629         state->m_fds_read_mode = BIT(data, 2);
1630         set_nt_mirroring(space->machine(), BIT(data, 3) ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT);
1631
1632         if ((!(data & 0x40)) && (state->m_fds_write_reg & 0x40))
1633            state->m_fds_head_position -= 2; // ???
1634
1635         state->m_IRQ_enable_latch = BIT(data, 7);
1636         state->m_fds_write_reg = data;
1637         break;
1638   }
1639}
1640
1641static void nes_load_proc( device_image_interface &image )
1642{
1643   nes_state *state = image.device().machine().driver_data<nes_state>();
1644   int header = 0;
1645   state->m_fds_sides = 0;
1646
1647   if (image.length() % 65500)
1648      header = 0x10;
1649
1650   state->m_fds_sides = (image.length() - header) / 65500;
1651
1652   if (state->m_fds_data == NULL)
1653      state->m_fds_data = (UINT8*)image.image_malloc(state->m_fds_sides * 65500);   // I don't think we can arrive here ever, probably it can be removed...
1654
1655   /* if there is an header, skip it */
1656   image.fseek(header, SEEK_SET);
1657
1658   image.fread(state->m_fds_data, 65500 * state->m_fds_sides);
1659   return;
1660}
1661
1662static void nes_unload_proc( device_image_interface &image )
1663{
1664   nes_state *state = image.device().machine().driver_data<nes_state>();
1665
1666   /* TODO: should write out changes here as well */
1667   state->m_fds_sides =  0;
1668}
1669
1670DRIVER_INIT( famicom )
1671{
1672   nes_state *state = machine.driver_data<nes_state>();
1673   int i;
1674
1675   /* clear some of the variables we don't use */
1676   state->m_trainer = 0;
1677   state->m_battery = 0;
1678   state->m_prg_ram = 0;
1679   state->m_four_screen_vram = 0;
1680   state->m_hard_mirroring = 0;
1681   state->m_prg_chunks = state->m_chr_chunks = 0;
1682
1683   /* initialize the disk system */
1684   state->m_disk_expansion = 1;
1685   state->m_pcb_id = NO_BOARD;
1686
1687   state->m_fds_sides = 0;
1688   state->m_fds_last_side = 0;
1689   state->m_fds_count = 0;
1690   state->m_fds_motor_on = 0;
1691   state->m_fds_door_closed = 0;
1692   state->m_fds_current_side = 1;
1693   state->m_fds_head_position = 0;
1694   state->m_fds_status0 = 0;
1695   state->m_fds_read_mode = state->m_fds_write_reg = 0;
1696
1697   state->m_fds_data = auto_alloc_array_clear(machine, UINT8, 65500 * 2);
1698   state->m_fds_ram = auto_alloc_array_clear(machine, UINT8, 0x8000);
1699   state->save_pointer(NAME(state->m_fds_ram), 0x8000);
1700
1701   // setup CHR accesses to 8k VRAM
1702   state->m_vram = machine.region("gfx2")->base();
1703   for (i = 0; i < 8; i++)
1704   {
1705      state->m_chr_map[i].source = CHRRAM;
1706      state->m_chr_map[i].origin = i * 0x400; // for save state uses!
1707      state->m_chr_map[i].access = &state->m_vram[state->m_chr_map[i].origin];
1708   }
1709
1710   floppy_install_load_proc(floppy_get_device(machine, 0), nes_load_proc);
1711   floppy_install_unload_proc(floppy_get_device(machine, 0), nes_unload_proc);
1712}
src/mess/machine/amigacd.h
r0r11532
1#ifndef __AMIGACD_H__
2#define __AMIGACD_H__
3
4
5MACHINE_START( amigacd );
6MACHINE_RESET( amigacd );
7
8/* 6525tpi */
9READ8_DEVICE_HANDLER( amigacd_tpi6525_portc_r );
10WRITE8_DEVICE_HANDLER( amigacd_tpi6525_portb_w );
11WRITE_LINE_DEVICE_HANDLER( amigacd_tpi6525_irq );
12
13
14#endif /* __AMIGACD_H__ */
src/mess/machine/nes_unif.c
r0r11532
1/*****************************************************************************************
2
3    NES MMC Emulation - UNIF boards
4
5    Very preliminary support for UNIF boards
6
7    TODO:
8    - properly support WRAM, etc.
9
10****************************************************************************************/
11
12typedef struct __unif
13{
14   const char *board; /* UNIF board */
15
16   int nvwram;
17   int wram;
18   int chrram;
19   int board_idx;
20} unif;
21
22
23/*************************************************************
24
25    Constants
26
27*************************************************************/
28
29/* CHRRAM sizes */
30enum
31{
32   CHRRAM_0 = 0,
33   CHRRAM_1,
34   CHRRAM_2,
35   CHRRAM_4,
36   CHRRAM_6,
37   CHRRAM_8,
38   CHRRAM_16,
39   CHRRAM_32
40};
41
42/*************************************************************
43
44    unif_list
45
46    Supported UNIF boards and corresponding handlers
47
48*************************************************************/
49
50static const unif unif_list[] =
51{
52/*       UNIF                       NVW  WRAM  CRAM     IDX*/
53   { "DREAMTECH01",                0,    0, CHRRAM_8,  DREAMTECH_BOARD},      //UNIF only!
54   { "NES-ANROM",                  0,    0, CHRRAM_8,  STD_AXROM},
55   { "NES-AOROM",                  0,    0, CHRRAM_8,  STD_AXROM},
56   { "NES-CNROM",                  0,    0, CHRRAM_0,  STD_CNROM},
57   { "NES-NROM",                   0,    0, CHRRAM_0,  STD_NROM},
58   { "NES-NROM-128",               0,    0, CHRRAM_0,  STD_NROM},
59   { "NES-NROM-256",               0,    0, CHRRAM_0,  STD_NROM},
60   { "NES-NTBROM",                 8,    0, CHRRAM_0,  STD_NXROM},
61   { "NES-SLROM",                  0,    0, CHRRAM_0,  STD_SXROM},
62   { "NES-TBROM",                  0,    0, CHRRAM_0,  STD_TXROM},
63   { "NES-TFROM",                  0,    0, CHRRAM_0,  STD_TXROM},
64   { "NES-TKROM",                  8,    0, CHRRAM_0,  STD_TXROM},
65   { "NES-TLROM",                  0,    0, CHRRAM_0,  STD_TXROM},
66   { "NES-UOROM",                  0,    0, CHRRAM_8,  STD_UXROM},
67   { "UNL-22211",                  0,    0, CHRRAM_0,  TXC_22211A},
68   // mapper 172 & 173 are variant of this one... no UNIF?
69   { "UNL-KOF97",                  0,    0, CHRRAM_0,  UNL_KOF97},
70   { "UNL-SA-NROM",                0,    0, CHRRAM_0,  SACHEN_TCA01},
71   { "UNL-VRC7",                   0,    0, CHRRAM_0,  KONAMI_VRC7},
72   { "UNL-T-230",                  0,    0, CHRRAM_8,  UNL_T230},
73   { "UNL-CC-21",                  0,    0, CHRRAM_0,  UNL_CC21},
74   { "UNL-AX5705",                 0,    0, CHRRAM_0,  UNL_AX5705},
75   { "UNL-SMB2J",                  8,    8, CHRRAM_0,  UNL_SMB2J},
76   { "UNL-8237",                   0,    0, CHRRAM_0,  UNL_8237},
77   { "UNL-SL1632",                 0,    0, CHRRAM_0,  REXSOFT_SL1632},
78   { "UNL-SACHEN-74LS374N",        0,    0, CHRRAM_0,  SACHEN_74LS374},
79   // mapper 243 variant exists! how to distinguish?!?  mapper243_l_w, NULL, NULL, NULL, NULL, NULL, NULL (also uses NT_VERT!)
80   { "UNL-TC-U01-1.5M",            0,    0, CHRRAM_0,  SACHEN_TCU01},
81   { "UNL-SACHEN-8259C",           0,    0, CHRRAM_0,  SACHEN_8259C},
82   { "UNL-SA-016-1M",              0,    0, CHRRAM_0,  AVE_NINA06},   // actually this is Mapper 146, but works like 79!
83   { "UNL-SACHEN-8259D",           0,    0, CHRRAM_0,  SACHEN_8259D},
84   { "UNL-SA-72007",               0,    0, CHRRAM_0,  SACHEN_SA72007},
85   { "UNL-SA-72008",               0,    0, CHRRAM_0,  SACHEN_SA72008},
86   { "UNL-SA-0037",                0,    0, CHRRAM_0,  SACHEN_SA0037},
87   { "UNL-SA-0036",                0,    0, CHRRAM_0,  SACHEN_SA0036},
88   { "UNL-SACHEN-8259A",           0,    0, CHRRAM_0,  SACHEN_8259A},
89   { "UNL-SACHEN-8259B",           0,    0, CHRRAM_0,  SACHEN_8259B},
90   { "BMC-190IN1",                 0,    0, CHRRAM_0,  BMC_190IN1},
91   { "BMC-64IN1NOREPEAT",          0,    0, CHRRAM_0,  BMC_64IN1NR},      //UNIF only!
92   { "BMC-A65AS",                  0,    0, CHRRAM_8,  BMC_A65AS},      //UNIF only!
93   { "BMC-GS-2004",                0,    0, CHRRAM_8,  BMC_GS2004},      //UNIF only!
94   { "BMC-GS-2013",                0,    0, CHRRAM_8,  BMC_GS2013},      //UNIF only!
95   { "BMC-NOVELDIAMOND9999999IN1", 0,    0, CHRRAM_0,  BMC_NOVELDIAMOND},
96   { "BMC-SUPER24IN1SC03",         8,    0, CHRRAM_8,  BMC_S24IN1SC03},
97   { "BMC-SUPERHIK8IN1",           8,    0, CHRRAM_0,  BMC_HIK8IN1},
98   { "BMC-T-262",                  0,    0, CHRRAM_8,  BMC_T262},      //UNIF only!
99   { "BMC-WS",                     0,    0, CHRRAM_0,  BMC_WS},      //UNIF only!
100   { "BMC-N625092",                0,    0, CHRRAM_0,  UNL_N625092},
101   // below are boards which are not yet supported, but are used by some UNIF files. they are here as a reminder to what is missing to be added
102   { "UNL-TEK90",                  0,    0, CHRRAM_0,  UNSUPPORTED_BOARD},   // related to JY Company? (i.e. mappers 90, 209, 211?)
103   { "UNL-KS7017",                 0,    0, CHRRAM_0,  UNSUPPORTED_BOARD},
104   { "UNL-KS7032",                 0,    0, CHRRAM_0,  KAISER_KS7032}, //  mapper 142
105   { "UNL-DANCE",                  0,    0, CHRRAM_0,  UNSUPPORTED_BOARD},
106   { "UNL-603-5052",               0,    0, CHRRAM_0,  UNL_603_5052}, // mapper 238?
107   { "UNL-EDU2000",               32,    0, CHRRAM_8,  UNL_EDU2K},
108   { "UNL-H2288",                  0,    0, CHRRAM_0,  UNL_H2288},   // mapper 123
109   { "UNL-SHERO",                  0,    0, CHRRAM_8,  UNSUPPORTED_BOARD /*SACHEN_SHERO*/},
110   { "UNL-TF1201",                 0,    0, CHRRAM_0,  UNSUPPORTED_BOARD /*UNL_TF1201*/},
111   { "UNL-DRIPGAME",               0,    0, CHRRAM_0,  UNSUPPORTED_BOARD}, // [by Quietust - we need more info]}
112   { "UNL-OneBus",                 0,    0, CHRRAM_0,  UNSUPPORTED_BOARD},
113   { "BTL-MARIO1-MALEE2",          0,    0, CHRRAM_0,  UNSUPPORTED_BOARD},   // mapper 55?
114   { "BMC-FK23C",                  0,    0, CHRRAM_0,  BMC_FK23C},
115   { "BMC-FK23CA",                 0,    0, CHRRAM_0,  BMC_FK23CA},
116   { "BMC-GHOSTBUSTERS63IN1",      0,    0, CHRRAM_8,  BMC_G63IN1 },
117   { "BMC-BS-5",                   0,    0, CHRRAM_0,  BMC_BENSHENG_BS5},
118   { "BMC-810544-C-A1",            0,    0, CHRRAM_0,  BMC_810544},
119   { "BMC-411120-C",               0,    0, CHRRAM_0,  UNSUPPORTED_BOARD},
120   { "BMC-8157",                   0,    0, CHRRAM_8,  UNSUPPORTED_BOARD /*BMC_8157*/},
121   { "BMC-42IN1RESETSWITCH",       0,    0, CHRRAM_0,  UNSUPPORTED_BOARD},   // mapper 60?
122   { "BMC-830118C",                0,    0, CHRRAM_0,  UNSUPPORTED_BOARD},
123   { "BMC-D1038",                  0,    0, CHRRAM_0,  BMC_VT5201}, // mapper 60?
124   { "BMC-12-IN-1",                0,    0, CHRRAM_0,  UNSUPPORTED_BOARD},
125   { "BMC-70IN1",                  0,    0, CHRRAM_0,  UNSUPPORTED_BOARD},   // mapper 236?
126   { "BMC-70IN1B",                 0,    0, CHRRAM_0,  UNSUPPORTED_BOARD},   // mapper 236?
127   { "BMC-SUPERVISION16IN1",       0,    0, CHRRAM_0,  UNSUPPORTED_BOARD},   // mapper 53
128   { "BMC-NTD-03",                 0,    0, CHRRAM_0,  BMC_NTD_03}
129};
130
131const unif *nes_unif_lookup( const char *board )
132{
133   int i;
134   for (i = 0; i < ARRAY_LENGTH(unif_list); i++)
135   {
136      if (!mame_stricmp(unif_list[i].board, board))
137         return &unif_list[i];
138   }
139   return NULL;
140}
141
142/*************************************************************
143
144 unif_mapr_setup
145
146 setup the board specific variables (wram, nvwram, pcb_id etc.)
147 for a given board (after reading the MAPR chunk of the UNIF file)
148
149 *************************************************************/
150
151void unif_mapr_setup( running_machine &machine, const char *board )
152{
153   nes_state *state = machine.driver_data<nes_state>();
154   const unif *unif_board = nes_unif_lookup(board);
155
156   logerror("%s\n", board);
157
158   if (unif_board == NULL)
159      fatalerror("Unknown UNIF board %s.", board);
160
161   state->m_pcb_id = unif_board->board_idx;
162   state->m_battery = unif_board->nvwram;   // we should implement battery banks based on the size of this...
163   state->m_battery_size = NES_BATTERY_SIZE; // FIXME: we should allow for smaller battery!
164   state->m_prg_ram = unif_board->wram;   // we should implement WRAM banks based on the size of this...
165
166   if (unif_board->chrram <= CHRRAM_8)
167      state->m_vram_chunks = 1;
168   else if (unif_board->chrram == CHRRAM_16)
169      state->m_vram_chunks = 2;
170   else if (unif_board->chrram == CHRRAM_32)
171      state->m_vram_chunks = 4;
172}
src/mess/machine/nes_mmc.c
r0r11532
1/*****************************************************************************************
2
3    NES MMC Emulation
4
5
6    MESS source file to handle various Multi-Memory Controllers (aka Mappers) used by NES carts.
7
8    Many information about the mappers below come from the wonderful doc written by Disch.
9    Current info (when used) are based on v0.6.1 of his docs.
10    You can find the latest version of the doc at http://www.romhacking.net/docs/362/
11
12
13    Missing components:
14    * Currently, we are not emulating 4-screen mirroring (only 3 games use it)
15    * We need a better way to implement CPU cycle based IRQ. Currently we update their counter once every scanline
16      but, with this approach, every time 114 clocks have passed and for certain games it is too much!
17    * We need to emulate additional sound hardware in mappers 019, 024, 026, 069, 085 (and possibly other ones)
18    * We need to emulate EEPROM in mapper 016 and 159
19    * Barcode World (mapper 069) and Datach games (mapper 157) need Barcode Reader emulation
20      Notice that for mapper 157, the barcode reader enters in the irq, so glitches may be related to this!
21    * Karaoke Studio (mapper 188) misses input devices
22
23    Known issues on specific mappers:
24
25    * 000 F1 Race requires more precise PPU timing. It currently has plenty of 1-line glitches.
26    * 001 Yoshi flashes in-game. Back to the Future have heavily corrupted graphics (since forever).
27    * 001 SOROM boards do not properly handle the two WRAM/Battery banks
28    * 002, 003, 094, 097, 152 Bus conflict?
29    * 003 Firehouse Rescue has flashing graphics
30    * 004 Mendel Palace has never worked properly
31    * 004 Ninja Gaiden 2 has flashing bg graphics in the second level
32    * 005 has issues (see e.g. Just Breed or Metal Slader Glory), RAM banking needs hardware flags to determine size
33    * 007 Marble Madness has small graphics corruptions
34    * 014 in-game graphics is glitched
35    * 015 Shanghai Tycoon has corrupted graphics
36    * 033 has still some graphics problem (e.g. missing text in Akira)
37    * 034 Impossible Mission II does not show graphics
38    * 038 seems to miss inputs. separate reads?
39    * 042 Ai Senshi Nicol has broken graphics (our Mapper 42 implementation does not handle CHR banks)
40    * 048 Don Doko Don 2 freezes when you reach the first boss
41    * 051 only half of the games work
42    * 064 has many IRQ problems (due to the way we implement CPU based IRQ) - see Skull & Crossbones.
43          Klax has problems as well (even if it uses scanline based IRQ, according to Disch's docs).
44    * 067 some 1-line glitches that cannot be solved without a better implementation for cycle-based IRQs
45    * 071 Fire Hawk is flashing all the times.
46    * 072, 086, 092 lack samples support (maybe others as well)
47    * 073 16 bit IRQ mode is not implemented
48    * 077 Requires 4-screen mirroring. Currently, it is very glitchy
49    * 083 has serious glitches
50    * 088 Quinty has never worked properly
51    * 096 is preliminary (no correct chr switch in connection to PPU)
52    * 104 Not all the games work
53    * 107 Are the scrolling glitches (check status bar) correct? NEStopia behaves similarly
54    * 112 Master Shooter is not working and misses some graphics
55    * 117 In-game glitches
56    * 119 Pin Bot has glitches when the ball is in the upper half of the screen
57    * 133 Qi Wang starts with corrupted graphics (ingame seems better)
58    * 143 are Dancing Block borders (in the intro) correct?
59    * 158 In addition to IRQ problems (same as 64), mirroring was just a guess (wrong?). info needed!
60    * 164 preliminary - no sprites?
61    * 176 has some graphics problem
62    * 178 Fan Kong Jin Ying is not working (but not even in NEStopia)
63    * 180 Crazy Climber controller?
64    * 187, 198, 208, 215 have some PRG banking issues - preliminary!
65    * 188 needs mic input (reads from 0x6000-0x7fff)
66    * 197 Super Fighter 3 has some glitch in-game (maybe mirroring?)
67    * 222 is only preliminar (wrong IRQ, mirroring or CHR banking?)
68    * 225 115-in-1 has glitches in the menu (games seem fine)
69    * 229 is preliminary
70    * 230 not working yet (needs a value to flip at reset)
71    * 232 has graphics glitches
72    * 241 Commandos is not working (but not even in NEStopia)
73    * 242 In Dragon Quest VIII graphics of the main character is not drawn (it seems similar to Shanghai Tycoon [map15]
74          because in place of the missing graphics we get glitches in the left border)
75    * 249 only half of the games work (and Du Bao Ying Hao seems to suffer the same problem as DQ8 and Shanghai Tycoon)
76    * 255 does not really select game (same in NEStopia apparently)
77
78    A few Mappers suffer of hardware conflict: original dumpers have used the same mapper number for more than
79    a kind of boards. In these cases (and only in these cases) we exploit nes.hsi to set up accordingly
80    emulation. Games which requires this hack are the following:
81    * 032 - Major League needs hardwired mirroring (missing windows and glitched field in top view, otherwise)
82    * 034 - Impossible Mission II is not like BxROM games (it writes to 0x7ffd-0x7fff, instead of 0x8000). It is still
83          unplayable though (see above)
84    * 071 - Fire Hawk is different from other Camerica games (no hardwired mirroring). Without crc_hack no helicopter graphics
85    * 078 - Cosmo Carrier needs a different mirroring than Holy Diver
86    * 113 - HES 6-in-1 requires mirroring (check Bookyman playfield), while other games break with this (check AV Soccer)
87    * 153 - Famicom Jump II uses a different board (or the same in a very different way)
88    * 242 - DQ8 has no mirroring (missing graphics is due to other reasons though)
89
90    crc_hacks have been added also to handle a few wiring settings which would require submappers:
91    * CHR protection pins for mapper 185
92    * VRC-2, VRC-4 and VRC-6 line wiring
93
94    Known issues on specific UNIF boards:
95    * BMC-GS2004 is not working
96    * BMC-GS2013 is not working
97    * BMC-WS some games have corrupted graphics (e.g. Galaxian)
98    * UNL-8237 is not working
99    * UNL-KOF97 is not working
100
101    Details to investigate:
102    * 034 writes to 0x8000-0xffff should not be used for NINA-001 and BNROM, only unlicensed BxROM...
103    * 144 we ignore writes to 0x8000 while NEStopia does not. is it a problem?
104    * 240 we do not map writes to 0x4020-0x40ff. is this a problem?
105    * some other emus uses mapper 210 for mapper 019 games without additional sound hardware and mirroring capabilities
106      (in 210 mirroring is hardwired). However, simply initializing mirroring to Vertical in 019 seems to fix all glitches
107      in 210 games, so there seems to be no reason to have this duplicate mapper
108
109    Some mappers copy PRG rom in SRAM region. Below is a list of those which does it (in MESS) to further
110    investigate if we are supporting them in the right way (e.g. do any of the following have conflicts with SRAM?):
111    * 065 (Gimmick! breaks badly without it)
112    * 040, 042, 050
113
114    Remember that the MMC # does not equal the mapper #. In particular, Mapper 4 is
115    in fact MMC3, Mapper 9 is MMC2 and Mapper 10 is MMC4. Makes perfect sense, right?
116
117    TODO:
118    - add more info
119    - add missing mappers
120
121****************************************************************************************/
122
123#include "emu.h"
124#include "cpu/m6502/m6502.h"
125#include "video/ppu2c0x.h"
126#include "includes/nes.h"
127#include "nes_mmc.h"
128#include "sound/nes_apu.h"
129
130#ifdef MAME_DEBUG
131#define VERBOSE 1
132#else
133#define VERBOSE 0
134#endif
135
136#define LOG_MMC(x) do { if (VERBOSE) logerror x; } while (0)
137#define LOG_FDS(x) do { if (VERBOSE) logerror x; } while (0)
138
139static void ffe_irq( device_t *device, int scanline, int vblank, int blanked );
140static WRITE8_HANDLER( mapper6_l_w );
141static WRITE8_HANDLER( mapper6_w );
142static WRITE8_HANDLER( mapper8_w );
143static WRITE8_HANDLER( mapper17_l_w );
144
145/*************************************************************
146
147    Base emulation (see drivers/nes.c):
148    memory 0x0000-0x1fff RAM
149           0x2000-0x3fff PPU
150           0x4000-0x4017 APU
151           0x4018-0x5fff Expansion Area
152           0x6000-0x7fff PRG RAM
153           0x8000-0xffff PRG ROM
154
155    nes_chr_r/w take care of RAM, nes_nt_r/w take care of PPU.
156    for mapper specific emulation, we generically setup the
157    following handlers:
158    - nes_low_mapper_r/w take care of accesses to 0x4100-0x5fff
159      (calling state->m_mmc_write_low/state->m_mmc_read_low)
160    - state->m_mmc_write/read_mid take care of 0x6000-0x7fff
161    - state->m_mmc_write/read take care of access to 0x8000-0xffff
162      (most mappers only writes in this area)
163    some mappers may access 0x4018-0x4100: this must be taken
164    care separately in init_nes_core
165
166*************************************************************/
167
168WRITE8_HANDLER( nes_chr_w )
169{
170   nes_state *state = space->machine().driver_data<nes_state>();
171   int bank = offset >> 10;
172
173   if (state->m_chr_map[bank].source == CHRRAM)
174   {
175      state->m_chr_map[bank].access[offset & 0x3ff] = data;
176   }
177}
178
179READ8_HANDLER( nes_chr_r )
180{
181   nes_state *state = space->machine().driver_data<nes_state>();
182   int bank = offset >> 10;
183
184   // a few CNROM boards contained copy protection schemes through
185   // suitably configured diodes, so that subsequent CHR reads can
186   // give actual VROM content or open bus values.
187   // For most boards, chr_open_bus remains always zero.
188   if (state->m_chr_open_bus)
189      return 0xff;
190
191   return state->m_chr_map[bank].access[offset & 0x3ff];
192}
193
194WRITE8_HANDLER( nes_nt_w )
195{
196   nes_state *state = space->machine().driver_data<nes_state>();
197   int page = ((offset & 0xc00) >> 10);
198
199   if (state->m_nt_page[page].writable == 0)
200      return;
201
202   state->m_nt_page[page].access[offset & 0x3ff] = data;
203}
204
205READ8_HANDLER( nes_nt_r )
206{
207   nes_state *state = space->machine().driver_data<nes_state>();
208   int page = ((offset & 0xc00) >> 10);
209
210   if (state->m_nt_page[page].source == MMC5FILL)
211   {
212      if ((offset & 0x3ff) >= 0x3c0)
213         return state->m_MMC5_floodattr;
214
215      return state->m_MMC5_floodtile;
216   }
217   return state->m_nt_page[page].access[offset & 0x3ff];
218}
219
220WRITE8_HANDLER( nes_low_mapper_w )
221{
222   nes_state *state = space->machine().driver_data<nes_state>();
223
224   if (state->m_mmc_write_low)
225      (*state->m_mmc_write_low)(space, offset, data);
226   else
227      logerror("Unimplemented LOW mapper write, offset: %04x, data: %02x\n", offset + 0x4100, data);
228}
229
230READ8_HANDLER( nes_low_mapper_r )
231{
232   nes_state *state = space->machine().driver_data<nes_state>();
233
234   if (state->m_mmc_read_low)
235      return (*state->m_mmc_read_low)(space, offset);
236   else
237      logerror("Unimplemented LOW mapper read, offset: %04x\n", offset + 0x4100);
238
239   return 0;
240}
241
242/*************************************************************
243
244    Helpers to handle MMC
245
246*************************************************************/
247
248static void wram_bank( running_machine &machine, int bank, int source )
249{
250   nes_state *state = machine.driver_data<nes_state>();
251
252   assert(state->m_battery || state->m_prg_ram);
253   if (source == NES_BATTERY)
254   {
255      bank &= (state->m_battery_size / 0x2000) - 1;
256      state->m_prg_bank[4] = state->m_battery_bank5_start + bank;
257   }
258   else
259   {
260      bank &= (state->m_wram_size / 0x2000) - 1;
261      state->m_prg_bank[4] = state->m_prgram_bank5_start + bank;
262   }
263   memory_set_bank(machine, "bank5", state->m_prg_bank[4]);
264}
265
266INLINE void prg_bank_refresh( running_machine &machine )
267{
268   nes_state *state = machine.driver_data<nes_state>();
269   memory_set_bank(machine, "bank1", state->m_prg_bank[0]);
270   memory_set_bank(machine, "bank2", state->m_prg_bank[1]);
271   memory_set_bank(machine, "bank3", state->m_prg_bank[2]);
272   memory_set_bank(machine, "bank4", state->m_prg_bank[3]);
273}
274
275/* PRG ROM in 8K, 16K or 32K blocks */
276
277static void prg32( running_machine &machine, int bank )
278{
279   nes_state *state = machine.driver_data<nes_state>();
280
281   /* if there is only 16k PRG, return */
282   if (!(state->m_prg_chunks >> 1))
283      return;
284
285   /* assumes that bank references a 32k chunk */
286   bank &= ((state->m_prg_chunks >> 1) - 1);
287
288   state->m_prg_bank[0] = bank * 4 + 0;
289   state->m_prg_bank[1] = bank * 4 + 1;
290   state->m_prg_bank[2] = bank * 4 + 2;
291   state->m_prg_bank[3] = bank * 4 + 3;
292   prg_bank_refresh(machine);
293}
294
295static void prg16_89ab( running_machine &machine, int bank )
296{
297   nes_state *state = machine.driver_data<nes_state>();
298
299   /* assumes that bank references a 16k chunk */
300   bank &= (state->m_prg_chunks - 1);
301
302   state->m_prg_bank[0] = bank * 2 + 0;
303   state->m_prg_bank[1] = bank * 2 + 1;
304   prg_bank_refresh(machine);
305}
306
307static void prg16_cdef( running_machine &machine, int bank )
308{
309   nes_state *state = machine.driver_data<nes_state>();
310
311   /* assumes that bank references a 16k chunk */
312   bank &= (state->m_prg_chunks - 1);
313
314   state->m_prg_bank[2] = bank * 2 + 0;
315   state->m_prg_bank[3] = bank * 2 + 1;
316   prg_bank_refresh(machine);
317}
318
319static void prg8_89( running_machine &machine, int bank )
320{
321   nes_state *state = machine.driver_data<nes_state>();
322
323   /* assumes that bank references an 8k chunk */
324   bank &= ((state->m_prg_chunks << 1) - 1);
325
326   state->m_prg_bank[0] = bank;
327   prg_bank_refresh(machine);
328}
329
330static void prg8_ab( running_machine &machine, int bank )
331{
332   nes_state *state = machine.driver_data<nes_state>();
333
334   /* assumes that bank references an 8k chunk */
335   bank &= ((state->m_prg_chunks << 1) - 1);
336
337   state->m_prg_bank[1] = bank;
338   prg_bank_refresh(machine);
339}
340
341static void prg8_cd( running_machine &machine, int bank )
342{
343   nes_state *state = machine.driver_data<nes_state>();
344
345   /* assumes that bank references an 8k chunk */
346   bank &= ((state->m_prg_chunks << 1) - 1);
347
348   state->m_prg_bank[2] = bank;
349   prg_bank_refresh(machine);
350}
351
352static void prg8_ef( running_machine &machine, int bank )
353{
354   nes_state *state = machine.driver_data<nes_state>();
355
356   /* assumes that bank references an 8k chunk */
357   bank &= ((state->m_prg_chunks << 1) - 1);
358
359   state->m_prg_bank[3] = bank;
360   prg_bank_refresh(machine);
361}
362
363/* We define an additional helper to map PRG-ROM to 0x6000-0x7000 */
364// TODO: are we implementing this correctly in the mappers which uses it? check!
365
366static void prg8_67( running_machine &machine, int bank )
367{
368   nes_state *state = machine.driver_data<nes_state>();
369
370   /* assumes that bank references an 8k chunk */
371   bank &= ((state->m_prg_chunks << 1) - 1);
372
373   state->m_prg_bank[4] = bank;
374   memory_set_bank(machine, "bank5", state->m_prg_bank[4]);
375}
376
377/* We also define an additional helper to map 8k PRG-ROM to one of the banks (passed as parameter) */
378static void prg8_x( running_machine &machine, int start, int bank )
379{
380   nes_state *state = machine.driver_data<nes_state>();
381
382   assert(start < 4);
383
384   /* assumes that bank references an 8k chunk */
385   bank &= ((state->m_prg_chunks << 1) - 1);
386
387   state->m_prg_bank[start] = bank;
388   prg_bank_refresh(machine);
389}
390
391/* CHR ROM in 1K, 2K, 4K or 8K blocks */
392
393// this can be probably removed later, but it is useful while testing xml and unf handling with VRAM & VROM
394INLINE void chr_sanity_check( running_machine &machine, int source )
395{
396   nes_state *state = machine.driver_data<nes_state>();
397
398   if (source == CHRRAM && state->m_vram == NULL)
399      fatalerror("CHRRAM bankswitch with no VRAM");
400
401   if (source == CHRROM && state->m_vrom == NULL)
402      fatalerror("CHRROM bankswitch with no VROM");
403}
404
405static void chr8( running_machine &machine, int bank, int source )
406{
407   nes_state *state = machine.driver_data<nes_state>();
408   int i;
409
410   chr_sanity_check(machine, source);
411
412   if (source == CHRRAM)
413   {
414      bank &= (state->m_vram_chunks - 1);
415      for (i = 0; i < 8; i++)
416      {
417         state->m_chr_map[i].source = source;
418         state->m_chr_map[i].origin = (bank * 0x2000) + (i * 0x400); // for save state uses!
419         state->m_chr_map[i].access = &state->m_vram[state->m_chr_map[i].origin];
420      }
421   }
422   else
423   {
424      bank &= (state->m_chr_chunks - 1);
425      for (i = 0; i < 8; i++)
426      {
427         state->m_chr_map[i].source = source;
428         state->m_chr_map[i].origin = (bank * 0x2000) + (i * 0x400); // for save state uses!
429         state->m_chr_map[i].access = &state->m_vrom[state->m_chr_map[i].origin];
430      }
431   }
432}
433
434static void chr4_x( running_machine &machine, int start, int bank, int source )
435{
436   nes_state *state = machine.driver_data<nes_state>();
437   int i;
438
439   chr_sanity_check(machine, source);
440
441   if (source == CHRRAM)
442   {
443      bank &= ((state->m_vram_chunks << 1) - 1);
444      for (i = 0; i < 4; i++)
445      {
446         state->m_chr_map[i + start].source = source;
447         state->m_chr_map[i + start].origin = (bank * 0x1000) + (i * 0x400); // for save state uses!
448         state->m_chr_map[i + start].access = &state->m_vram[state->m_chr_map[i + start].origin];
449      }
450   }
451   else
452   {
453      bank &= ((state->m_chr_chunks << 1) - 1);
454      for (i = 0; i < 4; i++)
455      {
456         state->m_chr_map[i + start].source = source;
457         state->m_chr_map[i + start].origin = (bank * 0x1000) + (i * 0x400); // for save state uses!
458         state->m_chr_map[i + start].access = &state->m_vrom[state->m_chr_map[i + start].origin];
459      }
460   }
461}
462
463static void chr4_0( running_machine &machine, int bank, int source )
464{
465   chr4_x(machine, 0, bank, source);
466}
467
468static void chr4_4( running_machine &machine, int bank, int source )
469{
470   chr4_x(machine, 4, bank, source);
471}
472
473static void chr2_x( running_machine &machine, int start, int bank, int source )
474{
475   nes_state *state = machine.driver_data<nes_state>();
476   int i;
477
478   chr_sanity_check(machine, source);
479
480   if (source == CHRRAM)
481   {
482      bank &= ((state->m_vram_chunks << 2) - 1);
483      for (i = 0; i < 2; i++)
484      {
485         state->m_chr_map[i + start].source = source;
486         state->m_chr_map[i + start].origin = (bank * 0x800) + (i * 0x400); // for save state uses!
487         state->m_chr_map[i + start].access = &state->m_vram[state->m_chr_map[i + start].origin];
488      }
489   }
490   else
491   {
492      bank &= ((state->m_chr_chunks << 2) - 1);
493      for (i = 0; i < 2; i++)
494      {
495         state->m_chr_map[i + start].source = source;
496         state->m_chr_map[i + start].origin = (bank * 0x800) + (i * 0x400); // for save state uses!
497         state->m_chr_map[i + start].access = &state->m_vrom[state->m_chr_map[i + start].origin];
498      }
499   }
500}
501
502static void chr2_0( running_machine &machine, int bank, int source )
503{
504   chr2_x(machine, 0, bank, source);
505}
506
507static void chr2_2( running_machine &machine, int bank, int source )
508{
509   chr2_x(machine, 2, bank, source);
510}
511
512static void chr2_4( running_machine &machine, int bank, int source )
513{
514   chr2_x(machine, 4, bank, source);
515}
516
517static void chr2_6( running_machine &machine, int bank, int source )
518{
519   chr2_x(machine, 6, bank, source);
520}
521
522static void chr1_x( running_machine &machine, int start, int bank, int source )
523{
524   nes_state *state = machine.driver_data<nes_state>();
525
526   chr_sanity_check(machine, source);
527
528   if (source == CHRRAM)
529   {
530      bank &= ((state->m_vram_chunks << 3) - 1);
531      state->m_chr_map[start].source = source;
532      state->m_chr_map[start].origin = (bank * 0x400); // for save state uses!
533      state->m_chr_map[start].access = &state->m_vram[state->m_chr_map[start].origin];
534   }
535   else
536   {
537      bank &= ((state->m_chr_chunks << 3) - 1);
538      state->m_chr_map[start].source = source;
539      state->m_chr_map[start].origin = (bank * 0x400); // for save state uses!
540      state->m_chr_map[start].access = &state->m_vrom[state->m_chr_map[start].origin];
541   }
542}
543
544static void chr1_0 (running_machine &machine, int bank, int source)
545{
546   chr1_x(machine, 0, bank, source);
547}
548
549static void chr1_1( running_machine &machine, int bank, int source )
550{
551   chr1_x(machine, 1, bank, source);
552}
553
554static void chr1_2( running_machine &machine, int bank, int source )
555{
556   chr1_x(machine, 2, bank, source);
557}
558
559static void chr1_3( running_machine &machine, int bank, int source )
560{
561   chr1_x(machine, 3, bank, source);
562}
563
564static void chr1_4( running_machine &machine, int bank, int source )
565{
566   chr1_x(machine, 4, bank, source);
567}
568
569static void chr1_5( running_machine &machine, int bank, int source )
570{
571   chr1_x(machine, 5, bank, source);
572}
573
574static void chr1_6( running_machine &machine, int bank, int source )
575{
576   chr1_x(machine, 6, bank, source);
577}
578
579static void chr1_7( running_machine &machine, int bank, int source )
580{
581   chr1_x(machine, 7, bank, source);
582}
583
584
585/* NameTable paging and mirroring */
586
587static void set_nt_page( running_machine &machine, int page, int source, int bank, int writable )
588{
589   nes_state *state = machine.driver_data<nes_state>();
590   UINT8* base_ptr;
591
592   switch (source)
593   {
594      case CART_NTRAM:
595         base_ptr = state->m_extended_ntram;
596         break;
597      case MMC5FILL:
598         base_ptr = NULL;
599         break;
600      case ROM:
601         base_ptr = state->m_vrom;
602         break;
603      case EXRAM:
604         base_ptr = state->m_mapper_ram;
605         break;
606      case CIRAM:
607      default:
608         base_ptr = state->m_ciram;
609         break;
610   }
611
612   page &= 3; /* mask down to the 4 logical pages */
613   state->m_nt_page[page].source = source;
614
615   if (base_ptr != NULL)
616   {
617      state->m_nt_page[page].origin = bank * 0x400;
618      state->m_nt_page[page].access = base_ptr + state->m_nt_page[page].origin;
619   }
620
621   state->m_nt_page[page].writable = writable;
622}
623
624void set_nt_mirroring( running_machine &machine, int mirroring )
625{
626   /* setup our videomem handlers based on mirroring */
627   switch (mirroring)
628   {
629      case PPU_MIRROR_VERT:
630         set_nt_page(machine, 0, CIRAM, 0, 1);
631         set_nt_page(machine, 1, CIRAM, 1, 1);
632         set_nt_page(machine, 2, CIRAM, 0, 1);
633         set_nt_page(machine, 3, CIRAM, 1, 1);
634         break;
635
636      case PPU_MIRROR_HORZ:
637         set_nt_page(machine, 0, CIRAM, 0, 1);
638         set_nt_page(machine, 1, CIRAM, 0, 1);
639         set_nt_page(machine, 2, CIRAM, 1, 1);
640         set_nt_page(machine, 3, CIRAM, 1, 1);
641         break;
642
643      case PPU_MIRROR_HIGH:
644         set_nt_page(machine, 0, CIRAM, 1, 1);
645         set_nt_page(machine, 1, CIRAM, 1, 1);
646         set_nt_page(machine, 2, CIRAM, 1, 1);
647         set_nt_page(machine, 3, CIRAM, 1, 1);
648         break;
649
650      case PPU_MIRROR_LOW:
651         set_nt_page(machine, 0, CIRAM, 0, 1);
652         set_nt_page(machine, 1, CIRAM, 0, 1);
653         set_nt_page(machine, 2, CIRAM, 0, 1);
654         set_nt_page(machine, 3, CIRAM, 0, 1);
655         break;
656
657      case PPU_MIRROR_NONE:
658      case PPU_MIRROR_4SCREEN:
659      default:
660         /* external RAM needs to be used somehow. */
661         /* but as a default, we'll arbitrarily set vertical so as not to crash*/
662         /* mappers should use set_nt_page and assign which pages are which */
663
664         logerror("Mapper set 4-screen mirroring without supplying external nametable memory!\n");
665
666         set_nt_page(machine, 0, CIRAM, 0, 1);
667         set_nt_page(machine, 1, CIRAM, 0, 1);
668         set_nt_page(machine, 2, CIRAM, 1, 1);
669         set_nt_page(machine, 3, CIRAM, 1, 1);
670         break;
671   }
672}
673
674/*  Other custom mirroring helpers are defined below: Waixing games use waixing_set_mirror (which swaps
675    MIRROR_HIGH and MIRROR_LOW compared to the above) and Sachen games use sachen_set_mirror (which has
676    a slightly different MIRROR_HIGH, with page 0 set to 0) */
677
678
679/*************************************************************
680
681 Support for xml list
682
683 *************************************************************/
684
685/* Include emulation of NES PCBs for softlist */
686#include "machine/nes_pcb.c"
687
688
689/*************************************************************
690
691    Support for .unf Files
692
693*************************************************************/
694
695/* Include emulation of UNIF Boards for .unf files */
696#include "machine/nes_unif.c"
697
698
699/*************************************************************
700
701 Support for .nes Files
702
703 *************************************************************/
704
705/* Include emulation of iNES Mappers for .nes files */
706#include "machine/nes_ines.c"
707
src/mess/machine/nes_mmc.h
r0r11532
1#ifndef __MMC_H
2#define __MMC_H
3
4/* Boards */
5enum
6{
7   STD_NROM = 0,
8   STD_AXROM, STD_BXROM, STD_CNROM, STD_CPROM,
9   STD_DXROM, STD_EXROM, STD_FXROM, STD_GXROM,
10   STD_HKROM, STD_JXROM, STD_MXROM, STD_NXROM,
11   STD_PXROM, STD_SXROM, STD_TXROM, STD_TXSROM,
12   STD_TKROM, STD_TQROM, STD_TVROM,
13   STD_UN1ROM, STD_UXROM,
14   HVC_FAMBASIC, NES_QJ, PAL_ZZ, UXROM_CC,
15   STD_DRROM, STD_SXROM_A, STD_SOROM, STD_SOROM_A,
16   /* Discrete components boards (by various manufacturer) */
17   DIS_74X161X138, DIS_74X139X74,
18   DIS_74X377, DIS_74X161X161X32,
19   /* Active Enterprises */
20   ACTENT_ACT52,
21   /* AGCI */
22   AGCI_50282,
23   /* AVE */
24   AVE_NINA01, AVE_NINA06,
25   /* Bandai */
26   BANDAI_JUMP2, BANDAI_PT554,
27   BANDAI_DATACH, BANDAI_KARAOKE, BANDAI_OEKAKIDS,
28   BANDAI_FCG, BANDAI_LZ93, BANDAI_LZ93EX,
29   /* Caltron */
30   CALTRON_6IN1,
31   /* Camerica */
32   CAMERICA_BF9093, CAMERICA_BF9097, CAMERICA_BF9096,
33   CAMERICA_GOLDENFIVE, GG_NROM,
34   /* Dreamtech */
35   DREAMTECH_BOARD,
36   /* Irem */
37   IREM_G101, IREM_H3001, IREM_LROG017,
38   IREM_TAM_S1, IREM_HOLYDIV,
39   /* Jaleco */
40   JALECO_SS88006, JALECO_JF11, JALECO_JF13,
41   JALECO_JF16, JALECO_JF17, JALECO_JF19,
42   /* Konami */
43   KONAMI_VRC1, KONAMI_VRC2, KONAMI_VRC3,
44   KONAMI_VRC4, KONAMI_VRC6, KONAMI_VRC7,
45   /* Namcot */
46   NAMCOT_163, NAMCOT_3453,
47   NAMCOT_3425, NAMCOT_34X3, NAMCOT_3446,
48   /* NTDEC */
49   NTDEC_ASDER, NTDEC_FIGHTINGHERO,
50   /* Rex Soft */
51   REXSOFT_SL1632, REXSOFT_DBZ5,
52   /* Sachen */
53   SACHEN_8259A, SACHEN_8259B, SACHEN_8259C, SACHEN_8259D,
54   SACHEN_SA009, SACHEN_SA0036, SACHEN_SA0037,
55   SACHEN_SA72007, SACHEN_SA72008, SACHEN_TCA01,
56   SACHEN_TCU01, SACHEN_TCU02,
57   SACHEN_74LS374, SACHEN_74LS374_A,
58   /* Sunsoft */
59   SUNSOFT_1, SUNSOFT_2, SUNSOFT_3, SUNSOFT_4,
60   SUNSOFT_DCS, SUNSOFT_5B, SUNSOFT_FME7,
61   /* Taito */
62   TAITO_TC0190FMC, TAITO_TC0190FMCP,
63   TAITO_X1_005, TAITO_X1_005_A, TAITO_X1_017,
64   /* Tengen */
65   TENGEN_800008, TENGEN_800032, TENGEN_800037,
66   /* TXC */
67   TXC_22211A, TXC_22211B, TXC_22211C,
68   TXC_MXMDHTWO, TXC_TW, TXC_STRIKEWOLF,
69   /* Multigame Carts */
70   BMC_64IN1NR, BMC_190IN1, BMC_A65AS, BMC_GS2004, BMC_GS2013,
71   BMC_HIK8IN1, BMC_NOVELDIAMOND, BMC_S24IN1SC03, BMC_T262,
72   BMC_WS, BMC_SUPERBIG_7IN1, BMC_SUPERHIK_4IN1, BMC_BALLGAMES_11IN1,
73   BMC_MARIOPARTY_7IN1, BMC_SUPER_700IN1, BMC_FAMILY_4646B,
74   BMC_36IN1, BMC_21IN1, BMC_150IN1, BMC_35IN1, BMC_64IN1,
75   BMC_15IN1, BMC_SUPERHIK_300IN1, BMC_9999999IN1, BMC_SUPERGUN_20IN1,
76   BMC_GOLDENCARD_6IN1, BMC_72IN1, BMC_SUPER_42IN1, BMC_76IN1,
77   BMC_1200IN1, BMC_31IN1, BMC_22GAMES, BMC_20IN1, BMC_110IN1,
78   BMC_GKA, BMC_GKB, BMC_VT5201, BMC_BENSHENG_BS5, BMC_810544,
79   BMC_NTD_03, BMC_G63IN1, BMC_FK23C, BMC_FK23CA, BMC_PJOY84,
80   /* Unlicensed */
81   UNL_8237, UNL_CC21, UNL_AX5705, UNL_KOF97,
82   UNL_N625092, UNL_SC127, UNL_SMB2J, UNL_T230,
83   UNL_UXROM, UNL_MK2, UNL_XZY, UNL_KOF96,
84   UNL_SUPERFIGHTER3, UNL_RACERMATE, UNL_EDU2K,
85   UNL_SHJY3, UNL_STUDYNGAME, UNL_603_5052, UNL_H2288,
86   /* Bootleg boards */
87   BTL_SMB2A, BTL_MARIOBABY, BTL_AISENSHINICOL, BTL_TOBIDASE,
88   BTL_SMB2B, BTL_SMB3, BTL_SUPERBROS11, BTL_DRAGONNINJA,
89   BTL_PIKACHUY2K,
90   /* Misc: these are needed to convert mappers to boards, I will sort them later */
91   OPENCORP_DAOU306, HES_BOARD, HES6IN1_BOARD, RUMBLESTATION_BOARD,
92   MAGICSERIES_MD, KASING_BOARD, FUTUREMEDIA_BOARD, FUKUTAKE_BOARD, SOMERI_SL12,
93   HENGEDIANZI_BOARD, HENGEDIANZI_XJZB, SUBOR_TYPE0, SUBOR_TYPE1,
94   KAISER_KS7058, KAISER_KS7032, KAISER_KS7022, KAISER_KS7017, KAISER_KS202, CONY_BOARD,
95   CNE_DECATHLON, CNE_FSB, CNE_SHLZ, RCM_GS2015, RCM_TETRISFAMILY,
96   WAIXING_TYPE_A, WAIXING_TYPE_A_1, WAIXING_TYPE_B, WAIXING_TYPE_C, WAIXING_TYPE_D,
97   WAIXING_TYPE_E, WAIXING_TYPE_F, WAIXING_TYPE_G, WAIXING_TYPE_H,
98   WAIXING_TYPE_I, WAIXING_TYPE_J,
99   WAIXING_SGZLZ, WAIXING_SGZ, WAIXING_ZS, WAIXING_SECURITY, WAIXING_SH2,
100   WAIXING_DQ8, WAIXING_FFV, WAIXING_PS2, SUPERGAME_LIONKING, SUPERGAME_BOOGERMAN,
101   KAY_PANDAPRINCE, HOSENKAN_BOARD, NITRA_TDA, GOUDER_37017, NANJING_BOARD,
102   WHIRLWIND_2706,
103   /* FFE boards, for mappers 6, 8, 17 */
104   FFE_MAPPER6, FFE_MAPPER8, FFE_MAPPER17,
105   /* Unsupported (for place-holder boards, with no working emulation) & no-board (at init) */
106   UNSUPPORTED_BOARD, UNKNOWN_BOARD, NO_BOARD
107};
108
109// these are used to setup the proper PCB ID, for each supported type of files
110int nes_get_pcb_id(running_machine &machine, const char *feature);   // for softlist
111void unif_mapr_setup(running_machine &machine, const char *board);   // for UNIF files
112int nes_get_mmc_id(running_machine &machine, int mapper);   // for iNES files
113
114// these are used to setup handlers and callbacks necessary to the emulation (resp. at start and reset)
115void pcb_handlers_setup(running_machine &machine);
116int nes_pcb_reset(running_machine &machine);
117
118
119WRITE8_HANDLER( nes_low_mapper_w );
120READ8_HANDLER( nes_low_mapper_r );
121WRITE8_HANDLER( nes_chr_w );
122READ8_HANDLER( nes_chr_r );
123WRITE8_HANDLER( nes_nt_w );
124READ8_HANDLER( nes_nt_r );
125
126WRITE8_HANDLER( smb2jb_extra_w );
127WRITE8_HANDLER( ks7017_extra_w );
128READ8_HANDLER( ks7017_extra_r );
129WRITE8_HANDLER( unl_6035052_extra_w );
130READ8_HANDLER( unl_6035052_extra_r );
131READ8_HANDLER( waixing_sh2_chr_r );
132
133//TEMPORARY PPU STUFF
134
135/* mirroring types */
136#define PPU_MIRROR_NONE      0
137#define PPU_MIRROR_VERT      1
138#define PPU_MIRROR_HORZ      2
139#define PPU_MIRROR_HIGH      3
140#define PPU_MIRROR_LOW      4
141#define PPU_MIRROR_4SCREEN   5   // Same effect as NONE, but signals that we should never mirror
142
143void set_nt_mirroring(running_machine &machine, int mirroring);
144
145
146#endif
src/mess/machine/nes_ines.c
r0r11532
1/*****************************************************************************************
2
3    NES MMC Emulation
4
5    Support for iNES Mappers
6
7****************************************************************************************/
8
9typedef struct _nes_mmc  nes_mmc;
10struct _nes_mmc
11{
12   int    iNesMapper; /* iNES Mapper # */
13   int    pcb_id;
14};
15
16/*************************************************************
17
18    Mapper 6
19
20    Known Boards: FFE4 Copier Board
21    Games: Hacked versions of games
22
23    In MESS: Supported? Not sure if we could also have ExRAM or not...
24       However, priority is pretty low for this mapper.
25
26*************************************************************/
27
28/* Here, IRQ counter decrements every CPU cycle. Since we update it every scanline,
29we need to decrement it by 114 (Each scanline consists of 341 dots and, on NTSC,
30there are 3 dots to every 1 CPU cycle, hence 114 is the number of cycles per scanline ) */
31static void ffe_irq( device_t *device, int scanline, int vblank, int blanked )
32{
33   nes_state *state = device->machine().driver_data<nes_state>();
34
35   /* 114 is the number of cycles per scanline */
36   /* TODO: change to reflect the actual number of cycles spent */
37   if (state->m_IRQ_enable)
38   {
39      if ((0xffff - state->m_IRQ_count) < 114)
40      {
41         device_set_input_line(state->m_maincpu, M6502_IRQ_LINE, HOLD_LINE);
42         state->m_IRQ_count = 0xffff;
43         state->m_IRQ_enable = 0;
44      }
45      state->m_IRQ_count -= 114;
46   }
47}
48
49static WRITE8_HANDLER( mapper6_l_w )
50{
51   nes_state *state = space->machine().driver_data<nes_state>();
52   LOG_MMC(("mapper6_l_w, offset: %04x, data: %02x\n", offset, data));
53
54   switch (offset)
55   {
56      case 0x1fe:
57         state->m_mmc_latch1 = data & 0x80;
58         set_nt_mirroring(space->machine(), BIT(data, 4) ? PPU_MIRROR_HIGH : PPU_MIRROR_LOW);
59         break;
60      case 0x1ff:
61         set_nt_mirroring(space->machine(), BIT(data, 4) ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT);
62         break;
63
64      case 0x401:
65         state->m_IRQ_enable = data & 0x01;
66         break;
67      case 0x402:
68         state->m_IRQ_count = (state->m_IRQ_count & 0xff00) | data;
69         break;
70      case 0x403:
71         state->m_IRQ_enable = 1;
72         state->m_IRQ_count = (state->m_IRQ_count & 0x00ff) | (data << 8);
73         break;
74   }
75}
76
77static WRITE8_HANDLER( mapper6_w )
78{
79   nes_state *state = space->machine().driver_data<nes_state>();
80   LOG_MMC(("mapper6_w, offset: %04x, data: %02x\n", offset, data));
81
82   if (!state->m_mmc_latch1)   // when in "FFE mode" we are forced to use CHRRAM/EXRAM bank?
83   {
84      prg16_89ab(space->machine(), data >> 2);
85      // chr8(space->machine(), data & 0x03, ???);
86      // due to lack of info on the exact behavior, we simply act as if mmc_latch1=1
87      if (state->m_mmc_chr_source == CHRROM)
88         chr8(space->machine(), data & 0x03, CHRROM);
89   }
90   else if (state->m_mmc_chr_source == CHRROM)         // otherwise, we can use CHRROM (when present)
91      chr8(space->machine(), data, CHRROM);
92}
93
94/*************************************************************
95
96    Mapper 8
97
98    Known Boards: FFE3 Copier Board
99    Games: Hacked versions of games
100
101    In MESS: Supported? (I have no games to test this)
102
103*************************************************************/
104
105static WRITE8_HANDLER( mapper8_w )
106{
107   LOG_MMC(("mapper8_w, offset: %04x, data: %02x\n", offset, data));
108
109   chr8(space->machine(), data & 0x07, CHRROM);
110   prg16_89ab(space->machine(), data >> 3);
111}
112
113/*************************************************************
114
115    Mapper 17
116
117    Known Boards: FFE8 Copier Board
118    Games: Hacked versions of games
119
120    In MESS: Supported?. IRQ support is just a guess (used to
121      use MMC3 IRQ but it was wrong and it never enabled it)
122
123*************************************************************/
124
125static WRITE8_HANDLER( mapper17_l_w )
126{
127   nes_state *state = space->machine().driver_data<nes_state>();
128   LOG_MMC(("mapper17_l_w, offset: %04x, data: %02x\n", offset, data));
129
130   switch (offset)
131   {
132      case 0x1fe:
133         set_nt_mirroring(space->machine(), BIT(data, 4) ? PPU_MIRROR_HIGH : PPU_MIRROR_LOW);
134         break;
135      case 0x1ff:
136         set_nt_mirroring(space->machine(), BIT(data, 4) ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT);
137         break;
138
139      case 0x401:
140         state->m_IRQ_enable = data & 0x01;
141         break;
142      case 0x402:
143         state->m_IRQ_count = (state->m_IRQ_count & 0xff00) | data;
144         break;
145      case 0x403:
146         state->m_IRQ_enable = 1;
147         state->m_IRQ_count = (state->m_IRQ_count & 0x00ff) | (data << 8);
148         break;
149
150      case 0x404:
151         prg8_89(space->machine(), data);
152         break;
153      case 0x405:
154         prg8_ab(space->machine(), data);
155         break;
156      case 0x406:
157         prg8_cd(space->machine(), data);
158         break;
159      case 0x407:
160         prg8_ef(space->machine(), data);
161         break;
162
163      case 0x410:
164      case 0x411:
165      case 0x412:
166      case 0x413:
167      case 0x414:
168      case 0x415:
169      case 0x416:
170      case 0x417:
171         chr1_x(space->machine(), offset & 7, data, CHRROM);
172         break;
173   }
174}
175
176/*************************************************************
177
178    mmc_list
179
180    Supported mappers and corresponding pcb id
181
182*************************************************************/
183
184static const nes_mmc mmc_list[] =
185{
186/*  INES   DESC                          LOW_W, LOW_R, MED_W, HIGH_W, PPU_latch, scanline CB, hblank CB */
187   {  0, STD_NROM },
188   {  1, STD_SXROM },
189   {  2, STD_UXROM },
190   {  3, STD_CNROM },
191   {  4, STD_TXROM },
192   {  5, STD_EXROM },
193   {  6, FFE_MAPPER6 },
194   {  7, STD_AXROM },
195   {  8, FFE_MAPPER8 },
196   {  9, STD_PXROM },
197   { 10, STD_FXROM },
198   { 11, DIS_74X377 },
199   { 12, REXSOFT_DBZ5 },
200   { 13, STD_CPROM },
201   { 14, REXSOFT_SL1632 },
202   { 15, WAIXING_PS2 },
203   { 16, BANDAI_LZ93EX },   // with 24c02
204   { 17, FFE_MAPPER17 },
205   { 18, JALECO_SS88006 },
206   { 19, NAMCOT_163 },
207   { 21, KONAMI_VRC4 },
208   { 22, KONAMI_VRC2 },
209   { 23, KONAMI_VRC2 },
210   { 24, KONAMI_VRC6 },
211   { 25, KONAMI_VRC4 },
212   { 26, KONAMI_VRC6 },
213   // 27 World Hero board - Unsupported
214   // 28 Unused
215   // 29 Unused
216   // 30 Unused
217   // 31 Unused
218   { 32, IREM_G101 },
219   { 33, TAITO_TC0190FMC },
220   { 34, STD_BXROM },
221   { 35, UNL_SC127 },
222   { 36, TXC_STRIKEWOLF },
223   { 37, PAL_ZZ },
224   { 38, DIS_74X161X138 },
225   { 39, UNL_STUDYNGAME },
226   { 40, BTL_SMB2A },
227   { 41, CALTRON_6IN1 },
228   { 42, BTL_MARIOBABY },   // ai senshi nicol?
229   { 43, UNL_SMB2J },
230   { 44, BMC_SUPERBIG_7IN1 },
231   { 45, BMC_HIK8IN1 },
232   { 46, RUMBLESTATION_BOARD },
233   { 47, NES_QJ },
234   { 48, TAITO_TC0190FMCP },
235   { 49, BMC_SUPERHIK_4IN1 },
236   { 50, BTL_SMB2B },
237   { 51, BMC_BALLGAMES_11IN1 },
238   { 52, BMC_MARIOPARTY_7IN1 },
239   // 53 Supervision 16-in-1 - Unsupported
240   { 54, BMC_NOVELDIAMOND },
241   // 55 Genius SMB - No info (nor images) available
242   { 56, KAISER_KS202 },
243   { 57, BMC_GKA },
244   { 58, BMC_GKB },
245   // 59 Unused
246   // 60 4-in-1, 35-in-1 Reset based
247   { 61, RCM_TETRISFAMILY },
248   { 62, BMC_SUPER_700IN1 },
249   // 63 CH001 X-in-1 - No info (nor images) available
250   { 64, TENGEN_800032 },
251   { 65, IREM_H3001 },
252   { 66, STD_GXROM },
253   { 67, SUNSOFT_3 },
254   { 68, STD_NXROM },
255   { 69, STD_JXROM },
256   { 70, DIS_74X161X161X32 },
257   { 71, CAMERICA_BF9093 },
258   { 72, JALECO_JF17 },
259   { 73, KONAMI_VRC3 },
260   { 74, WAIXING_TYPE_A },
261   { 75, KONAMI_VRC1 },
262   { 76, NAMCOT_3446 },
263   { 77, IREM_LROG017 },
264   { 78, IREM_HOLYDIV },
265   { 79, AVE_NINA06 },
266   { 80, TAITO_X1_005 },
267   // 81 Unused
268   { 82, TAITO_X1_017 },
269   { 83, CONY_BOARD },
270   // 84 Pasofami hacked images?
271   { 85, KONAMI_VRC7 },
272   { 86, JALECO_JF13 },
273   { 87, DIS_74X139X74 },
274   { 88, NAMCOT_34X3 },
275   { 89, SUNSOFT_2 },
276   // 90 JY Company Type A (Aladdin, Final Fight 3, Super Mario World, Tekken 2) - Unsupported
277   { 91, UNL_MK2 },
278   { 92, JALECO_JF19 },
279   { 93, SUNSOFT_2 },
280   { 94, STD_UN1ROM },
281   { 95, NAMCOT_3425 },
282   { 96, BANDAI_OEKAKIDS },
283   { 97, IREM_TAM_S1 },
284   // 98 Unused
285   // 99 VS. system - Not going to be implemented (use MAME instead)
286   // 100 images hacked to work with nesticle?
287   // 101 Unused (Urusei Yatsura had been assigned to this mapper, but it's Mapper 87)
288   // 102 Unused
289   // 103 Bootleg cart 2708 (Doki Doki Panic - FDS Conversion) - Unsupported
290   { 104, CAMERICA_GOLDENFIVE },
291   // 105 Nintendo World Championship - Unsupported
292   { 106, BTL_SMB3 },
293   { 107, MAGICSERIES_MD },
294   { 108, WHIRLWIND_2706 },
295   // 109 Unused
296   // 110 Unused
297   // 111 Ninja Ryuukenden Chinese? - Unsupported
298   { 112, NTDEC_ASDER },
299   { 113, HES_BOARD },
300   { 114, SUPERGAME_LIONKING },
301   { 115, KASING_BOARD },
302   { 116, SOMERI_SL12 },
303   { 117, FUTUREMEDIA_BOARD },
304   { 118, STD_TXSROM },
305   { 119, STD_TQROM },
306   { 120, BTL_TOBIDASE },
307   { 121, KAY_PANDAPRINCE },
308   // 122 Unused
309   { 123, UNL_H2288 },
310   // 124 Unused
311   // 125 Unused
312   { 126, BMC_PJOY84 },
313   // 127 Unused
314   // 128 Unused
315   // 129 Unused
316   // 130 Unused
317   // 131 Unused
318   { 132, TXC_22211B },
319   { 133, SACHEN_SA72008 },
320   { 134, BMC_FAMILY_4646B },
321   // 135 Unused
322   { 136, SACHEN_TCU02 },
323   { 137, SACHEN_8259D },
324   { 138, SACHEN_8259B },
325   { 139, SACHEN_8259C },
326   { 140, JALECO_JF11 },
327   { 141, SACHEN_8259A },
328   { 142, KAISER_KS7032},
329   { 143, SACHEN_TCA01 },
330   { 144, AGCI_50282 },
331   { 145, SACHEN_SA72007 },
332   { 146, AVE_NINA06 }, // basically same as Mapper 79 (Nina006)
333   { 147, SACHEN_TCU01 },
334   { 148, SACHEN_SA0037 },
335   { 149, SACHEN_SA0036 },
336   { 150, SACHEN_74LS374 },
337   // 151 VS. system by Konami - Not going to be implemented (use MAME instead)
338   { 152, DIS_74X161X161X32 },
339   { 153, BANDAI_LZ93 },
340   { 154, NAMCOT_3453 },
341   { 155, STD_SXROM_A }, // diff compared to MMC1 concern WRAM
342   { 156, OPENCORP_DAOU306 },
343   { 157, BANDAI_DATACH },   // no Datach Reader -> we fall back to mapper 16
344   { 158, TENGEN_800037 },
345   { 159, BANDAI_LZ93EX },   // with 24c01
346   { 160, SACHEN_SA009 },
347   // 161 Unused
348   // 162 Unused
349   { 163, NANJING_BOARD},
350   { 164, WAIXING_FFV },
351   { 165, WAIXING_SH2 },
352   { 166, SUBOR_TYPE1 },
353   { 167, SUBOR_TYPE0 },
354   { 168, UNL_RACERMATE },
355   // 169 Unused
356   // 170 Fujiya
357   { 171, KAISER_KS7058 },
358   { 172, TXC_22211B },
359   { 173, TXC_22211C },
360   // 174 Unused
361   { 175, KAISER_KS7022},
362   { 176, UNL_XZY },
363   { 177, HENGEDIANZI_BOARD },
364   { 178, WAIXING_SGZLZ },
365   { 179, HENGEDIANZI_XJZB },
366   { 180, UXROM_CC },
367   // 181 Unused
368   { 182, HOSENKAN_BOARD },
369   // 183 FDS bootleg (Shui Guan Pipe) - Unsupported
370   { 184, SUNSOFT_1 },
371   { 185, STD_CNROM },
372   { 186, FUKUTAKE_BOARD },
373   { 187, UNL_KOF96 },
374   { 188, BANDAI_KARAOKE },
375   { 189, TXC_TW },
376   // 190 Unused
377   { 191, WAIXING_TYPE_B },
378   { 192, WAIXING_TYPE_C },
379   { 193, NTDEC_FIGHTINGHERO },
380   { 194, WAIXING_TYPE_D },
381   { 195, WAIXING_TYPE_E },
382   { 196, BTL_SUPERBROS11 },
383   { 197, UNL_SUPERFIGHTER3 },
384   { 198, WAIXING_TYPE_F },
385   { 199, WAIXING_TYPE_G },
386   { 200, BMC_36IN1 },
387   { 201, BMC_21IN1 },
388   { 202, BMC_150IN1 },
389   { 203, BMC_35IN1 },
390   { 204, BMC_64IN1 },
391   { 205, BMC_15IN1 },
392   { 206, STD_DXROM },
393   { 207, TAITO_X1_005_A },
394   { 208, GOUDER_37017 },
395   // 209 JY Company Type B (Power Rangers 3 & 4, Shin Samurai Spirits 2) - Unsupported
396   // 210 Some emu uses this as Mapper 19 without some features
397   // 211 JY Company Type C (Tiny Toon Adventures 6, Donkey Kong Country 4) - Unsupported
398   { 212, BMC_SUPERHIK_300IN1 },
399   { 213, BMC_9999999IN1 },
400   { 214, BMC_SUPERGUN_20IN1 },
401   { 215, SUPERGAME_BOOGERMAN },
402   { 216, RCM_GS2015 },
403   { 217, BMC_GOLDENCARD_6IN1 },
404   // 218 Unused
405   // 219 Bootleg A9746 - Unsupported
406   // 220 Unused
407   { 221, UNL_N625092 },
408   { 222, BTL_DRAGONNINJA },
409   { 223, WAIXING_TYPE_I },   // (according to NEStopia source, it's MMC3 with more WRAM)
410   { 224, WAIXING_TYPE_J },   // (according to NEStopia source, it's MMC3 with more WRAM)
411   { 225, BMC_72IN1 },
412   { 226, BMC_76IN1 },
413   { 227, BMC_1200IN1 },
414   { 228, ACTENT_ACT52 },
415   { 229, BMC_31IN1 },
416   { 230, BMC_22GAMES },
417   { 231, BMC_20IN1 },
418   { 232, CAMERICA_BF9096 },
419   // 233 Super 22 Games - Unsupported
420   // 234 AVE Maxi 15 - Unsupported
421   // 235 Golden Game x-in-1 - Unsupported
422   // 236 Game 800-in-1 - Unsupported
423   // 237 Unused
424   { 238, UNL_603_5052 },
425   // 239 Unused
426   { 240, CNE_SHLZ },
427   { 241, TXC_MXMDHTWO },
428   { 242, WAIXING_ZS },
429   { 243, SACHEN_74LS374_A },
430   { 244, CNE_DECATHLON },
431   { 245, WAIXING_TYPE_H },
432   { 246, CNE_FSB },
433   // 247 Unused
434   // 248 Unused
435   { 249, WAIXING_SECURITY },
436   { 250, NITRA_TDA },
437   // 251 Shen Hua Jian Yun III?? - Unsupported
438   { 252, WAIXING_SGZ },
439   // 253 Super 8-in-1 99 King Fighter?? - Unsupported
440   { 254, BTL_PIKACHUY2K },
441   { 255, BMC_110IN1 },
442};
443
444const nes_mmc *nes_mapper_lookup( int mapper )
445{
446   int i;
447
448   for (i = 0; i < ARRAY_LENGTH(mmc_list); i++)
449   {
450      if (mmc_list[i].iNesMapper == mapper)
451         return &mmc_list[i];
452   }
453
454   return NULL;
455}
456
457int nes_get_mmc_id( running_machine &machine, int mapper )
458{
459   const nes_mmc *mmc = nes_mapper_lookup(mapper);
460
461   if (mmc == NULL)
462      fatalerror("Unimplemented Mapper %d", mapper);
463
464   return mmc->pcb_id;
465}
src/mess/machine/snescart.c
r0r11532
1/***************************************************************************
2
3  snescart.c
4
5  Machine file to handle cart loading in the Nintendo Super NES emulation.
6
7***************************************************************************/
8
9#include "emu.h"
10#include "includes/snes.h"
11#include "imagedev/cartslot.h"
12#include "snescart.h"
13
14#define SNES_CART_DEBUG 0
15
16/****** Strings for Cart Header Logging ******/
17
18#define UNK "Unknown"
19
20/* Some known type of cart */
21static const char *const types[] =
22{
23   "ROM",
24   "ROM, DSP-1",
25   "ROM, DSP-2",
26   "ROM, DSP-3",
27   "ROM, DSP-4",
28   "ROM, Super FX / FX2",
29   "ROM, SA-1",
30   "ROM, S-DD1",
31   "ROM, OBC-1",
32   "ROM, S-RTC",
33   "ROM, Z80GB (Super Game Boy)",
34   "ROM, C4",
35   "ROM, Seta ST-010",
36   "ROM, Seta ST-011",
37   "ROM, Seta ST-018",
38   "ROM, SPC7110",
39   "ROM, SPC7110, RTC",
40   UNK,                     // to add: Satellaview BS-X detection
41};
42
43/* Some known countries */
44static const char *const countries[] =
45{
46/* 0*/   "Japan (NTSC)", "USA & Canada (NTSC)", "Europe, Oceania & Asia (PAL)", "Sweden (PAL)",
47/* 4*/   "Finland (PAL)", "Denmark (PAL)", "France (PAL)", "Holland (PAL)",
48/* 8*/   "Spain (PAL)", "Germany, Austria & Switzerland (PAL)", "Italy (PAL)", "Hong Kong & China (PAL)",
49/* c*/   "Indonesia (PAL)", "South Korea (NTSC)", UNK, UNK,
50};
51
52/* Some known companies (integrations to the list from Snes9x) */
53static const char *const companies[] =
54{
55/* 0*/   "Invalid", "Nintendo", "Ajinomoto", "Imagineer-Zoom", "Chris Gray Enterprises Inc.", "Zamuse", "Falcom", UNK,
56/* 8*/   "Capcom", "HOT-B", "Jaleco", "Coconuts", "Rage Software", "Micronet", "Technos", "Mebio Software",
57/*10*/   "SHOUEi System", "Starfish", "Gremlin Graphics", "Electronic Arts", "NCS / Masaya", "COBRA Team", "Human/Field", "KOEI",
58/*18*/   "Hudson Soft", "Game Village", "Yanoman", UNK, "Tecmo", UNK, "Open System", "Virgin Games",
59/*20*/   "KSS", "Sunsoft", "POW", "Micro World", UNK, UNK, "Enix", "Loriciel/Electro Brain",
60/*28*/   "Kemco", "Seta Co.,Ltd.", "Culture Brain", "Irem Japan", "Pal Soft", "Visit Co.,Ltd.", "INTEC Inc.", "System Sacom Corp.",
61/*30*/   "Viacom New Media", "Carrozzeria", "Dynamic", "Nintendo", "Magifact", "Hect", UNK, UNK,
62/*38*/   "Capcom Europe", "Accolade Europe", UNK, "Arcade Zone", "Empire Software", "Loriciel", "Gremlin Graphics", UNK,
63/*40*/   "Seika Corp.", "UBI Soft", UNK, UNK, "LifeFitness Exertainment", UNK, "System 3", "Spectrum Holobyte",
64/*48*/   UNK, "Irem", UNK, "Raya Systems/Sculptured Software", "Renovation Products", "Malibu Games/Black Pearl", UNK, "U.S. Gold",
65/*50*/   "Absolute Entertainment", "Acclaim", "Activision", "American Sammy", "GameTek", "Hi Tech Expressions", "LJN Toys", UNK,
66/*58*/   UNK, UNK, "Mindscape", "Romstar, Inc.", UNK, "Tradewest", UNK, "American Softworks Corp.",
67/*60*/   "Titus", "Virgin Interactive Entertainment", "Maxis", "Origin/FCI/Pony Canyon", UNK, UNK, UNK, "Ocean",
68/*68*/   UNK, "Electronic Arts", UNK, "Laser Beam", UNK, UNK, "Elite", "Electro Brain",
69/*70*/   "Infogrames", "Interplay", "LucasArts", "Parker Brothers", "Konami", "STORM", UNK, UNK,
70/*78*/   "THQ Software", "Accolade Inc.", "Triffix Entertainment", UNK, "Microprose", UNK, UNK, "Kemco",
71/*80*/   "Misawa", "Teichio", "Namco Ltd.", "Lozc", "Koei", UNK, "Tokuma Shoten Intermedia", "Tsukuda Original",
72/*88*/   "DATAM-Polystar", UNK, UNK, "Bullet-Proof Software", "Vic Tokai", UNK, "Character Soft", "I\'\'Max",
73/*90*/   "Takara", "CHUN Soft", "Video System Co., Ltd.", "BEC", UNK, "Varie", "Yonezawa / S'Pal Corp.", "Kaneco",
74/*98*/   UNK, "Pack in Video", "Nichibutsu", "TECMO", "Imagineer Co.", UNK, UNK, UNK,
75/*a0*/   "Telenet", "Hori", UNK, UNK, "Konami", "K.Amusement Leasing Co.", UNK, "Takara",
76/*a8*/   UNK, "Technos Jap.", "JVC", UNK, "Toei Animation", "Toho", UNK, "Namco Ltd.",
77/*b0*/   "Media Rings Corp.", "ASCII Co. Activison", "Bandai", UNK, "Enix America", UNK, "Halken", UNK,
78/*b8*/   UNK, UNK, "Culture Brain", "Sunsoft", "Toshiba EMI", "Sony Imagesoft", UNK, "Sammy",
79/*c0*/   "Taito", UNK, "Kemco", "Square", "Tokuma Soft", "Data East", "Tonkin House", UNK,
80/*c8*/   "KOEI", UNK, "Konami USA", "NTVIC", UNK, "Meldac", "Pony Canyon", "Sotsu Agency/Sunrise",
81/*d0*/   "Disco/Taito", "Sofel", "Quest Corp.", "Sigma", "Ask Kodansha Co., Ltd.", UNK, "Naxat", UNK,
82/*d8*/   "Capcom Co., Ltd.", "Banpresto", "Tomy", "Acclaim", UNK, "NCS", "Human Entertainment", "Altron",
83/*e0*/   "Jaleco", UNK, "Yutaka", UNK, "T&ESoft", "EPOCH Co.,Ltd.", UNK, "Athena",
84/*e8*/   "Asmik", "Natsume", "King Records", "Atlus", "Sony Music Entertainment", UNK, "IGS", UNK,
85/*f0*/   UNK, "Motown Software", "Left Field Entertainment", "Beam Software", "Tec Magik", UNK, UNK, UNK,
86/*f8*/   UNK, "Cybersoft", UNK, "Psygnosis", UNK, UNK, "Davidson", UNK,
87};
88
89
90/* We use this to convert the company_id in the header to int value to be passed in companies[] */
91static int char_to_int_conv( char id )
92{
93   int value;
94
95   if (id == '1') value = 0x01;
96   else if (id == '2') value = 0x02;
97   else if (id == '3') value = 0x03;
98   else if (id == '4') value = 0x04;
99   else if (id == '5') value = 0x05;
100   else if (id == '6') value = 0x06;
101   else if (id == '7') value = 0x07;
102   else if (id == '8') value = 0x08;
103   else if (id == '9') value = 0x09;
104   else if (id == 'A') value = 0x0a;
105   else if (id == 'B') value = 0x0b;
106   else if (id == 'C') value = 0x0c;
107   else if (id == 'D') value = 0x0d;
108   else if (id == 'E') value = 0x0e;
109   else if (id == 'F') value = 0x0f;
110   else value = 0x00;
111
112   return value;
113}
114
115
116/***************************************************************************
117
118  SRAM handling
119
120***************************************************************************/
121
122/* Loads the battery backed RAM into the appropriate memory area */
123static void snes_load_sram(running_machine &machine)
124{
125   snes_state *state = machine.driver_data<snes_state>();
126   UINT8 ii;
127   UINT8 *battery_ram, *ptr;
128
129   battery_ram = (UINT8*)malloc(state->m_cart[0].sram_max);
130   ptr = battery_ram;
131   device_image_interface *image = dynamic_cast<device_image_interface *>(machine.device("cart"));
132   image->battery_load(battery_ram, state->m_cart[0].sram_max, 0xff);
133
134   if (state->m_cart[0].mode == SNES_MODE_20)
135   {
136      UINT32 size = state->m_cart[0].small_sram ? 0x8000 : 0x10000;
137
138      /* There could be some larger image needing banks 0x70 to 0x7f at address 0x8000 for ROM
139         * mirroring. These should be treated separately or data would be overwritten by SRAM */
140      for (ii = 0; ii < 16; ii++)
141      {
142         /* loading */
143         memmove(&snes_ram[0x700000 + (ii * 0x010000)], ptr, size);
144         /* mirroring */
145         memcpy(&snes_ram[0xf00000 + (ii * 0x010000)], &snes_ram[0x700000 + (ii * 0x010000)], size);
146         ptr += size;
147      }
148   }
149   else if (state->m_cart[0].mode == SNES_MODE_21)
150   {
151      for (ii = 0; ii < 16; ii++)
152      {
153         /* loading */
154         memmove(&snes_ram[0x306000 + (ii * 0x010000)], ptr, 0x2000);
155         /* mirroring */
156         memcpy(&snes_ram[0xb06000 + (ii * 0x010000)], &snes_ram[0x306000 + (ii * 0x010000)], 0x2000);
157         ptr += 0x2000;
158      }
159   }
160   else if (state->m_cart[0].mode == SNES_MODE_25)
161   {
162      for (ii = 0; ii < 16; ii++)
163      {
164         memmove(&snes_ram[0xb06000 + (ii * 0x010000)], ptr, 0x2000);
165         ptr += 0x2000;
166      }
167   }
168
169   free(battery_ram);
170}
171
172/* Saves the battery backed RAM from the appropriate memory area */
173static void snes_save_sram(running_machine &machine)
174{
175   snes_state *state = machine.driver_data<snes_state>();
176   UINT8 ii;
177   UINT8 *battery_ram, *ptr;
178
179   battery_ram = (UINT8*)malloc(state->m_cart[0].sram_max);
180   ptr = battery_ram;
181
182   if (state->m_cart[0].mode == SNES_MODE_20)
183   {
184      UINT32 size = state->m_cart[0].small_sram ? 0x8000 : 0x10000;
185
186      for (ii = 0; ii < 16; ii++)
187      {
188         memmove(ptr, &snes_ram[0x700000 + (ii * 0x010000)], size);
189         ptr += size;
190      }
191   }
192   else if (state->m_cart[0].mode == SNES_MODE_21)
193   {
194      for (ii = 0; ii < 16; ii++)
195      {
196         memmove(ptr, &snes_ram[0x306000 + (ii * 0x010000)], 0x2000);
197         ptr += 0x2000;
198      }
199   }
200   else if (state->m_cart[0].mode == SNES_MODE_25)
201   {
202      for (ii = 0; ii < 16; ii++)
203      {
204         memmove(ptr, &snes_ram[0xb06000 + (ii * 0x010000)], 0x2000);
205         ptr += 0x2000;
206      }
207   }
208   device_image_interface *image = dynamic_cast<device_image_interface *>(machine.device("cart"));
209   image->battery_save(battery_ram, state->m_cart[0].sram_max);
210
211   free(battery_ram);
212}
213
214static void snes_machine_stop(running_machine &machine)
215{
216   snes_state *state = machine.driver_data<snes_state>();
217
218   /* Save SRAM */
219   if (state->m_cart[0].sram > 0)
220      snes_save_sram(machine);
221}
222
223MACHINE_START( snes_mess )
224{
225   machine.add_notifier(MACHINE_NOTIFY_EXIT, machine_notify_delegate(FUNC(snes_machine_stop),&machine));
226   MACHINE_START_CALL(snes);
227}
228
229
230static void sufami_load_sram(running_machine &machine, const char *cart_tag)
231{
232   UINT8 ii;
233   UINT8 *battery_ram, *ptr;
234   int st_sram_offset = 0;
235
236   battery_ram = (UINT8*)malloc(0x20000);
237   ptr = battery_ram;
238   device_image_interface *image = dynamic_cast<device_image_interface *>(machine.device(cart_tag));
239   image->battery_load(battery_ram, 0x20000, 0);
240
241   if (strcmp(cart_tag, "slot_a") == 0)
242      st_sram_offset = 0x608000;
243
244   if (strcmp(cart_tag, "slot_b") == 0)
245      st_sram_offset = 0x708000;
246
247   /* Cart RAM is at 0x60-0x63:0x8000-0xffff (+0x10 for slot2) */
248   for (ii = 0; ii < 4; ii++)
249   {
250      /* loading */
251      memcpy(&snes_ram[st_sram_offset + (ii * 0x010000)], ptr + (ii * 0x8000), 0x8000);
252      /* mirroring */
253      memcpy(&snes_ram[0x800000 + st_sram_offset + (ii * 0x010000)], &snes_ram[st_sram_offset + (ii * 0x010000)], 0x8000);
254   }
255
256   free(battery_ram);
257}
258
259static void sufami_machine_stop(running_machine &machine)
260{
261   snes_state *state = machine.driver_data<snes_state>();
262   UINT8 ii;
263   UINT8 *battery_ram, *ptr;
264
265   battery_ram = (UINT8*)malloc(0x20000);
266   ptr = battery_ram;
267
268   if (state->m_cart[0].slot_in_use)
269   {
270      for (ii = 0; ii < 4; ii++)
271      {
272         memmove(ptr + ii * 0x8000, &snes_ram[0x608000 + (ii * 0x010000)], 0x8000);
273      }
274      device_image_interface *image = dynamic_cast<device_image_interface *>(machine.device("slot_a"));
275      image->battery_save(battery_ram, 0x20000);
276   }
277
278   if (state->m_cart[1].slot_in_use)
279   {
280      for (ii = 0; ii < 4; ii++)
281      {
282         memmove(ptr + ii * 0x8000, &snes_ram[0x708000 + (ii * 0x010000)], 0x8000);
283      }
284      device_image_interface *image = dynamic_cast<device_image_interface *>(machine.device("slot_b"));
285      image->battery_save(battery_ram, 0x20000);
286   }
287
288   free(battery_ram);
289}
290
291MACHINE_START( snesst )
292{
293   machine.add_notifier(MACHINE_NOTIFY_EXIT, machine_notify_delegate(FUNC(sufami_machine_stop),&machine));
294   MACHINE_START_CALL(snes);
295}
296
297
298/***************************************************************************
299
300  Cart handling
301
302***************************************************************************/
303
304/* This function assign a 'score' to data immediately after 'offset' to measure how valid they are
305as information block (to decide if the image is HiRom, LoRom, ExLoRom or ExHiRom) */
306/* Code from bsnes, courtesy of byuu - http://byuu.cinnamonpirate.com/ */
307static int snes_validate_infoblock( UINT8 *infoblock, UINT32 offset )
308{
309   int score = 0;
310   UINT16 reset_vector = infoblock[offset + 0x3c] | (infoblock[offset + 0x3d] << 8);
311   UINT16 checksum     = infoblock[offset + 0x1e] | (infoblock[offset + 0x1f] << 8);
312   UINT16 ichecksum    = infoblock[offset + 0x1c] | (infoblock[offset + 0x1d] << 8);
313   UINT8 reset_opcode  = infoblock[(offset & ~0x7fff) | (reset_vector & 0x7fff)];   //first opcode executed upon reset
314   UINT8 mapper        = infoblock[offset + 0x15] & ~0x10;                     //mask off irrelevent FastROM-capable bit
315
316   /* $00:[000-7fff] contains uninitialized RAM and MMIO.
317    reset vector must point to ROM at $00:[8000-ffff] to be considered valid. */
318   if (reset_vector < 0x8000)
319      return 0;
320
321   /* some images duplicate the header in multiple locations, and others have completely
322    invalid header information that cannot be relied upon. The code below will analyze
323    the first opcode executed at the specified reset vector to determine the probability
324    that this is the correct header. Score is assigned accordingly. */
325
326   /* most likely opcodes */
327   if (reset_opcode == 0x78      //sei
328      || reset_opcode == 0x18      //clc (clc; xce)
329      || reset_opcode == 0x38      //sec (sec; xce)
330      || reset_opcode == 0x9c      //stz $nnnn (stz $4200)
331      || reset_opcode == 0x4c      //jmp $nnnn
332      || reset_opcode == 0x5c      //jml $nnnnnn
333   )
334      score += 8;
335
336   /* plausible opcodes */
337   if (reset_opcode == 0xc2      //rep #$nn
338      || reset_opcode == 0xe2      //sep #$nn
339      || reset_opcode == 0xad      //lda $nnnn
340      || reset_opcode == 0xae      //ldx $nnnn
341      || reset_opcode == 0xac      //ldy $nnnn
342      || reset_opcode == 0xaf      //lda $nnnnnn
343      || reset_opcode == 0xa9      //lda #$nn
344      || reset_opcode == 0xa2      //ldx #$nn
345      || reset_opcode == 0xa0      //ldy #$nn
346      || reset_opcode == 0x20      //jsr $nnnn
347      || reset_opcode == 0x22      //jsl $nnnnnn
348   )
349      score += 4;
350
351   /* implausible opcodes */
352   if (reset_opcode == 0x40      //rti
353      || reset_opcode == 0x60      //rts
354      || reset_opcode == 0x6b      //rtl
355      || reset_opcode == 0xcd      //cmp $nnnn
356      || reset_opcode == 0xec      //cpx $nnnn
357      || reset_opcode == 0xcc      //cpy $nnnn
358   )
359      score -= 4;
360
361   /* least likely opcodes */
362   if (reset_opcode == 0x00      //brk #$nn
363      || reset_opcode == 0x02      //cop #$nn
364      || reset_opcode == 0xdb      //stp
365      || reset_opcode == 0x42      //wdm
366      || reset_opcode == 0xff      //sbc $nnnnnn,x
367   )
368      score -= 8;
369
370   /* Sometimes, both the header and reset vector's first opcode will match ...
371    fallback and rely on info validity in these cases to determine more likely header. */
372
373   /* a valid checksum is the biggest indicator of a valid header. */
374   if ((checksum + ichecksum) == 0xffff && (checksum != 0) && (ichecksum != 0))
375      score += 4;
376
377   /* then there are the expected mapper values */
378   if (offset == 0x007fc0 && mapper == 0x20)   // 0x20 is usually LoROM
379      score += 2;
380
381   if (offset == 0x00ffc0 && mapper == 0x21)   // 0x21 is usually HiROM
382      score += 2;
383
384   if (offset == 0x007fc0 && mapper == 0x22)   // 0x22 is usually ExLoROM
385      score += 2;
386
387   if (offset == 0x40ffc0 && mapper == 0x25)   // 0x25 is usually ExHiROM
388      score += 2;
389
390   /* finally, there are valid values in the Company, Region etc. fields */
391   if (infoblock[offset + 0x1a] == 0x33)         // Company field: 0x33 indicates extended header
392      score += 2;
393
394   if (infoblock[offset + 0x16] < 0x08)         // ROM Type field
395      score++;
396
397   if (infoblock[offset + 0x17] < 0x10)         // ROM Size field
398      score++;
399
400   if (infoblock[offset + 0x18] < 0x08)         // SRAM Size field
401      score++;
402
403   if (infoblock[offset + 0x19] < 14)            // Region field
404      score++;
405
406   /* do we still have a positive score? */
407   if (score < 0)
408      score = 0;
409
410   return score;
411}
412
413/* Here we add a couple of cart utilities, to avoid duplicating the code in each DEVICE_IMAGE_LOAD */
414static UINT32 snes_skip_header( device_image_interface &image, UINT32 snes_rom_size )
415{
416   UINT8 header[512];
417   UINT32 offset = 512;
418
419   /* Check for a header (512 bytes) */
420   if (image.software_entry() == NULL)
421      image.fread( header, 512);
422   else
423      memcpy(header, image.get_software_region("rom"), 512);
424
425   if ((header[8] == 0xaa) && (header[9] == 0xbb) && (header[10] == 0x04))
426   {
427      /* Found an SWC identifier */
428      logerror("Found header (SWC) - Skipped\n");
429   }
430   else if ((header[0] | (header[1] << 8)) == (((snes_rom_size - 512) / 1024) / 8))
431   {
432      /* Some headers have the rom size at the start, if this matches with the actual rom size, we probably have a header */
433      logerror("Found header (size) - Skipped\n");
434   }
435   else if ((snes_rom_size % 0x8000) == 512)
436   {
437      /* As a last check we'll see if there's exactly 512 bytes extra to this image. */
438      logerror("Found header (extra) - Skipped\n");
439   }
440   else
441   {
442      /* No header found so go back to the start of the file */
443      logerror("No header found.\n");
444      offset = 0;
445   }
446
447   return offset;
448}
449
450
451/* This determines if a cart is in Mode 20, 21, 22 or 25; sets state->m_cart[0].mode and
452 state->m_cart[0].sram accordingly; and returns the offset of the internal header (needed to
453 detect BSX and ST carts) */
454static UINT32 snes_find_hilo_mode( device_image_interface &image, UINT8 *buffer, UINT32 offset, int cartid )
455{
456   snes_state *state = image.device().machine().driver_data<snes_state>();
457   UINT8 valid_mode20, valid_mode21, valid_mode25;
458   UINT32 retvalue;
459
460   /* Now to determine if this is a lo-ROM, a hi-ROM or an extended lo/hi-ROM */
461   valid_mode20 = snes_validate_infoblock(buffer, 0x007fc0);
462   valid_mode21 = snes_validate_infoblock(buffer, 0x00ffc0);
463   valid_mode25 = snes_validate_infoblock(buffer, 0x40ffc0);
464
465   /* Images larger than 32mbits are likely ExHiRom */
466   if (valid_mode25)
467      valid_mode25 += 4;
468
469   if ((valid_mode20 >= valid_mode21) && (valid_mode20 >= valid_mode25))
470   {
471      if ((buffer[0x007fd5] == 0x32) || ((state->m_cart_size - offset) > 0x401000))
472         state->m_cart[cartid].mode = SNES_MODE_22;   // ExLoRom
473      else
474         state->m_cart[cartid].mode = SNES_MODE_20;   // LoRom
475
476      retvalue = 0x007fc0;
477
478      /* a few games require 512k, however we store twice as much to be sure to cover the various mirrors */
479      state->m_cart[cartid].sram_max = 0x100000;
480   }
481   else if (valid_mode21 >= valid_mode25)
482   {
483      state->m_cart[cartid].mode = SNES_MODE_21;   // HiRom
484      retvalue = 0x00ffc0;
485      state->m_cart[cartid].sram_max = 0x20000;
486   }
487   else
488   {
489      state->m_cart[cartid].mode = SNES_MODE_25;   // ExHiRom
490      retvalue = 0x40ffc0;
491      state->m_cart[cartid].sram_max = 0x20000;
492   }
493
494   logerror( "\t HiROM/LoROM id: %s (LoROM: %d , HiROM: %d, ExHiROM: %d)\n",
495          (state->m_cart[cartid].mode == SNES_MODE_20) ? "LoROM" :
496          (state->m_cart[cartid].mode == SNES_MODE_21) ? "HiROM" :
497          (state->m_cart[cartid].mode == SNES_MODE_22) ? "ExLoROM" :
498          (state->m_cart[cartid].mode == SNES_MODE_25) ? "ExHiROM" : "Other (BSX or ST)",
499          valid_mode20, valid_mode21, valid_mode25);
500
501   return retvalue;
502}
503
504static int snes_find_addon_chip( running_machine &machine )
505{
506   snes_state *state = machine.driver_data<snes_state>();
507   address_space *space = machine.device("maincpu")->memory().space(AS_PROGRAM);
508   int supported_type = 1;
509   int dsp_prg_offset = 0;
510
511   /* Info mostly taken from http://snesemu.black-ship.net/misc/-from%20nsrt.edgeemu.com-chipinfo.htm */
512   switch (snes_r_bank1(space, 0x00ffd6))
513   {
514      case 0x00:
515      case 0x01:
516      case 0x02:
517         state->m_has_addon_chip = HAS_NONE;
518         break;
519
520      case 0x03:
521         if (snes_r_bank1(space, 0x00ffd5) == 0x30)
522         {
523            state->m_has_addon_chip = HAS_DSP4;
524            dsp_prg_offset = SNES_DSP4_OFFSET;
525         }
526         else
527         {
528            state->m_has_addon_chip = HAS_DSP1;
529            dsp_prg_offset = SNES_DSP1B_OFFSET;
530         }
531         break;
532
533      case 0x04:
534         state->m_has_addon_chip = HAS_DSP1;
535         dsp_prg_offset = SNES_DSP1B_OFFSET;
536         break;
537
538      case 0x05:
539         if (snes_r_bank1(space, 0x00ffd5) == 0x20)
540         {
541            state->m_has_addon_chip = HAS_DSP2;
542            dsp_prg_offset = SNES_DSP2_OFFSET;
543         }
544         /* DSP-3 is hard to detect. We exploit the fact that the only game has been manufactured by Bandai */
545         else if ((snes_r_bank1(space, 0x00ffd5) == 0x30) && (snes_r_bank1(space, 0x00ffda) == 0xb2))
546         {
547            state->m_has_addon_chip = HAS_DSP3;
548            dsp_prg_offset = SNES_DSP3_OFFSET;
549         }
550         else
551         {
552            state->m_has_addon_chip = HAS_DSP1;
553            dsp_prg_offset = SNES_DSP1B_OFFSET;
554         }
555         break;
556
557      case 0x13:   // Mario Chip 1
558      case 0x14:   // GSU-x
559      case 0x15:   // GSU-x
560      case 0x1a:   // GSU-1 (21 MHz at start)
561         if (snes_r_bank1(space, 0x00ffd5) == 0x20)
562            state->m_has_addon_chip = HAS_SUPERFX;
563         break;
564
565      case 0x25:
566         state->m_has_addon_chip = HAS_OBC1;
567         break;
568
569      case 0x32:   // needed by a Sample game (according to ZSNES)
570      case 0x34:
571      case 0x35:
572         if (snes_r_bank1(space, 0x00ffd5) == 0x23)
573         {
574            state->m_has_addon_chip = HAS_SA1;
575            supported_type = 0;
576            mame_printf_error("This is a SA-1 type game, currently unsupported by the driver\n");
577         }
578         break;
579
580      case 0x43:
581      case 0x45:
582         if (snes_r_bank1(space, 0x00ffd5) == 0x32)
583         {
584            state->m_has_addon_chip = HAS_SDD1;
585         }
586         break;
587
588      case 0x55:
589         if (snes_r_bank1(space, 0x00ffd5) == 0x35)
590         {
591            state->m_has_addon_chip = HAS_RTC;
592         }
593         break;
594
595      case 0xe3:
596         state->m_has_addon_chip = HAS_Z80GB;
597         supported_type = 0;
598         break;
599
600      case 0xf3:
601         state->m_has_addon_chip = HAS_CX4;
602         break;
603
604      case 0xf5:
605         if (snes_r_bank1(space, 0x00ffd5) == 0x30)
606         {
607            state->m_has_addon_chip = HAS_ST018;
608            supported_type = 0;
609         }
610         else if (snes_r_bank1(space, 0x00ffd5) == 0x3a)
611         {
612            state->m_has_addon_chip = HAS_SPC7110;
613         }
614         break;
615
616      case 0xf6:
617         /* These Seta ST-01X chips have both 0x30 at 0x00ffd5,
618             they only differ for the 'size' at 0x00ffd7 */
619         if (snes_r_bank1(space, 0x00ffd7) < 0x0a)
620            state->m_has_addon_chip = HAS_ST011;
621         else
622            state->m_has_addon_chip = HAS_ST010;
623
624         // if we are loading the game in a driver without the ST01X DSP, revert to HAS_NONE to avoid crash
625         if (!state->m_upd96050)
626            state->m_has_addon_chip = HAS_NONE;
627         break;
628
629      case 0xf9:
630         if (snes_r_bank1(space, 0x00ffd5) == 0x3a)
631         {
632            state->m_has_addon_chip = HAS_SPC7110_RTC;
633            supported_type = 0;
634         }
635         break;
636
637      default:
638         state->m_has_addon_chip = HAS_UNK;
639         supported_type = 0;
640         break;
641   }
642
643   if ((state->m_has_addon_chip >= HAS_DSP1) && (state->m_has_addon_chip <= HAS_DSP4))
644   {
645      UINT8 *dspsrc = (UINT8 *)machine.region("addons")->base();
646      UINT32 *dspprg = (UINT32 *)machine.region("dspprg")->base();
647      UINT16 *dspdata = (UINT16 *)machine.region("dspdata")->base();
648
649      // copy DSP program
650      for (int i = 0; i < 0x2000; i+= 4)
651      {
652         *dspprg = dspsrc[dsp_prg_offset+0+i]<<24 | dspsrc[dsp_prg_offset+1+i]<<16 | dspsrc[dsp_prg_offset+2+i]<<8;
653         dspprg++;
654      }
655
656      // copy DSP data
657      for (int i = 0; i < 0x800; i+= 2)
658      {
659         *dspdata++ = dspsrc[dsp_prg_offset+0x2000+i]<<8 | dspsrc[dsp_prg_offset+0x2001+i];
660      }
661   }
662
663   if ((state->m_has_addon_chip == HAS_ST010) || (state->m_has_addon_chip == HAS_ST011))
664   {
665      UINT8 *dspsrc = (UINT8 *)machine.region("addons")->base();
666      UINT32 *dspprg = (UINT32 *)machine.region("dspprg")->base();
667      UINT16 *dspdata = (UINT16 *)machine.region("dspdata")->base();
668
669      // copy DSP program
670      for (int i = 0; i < 0x10000; i+= 4)
671      {
672         *dspprg = dspsrc[0+i]<<24 | dspsrc[1+i]<<16 | dspsrc[2+i]<<8;
673         dspprg++;
674      }
675
676      // copy DSP data
677      for (int i = 0; i < 0x1000; i+= 2)
678      {
679         *dspdata++ = dspsrc[0x10000+i]<<8 | dspsrc[0x10001+i];
680      }
681   }
682
683   return supported_type;
684}
685
686static void snes_cart_log_info( running_machine &machine, int total_blocks, int supported )
687{
688   snes_state *state = machine.driver_data<snes_state>();
689   address_space *space = machine.device("maincpu")->memory().space(AS_PROGRAM);
690   char title[21], rom_id[4], company_id[2];
691   int i, company, has_ram = 0, has_sram = 0;
692
693   /* Company */
694   for (i = 0; i < 2; i++)
695      company_id[i] = snes_r_bank1(space, 0x00ffb0 + i);
696   company = (char_to_int_conv(company_id[0]) << 4) + char_to_int_conv(company_id[1]);
697   if (company == 0)
698      company = snes_r_bank1(space, 0x00ffda);
699
700   /* ROM ID */
701   for( i = 0; i < 4; i++ )
702      rom_id[i] = snes_r_bank1(space, 0x00ffb2 + i);
703
704   /* Title */
705   for( i = 0; i < 21; i++ )
706      title[i] = snes_r_bank1(space, 0x00ffc0 + i);
707
708   /* RAM */
709   if (((snes_r_bank1(space, 0x00ffd6) & 0xf) == 1) ||
710      ((snes_r_bank1(space, 0x00ffd6) & 0xf) == 2) ||
711      ((snes_r_bank1(space, 0x00ffd6) & 0xf) == 4) ||
712      ((snes_r_bank1(space, 0x00ffd6) & 0xf) == 5))
713      has_ram = 1;
714
715   /* SRAM */
716   if (((snes_r_bank1(space, 0x00ffd6) & 0xf) == 2) ||
717      ((snes_r_bank1(space, 0x00ffd6) & 0xf) == 5) ||
718      ((snes_r_bank1(space, 0x00ffd6) & 0xf) == 6))
719      has_sram = 1;
720
721   logerror( "ROM DETAILS\n" );
722   logerror( "===========\n\n" );
723   logerror( "\tTotal blocks:  %d (%dmb)\n", total_blocks, total_blocks / (state->m_cart[0].mode & 5 ? 32 : 16) );
724   logerror( "\tROM bank size: %s \n",
725          (state->m_cart[0].mode == SNES_MODE_20) ? "LoROM" :
726          (state->m_cart[0].mode == SNES_MODE_21) ? "HiROM" :
727          (state->m_cart[0].mode == SNES_MODE_22) ? "ExLoROM" :
728          (state->m_cart[0].mode == SNES_MODE_25) ? "ExHiROM" : "Other (BSX or ST)" );
729   logerror( "\tCompany:       %s [%.2s]\n", companies[company], company_id );
730   logerror( "\tROM ID:        %.4s\n\n", rom_id );
731
732   logerror( "HEADER DETAILS\n" );
733   logerror( "==============\n\n" );
734   logerror( "\tName:          %.21s\n", title );
735   logerror( "\tSpeed:         %s [%d]\n", ((snes_r_bank1(space, 0x00ffd5) & 0xf0)) ? "FastROM" : "SlowROM", (snes_r_bank1(space, 0x00ffd5) & 0xf0) >> 4 );
736   logerror( "\tBank size:     %s [%d]\n", (snes_r_bank1(space, 0x00ffd5) & 0xf) ? "HiROM" : "LoROM", snes_r_bank1(space, 0x00ffd5) & 0xf );
737
738   logerror( "\tType:          %s", types[state->m_has_addon_chip]);
739   if (has_ram)
740      logerror( ", RAM");
741   if (has_sram)
742      logerror( ", SRAM");
743   logerror( " [%d]\n", snes_r_bank1(space, 0x00ffd6) );
744
745   logerror( "\tSize:          %d megabits [%d]\n", 1 << (snes_r_bank1(space, 0x00ffd7) - 7), snes_r_bank1(space, 0x00ffd7) );
746   logerror( "\tSRAM:          %d kilobits [%d]\n", state->m_cart[0].sram * 8, snes_ram[0xffd8] );
747   logerror( "\tCountry:       %s [%d]\n", countries[snes_r_bank1(space, 0x00ffd9)], snes_r_bank1(space, 0x00ffd9) );
748   logerror( "\tLicense:       %s [%X]\n", companies[snes_r_bank1(space, 0x00ffda)], snes_r_bank1(space, 0x00ffda) );
749   logerror( "\tVersion:       1.%d\n", snes_r_bank1(space, 0x00ffdb) );
750   logerror( "\tInv Checksum:  %X %X\n", snes_r_bank1(space, 0x00ffdd), snes_r_bank1(space, 0x00ffdc) );
751   logerror( "\tChecksum:      %X %X\n", snes_r_bank1(space, 0x00ffdf), snes_r_bank1(space, 0x00ffde) );
752   logerror( "\tNMI Address:   %2X%2Xh\n", snes_r_bank1(space, 0x00fffb), snes_r_bank1(space, 0x00fffa) );
753   logerror( "\tStart Address: %2X%2Xh\n\n", snes_r_bank1(space, 0x00fffd), snes_r_bank1(space, 0x00fffc) );
754
755   logerror( "\tMode: %d\n", state->m_cart[0].mode);
756
757   if (!supported)
758      logerror("WARNING: This cart type \"%s\" is not supported yet!\n", types[state->m_has_addon_chip]);
759}
760
761static DEVICE_IMAGE_LOAD( snes_cart )
762{
763   int supported_type = 1, i, j;
764   running_machine &machine = image.device().machine();
765   snes_state *state = machine.driver_data<snes_state>();
766   address_space *space = machine.device( "maincpu")->memory().space( AS_PROGRAM );
767   int total_blocks, read_blocks, has_bsx_slot = 0, st_bios = 0;
768   UINT32 offset, int_header_offs;
769   UINT8 *ROM = image.device().machine().region("cart")->base();
770
771   if (image.software_entry() == NULL)
772      state->m_cart_size = image.length();
773   else
774      state->m_cart_size = image.get_software_region_length("rom");
775
776   /* Check for a header (512 bytes), and skip it if found */
777   offset = snes_skip_header(image, state->m_cart_size);
778
779   if (image.software_entry() == NULL)
780   {
781      image.fseek(offset, SEEK_SET);
782      image.fread( ROM, state->m_cart_size - offset);
783   }
784   else
785      memcpy(ROM, image.get_software_region("rom") + offset, state->m_cart_size - offset);
786
787   if (SNES_CART_DEBUG) mame_printf_error("size %08X\n", state->m_cart_size - offset);
788
789   /* First, look if the cart is HiROM or LoROM (and set snes_cart accordingly) */
790   int_header_offs = snes_find_hilo_mode(image, ROM, offset, 0);
791
792   /* Then, detect BS-X carts */
793   // Detect presence of BS-X Flash Cart
794   if ((ROM[int_header_offs + 0x13] == 0x00 || ROM[int_header_offs + 0x13] == 0xff) &&
795         ROM[int_header_offs + 0x14] == 0x00)
796   {
797      UINT8 n15 = ROM[int_header_offs + 0x15];
798      if (n15 == 0x00 || n15 == 0x80 || n15 == 0x84 || n15 == 0x9c || n15 == 0xbc || n15 == 0xfc)
799      {
800         if (ROM[int_header_offs + 0x1a] == 0x33 || ROM[int_header_offs + 0x1a] == 0xff)
801         {
802            // BS-X Flash Cart
803            state->m_cart[0].mode = SNES_MODE_BSX;
804         }
805      }
806   }
807
808   // Detect presence of BS-X flash cartridge connector
809   if ((ROM[int_header_offs - 14] == 'Z') && (ROM[int_header_offs - 11] == 'J'))
810   {
811      UINT8 n13 = ROM[int_header_offs - 13];
812      if ((n13 >= 'A' && n13 <= 'Z') || (n13 >= '0' && n13 <= '9'))
813      {
814         if (ROM[int_header_offs + 0x1a] == 0x33 ||
815            (ROM[int_header_offs - 10] == 0x00 && ROM[int_header_offs - 4] == 0x00))
816         {
817            has_bsx_slot = 1;
818         }
819      }
820   }
821
822   // If there is a BS-X connector, detect if it is the Base Cart or a compatible slotted cart
823   if (has_bsx_slot)
824   {
825      if (!memcmp(ROM + int_header_offs, "Satellaview BS-X     ", 21))
826      {
827         //BS-X Base Cart
828         state->m_cart[0].mode = SNES_MODE_BSX;
829         // handle RAM
830      }
831      else
832      {
833         state->m_cart[0].mode = (int_header_offs ==0x007fc0) ? SNES_MODE_BSLO : SNES_MODE_BSHI;
834         // handle RAM?
835      }
836   }
837
838   /* Then, detect Sufami Turbo carts */
839   if (!memcmp(ROM, "BANDAI SFC-ADX", 14))
840   {
841      state->m_cart[0].mode = SNES_MODE_ST;
842      if (!memcmp(ROM + 16, "SFC-ADX BACKUP", 14))
843         st_bios = 1;
844   }
845
846   if (SNES_CART_DEBUG) mame_printf_error("mode %d\n", state->m_cart[0].mode);
847
848   /* FIXME: Insert crc check here? */
849
850   /* How many blocks of data are available to be loaded? */
851   total_blocks = ((state->m_cart_size - offset) / (state->m_cart[0].mode & 0xa5 ? 0x8000 : 0x10000));
852   read_blocks = 0;
853
854   if (SNES_CART_DEBUG) mame_printf_error("blocks %d\n", total_blocks);
855
856   /* Loading all the data blocks from cart, we only partially cover banks 0x00 to 0x7f. Therefore, we
857     * have to mirror the blocks until we reach the end. E.g. for a 11Mbits image (44 blocks), we proceed
858     * as follows:
859     * 11 Mbits = 8 Mbits (blocks 1->32) + 2 Mbits (blocks 33->40) + 1 Mbit (blocks 41->44).
860     * Hence, we fill memory up to 16 Mbits (banks 0x00 to 0x3f) mirroring as follows
861     * 8 Mbits (blocks 1->32) + 2 Mbits (blocks 33->40) + 1 Mbit (blocks 41->44) + 1 Mbit (blocks 41->44)
862     *   + 2 Mbits (blocks 33->40) + 1 Mbit (blocks 41->44) + 1 Mbit (blocks 41->44)
863     * and we repeat the same blocks in the second half of the banks (banks 0x40 to 0x7f).
864     * This is likely what happens in the real SNES as well, because the unit cannot be aware of the exact
865     * size of data in the cart (procedure confirmed by byuu)
866     */
867   switch (state->m_cart[0].mode)
868   {
869      case SNES_MODE_21:
870      /* HiROM carts load data in banks 0xc0 to 0xff. Each bank is fully mirrored in banks 0x40 to 0x7f
871         * (actually up to 0x7d, because 0x7e and 0x7f are overwritten by WRAM). The top half (address
872         * range 0x8000 - 0xffff) of each bank is also mirrored in banks 0x00 to 0x3f and 0x80 to 0xbf.
873         */
874         /* SPC7110 games needs this different loading routine */
875         if ((ROM[0x00ffd6] == 0xf9 || ROM[0x00ffd6] == 0xf5) && (ROM[0x00ffd5] == 0x3a))
876         {
877            while (read_blocks < 16 && read_blocks < total_blocks)
878            {
879               /* Loading data */
880               memcpy(&snes_ram[0xc00000 + read_blocks * 0x10000], &ROM[0x000000 + read_blocks * 0x10000], 0x10000);
881               /* Mirroring */
882               memcpy(&snes_ram[0x008000 + read_blocks * 0x10000], &snes_ram[0xc08000 + read_blocks * 0x10000], 0x8000);
883               memcpy(&snes_ram[0x808000 + read_blocks * 0x10000], &snes_ram[0xc08000 + read_blocks * 0x10000], 0x8000);
884               read_blocks++;
885            }
886         }
887         else
888         {
889            while (read_blocks < 64 && read_blocks < total_blocks)
890            {
891               /* Loading data */
892               memcpy(&snes_ram[0xc00000 + read_blocks * 0x10000], &ROM[0x000000 + read_blocks * 0x10000], 0x10000);
893               /* Mirroring */
894               memcpy(&snes_ram[0x008000 + read_blocks * 0x10000], &snes_ram[0xc08000 + read_blocks * 0x10000], 0x8000);
895               memcpy(&snes_ram[0x400000 + read_blocks * 0x10000], &snes_ram[0xc00000 + read_blocks * 0x10000], 0x10000);
896               memcpy(&snes_ram[0x808000 + read_blocks * 0x10000], &snes_ram[0xc08000 + read_blocks * 0x10000], 0x8000);
897               read_blocks++;
898            }
899            /* Filling banks up to 0xff and their mirrors */
900            while (read_blocks % 64)
901            {
902               int j = 0, repeat_blocks;
903               while ((read_blocks % (64 >> j)) && j < 6)
904                  j++;
905               repeat_blocks = read_blocks % (64 >> (j - 1));
906
907               memcpy(&snes_ram[0xc00000 + read_blocks * 0x10000], &snes_ram[0xc00000 + (read_blocks - repeat_blocks) * 0x10000], repeat_blocks * 0x10000);
908               memcpy(&snes_ram[read_blocks * 0x10000], &snes_ram[(read_blocks - repeat_blocks) * 0x10000], repeat_blocks * 0x10000);
909               memcpy(&snes_ram[0x400000 + read_blocks * 0x10000], &snes_ram[0x400000 + (read_blocks - repeat_blocks) * 0x10000], repeat_blocks * 0x10000);
910               memcpy(&snes_ram[0x800000 + read_blocks * 0x10000], &snes_ram[0x800000 + (read_blocks - repeat_blocks) * 0x10000], repeat_blocks * 0x10000);
911               read_blocks += repeat_blocks;
912            }
913         }
914         break;
915
916      case SNES_MODE_25:
917      /* Extendend HiROM carts start to load data in banks 0xc0 to 0xff. However, they exceed the
918         * available space in these banks, and continue loading at banks 0x40 to 0x7f. The top half
919         * (address range 0x8000 - 0xffff) of each bank is also mirrored either to banks 0x00 to 0x3f
920         * (for data in banks 0x40 to 0x7f) or to banks 0x80 to 0xbf (for data in banks 0xc0 to 0xff).
921         * Notice that banks 0x7e and 0x7f are overwritten by WRAM, but they could contain data at
922         * address > 0x8000 because the mirrors at 0x3e and 0x3f are not overwritten.
923         */
924         /* Reading the first 64 blocks */
925         while (read_blocks < 64 && read_blocks < total_blocks)
926         {
927            /* Loading data */
928            memcpy(&snes_ram[0xc00000 + read_blocks * 0x10000], &ROM[0x000000 + read_blocks * 0x10000], 0x10000);
929            /* Mirroring */
930            memcpy( &snes_ram[0x808000 + read_blocks * 0x10000], &snes_ram[0xc08000 + read_blocks * 0x10000], 0x8000);
931            read_blocks++;
932         }
933         /* ExHiROMs are supposed to be larger than 32Mbits! */
934         if (read_blocks < 64)
935         {
936            logerror("This image has been identified as ExHiROM, but it's too small!\n");
937            logerror("Please verify if it's corrupted. If it's not please report this as a bug.\n");
938            return IMAGE_INIT_FAIL;
939         }
940         /* Scaling down the counter */
941         read_blocks -= 64;
942         /* Reading the next blocks */
943         while (read_blocks < 64  && read_blocks < (total_blocks - 64))
944         {
945            /* Loading data */
946            memcpy(&snes_ram[0x400000 + read_blocks * 0x10000], &ROM[0x400000 + read_blocks * 0x10000], 0x10000);
947            /* Mirroring */
948            memcpy(&snes_ram[0x8000 + read_blocks * 0x10000], &snes_ram[0x408000 + read_blocks * 0x10000], 0x8000);
949            read_blocks++;
950         }
951         /* Filling banks up to 0x7f and their mirrors */
952         while (read_blocks % 64)
953         {
954            int j = 0, repeat_blocks;
955            while ((read_blocks % (64 >> j)) && j < 6)
956               j++;
957            repeat_blocks = read_blocks % (64 >> (j - 1));
958
959            memcpy(&snes_ram[0x400000 + read_blocks * 0x10000], &snes_ram[0x400000 + (read_blocks - repeat_blocks) * 0x10000], repeat_blocks * 0x10000);
960            memcpy(&snes_ram[read_blocks * 0x10000], &snes_ram[(read_blocks - repeat_blocks) * 0x10000], repeat_blocks * 0x10000);
961            read_blocks += repeat_blocks;
962         }
963         break;
964
965      case SNES_MODE_22:
966      /* "Extendend LoROM" carts have their data loaded in banks 0x00 to 0x3f at address 0x8000.
967         * These are then mirrored in banks 0x40 to 0x7f, both at address 0x0000 and at address
968         * 0x8000, in banks 0x80 to 0xbf at address 0x8000 and in banks 0xc0 to 0xff, both at address
969         * 0x0000 and at address 0x8000. Notice that SDD-1 games (Star Ocean and Street Fighter Zero 2)
970         * use SNES_MODE_22
971         */
972         while (read_blocks < 64 && read_blocks < total_blocks)
973         {
974            /* Loading and mirroring data */
975            memcpy(&snes_ram[0x008000 + read_blocks * 0x10000], &ROM[0x000000 + read_blocks * 0x8000], 0x8000);
976            memcpy(&snes_ram[0x808000 + read_blocks * 0x10000], &ROM[0x000000 + read_blocks * 0x8000], 0x8000);
977            memcpy(&snes_ram[0x400000 + read_blocks * 0x10000], &ROM[0x000000 + read_blocks * 0x10000], 0x10000);
978            memcpy(&snes_ram[0xc00000 + read_blocks * 0x10000], &ROM[0x000000 + read_blocks * 0x10000], 0x10000);
979            read_blocks++;
980         }
981         /* Filling banks up to 0x3f and their mirrors */
982         while (read_blocks % 64)
983         {
984            int j = 0, repeat_blocks;
985            while ((read_blocks % (64 >> j)) && j < 6)
986               j++;
987            repeat_blocks = read_blocks % (64 >> (j - 1));
988
989            memcpy(&snes_ram[read_blocks * 0x10000], &snes_ram[(read_blocks - repeat_blocks) * 0x10000], repeat_blocks * 0x10000);
990            memcpy(&snes_ram[0x800000 + read_blocks * 0x10000], &snes_ram[0x800000 + (read_blocks - repeat_blocks) * 0x10000], repeat_blocks * 0x10000);
991            memcpy(&snes_ram[0x400000 + read_blocks * 0x10000], &snes_ram[0x400000 + (read_blocks - repeat_blocks) * 0x10000], repeat_blocks * 0x10000);
992            memcpy(&snes_ram[0xc00000 + read_blocks * 0x10000], &snes_ram[0xc00000 + (read_blocks - repeat_blocks) * 0x10000], repeat_blocks * 0x10000);
993            read_blocks += repeat_blocks;
994         }
995         break;
996
997      case SNES_MODE_ST:
998         if (!st_bios)
999         {
1000            mame_printf_error("This is a Sufami Turbo data cart and cannot be loaded for snes/snespal in MESS.\n");
1001            mame_printf_error("Please use snesst driver to load it, instead.\n");
1002            return IMAGE_INIT_FAIL;
1003         }
1004         else
1005         {
1006            // The Base ST cart consists of 8 * 0x8000 block which have to be loaded (and mirrored)
1007            // at 0x00-0x1f:0x8000-0xffff and 0x80-0x9f:0x8000-0xffff
1008            for (i = 0; i < 8; i++)
1009            {
1010               /* Loading data */
1011               memcpy(&snes_ram[0x008000 + i * 0x10000], &ROM[0x000000 + i * 0x8000], 0x8000);
1012               /* Mirroring */
1013               memcpy(&snes_ram[0x808000 + i * 0x10000], &snes_ram[0x8000 + (i * 0x10000)], 0x8000);
1014
1015               /* Additional mirrors (to fill snes_ram up to 0x1fffff) */
1016               for (j = 1; j < 4; j++)
1017               {
1018                  memcpy(&snes_ram[0x008000 + i * 0x10000 + j * 0x80000], &snes_ram[0x8000 + (i * 0x10000)], 0x8000);
1019                  memcpy(&snes_ram[0x808000 + i * 0x10000 + j * 0x80000], &snes_ram[0x8000 + (i * 0x10000)], 0x8000);
1020               }
1021            }
1022         }
1023         break;
1024
1025      case SNES_MODE_BSX:
1026      case SNES_MODE_BSLO:
1027      case SNES_MODE_BSHI:
1028         /* not handled yet */
1029         mame_printf_error("This is a BS-X Satellaview image: MESS does not support these yet, sorry.\n");
1030#if 0
1031         // shall we force incompatibility of flash carts without a base unit?
1032         if (!has_bsx_slot)
1033         {
1034            mame_printf_error("This is a BS-X flash cart and cannot be loaded in snes/snespal.\n");
1035//              mame_printf_error("Please use snesbsx driver to load it, instead.\n");
1036            return IMAGE_INIT_FAIL;
1037         }
1038#endif
1039         break;
1040
1041      default:
1042      case SNES_MODE_20:
1043      /* LoROM carts load data in banks 0x00 to 0x7f at address 0x8000 (actually up to 0x7d, because 0x7e and
1044         * 0x7f are overwritten by WRAM). Each block is also mirrored in banks 0x80 to 0xff (up to 0xff for real)
1045         */
1046         /* SuperFX games needs this different loading routine */
1047         if (((ROM[0x007fd6] >= 0x13 && ROM[0x007fd6] <= 0x15) || ROM[0x007fd6] == 0x1a) && (ROM[0x007fd5] == 0x20))
1048         {
1049            while (read_blocks < 64 && read_blocks < total_blocks)
1050            {
1051               /* Loading data primary: banks 0-3f from 8000-ffff*/
1052               memcpy(&snes_ram[0x008000 + read_blocks * 0x10000], &ROM[0x000000 + read_blocks * 0x8000], 0x8000);
1053               /* Mirroring at banks 80-bf from 8000-ffff */
1054               memcpy(&snes_ram[0x808000 + read_blocks * 0x10000], &snes_ram[0x8000 + (read_blocks * 0x10000)], 0x8000);
1055               /* Mirroring at banks 40-5f and c0-df */
1056               memcpy(&snes_ram[0x400000 + read_blocks * 0x8000], &snes_ram[0x8000 + (read_blocks * 0x10000)], total_blocks * 0x8000);
1057               memcpy(&snes_ram[0xc00000 + read_blocks * 0x8000], &snes_ram[0x8000 + (read_blocks * 0x10000)], total_blocks * 0x8000);
1058
1059               read_blocks++;
1060            }
1061            /* SuperFX games are supposed to contain 64 blocks! */
1062            if (read_blocks < total_blocks)
1063            {
1064               logerror("This image has been identified as a SuperFX game, but it's too large!\n");
1065               logerror("Please verify if it's corrupted. If it's not please report this as a bug.\n");
1066               return IMAGE_INIT_FAIL;
1067            }
1068         }
1069         else
1070         {
1071            while (read_blocks < 128 && read_blocks < total_blocks)
1072            {
1073               /* Loading data */
1074               memcpy(&snes_ram[0x008000 + read_blocks * 0x10000], &ROM[0x000000 + read_blocks * 0x8000], 0x8000);
1075               /* Mirroring */
1076               memcpy(&snes_ram[0x808000 + read_blocks * 0x10000], &snes_ram[0x8000 + (read_blocks * 0x10000)], 0x8000);
1077               read_blocks++;
1078            }
1079            /* Filling banks up to 0x7f and their mirrors */
1080            while (read_blocks % 128)
1081            {
1082               int j = 0, repeat_blocks;
1083               while ((read_blocks % (128 >> j)) && j < 7)
1084                  j++;
1085               repeat_blocks = read_blocks % (128 >> (j - 1));
1086
1087               memcpy( &snes_ram[read_blocks * 0x10000], &snes_ram[(read_blocks - repeat_blocks) * 0x10000], repeat_blocks * 0x10000);
1088               memcpy( &snes_ram[0x800000 + read_blocks * 0x10000], &snes_ram[(read_blocks - repeat_blocks) * 0x10000], repeat_blocks * 0x10000);
1089               read_blocks += repeat_blocks;
1090            }
1091         }
1092         break;
1093   }
1094
1095   /* Detect special chips */
1096   supported_type = snes_find_addon_chip(machine);
1097
1098   /* Find the amount of cart ram (even if we call it sram...) */
1099   if (image.software_entry() == NULL)
1100   {
1101      if ((state->m_has_addon_chip != HAS_SUPERFX))
1102         state->m_cart[0].sram = snes_r_bank1(space, 0x00ffd8);
1103      else
1104         state->m_cart[0].sram = (snes_r_bank1(space, 0x00ffbd) & 0x07);
1105
1106      if (state->m_cart[0].sram > 0)
1107      {
1108         state->m_cart[0].sram = (1024 << state->m_cart[0].sram);
1109         if (state->m_cart[0].sram > state->m_cart[0].sram_max)
1110            state->m_cart[0].sram = state->m_cart[0].sram_max;
1111      }
1112//      printf("size %x\n", state->m_cart[0].sram);
1113   }
1114   else
1115   {
1116      // if we are loading from softlist, take sram from the xml
1117      state->m_cart[0].sram = image.get_software_region("sram") ? image.get_software_region_length("sram") : 0;
1118
1119      if (state->m_cart[0].sram > 0)
1120      {
1121         if (state->m_cart[0].sram > state->m_cart[0].sram_max)
1122            fatalerror("Found more SRAM than max allowed (found: %x, max: %x), check xml file!\n", state->m_cart[0].sram, state->m_cart[0].sram_max);
1123      }
1124      // TODO: Eventually sram handlers should point to the allocated cart:sram region!
1125      // For now, we only use the region as a placeholder to carry size info...
1126//      printf("size %x\n", state->m_cart[0].sram);
1127   }
1128
1129   /* adjust size for very large carts */
1130   if (state->m_cart[0].mode == SNES_MODE_20 && ((state->m_cart_size - offset) > 0x200000 || state->m_cart[0].sram > (32 * 1024)))
1131      state->m_cart[0].small_sram = 1;
1132   else
1133      state->m_cart[0].small_sram = 0;
1134
1135   /* Log snes_cart information */
1136   snes_cart_log_info(machine, total_blocks, supported_type);
1137
1138   /* Load SRAM */
1139   snes_load_sram(machine);
1140
1141   /* All done */
1142   return IMAGE_INIT_PASS;
1143}
1144
1145static DEVICE_IMAGE_LOAD( sufami_cart )
1146{
1147   running_machine &machine = image.device().machine();
1148   snes_state *state = machine.driver_data<snes_state>();
1149   int total_blocks, read_blocks;
1150   int st_bios = 0, slot_id = 0;
1151   UINT32 offset, st_data_offset = 0;
1152   UINT8 *ROM = image.device().machine().region(image.device().tag())->base();
1153
1154   snes_ram = machine.region("maincpu")->base();
1155
1156   if (strcmp(image.device().tag(), "slot_a") == 0)
1157   {
1158      st_data_offset = 0x200000;
1159      slot_id = 0;
1160   }
1161
1162   if (strcmp(image.device().tag(), "slot_b") == 0)
1163   {
1164      st_data_offset = 0x400000;
1165      slot_id = 1;
1166   }
1167
1168   if (image.software_entry() == NULL)
1169      state->m_cart_size = image.length();
1170   else
1171      state->m_cart_size = image.get_software_region_length("rom");
1172
1173   /* Check for a header (512 bytes), and skip it if found */
1174   offset = snes_skip_header(image, state->m_cart_size);
1175
1176   if (image.software_entry() == NULL)
1177   {
1178      image.fseek(offset, SEEK_SET);
1179      image.fread( ROM, state->m_cart_size - offset);
1180   }
1181   else
1182      memcpy(ROM, image.get_software_region("rom") + offset, state->m_cart_size - offset);
1183
1184   if (SNES_CART_DEBUG) mame_printf_error("size %08X\n", state->m_cart_size - offset);
1185
1186   /* Detect Sufami Turbo carts */
1187   if (!memcmp(ROM, "BANDAI SFC-ADX", 14))
1188   {
1189      state->m_cart[slot_id].mode = SNES_MODE_ST;
1190      if (!memcmp(ROM + 16, "SFC-ADX BACKUP", 14))
1191         st_bios = 1;
1192   }
1193   else
1194   {
1195      mame_printf_error("This is not a Sufami Turbo data pack.\n");
1196      mame_printf_error("This image cannot be loaded in snesst (Use snes or snespal drivers, instead).\n");
1197      return IMAGE_INIT_FAIL;
1198   }
1199
1200   if (st_bios == 1)
1201   {
1202      mame_printf_error("This is the Sufami Turbo BIOS and not a Sufami Turbo data pack.\n");
1203      mame_printf_error("This image cannot be loaded in snesst.\n");
1204      return IMAGE_INIT_FAIL;
1205   }
1206
1207   /* FIXME: Insert crc check here? */
1208
1209   /* How many blocks of data are available to be loaded? */
1210   total_blocks = (state->m_cart_size - offset) / 0x8000;
1211   read_blocks = 0;
1212
1213   if (SNES_CART_DEBUG)
1214      mame_printf_error("blocks %d\n", total_blocks);
1215
1216   // actually load the cart
1217   while (read_blocks < 32 && read_blocks < total_blocks)
1218   {
1219      /* Loading data */
1220      // CART (either A or B)
1221      memcpy(&snes_ram[0x008000 + st_data_offset + read_blocks * 0x10000], &ROM[0x000000 + read_blocks * 0x8000], 0x8000);
1222      /* Mirroring */
1223      memcpy(&snes_ram[0x808000 + st_data_offset + read_blocks * 0x10000], &snes_ram[0x8000 + st_data_offset + (read_blocks * 0x10000)], 0x8000);
1224
1225      read_blocks++;
1226   }
1227
1228   /* Filling banks up to 0x1f and their mirrors */
1229   while (read_blocks % 32)
1230   {
1231      int j = 0, repeat_blocks;
1232      while ((read_blocks % (32 >> j)) && j < 5)
1233         j++;
1234      repeat_blocks = read_blocks % (32 >> (j - 1));
1235
1236      memcpy(&snes_ram[st_data_offset + read_blocks * 0x10000], &snes_ram[st_data_offset + (read_blocks - repeat_blocks) * 0x10000], repeat_blocks * 0x10000);
1237      memcpy(&snes_ram[0x800000 + st_data_offset + read_blocks * 0x10000], &snes_ram[st_data_offset + (read_blocks - repeat_blocks) * 0x10000], repeat_blocks * 0x10000);
1238      read_blocks += repeat_blocks;
1239   }
1240
1241   sufami_load_sram(machine, image.device().tag());
1242
1243   state->m_cart[slot_id].slot_in_use = 1;   // aknowledge the cart in this slot, for saving sram at exit
1244
1245   auto_free(image.device().machine(), ROM);
1246
1247   return IMAGE_INIT_PASS;
1248}
1249
1250static DEVICE_IMAGE_LOAD( bsx_cart )
1251{
1252   running_machine &machine = image.device().machine();
1253   snes_state *state = machine.driver_data<snes_state>();
1254   int total_blocks, read_blocks;
1255   int has_bsx_slot = 0;
1256   UINT32 offset, int_header_offs;
1257   UINT8 *ROM = image.device().machine().region("cart")->base();
1258
1259   if (image.software_entry() == NULL)
1260      state->m_cart_size = image.length();
1261   else
1262      state->m_cart_size = image.get_software_region_length("rom");
1263
1264   /* Check for a header (512 bytes), and skip it if found */
1265   offset = snes_skip_header(image, state->m_cart_size);
1266
1267   if (image.software_entry() == NULL)
1268   {
1269      image.fseek(offset, SEEK_SET);
1270      image.fread( ROM, state->m_cart_size - offset);
1271   }
1272   else
1273      memcpy(ROM, image.get_software_region("rom") + offset, state->m_cart_size - offset);
1274
1275   if (SNES_CART_DEBUG) mame_printf_error("size %08X\n", state->m_cart_size - offset);
1276
1277   /* First, look if the cart is HiROM or LoROM (and set snes_cart accordingly) */
1278   int_header_offs = snes_find_hilo_mode(image, ROM, offset, 0);
1279
1280   // Detect presence of BS-X flash cartridge connector
1281   if ((ROM[int_header_offs - 14] == 'Z') && (ROM[int_header_offs - 11] == 'J'))
1282   {
1283      UINT8 n13 = ROM[int_header_offs - 13];
1284      if ((n13 >= 'A' && n13 <= 'Z') || (n13 >= '0' && n13 <= '9'))
1285      {
1286         if (ROM[int_header_offs + 0x1a] == 0x33 ||
1287            (ROM[int_header_offs - 10] == 0x00 && ROM[int_header_offs - 4] == 0x00))
1288         {
1289            has_bsx_slot = 1;
1290         }
1291      }
1292   }
1293
1294   // If there is a BS-X connector, detect if it is the Base Cart or a compatible slotted cart
1295   if (has_bsx_slot)
1296   {
1297      if (!memcmp(ROM + int_header_offs, "Satellaview BS-X     ", 21))
1298      {
1299         //BS-X Base Cart
1300         state->m_cart[0].mode = SNES_MODE_BSX;
1301         // handle RAM
1302      }
1303      else
1304      {
1305         state->m_cart[0].mode = (int_header_offs ==0x007fc0) ? SNES_MODE_BSLO : SNES_MODE_BSHI;
1306         // handle RAM?
1307      }
1308   }
1309   else
1310   {
1311      mame_printf_error("This is not a BS-X compatible cart.\n");
1312      mame_printf_error("This image cannot be loaded in the first cartslot of snesbsx.\n");
1313      return IMAGE_INIT_FAIL;
1314   }
1315
1316
1317   /* FIXME: Insert crc check here? */
1318
1319   /* How many blocks of data are available to be loaded? */
1320   total_blocks = (state->m_cart_size - offset) / 0x8000;
1321   read_blocks = 0;
1322
1323   if (SNES_CART_DEBUG) mame_printf_error("blocks %d\n", total_blocks);
1324
1325   // actually load the cart
1326   while (read_blocks < 64 && read_blocks < total_blocks)
1327   {
1328      /* Loading data */
1329      memcpy(&snes_ram[0x008000 + read_blocks * 0x10000], &ROM[0x000000 + read_blocks * 0x8000], 0x8000);
1330      /* Mirroring */
1331      memcpy(&snes_ram[0x808000 + read_blocks * 0x10000], &snes_ram[0x8000 + (read_blocks * 0x10000)], 0x8000);
1332
1333      read_blocks++;
1334   }
1335
1336   /* Filling banks up to 0x3f and their mirrors */
1337   while (read_blocks % 64)
1338   {
1339      int j = 0, repeat_blocks;
1340      while ((read_blocks % (64 >> j)) && j < 6)
1341         j++;
1342      repeat_blocks = read_blocks % (64 >> (j - 1));
1343
1344      memcpy(&snes_ram[read_blocks * 0x10000], &snes_ram[(read_blocks - repeat_blocks) * 0x10000], repeat_blocks * 0x10000);
1345      memcpy(&snes_ram[0x800000 + read_blocks * 0x10000], &snes_ram[(read_blocks - repeat_blocks) * 0x10000], repeat_blocks * 0x10000);
1346      read_blocks += repeat_blocks;
1347   }
1348
1349   return IMAGE_INIT_PASS;
1350}
1351
1352static DEVICE_IMAGE_LOAD( bsx2slot_cart )
1353{
1354   running_machine &machine = image.device().machine();
1355   snes_state *state = machine.driver_data<snes_state>();
1356   UINT32 offset, int_header_offs;
1357   UINT8 *ROM = image.device().machine().region("flash")->base();
1358
1359   if (image.software_entry() == NULL)
1360      state->m_cart_size = image.length();
1361   else
1362      state->m_cart_size = image.get_software_region_length("rom");
1363
1364   /* Check for a header (512 bytes), and skip it if found */
1365   offset = snes_skip_header(image, state->m_cart_size);
1366
1367   if (image.software_entry() == NULL)
1368   {
1369      image.fseek(offset, SEEK_SET);
1370      image.fread( ROM, state->m_cart_size - offset);
1371   }
1372   else
1373      memcpy(ROM, image.get_software_region("rom") + offset, state->m_cart_size - offset);
1374
1375   if (SNES_CART_DEBUG) mame_printf_error("size %08X\n", state->m_cart_size - offset);
1376
1377   /* First, look if the cart is HiROM or LoROM (and set snes_cart accordingly) */
1378   int_header_offs = snes_find_hilo_mode(image, ROM, offset, 1);
1379
1380   // Detect presence of BS-X Flash Cart
1381   if ((ROM[int_header_offs + 0x13] == 0x00 || ROM[int_header_offs + 0x13] == 0xff) &&
1382      ROM[int_header_offs + 0x14] == 0x00)
1383   {
1384      UINT8 n15 = ROM[int_header_offs + 0x15];
1385      if (n15 == 0x00 || n15 == 0x80 || n15 == 0x84 || n15 == 0x9c || n15 == 0xbc || n15 == 0xfc)
1386      {
1387         if (ROM[int_header_offs + 0x1a] == 0x33 || ROM[int_header_offs + 0x1a] == 0xff)
1388         {
1389            // BS-X Flash Cart
1390            state->m_cart[1].mode = SNES_MODE_BSX;
1391         }
1392      }
1393   }
1394
1395   if (state->m_cart[1].mode != SNES_MODE_BSX)
1396   {
1397      mame_printf_error("This is not a BS-X flash cart.\n");
1398      mame_printf_error("This image cannot be loaded in the second cartslot of snesbsx.\n");
1399      return IMAGE_INIT_FAIL;
1400   }
1401
1402   // actually load the cart
1403   return IMAGE_INIT_PASS;
1404}
1405
1406MACHINE_CONFIG_FRAGMENT( snes_cartslot )
1407   MCFG_CARTSLOT_ADD("cart")
1408   MCFG_CARTSLOT_EXTENSION_LIST("sfc,smc,fig,swc,bin")
1409   MCFG_CARTSLOT_NOT_MANDATORY
1410   MCFG_CARTSLOT_INTERFACE("snes_cart")
1411   MCFG_CARTSLOT_LOAD(snes_cart)
1412   MCFG_SOFTWARE_LIST_ADD("cart_list","snes")
1413MACHINE_CONFIG_END
1414
1415// This (hackily) emulates a SNES unit with a Sufami Turbo Unit cart inserted:
1416// hence, the user can mount two data cart in the two slots available on the ST Unit
1417MACHINE_CONFIG_FRAGMENT( sufami_cartslot )
1418   MCFG_CARTSLOT_ADD("slot_a")
1419   MCFG_CARTSLOT_EXTENSION_LIST("st,sfc")
1420   MCFG_CARTSLOT_NOT_MANDATORY
1421   MCFG_CARTSLOT_INTERFACE("sufami_cart")
1422   MCFG_CARTSLOT_LOAD(sufami_cart)
1423
1424   MCFG_CARTSLOT_ADD("slot_b")
1425   MCFG_CARTSLOT_EXTENSION_LIST("st,sfc")
1426   MCFG_CARTSLOT_NOT_MANDATORY
1427   MCFG_CARTSLOT_INTERFACE("sufami_cart")
1428   MCFG_CARTSLOT_LOAD(sufami_cart)
1429
1430//  MCFG_SOFTWARE_LIST_ADD("cart_list","snes")
1431MACHINE_CONFIG_END
1432
1433// This (hackily) emulates a SNES unit where you want to load a BS-X compatible cart:
1434// hence, the user can mount a SNES cart in the first slot (either a BS-X BIOS cart, or a
1435// BS-X compatible one, e.g. Same Game), and there is a second slot for the 8M data pack
1436// (in a real SNES this would have been inserted in the smaller slot on the cart itself)
1437MACHINE_CONFIG_FRAGMENT( bsx_cartslot )
1438   MCFG_CARTSLOT_ADD("cart")
1439   MCFG_CARTSLOT_EXTENSION_LIST("sfc,smc,fig,swc,bin")
1440   MCFG_CARTSLOT_NOT_MANDATORY
1441   MCFG_CARTSLOT_INTERFACE("snes_cart")
1442   MCFG_CARTSLOT_LOAD(bsx_cart)
1443
1444   MCFG_CARTSLOT_ADD("slot2")
1445   MCFG_CARTSLOT_EXTENSION_LIST("bs,sfc")
1446   MCFG_CARTSLOT_NOT_MANDATORY
1447   MCFG_CARTSLOT_INTERFACE("bsx_cart")
1448   MCFG_CARTSLOT_LOAD(bsx2slot_cart)
1449
1450//  MCFG_SOFTWARE_LIST_ADD("cart_list","snes")
1451MACHINE_CONFIG_END
1452
1453DRIVER_INIT( snes_mess )
1454{
1455   snes_ram = machine.region("maincpu")->base();
1456   memset(snes_ram, 0, 0x1000000);
1457}
1458
1459DRIVER_INIT( snesst )
1460{
1461   snes_state *state = machine.driver_data<snes_state>();
1462   UINT8 *STBIOS = machine.region("sufami")->base();
1463   int i, j;
1464
1465   state->m_cart[0].slot_in_use = 0;
1466   state->m_cart[1].slot_in_use = 0;
1467
1468   DRIVER_INIT_CALL(snes_mess);
1469
1470   // the Base ST cart consists of 8 * 0x8000 block which have to be loaded (and mirrored)
1471   // at 0x00-0x1f:0x8000-0xffff and 0x80-0x9f:0x8000-0xffff
1472   for (i = 0; i < 8; i++)
1473   {
1474      /* Loading data */
1475      memcpy(&snes_ram[0x008000 + i * 0x10000], &STBIOS[0x000000 + i * 0x8000], 0x8000);
1476      /* Mirroring */
1477      memcpy(&snes_ram[0x808000 + i * 0x10000], &snes_ram[0x8000 + (i * 0x10000)], 0x8000);
1478
1479      /* Additional mirrors (to fill snes_ram up to 0x1fffff) */
1480      for (j = 1; j < 4; j++)
1481      {
1482         memcpy(&snes_ram[0x008000 + i * 0x10000 + j * 0x80000], &snes_ram[0x8000 + (i * 0x10000)], 0x8000);
1483         memcpy(&snes_ram[0x808000 + i * 0x10000 + j * 0x80000], &snes_ram[0x8000 + (i * 0x10000)], 0x8000);
1484      }
1485   }
1486
1487}
src/mess/machine/snescart.h
r0r11532
1/*
2    snescart.h
3
4*/
5
6#ifndef _SNESCART_H
7#define _SNESCART_H
8
9#include "imagedev/cartslot.h"
10
11MACHINE_START( snes_mess );
12MACHINE_START( snesst );
13
14DRIVER_INIT( snes_mess );
15DRIVER_INIT( snesst );
16
17MACHINE_CONFIG_EXTERN( snes_cartslot );
18MACHINE_CONFIG_EXTERN( sufami_cartslot );
19MACHINE_CONFIG_EXTERN( bsx_cartslot );
20
21#endif /* _SNESCART_H */
22
src/mess/machine/pce.c
r0r11532
1/************************************************************
2
3PC Engine CD HW notes:
4
5CD Interface Register 0x00 - CDC status
6x--- ---- busy signal
7-x-- ---- request signal
8---x ---- cd signal
9---- x--- i/o signal
10
11CD Interface Register 0x03 - BRAM lock / CD status
12-x-- ---- acknowledge signal
13--x- ---- done signal
14---x ---- bram signal
15---- x--- ADPCM 2
16---- -x-- ADPCM 1
17---- --x- CDDA left/right speaker select
18
19CD Interface Register 0x05 - CD-DA Volume low 8-bit port
20
21CD Interface Register 0x06 - CD-DA Volume high 8-bit port
22
23CD Interface Register 0x07 - BRAM unlock / CD status
24x--- ---- Enables BRAM
25
26CD Interface Register 0x0c - ADPCM status
27x--- ---- ADPCM is reading data
28---- x--- ADPCM playback (0) stopped (1) currently playing
29---- -x-- pending ADPCM data write
30---- ---x ADPCM playback (1) stopped (0) currently playing
31
32CD Interface Register 0x0d - ADPCM address control
33x--- ---- ADPCM reset
34-x-- ---- ADPCM play
35--x- ---- ADPCM repeat
36---x ---- ADPCM set length
37---- x--- ADPCM set read address
38---- --xx ADPCM set write address
39(note: some games reads bit 5 and wants it to be low otherwise they hangs, surely NOT an ADPCM repeat flag read because it doesn't make sense)
40
41CD Interface Register 0x0e - ADPCM playback rate
42
43CD Interface Register 0x0f - ADPCM fade in/out register
44---- xxxx command setting:
450x00 ADPCM/CD-DA Fade-in
460x01 CD-DA fade-in
470x08 CD-DA fade-out (short) ADPCM fade-in
480x09 CD-DA fade-out (long)
490x0a ADPCM fade-out (long)
500x0c CD-DA fade-out (short) ADPCM fade-in
510x0d CD-DA fade-out (short)
520x0e ADPCM fade-out (short)
53
54*************************************************************/
55
56#include "emu.h"
57#include "coreutil.h"
58#include "cpu/h6280/h6280.h"
59#include "includes/pce.h"
60#include "imagedev/chd_cd.h"
61#include "sound/msm5205.h"
62#include "sound/cdda.h"
63#include "hashfile.h"
64
65
66#define PCE_BRAM_SIZE            0x800
67#define PCE_ADPCM_RAM_SIZE         0x10000
68#define PCE_ACARD_RAM_SIZE         0x200000
69#define PCE_CD_COMMAND_BUFFER_SIZE   0x100
70
71#define PCE_CD_IRQ_TRANSFER_READY      0x40
72#define PCE_CD_IRQ_TRANSFER_DONE      0x20
73#define PCE_CD_IRQ_SAMPLE_FULL_PLAY      0x08
74#define PCE_CD_IRQ_SAMPLE_HALF_PLAY      0x04
75
76#define PCE_CD_ADPCM_PLAY_FLAG      0x08
77#define PCE_CD_ADPCM_STOP_FLAG      0x01
78
79#define PCE_CD_DATA_FRAMES_PER_SECOND   75
80
81enum {
82   PCE_CD_CDDA_OFF=0,
83   PCE_CD_CDDA_PLAYING,
84   PCE_CD_CDDA_PAUSED
85};
86
87
88/* CD Unit RAM */
89
90/* MSM5205 ADPCM decoder definition */
91static void pce_cd_msm5205_int(device_t *device);
92const msm5205_interface pce_cd_msm5205_interface = {
93   pce_cd_msm5205_int,   /* interrupt function */
94   MSM5205_S48_4B      /* 1/48 prescaler, 4bit data */
95};
96
97
98/* joystick related data*/
99
100#define JOY_CLOCK   0x01
101#define JOY_RESET   0x02
102
103
104/* prototypes */
105static void pce_cd_init( running_machine &machine );
106static void pce_cd_set_irq_line( running_machine &machine, int num, int state );
107static TIMER_CALLBACK( pce_cd_adpcm_dma_timer_callback );
108static TIMER_CALLBACK( pce_cd_cdda_fadeout_callback );
109static TIMER_CALLBACK( pce_cd_cdda_fadein_callback );
110static TIMER_CALLBACK( pce_cd_adpcm_fadeout_callback );
111static TIMER_CALLBACK( pce_cd_adpcm_fadein_callback );
112
113static WRITE8_HANDLER( pce_sf2_banking_w )
114{
115   memory_set_bankptr( space->machine(), "bank2", space->machine().region("user1")->base() + offset * 0x080000 + 0x080000 );
116   memory_set_bankptr( space->machine(), "bank3", space->machine().region("user1")->base() + offset * 0x080000 + 0x088000 );
117   memory_set_bankptr( space->machine(), "bank4", space->machine().region("user1")->base() + offset * 0x080000 + 0x0D0000 );
118}
119
120static WRITE8_HANDLER( pce_cartridge_ram_w )
121{
122   pce_state *state = space->machine().driver_data<pce_state>();
123   state->m_cartridge_ram[offset] = data;
124}
125
126DEVICE_IMAGE_LOAD(pce_cart)
127{
128   pce_state *state = image.device().machine().driver_data<pce_state>();
129   UINT32 size;
130   int split_rom = 0, offset = 0;
131   const char *extrainfo = NULL;
132   unsigned char *ROM;
133   logerror("*** DEVICE_IMAGE_LOAD(pce_cart) : %s\n", image.filename());
134
135   /* open file to get size */
136   ROM = image.device().machine().region("user1")->base();
137
138   if (image.software_entry() == NULL)
139      size = image.length();
140   else
141      size = image.get_software_region_length("rom");
142
143   /* handle header accordingly */
144   if ((size / 512) & 1)
145   {
146      logerror("*** DEVICE_IMAGE_LOAD(pce_cart) : Header present\n");
147      size -= 512;
148      offset = 512;
149   }
150
151   if (size > PCE_ROM_MAXSIZE)
152      size = PCE_ROM_MAXSIZE;
153
154   if (image.software_entry() == NULL)
155   {
156      image.fseek(offset, SEEK_SET);
157      image.fread( ROM, size);
158      extrainfo = hashfile_extrainfo(image);
159   }
160   else
161      memcpy(ROM, image.get_software_region("rom") + offset, size);
162
163   if (extrainfo)
164   {
165      logerror("extrainfo: %s\n", extrainfo);
166      if (strstr(extrainfo, "ROM_SPLIT"))
167         split_rom = 1;
168   }
169
170   if (ROM[0x1fff] < 0xe0)
171   {
172      int i;
173      UINT8 decrypted[256];
174
175      logerror( "*** DEVICE_IMAGE_LOAD(pce_cart) : ROM image seems encrypted, decrypting...\n" );
176
177      /* Initialize decryption table */
178      for (i = 0; i < 256; i++)
179         decrypted[i] = ((i & 0x01) << 7) | ((i & 0x02) << 5) | ((i & 0x04) << 3) | ((i & 0x08) << 1) | ((i & 0x10) >> 1) | ((i & 0x20 ) >> 3) | ((i & 0x40) >> 5) | ((i & 0x80) >> 7);
180
181      /* Decrypt ROM image */
182      for (i = 0; i < size; i++)
183         ROM[i] = decrypted[ROM[i]];
184   }
185
186   /* check if we're dealing with a split rom image */
187   if (size == 384 * 1024)
188   {
189      split_rom = 1;
190      /* Mirror the upper 128KB part of the image */
191      memcpy(ROM + 0x060000, ROM + 0x040000, 0x020000);   /* Set up 060000 - 07FFFF mirror */
192   }
193
194   /* set up the memory for a split rom image */
195   if (split_rom)
196   {
197      logerror("Split rom detected, setting up memory accordingly\n");
198      /* Set up ROM address space as follows:          */
199      /* 000000 - 03FFFF : ROM data 000000 - 03FFFF    */
200      /* 040000 - 07FFFF : ROM data 000000 - 03FFFF    */
201      /* 080000 - 0BFFFF : ROM data 040000 - 07FFFF    */
202      /* 0C0000 - 0FFFFF : ROM data 040000 - 07FFFF    */
203      memcpy(ROM + 0x080000, ROM + 0x040000, 0x040000);   /* Set up 080000 - 0BFFFF region */
204      memcpy(ROM + 0x0C0000, ROM + 0x040000, 0x040000);   /* Set up 0C0000 - 0FFFFF region */
205      memcpy(ROM + 0x040000, ROM, 0x040000);      /* Set up 040000 - 07FFFF region */
206   }
207   else
208   {
209      /* mirror 256KB rom data */
210      if (size <= 0x040000)
211         memcpy(ROM + 0x040000, ROM, 0x040000);
212
213      /* mirror 512KB rom data */
214      if (size <= 0x080000)
215         memcpy(ROM + 0x080000, ROM, 0x080000);
216   }
217
218   memory_set_bankptr(image.device().machine(), "bank1", ROM);
219   memory_set_bankptr(image.device().machine(), "bank2", ROM + 0x080000);
220   memory_set_bankptr(image.device().machine(), "bank3", ROM + 0x088000);
221   memory_set_bankptr(image.device().machine(), "bank4", ROM + 0x0d0000);
222
223   /* Check for Street fighter 2 */
224   if (size == PCE_ROM_MAXSIZE)
225   {
226      image.device().machine().device("maincpu")->memory().space(AS_PROGRAM)->install_legacy_write_handler(0x01ff0, 0x01ff3, FUNC(pce_sf2_banking_w));
227   }
228
229   /* Check for Populous */
230   if (!memcmp(ROM + 0x1F26, "POPULOUS", 8))
231   {
232      state->m_cartridge_ram = auto_alloc_array(image.device().machine(), UINT8, 0x8000);
233      memory_set_bankptr(image.device().machine(), "bank2", state->m_cartridge_ram);
234      image.device().machine().device("maincpu")->memory().space(AS_PROGRAM)->install_legacy_write_handler(0x080000, 0x087FFF, FUNC(pce_cartridge_ram_w));
235   }
236
237   /* Check for CD system card */
238   state->m_sys3_card = 0;
239   if (!memcmp(ROM + 0x3FFB6, "PC Engine CD-ROM SYSTEM", 23))
240   {
241      /* Check if 192KB additional system card ram should be used */
242      if(!memcmp(ROM + 0x29D1, "VER. 3.", 7))       { state->m_sys3_card = 1; } // JP version
243      else if(!memcmp(ROM + 0x29C4, "VER. 3.", 7 ))   { state->m_sys3_card = 3; } // US version
244
245      if(state->m_sys3_card)
246      {
247         state->m_cartridge_ram = auto_alloc_array(image.device().machine(), UINT8, 0x30000);
248         memory_set_bankptr(image.device().machine(), "bank4", state->m_cartridge_ram);
249         image.device().machine().device("maincpu")->memory().space(AS_PROGRAM)->install_legacy_write_handler(0x0D0000, 0x0FFFFF, FUNC(pce_cartridge_ram_w));
250         image.device().machine().device("maincpu")->memory().space(AS_PROGRAM)->install_legacy_readwrite_handler(0x080000, 0x087FFF, FUNC(pce_cd_acard_wram_r),FUNC(pce_cd_acard_wram_w));
251      }
252   }
253   return 0;
254}
255
256#ifdef MESS
257DRIVER_INIT( pce )
258{
259   pce_state *state = machine.driver_data<pce_state>();
260   state->m_io_port_options = PCE_JOY_SIG | CONST_SIG;
261}
262#endif
263
264DRIVER_INIT( tg16 )
265{
266   pce_state *state = machine.driver_data<pce_state>();
267   state->m_io_port_options = TG_16_JOY_SIG | CONST_SIG;
268}
269
270DRIVER_INIT( sgx )
271{
272   pce_state *state = machine.driver_data<pce_state>();
273   state->m_io_port_options = PCE_JOY_SIG | CONST_SIG;
274}
275
276MACHINE_START( pce )
277{
278   pce_cd_init( machine );
279}
280
281#ifdef MESS
282MACHINE_RESET( pce )
283{
284   pce_state *state = machine.driver_data<pce_state>();
285   pce_cd_t &pce_cd = state->m_cd;
286   int joy_i;
287
288   for (joy_i = 0; joy_i < 5; joy_i++)
289      state->m_joy_6b_packet[joy_i] = 0;
290
291   pce_cd.adpcm_read_buf = 0;
292   pce_cd.adpcm_write_buf = 0;
293
294   // TODO: add CD-DA stop command here
295
296   pce_cd.regs[0x0c] |= PCE_CD_ADPCM_STOP_FLAG;
297   pce_cd.regs[0x0c] &= ~PCE_CD_ADPCM_PLAY_FLAG;
298   //pce_cd.regs[0x03] = (pce_cd.regs[0x03] & ~0x0c) | (PCE_CD_SAMPLE_STOP_PLAY);
299
300   /* Note: Arcade Card BIOS contents are the same as System 3, only internal HW differs.
301       We use a category to select between modes (some games can be run in either S-CD or A-CD modes) */
302   state->m_acard = input_port_read(machine, "A_CARD") & 1;
303}
304
305/* todo: how many input ports does the PCE have? */
306WRITE8_HANDLER ( pce_joystick_w )
307{
308   pce_state *state = space->machine().driver_data<pce_state>();
309   int joy_i;
310   UINT8 joy_type = input_port_read(space->machine(),"JOY_TYPE");
311
312   h6280io_set_buffer(&space->device(), data);
313
314    /* bump counter on a low-to-high transition of bit 1 */
315    if ((!state->m_joystick_data_select) && (data & JOY_CLOCK))
316    {
317        state->m_joystick_port_select = (state->m_joystick_port_select + 1) & 0x07;
318    }
319
320    /* do we want buttons or direction? */
321    state->m_joystick_data_select = data & JOY_CLOCK;
322
323    /* clear counter if bit 2 is set */
324    if (data & JOY_RESET)
325    {
326      state->m_joystick_port_select = 0;
327
328      for (joy_i = 0; joy_i < 5; joy_i++)
329      {
330         if (((joy_type >> (joy_i*2)) & 3) == 2)
331              state->m_joy_6b_packet[joy_i] ^= 1;
332      }
333    }
334}
335
336READ8_HANDLER ( pce_joystick_r )
337{
338   pce_state *state = space->machine().driver_data<pce_state>();
339   static const char *const joyname[4][5] = {
340      { "JOY_P1", "JOY_P2", "JOY_P3", "JOY_P4", "JOY_P5" },
341      { },
342      { "JOY6B_P1", "JOY6B_P2", "JOY6B_P3", "JOY6B_P4", "JOY6B_P5" },
343      { }
344   };
345   UINT8 joy_type = input_port_read(space->machine(), "JOY_TYPE");
346   UINT8 ret, data;
347
348   if (state->m_joystick_port_select <= 4)
349   {
350      switch((joy_type >> (state->m_joystick_port_select*2)) & 3)
351      {
352         case 0: //2-buttons pad
353            data = input_port_read(space->machine(), joyname[0][state->m_joystick_port_select]);
354            break;
355         case 2: //6-buttons pad
356            /*
357                Two packets:
358                1st packet: directions + I, II, Run, Select
359                2nd packet: 6 buttons "header" (high 4 bits active low) + III, IV, V, VI
360                Note that six buttons pad just doesn't work with (almost?) every single 2-button-only games, it's really just an after-thought and it is like this
361                on real HW.
362                */
363            data = input_port_read(space->machine(), joyname[2][state->m_joystick_port_select]) >> (state->m_joy_6b_packet[state->m_joystick_port_select]*8);
364            break;
365         default:
366            data = 0xff;
367            break;
368      }
369   }
370   else
371      data = 0xff;
372
373
374   if (state->m_joystick_data_select)
375      data >>= 4;
376
377   ret = (data & 0x0f) | state->m_io_port_options;
378#ifdef UNIFIED_PCE
379   ret &= ~0x40;
380#endif
381
382   return (ret);
383}
384#endif
385NVRAM_HANDLER( pce )
386{
387   pce_state *state = machine.driver_data<pce_state>();
388   pce_cd_t &pce_cd = state->m_cd;
389   if (read_or_write)
390   {
391      file->write(pce_cd.bram, PCE_BRAM_SIZE);
392   }
393   else
394   {
395      /* load battery backed memory from disk */
396      if (file)
397         file->read(pce_cd.bram, PCE_BRAM_SIZE);
398   }
399}
400
401static void pce_set_cd_bram( running_machine &machine )
402{
403   pce_state *state = machine.driver_data<pce_state>();
404   pce_cd_t &pce_cd = state->m_cd;
405   memory_set_bankptr( machine, "bank10", pce_cd.bram + ( pce_cd.bram_locked ? PCE_BRAM_SIZE : 0 ) );
406}
407
408static void adpcm_stop(running_machine &machine)
409{
410   pce_state *state = machine.driver_data<pce_state>();
411   pce_cd_t &pce_cd = state->m_cd;
412   pce_cd.regs[0x0c] |= PCE_CD_ADPCM_STOP_FLAG;
413   pce_cd.regs[0x0c] &= ~PCE_CD_ADPCM_PLAY_FLAG;
414   //pce_cd.regs[0x03] = (pce_cd.regs[0x03] & ~0x0c) | (PCE_CD_SAMPLE_STOP_PLAY);
415   pce_cd_set_irq_line( machine, PCE_CD_IRQ_SAMPLE_FULL_PLAY, ASSERT_LINE );
416   pce_cd.regs[0x0d] &= ~0x60;
417   pce_cd.msm_idle = 1;
418}
419
420static void adpcm_play(running_machine &machine)
421{
422   pce_state *state = machine.driver_data<pce_state>();
423   pce_cd_t &pce_cd = state->m_cd;
424   pce_cd.regs[0x0c] &= ~PCE_CD_ADPCM_STOP_FLAG;
425   pce_cd.regs[0x0c] |= PCE_CD_ADPCM_PLAY_FLAG;
426   pce_cd_set_irq_line( machine, PCE_CD_IRQ_SAMPLE_FULL_PLAY, CLEAR_LINE );
427   pce_cd.regs[0x03] = (pce_cd.regs[0x03] & ~0x0c);
428   pce_cd.msm_idle = 0;
429}
430
431
432/* Callback for new data from the MSM5205.
433  The PCE cd unit actually divides the clock signal supplied to
434  the MSM5205. Currently we can only use static clocks for the
435  MSM5205.
436 */
437static void pce_cd_msm5205_int(device_t *device)
438{
439   pce_state *state = device->machine().driver_data<pce_state>();
440   pce_cd_t &pce_cd = state->m_cd;
441   UINT8 msm_data;
442
443//  popmessage("%08x %08x %08x %02x %02x",pce_cd.msm_start_addr,pce_cd.msm_end_addr,pce_cd.msm_half_addr,pce_cd.regs[0x0c],pce_cd.regs[0x0d]);
444
445   if ( pce_cd.msm_idle )
446      return;
447
448   /* Supply new ADPCM data */
449   msm_data = (pce_cd.msm_nibble) ? (pce_cd.adpcm_ram[pce_cd.msm_start_addr] & 0x0f) : ((pce_cd.adpcm_ram[pce_cd.msm_start_addr] & 0xf0) >> 4);
450
451   msm5205_data_w(device, msm_data);
452   pce_cd.msm_nibble ^= 1;
453
454   if(pce_cd.msm_nibble == 0)
455   {
456      pce_cd.msm_start_addr++;
457
458      if(pce_cd.msm_start_addr == pce_cd.msm_half_addr)
459      {
460         //pce_cd_set_irq_line( device->machine(), PCE_CD_IRQ_SAMPLE_FULL_PLAY, CLEAR_LINE );
461         //pce_cd_set_irq_line( device->machine(), PCE_CD_IRQ_SAMPLE_HALF_PLAY, ASSERT_LINE );
462      }
463
464      if(pce_cd.msm_start_addr > pce_cd.msm_end_addr)
465      {
466         //pce_cd_set_irq_line( device->machine(), PCE_CD_IRQ_SAMPLE_HALF_PLAY, CLEAR_LINE );
467         //pce_cd_set_irq_line( device->machine(), PCE_CD_IRQ_SAMPLE_FULL_PLAY, CLEAR_LINE );
468         adpcm_stop(device->machine());
469         msm5205_reset_w(device, 1);
470      }
471   }
472}
473
474#define   SCSI_STATUS_OK         0x00
475#define SCSI_CHECK_CONDITION   0x02
476
477static void pce_cd_reply_status_byte( pce_state *state, UINT8 status )
478{
479   pce_cd_t &pce_cd = state->m_cd;
480logerror("Setting CD in reply_status_byte\n");
481   pce_cd.scsi_CD = pce_cd.scsi_IO = pce_cd.scsi_REQ = 1;
482   pce_cd.scsi_MSG = 0;
483   pce_cd.message_after_status = 1;
484   pce_cd.status_sent = pce_cd.message_sent = 0;
485
486   if ( status == SCSI_STATUS_OK )
487   {
488      pce_cd.regs[0x01] = 0x00;
489   }
490   else
491   {
492      pce_cd.regs[0x01] = 0x01;
493   }
494}
495
496/* 0x00 - TEST UNIT READY */
497static void pce_cd_test_unit_ready( running_machine &machine )
498{
499   pce_state *state = machine.driver_data<pce_state>();
500   pce_cd_t &pce_cd = state->m_cd;
501   logerror("test unit ready\n");
502   if ( pce_cd.cd )
503   {
504      logerror( "Sending STATUS_OK status\n" );
505      pce_cd_reply_status_byte( state, SCSI_STATUS_OK );
506   }
507   else
508   {
509      logerror( "Sending CHECK_CONDITION status\n" );
510      pce_cd_reply_status_byte( state, SCSI_CHECK_CONDITION );
511   }
512}
513
514/* 0x08 - READ (6) */
515static void pce_cd_read_6( running_machine &machine )
516{
517   pce_state *state = machine.driver_data<pce_state>();
518   pce_cd_t &pce_cd = state->m_cd;
519   UINT32 frame = ( ( pce_cd.command_buffer[1] & 0x1F ) << 16 ) | ( pce_cd.command_buffer[2] << 8 ) | pce_cd.command_buffer[3];
520   UINT32 frame_count = pce_cd.command_buffer[4];
521
522   /* Check for presence of a CD */
523   if ( ! pce_cd.cd )
524   {
525      pce_cd_reply_status_byte( state, SCSI_CHECK_CONDITION );
526      return;
527   }
528
529   if ( pce_cd.cdda_status != PCE_CD_CDDA_OFF )
530   {
531      pce_cd.cdda_status = PCE_CD_CDDA_OFF;
532      cdda_stop_audio( machine.device( "cdda" ) );
533      pce_cd.end_mark = 0;
534   }
535
536   pce_cd.current_frame = frame;
537   pce_cd.end_frame = frame + frame_count;
538
539   if ( frame_count == 0 )
540   {
541      /* Star Breaker uses this */
542      popmessage("Read Sector frame count == 0, contact MESSdev");
543      pce_cd_reply_status_byte( state, SCSI_STATUS_OK );
544   }
545   else
546   {
547      pce_cd.data_timer->adjust(attotime::from_hz( PCE_CD_DATA_FRAMES_PER_SECOND ), 0, attotime::from_hz( PCE_CD_DATA_FRAMES_PER_SECOND ));
548   }
549}
550
551/* 0xD8 - SET AUDIO PLAYBACK START POSITION (NEC) */
552static void pce_cd_nec_set_audio_start_position( running_machine &machine )
553{
554   pce_state *state = machine.driver_data<pce_state>();
555   pce_cd_t &pce_cd = state->m_cd;
556   UINT32   frame = 0;
557
558   if ( ! pce_cd.cd )
559   {
560      /* Throw some error here */
561      pce_cd_reply_status_byte( state, SCSI_CHECK_CONDITION );
562      return;
563   }
564
565   switch( pce_cd.command_buffer[9] & 0xC0 )
566   {
567   case 0x00:
568      popmessage("CD-DA set start mode 0x00, contact MESSdev");
569      frame = ( pce_cd.command_buffer[3] << 16 ) | ( pce_cd.command_buffer[4] << 8 ) | pce_cd.command_buffer[5];
570      break;
571   case 0x40:
572   {
573      UINT8 m,s,f;
574
575      m = bcd_2_dec( pce_cd.command_buffer[2]);
576      s = bcd_2_dec( pce_cd.command_buffer[3]);
577      f = bcd_2_dec( pce_cd.command_buffer[4]);
578
579      frame = f + 75 * (s + m * 60);
580      if(frame >= 525) // TODO: seven seconds gap? O_o
581         frame -= 525;
582      break;
583   }
584   case 0x80:
585      frame = pce_cd.toc->tracks[ bcd_2_dec( pce_cd.command_buffer[2] ) - 1 ].physframeofs;
586      break;
587   default:
588      popmessage("CD-DA set start mode 0xc0, contact MESSdev");
589      //assert( NULL == pce_cd_nec_set_audio_start_position );
590      break;
591   }
592
593   pce_cd.current_frame = frame;
594
595   if ( pce_cd.cdda_status == PCE_CD_CDDA_PAUSED )
596   {
597      pce_cd.cdda_status = PCE_CD_CDDA_OFF;
598      cdda_stop_audio( machine.device( "cdda" ) );
599      pce_cd.end_frame = pce_cd.last_frame;
600      pce_cd.end_mark = 0;
601   }
602   else
603   {
604      if(pce_cd.command_buffer[1] & 0x03)
605      {
606         pce_cd.cdda_status = PCE_CD_CDDA_PLAYING;
607         pce_cd.end_frame = pce_cd.last_frame; //get the end of the CD
608         cdda_start_audio( machine.device( "cdda" ), pce_cd.current_frame, pce_cd.end_frame - pce_cd.current_frame );
609         pce_cd.cdda_play_mode = (pce_cd.command_buffer[1] & 0x02) ? 2 : 3; // mode 2 sets IRQ at end
610         pce_cd.end_mark =  (pce_cd.command_buffer[1] & 0x02) ? 1 : 0;
611      }
612      else
613      {
614         pce_cd.cdda_status = PCE_CD_CDDA_PLAYING;
615         pce_cd.end_frame = pce_cd.toc->tracks[ cdrom_get_track(pce_cd.cd, pce_cd.current_frame) + 1 ].physframeofs; //get the end of THIS track
616         cdda_start_audio( machine.device( "cdda" ), pce_cd.current_frame, pce_cd.end_frame - pce_cd.current_frame );
617         pce_cd.end_mark = 0;
618         pce_cd.cdda_play_mode = 3;
619      }
620   }
621
622   pce_cd_reply_status_byte( state, SCSI_STATUS_OK );
623   pce_cd_set_irq_line( machine, PCE_CD_IRQ_TRANSFER_DONE, ASSERT_LINE );
624}
625
626/* 0xD9 - SET AUDIO PLAYBACK END POSITION (NEC) */
627static void pce_cd_nec_set_audio_stop_position( running_machine &machine )
628{
629   pce_state *state = machine.driver_data<pce_state>();
630   pce_cd_t &pce_cd = state->m_cd;
631   UINT32  frame = 0;
632
633   if ( ! pce_cd.cd )
634   {
635      /* Throw some error here */
636      pce_cd_reply_status_byte( state, SCSI_CHECK_CONDITION );
637      return;
638   }
639
640   switch( pce_cd.command_buffer[9] & 0xC0 )
641   {
642   case 0x00:
643      popmessage("CD-DA set end mode 0x00, contact MESSdev");
644      frame = ( pce_cd.command_buffer[3] << 16 ) | ( pce_cd.command_buffer[4] << 8 ) | pce_cd.command_buffer[5];
645      break;
646   case 0x40:
647   {
648      UINT8 m,s,f;
649
650      m = bcd_2_dec( pce_cd.command_buffer[2]);
651      s = bcd_2_dec( pce_cd.command_buffer[3]);
652      f = bcd_2_dec( pce_cd.command_buffer[4]);
653
654      frame = f + 75 * (s + m * 60);
655      if(frame >= 525) // TODO: seven seconds gap? O_o
656         frame -= 525;
657      break;
658   }
659   case 0x80:
660      frame = pce_cd.toc->tracks[ bcd_2_dec( pce_cd.command_buffer[2] ) - 1 ].physframeofs;
661      break;
662   default:
663      popmessage("CD-DA set end mode 0xc0, contact MESSdev");
664      //assert( NULL == pce_cd_nec_set_audio_start_position );
665      break;
666   }
667
668   pce_cd.end_frame = frame;
669   pce_cd.cdda_play_mode = pce_cd.command_buffer[1] & 0x03;
670
671   if ( pce_cd.cdda_play_mode )
672   {
673      if ( pce_cd.cdda_status == PCE_CD_CDDA_PAUSED )
674      {
675         cdda_pause_audio( machine.device( "cdda" ), 0 );
676      }
677      else
678      {
679         cdda_start_audio( machine.device( "cdda" ), pce_cd.current_frame, pce_cd.end_frame - pce_cd.current_frame );
680         pce_cd.end_mark = 1;
681      }
682      pce_cd.cdda_status = PCE_CD_CDDA_PLAYING;
683   }
684   else
685   {
686      pce_cd.cdda_status = PCE_CD_CDDA_OFF;
687      cdda_stop_audio( machine.device( "cdda" ) );
688      pce_cd.end_frame = pce_cd.last_frame;
689      pce_cd.end_mark = 0;
690//      assert( NULL == pce_cd_nec_set_audio_stop_position );
691   }
692
693   pce_cd_reply_status_byte( state, SCSI_STATUS_OK );
694   pce_cd_set_irq_line( machine, PCE_CD_IRQ_TRANSFER_DONE, ASSERT_LINE );
695}
696
697/* 0xDA - PAUSE (NEC) */
698static void pce_cd_nec_pause( running_machine &machine )
699{
700   pce_state *state = machine.driver_data<pce_state>();
701   pce_cd_t &pce_cd = state->m_cd;
702
703   /* If no cd mounted throw an error */
704   if ( ! pce_cd.cd )
705   {
706      pce_cd_reply_status_byte( state, SCSI_CHECK_CONDITION );
707      return;
708   }
709
710   /* If there was no cdda playing, throw an error */
711   if ( pce_cd.cdda_status == PCE_CD_CDDA_OFF )
712   {
713      pce_cd_reply_status_byte( state, SCSI_CHECK_CONDITION );
714      return;
715   }
716
717   pce_cd.cdda_status = PCE_CD_CDDA_PAUSED;
718   pce_cd.current_frame = cdda_get_audio_lba( machine.device( "cdda" ) );
719   cdda_pause_audio( machine.device( "cdda" ), 1 );
720   pce_cd_reply_status_byte( state, SCSI_STATUS_OK );
721}
722
723/* 0xDD - READ SUBCHANNEL Q (NEC) */
724static void pce_cd_nec_get_subq( running_machine &machine )
725{
726   pce_state *state = machine.driver_data<pce_state>();
727   pce_cd_t &pce_cd = state->m_cd;
728   /* WP - I do not have access to chds with subchannel information yet, so I'm faking something here */
729   UINT32 msf_abs, msf_rel, track, frame;
730
731   if ( ! pce_cd.cd )
732   {
733      /* Throw some error here */
734      pce_cd_reply_status_byte( state, SCSI_CHECK_CONDITION );
735      return;
736   }
737
738   frame = pce_cd.current_frame;
739
740   switch( pce_cd.cdda_status )
741   {
742   case PCE_CD_CDDA_PAUSED:
743      pce_cd.data_buffer[0] = 2;
744      frame = cdda_get_audio_lba( machine.device( "cdda" ) );
745      break;
746   case PCE_CD_CDDA_PLAYING:
747      pce_cd.data_buffer[0] = 0;
748      frame = cdda_get_audio_lba( machine.device( "cdda" ) );
749      break;
750   default:
751      pce_cd.data_buffer[0] = 3;
752      break;
753   }
754
755   msf_abs = lba_to_msf( frame );
756   track = cdrom_get_track( pce_cd.cd, frame );
757   msf_rel = lba_to_msf( frame - cdrom_get_track_start( pce_cd.cd, track ) );
758
759   pce_cd.data_buffer[1] = 0;
760   pce_cd.data_buffer[2] = dec_2_bcd( track+1 );      /* track */
761   pce_cd.data_buffer[3] = 1;                     /* index */
762   pce_cd.data_buffer[4] = ( msf_rel >> 16 ) & 0xFF;   /* M (relative) */
763   pce_cd.data_buffer[5] = ( msf_rel >> 8 ) & 0xFF;   /* S (relative) */
764   pce_cd.data_buffer[6] = msf_rel & 0xFF;            /* F (relative) */
765   pce_cd.data_buffer[7] = ( msf_abs >> 16 ) & 0xFF;   /* M (absolute) */
766   pce_cd.data_buffer[8] = ( msf_abs >> 8 ) & 0xFF;   /* S (absolute) */
767   pce_cd.data_buffer[9] = msf_abs & 0xFF;            /* F (absolute) */
768   pce_cd.data_buffer_size = 10;
769
770   pce_cd.data_buffer_index = 0;
771   pce_cd.data_transferred = 1;
772   pce_cd.scsi_IO = 1;
773   pce_cd.scsi_CD = 0;
774}
775
776/* 0xDE - GET DIR INFO (NEC) */
777static void pce_cd_nec_get_dir_info( running_machine &machine )
778{
779   pce_state *state = machine.driver_data<pce_state>();
780   pce_cd_t &pce_cd = state->m_cd;
781   UINT32 frame, msf, track = 0;
782   const cdrom_toc   *toc;
783   logerror("nec get dir info\n");
784
785   if ( ! pce_cd.cd )
786   {
787      /* Throw some error here */
788      pce_cd_reply_status_byte( state, SCSI_CHECK_CONDITION );
789   }
790
791   toc = cdrom_get_toc( pce_cd.cd );
792
793   switch( pce_cd.command_buffer[1] )
794   {
795   case 0x00:      /* Get first and last track numbers */
796      pce_cd.data_buffer[0] = dec_2_bcd(1);
797      pce_cd.data_buffer[1] = dec_2_bcd(toc->numtrks);
798      pce_cd.data_buffer_size = 2;
799      break;
800   case 0x01:      /* Get total disk size in MSF format */
801      frame = toc->tracks[toc->numtrks-1].physframeofs;
802      frame += toc->tracks[toc->numtrks-1].frames;
803      msf = lba_to_msf( frame + 150 );
804
805      pce_cd.data_buffer[0] = ( msf >> 16 ) & 0xFF;   /* M */
806      pce_cd.data_buffer[1] = ( msf >> 8 ) & 0xFF;   /* S */
807      pce_cd.data_buffer[2] = msf & 0xFF;            /* F */
808      pce_cd.data_buffer_size = 3;
809      break;
810   case 0x02:      /* Get track information */
811      if ( pce_cd.command_buffer[2] == 0xAA )
812      {
813         frame = toc->tracks[toc->numtrks-1].physframeofs;
814         frame += toc->tracks[toc->numtrks-1].frames;
815         pce_cd.data_buffer[3] = 0x04;   /* correct? */
816      } else
817      {
818         track = MAX( bcd_2_dec( pce_cd.command_buffer[2] ), 1 );
819         frame = toc->tracks[track-1].physframeofs;
820         pce_cd.data_buffer[3] = ( toc->tracks[track-1].trktype == CD_TRACK_AUDIO ) ? 0x00 : 0x04;
821      }
822      logerror("track = %d, frame = %d\n", track, frame );
823      msf = lba_to_msf( frame + 150 );
824      pce_cd.data_buffer[0] = ( msf >> 16 ) & 0xFF;   /* M */
825      pce_cd.data_buffer[1] = ( msf >> 8 ) & 0xFF;   /* S */
826      pce_cd.data_buffer[2] = msf & 0xFF;            /* F */
827      pce_cd.data_buffer_size = 4;
828      break;
829   default:
830//      assert( pce_cd_nec_get_dir_info == NULL );  // Not implemented yet
831      break;
832   }
833
834   pce_cd.data_buffer_index = 0;
835   pce_cd.data_transferred = 1;
836   pce_cd.scsi_IO = 1;
837   pce_cd.scsi_CD = 0;
838}
839
840static void pce_cd_end_of_list( running_machine &machine )
841{
842   pce_state *state = machine.driver_data<pce_state>();
843   pce_cd_reply_status_byte( state, SCSI_CHECK_CONDITION );
844}
845
846static void pce_cd_handle_data_output( running_machine &machine )
847{
848   pce_state *state = machine.driver_data<pce_state>();
849   pce_cd_t &pce_cd = state->m_cd;
850   static const struct {
851      UINT8   command_byte;
852      UINT8   command_size;
853      void   (*command_handler)(running_machine &machine);
854   } pce_cd_commands[] = {
855      { 0x00, 6, pce_cd_test_unit_ready },            /* TEST UNIT READY */
856      { 0x08, 6, pce_cd_read_6 },                     /* READ (6) */
857      { 0xD8,10, pce_cd_nec_set_audio_start_position },   /* NEC SET AUDIO PLAYBACK START POSITION */
858      { 0xD9,10, pce_cd_nec_set_audio_stop_position },   /* NEC SET AUDIO PLAYBACK END POSITION */
859      { 0xDA,10, pce_cd_nec_pause },                  /* NEC PAUSE */
860      { 0xDD,10, pce_cd_nec_get_subq },               /* NEC GET SUBCHANNEL Q */
861      { 0xDE,10, pce_cd_nec_get_dir_info },            /* NEC GET DIR INFO */
862      { 0xFF, 1, pce_cd_end_of_list }                  /* end of list marker */
863   };
864
865   if ( pce_cd.scsi_REQ && pce_cd.scsi_ACK )
866   {
867      /* Command byte received */
868      logerror( "Command byte $%02X received\n", pce_cd.regs[0x01] );
869
870      /* Check for buffer overflow */
871      assert( pce_cd.command_buffer_index < PCE_CD_COMMAND_BUFFER_SIZE );
872
873      pce_cd.command_buffer[pce_cd.command_buffer_index] = pce_cd.regs[0x01];
874      pce_cd.command_buffer_index++;
875      pce_cd.scsi_REQ = 0;
876   }
877
878   if ( ! pce_cd.scsi_REQ && ! pce_cd.scsi_ACK && pce_cd.command_buffer_index )
879   {
880      int i = 0;
881
882      logerror( "Check if command done\n" );
883
884      for( i = 0; pce_cd.command_buffer[0] > pce_cd_commands[i].command_byte; i++ );
885
886      /* Check for unknown commands */
887      if ( pce_cd.command_buffer[0] != pce_cd_commands[i].command_byte )
888      {
889         logerror("Unrecognized command: %02X\n", pce_cd.command_buffer[0] );
890         if(pce_cd.command_buffer[0] == 0x03)
891            popmessage("CD command 0x03 issued (Request Sense), contact MESSdev");
892      }
893      assert( pce_cd.command_buffer[0] == pce_cd_commands[i].command_byte );
894
895      if ( pce_cd.command_buffer_index == pce_cd_commands[i].command_size )
896      {
897         (pce_cd_commands[i].command_handler)( machine );
898         pce_cd.command_buffer_index = 0;
899      }
900      else
901      {
902         pce_cd.scsi_REQ = 1;
903      }
904   }
905}
906
907static void pce_cd_handle_data_input( running_machine &machine )
908{
909   pce_state *state = machine.driver_data<pce_state>();
910   pce_cd_t &pce_cd = state->m_cd;
911   if ( pce_cd.scsi_CD )
912   {
913      /* Command / Status byte */
914      if ( pce_cd.scsi_REQ && pce_cd.scsi_ACK )
915      {
916         logerror( "status sent\n" );
917         pce_cd.scsi_REQ = 0;
918         pce_cd.status_sent = 1;
919      }
920
921      if ( ! pce_cd.scsi_REQ && ! pce_cd.scsi_ACK && pce_cd.status_sent )
922      {
923         pce_cd.status_sent = 0;
924         if ( pce_cd.message_after_status )
925         {
926            logerror( "message after status\n" );
927            pce_cd.message_after_status = 0;
928            pce_cd.scsi_MSG = pce_cd.scsi_REQ = 1;
929            pce_cd.regs[0x01] = 0;
930         }
931      }
932   }
933   else
934   {
935      /* Data */
936      if ( pce_cd.scsi_REQ && pce_cd.scsi_ACK )
937      {
938         pce_cd.scsi_REQ = 0;
939      }
940
941      if ( ! pce_cd.scsi_REQ && ! pce_cd.scsi_ACK )
942      {
943         if ( pce_cd.data_buffer_index == pce_cd.data_buffer_size )
944         {
945            pce_cd_set_irq_line( machine, PCE_CD_IRQ_TRANSFER_READY, CLEAR_LINE );
946            if ( pce_cd.data_transferred )
947            {
948               pce_cd.data_transferred = 0;
949               pce_cd_reply_status_byte( state, SCSI_STATUS_OK );
950               pce_cd_set_irq_line( machine, PCE_CD_IRQ_TRANSFER_DONE, ASSERT_LINE );
951            }
952         }
953         else
954         {
955            logerror("Transfer byte from offset %d\n", pce_cd.data_buffer_index);
956            pce_cd.regs[0x01] = pce_cd.data_buffer[pce_cd.data_buffer_index];
957            pce_cd.data_buffer_index++;
958            pce_cd.scsi_REQ = 1;
959         }
960      }
961   }
962}
963
964static void pce_cd_handle_message_output( pce_state *state )
965{
966   pce_cd_t &pce_cd = state->m_cd;
967   if ( pce_cd.scsi_REQ && pce_cd.scsi_ACK )
968   {
969      pce_cd.scsi_REQ = 0;
970   }
971}
972
973static void pce_cd_handle_message_input( pce_state *state )
974{
975   pce_cd_t &pce_cd = state->m_cd;
976   if ( pce_cd.scsi_REQ && pce_cd.scsi_ACK )
977   {
978      pce_cd.scsi_REQ = 0;
979      pce_cd.message_sent = 1;
980   }
981
982   if ( ! pce_cd.scsi_REQ && ! pce_cd.scsi_ACK && pce_cd.message_sent )
983   {
984      pce_cd.message_sent = 0;
985      pce_cd.scsi_BSY = 0;
986   }
987}
988
989/* Update internal CD statuses */
990static void pce_cd_update( running_machine &machine )
991{
992   pce_state *state = machine.driver_data<pce_state>();
993   pce_cd_t &pce_cd = state->m_cd;
994   /* Check for reset of CD unit */
995   if ( pce_cd.scsi_RST != pce_cd.scsi_last_RST )
996   {
997      if ( pce_cd.scsi_RST )
998      {
999         logerror("Performing CD reset\n");
1000         /* Reset internal data */
1001         pce_cd.scsi_BSY = pce_cd.scsi_SEL = pce_cd.scsi_CD = pce_cd.scsi_IO = 0;
1002         pce_cd.scsi_MSG = pce_cd.scsi_REQ = pce_cd.scsi_ATN = 0;
1003         pce_cd.cd_motor_on = 0;
1004         pce_cd.selected = 0;
1005         pce_cd.cdda_status = PCE_CD_CDDA_OFF;
1006         cdda_stop_audio( machine.device( "cdda" ) );
1007         pce_cd.adpcm_dma_timer->adjust(attotime::never); // stop ADPCM DMA here
1008      }
1009      pce_cd.scsi_last_RST = pce_cd.scsi_RST;
1010   }
1011
1012   /* Check if bus can be freed */
1013   if ( ! pce_cd.scsi_SEL && ! pce_cd.scsi_BSY && pce_cd.selected )
1014   {
1015      logerror( "freeing bus\n" );
1016      pce_cd.selected = 0;
1017      pce_cd.scsi_CD = pce_cd.scsi_MSG = pce_cd.scsi_IO = pce_cd.scsi_REQ = 0;
1018      pce_cd_set_irq_line( machine, PCE_CD_IRQ_TRANSFER_DONE, CLEAR_LINE );
1019   }
1020
1021   /* Select the CD device */
1022   if ( pce_cd.scsi_SEL )
1023   {
1024      if ( ! pce_cd.selected )
1025      {
1026         pce_cd.selected = 1;
1027         logerror("Setting CD in device selection\n");
1028         pce_cd.scsi_BSY = pce_cd.scsi_REQ = pce_cd.scsi_CD = 1;
1029         pce_cd.scsi_MSG = pce_cd.scsi_IO = 0;
1030      }
1031   }
1032
1033   if ( pce_cd.scsi_ATN )
1034   {
1035   }
1036   else
1037   {
1038      /* Check for data and pessage phases */
1039      if ( pce_cd.scsi_BSY )
1040      {
1041         if ( pce_cd.scsi_MSG )
1042         {
1043            /* message phase */
1044            if ( pce_cd.scsi_IO )
1045            {
1046               pce_cd_handle_message_input(state);
1047            }
1048            else
1049            {
1050               pce_cd_handle_message_output(state);
1051            }
1052         }
1053         else
1054         {
1055            /* data phase */
1056            if ( pce_cd.scsi_IO )
1057            {
1058               /* Reading data from target */
1059               pce_cd_handle_data_input( machine );
1060            }
1061            else
1062            {
1063               /* Sending data to target */
1064               pce_cd_handle_data_output( machine );
1065            }
1066         }
1067      }
1068   }
1069
1070   /* FIXME: presumably CD-DA needs an irq interface for this */
1071   if(cdda_audio_ended(machine.device("cdda")) && pce_cd.end_mark == 1)
1072   {
1073      switch(pce_cd.cdda_play_mode & 3)
1074      {
1075         case 1: cdda_start_audio( machine.device( "cdda" ), pce_cd.current_frame, pce_cd.end_frame - pce_cd.current_frame ); pce_cd.end_mark = 1; break; //play with repeat
1076         case 2: pce_cd_set_irq_line( machine, PCE_CD_IRQ_TRANSFER_DONE, ASSERT_LINE ); pce_cd.end_mark = 0; break; //irq when finished
1077         case 3: pce_cd.end_mark = 0; break; //play without repeat
1078      }
1079   }
1080}
1081
1082static void pce_cd_set_irq_line( running_machine &machine, int num, int state )
1083{
1084   pce_state *drvstate = machine.driver_data<pce_state>();
1085   pce_cd_t &pce_cd = drvstate->m_cd;
1086   switch( num )
1087   {
1088   case PCE_CD_IRQ_TRANSFER_DONE:
1089      if ( state == ASSERT_LINE )
1090      {
1091         pce_cd.regs[0x03] |= PCE_CD_IRQ_TRANSFER_DONE;
1092      }
1093      else
1094      {
1095         pce_cd.regs[0x03] &= ~ PCE_CD_IRQ_TRANSFER_DONE;
1096      }
1097      break;
1098   case PCE_CD_IRQ_TRANSFER_READY:
1099      if ( state == ASSERT_LINE )
1100      {
1101         pce_cd.regs[0x03] |= PCE_CD_IRQ_TRANSFER_READY;
1102      }
1103      else
1104      {
1105         pce_cd.regs[0x03] &= ~ PCE_CD_IRQ_TRANSFER_READY;
1106      }
1107      break;
1108   case PCE_CD_IRQ_SAMPLE_FULL_PLAY:
1109      if ( state == ASSERT_LINE )
1110      {
1111         pce_cd.regs[0x03] |= PCE_CD_IRQ_SAMPLE_FULL_PLAY;
1112         //printf("x %02x %02x\n",pce_cd.regs[0x02],pce_cd.regs[0x03]);
1113      }
1114      else
1115      {
1116         pce_cd.regs[0x03] &= ~ PCE_CD_IRQ_SAMPLE_FULL_PLAY;
1117      }
1118      break;
1119   case PCE_CD_IRQ_SAMPLE_HALF_PLAY:
1120      if ( state == ASSERT_LINE )
1121      {
1122         pce_cd.regs[0x03] |= PCE_CD_IRQ_SAMPLE_HALF_PLAY;
1123         //printf("y %02x %02x\n",pce_cd.regs[0x02],pce_cd.regs[0x03]);
1124      }
1125      else
1126      {
1127         pce_cd.regs[0x03] &= ~ PCE_CD_IRQ_SAMPLE_HALF_PLAY;
1128      }
1129      break;
1130   default:
1131      break;
1132   }
1133
1134   if ( pce_cd.regs[0x02] & pce_cd.regs[0x03] & ( PCE_CD_IRQ_TRANSFER_DONE | PCE_CD_IRQ_TRANSFER_READY | PCE_CD_IRQ_SAMPLE_HALF_PLAY | PCE_CD_IRQ_SAMPLE_FULL_PLAY) )
1135   {
1136      cputag_set_input_line(machine, "maincpu", 1, ASSERT_LINE );
1137   }
1138   else
1139   {
1140      cputag_set_input_line(machine, "maincpu", 1, CLEAR_LINE );
1141   }
1142}
1143
1144static TIMER_CALLBACK( pce_cd_data_timer_callback )
1145{
1146   pce_state *state = machine.driver_data<pce_state>();
1147   pce_cd_t &pce_cd = state->m_cd;
1148   if ( pce_cd.data_buffer_index == pce_cd.data_buffer_size )
1149   {
1150      /* Read next data sector */
1151      logerror("read sector %d\n", pce_cd.current_frame );
1152      if ( ! cdrom_read_data( pce_cd.cd, pce_cd.current_frame, pce_cd.data_buffer, CD_TRACK_MODE1 ) )
1153      {
1154         logerror("Mode1 CD read failed for frame #%d\n", pce_cd.current_frame );
1155      }
1156      else
1157      {
1158         logerror("Succesfully read mode1 frame #%d\n", pce_cd.current_frame );
1159      }
1160
1161      pce_cd.data_buffer_index = 0;
1162      pce_cd.data_buffer_size = 2048;
1163      pce_cd.current_frame++;
1164
1165      pce_cd.scsi_IO = 1;
1166      pce_cd.scsi_CD = 0;
1167
1168      if ( pce_cd.current_frame == pce_cd.end_frame )
1169      {
1170         /* We are done, disable the timer */
1171         logerror("Last frame read from CD\n");
1172         pce_cd.data_transferred = 1;
1173         pce_cd.data_timer->adjust(attotime::never);
1174      }
1175      else
1176      {
1177         pce_cd.data_transferred = 0;
1178      }
1179   }
1180}
1181
1182static void pce_cd_init( running_machine &machine )
1183{
1184   pce_state *state = machine.driver_data<pce_state>();
1185   pce_cd_t &pce_cd = state->m_cd;
1186   device_t *device;
1187
1188   /* Initialize pce_cd struct */
1189   memset( &pce_cd, 0, sizeof(pce_cd) );
1190
1191   /* Initialize BRAM */
1192   pce_cd.bram = auto_alloc_array(machine, UINT8, PCE_BRAM_SIZE * 2 );
1193   memset( pce_cd.bram, 0, PCE_BRAM_SIZE );
1194   memset( pce_cd.bram + PCE_BRAM_SIZE, 0xFF, PCE_BRAM_SIZE );
1195   pce_cd.bram_locked = 1;
1196   pce_set_cd_bram(machine);
1197
1198   /* set up adpcm related things */
1199   pce_cd.adpcm_ram = auto_alloc_array(machine, UINT8, PCE_ADPCM_RAM_SIZE );
1200   memset( pce_cd.adpcm_ram, 0, PCE_ADPCM_RAM_SIZE );
1201   pce_cd.adpcm_clock_divider = 1;
1202   msm5205_change_clock_w(machine.device("msm5205"), (PCE_CD_CLOCK / 6) / pce_cd.adpcm_clock_divider);
1203
1204   /* Set up cd command buffer */
1205   pce_cd.command_buffer = auto_alloc_array(machine, UINT8, PCE_CD_COMMAND_BUFFER_SIZE );
1206   memset( pce_cd.command_buffer, 0, PCE_CD_COMMAND_BUFFER_SIZE );
1207   pce_cd.command_buffer_index = 0;
1208
1209   /* Set up Arcade Card RAM buffer */
1210   pce_cd.acard_ram = auto_alloc_array(machine, UINT8, PCE_ACARD_RAM_SIZE );
1211   memset( pce_cd.acard_ram, 0, PCE_ACARD_RAM_SIZE );
1212
1213   pce_cd.data_buffer = auto_alloc_array(machine, UINT8, 8192 );
1214   memset( pce_cd.data_buffer, 0, 8192 );
1215   pce_cd.data_buffer_size = 0;
1216   pce_cd.data_buffer_index = 0;
1217
1218   pce_cd.subcode_buffer = auto_alloc_array(machine, UINT8, 96 );
1219
1220   device = machine.device("cdrom");
1221   if ( device )
1222   {
1223      pce_cd.cd = cd_get_cdrom_file(device);
1224      if ( pce_cd.cd )
1225      {
1226         pce_cd.toc = cdrom_get_toc( pce_cd.cd );
1227         cdda_set_cdrom( machine.device("cdda"), pce_cd.cd );
1228         pce_cd.last_frame = cdrom_get_track_start( pce_cd.cd, cdrom_get_last_track( pce_cd.cd ) - 1 );
1229         pce_cd.last_frame += pce_cd.toc->tracks[ cdrom_get_last_track( pce_cd.cd ) - 1 ].frames;
1230         pce_cd.end_frame = pce_cd.last_frame;
1231      }
1232   }
1233
1234   pce_cd.data_timer = machine.scheduler().timer_alloc(FUNC(pce_cd_data_timer_callback));
1235   pce_cd.data_timer->adjust(attotime::never);
1236   pce_cd.adpcm_dma_timer = machine.scheduler().timer_alloc(FUNC(pce_cd_adpcm_dma_timer_callback));
1237   pce_cd.adpcm_dma_timer->adjust(attotime::never);
1238
1239   pce_cd.cdda_fadeout_timer = machine.scheduler().timer_alloc(FUNC(pce_cd_cdda_fadeout_callback));
1240   pce_cd.cdda_fadeout_timer->adjust(attotime::never);
1241   pce_cd.cdda_fadein_timer = machine.scheduler().timer_alloc(FUNC(pce_cd_cdda_fadein_callback));
1242   pce_cd.cdda_fadein_timer->adjust(attotime::never);
1243
1244   pce_cd.adpcm_fadeout_timer = machine.scheduler().timer_alloc(FUNC(pce_cd_adpcm_fadeout_callback));
1245   pce_cd.adpcm_fadeout_timer->adjust(attotime::never);
1246   pce_cd.adpcm_fadein_timer = machine.scheduler().timer_alloc(FUNC(pce_cd_adpcm_fadein_callback));
1247   pce_cd.adpcm_fadein_timer->adjust(attotime::never);
1248}
1249
1250WRITE8_HANDLER( pce_cd_bram_w )
1251{
1252   pce_state *state = space->machine().driver_data<pce_state>();
1253   pce_cd_t &pce_cd = state->m_cd;
1254   if ( ! pce_cd.bram_locked )
1255   {
1256      pce_cd.bram[ offset ] = data;
1257   }
1258}
1259
1260static void pce_cd_set_adpcm_ram_byte(running_machine &machine, UINT8 val)
1261{
1262   pce_state *state = machine.driver_data<pce_state>();
1263   pce_cd_t &pce_cd = state->m_cd;
1264   if(pce_cd.adpcm_write_buf > 0)
1265   {
1266      pce_cd.adpcm_write_buf--;
1267   }
1268   else
1269   {
1270      pce_cd.adpcm_ram[pce_cd.adpcm_write_ptr] = val;
1271      pce_cd.adpcm_write_ptr = ((pce_cd.adpcm_write_ptr + 1) & 0xffff);
1272      //TODO: length + 1
1273   }
1274}
1275
1276static TIMER_CALLBACK( pce_cd_cdda_fadeout_callback )
1277{
1278   pce_state *state = machine.driver_data<pce_state>();
1279   pce_cd_t &pce_cd = state->m_cd;
1280   pce_cd.cdda_volume-= 0.1;
1281
1282   if(pce_cd.cdda_volume <= 0)
1283   {
1284      pce_cd.cdda_volume = 0.0;
1285      cdda_set_volume(machine.device("cdda"), 0.0);
1286      pce_cd.cdda_fadeout_timer->adjust(attotime::never);
1287   }
1288   else
1289   {
1290      cdda_set_volume(machine.device("cdda"), pce_cd.cdda_volume);
1291      pce_cd.cdda_fadeout_timer->adjust(attotime::from_usec(param), param);
1292   }
1293}
1294
1295static TIMER_CALLBACK( pce_cd_cdda_fadein_callback )
1296{
1297   pce_state *state = machine.driver_data<pce_state>();
1298   pce_cd_t &pce_cd = state->m_cd;
1299   pce_cd.cdda_volume+= 0.1;
1300
1301   if(pce_cd.cdda_volume >= 100.0)
1302   {
1303      pce_cd.cdda_volume = 100.0;
1304      cdda_set_volume(machine.device("cdda"), 100.0);
1305      pce_cd.cdda_fadein_timer->adjust(attotime::never);
1306   }
1307   else
1308   {
1309      cdda_set_volume(machine.device("cdda"), pce_cd.cdda_volume);
1310      pce_cd.cdda_fadein_timer->adjust(attotime::from_usec(param), param);
1311   }
1312}
1313
1314static TIMER_CALLBACK( pce_cd_adpcm_fadeout_callback )
1315{
1316   pce_state *state = machine.driver_data<pce_state>();
1317   pce_cd_t &pce_cd = state->m_cd;
1318   pce_cd.adpcm_volume-= 0.1;
1319
1320   if(pce_cd.adpcm_volume <= 0)
1321   {
1322      pce_cd.adpcm_volume = 0.0;
1323      msm5205_set_volume(machine.device("msm5205"), 0.0);
1324      pce_cd.adpcm_fadeout_timer->adjust(attotime::never);
1325   }
1326   else
1327   {
1328      msm5205_set_volume(machine.device("msm5205"), pce_cd.adpcm_volume);
1329      pce_cd.adpcm_fadeout_timer->adjust(attotime::from_usec(param), param);
1330   }
1331}
1332
1333static TIMER_CALLBACK( pce_cd_adpcm_fadein_callback )
1334{
1335   pce_state *state = machine.driver_data<pce_state>();
1336   pce_cd_t &pce_cd = state->m_cd;
1337   pce_cd.adpcm_volume+= 0.1;
1338
1339   if(pce_cd.adpcm_volume >= 100.0)
1340   {
1341      pce_cd.adpcm_volume = 100.0;
1342      msm5205_set_volume(machine.device("msm5205"), 100.0);
1343      pce_cd.adpcm_fadein_timer->adjust(attotime::never);
1344   }
1345   else
1346   {
1347      msm5205_set_volume(machine.device("msm5205"), pce_cd.adpcm_volume);
1348      pce_cd.adpcm_fadein_timer->adjust(attotime::from_usec(param), param);
1349   }
1350}
1351
1352
1353WRITE8_HANDLER( pce_cd_intf_w )
1354{
1355   pce_state *state = space->machine().driver_data<pce_state>();
1356   pce_cd_t &pce_cd = state->m_cd;
1357   pce_cd_update(space->machine());
1358
1359   if(offset & 0x200 && state->m_sys3_card && state->m_acard) // route Arcade Card handling ports
1360      return pce_cd_acard_w(space,offset,data);
1361
1362   logerror("%04X: write to CD interface offset %02X, data %02X\n", cpu_get_pc(&space->device()), offset, data );
1363
1364   switch( offset & 0xf )
1365   {
1366   case 0x00:   /* CDC status */
1367      /* select device (which bits??) */
1368      pce_cd.scsi_SEL = 1;
1369      pce_cd_update(space->machine());
1370      pce_cd.scsi_SEL = 0;
1371      pce_cd.adpcm_dma_timer->adjust(attotime::never); // stop ADPCM DMA here
1372      /* any write here clears CD transfer irqs */
1373      pce_cd.regs[0x03] &= ~0x70;
1374      cputag_set_input_line(space->machine(), "maincpu", 1, CLEAR_LINE );
1375      break;
1376   case 0x01:   /* CDC command / status / data */
1377      break;
1378   case 0x02:   /* ADPCM / CD control / IRQ enable/disable */
1379            /* bit 6 - transfer ready irq */
1380            /* bit 5 - transfer done irq */
1381            /* bit 4 - ?? irq */
1382            /* bit 3 - ?? irq */
1383            /* bit 2 - ?? irq */
1384      pce_cd.scsi_ACK = data & 0x80;
1385      /* Don't set or reset any irq lines, but just verify the current state */
1386      pce_cd_set_irq_line( space->machine(), 0, 0 );
1387      break;
1388   case 0x03:   /* BRAM lock / CD status / IRQ - Read Only register */
1389      break;
1390   case 0x04:   /* CD reset */
1391      pce_cd.scsi_RST = data & 0x02;
1392      break;
1393   case 0x05:   /* Convert PCM data / PCM data */
1394   case 0x06:   /* PCM data */
1395      break;
1396   case 0x07:   /* BRAM unlock / CD status */
1397      if ( data & 0x80 )
1398      {
1399         pce_cd.bram_locked = 0;
1400         pce_set_cd_bram(space->machine());
1401      }
1402      break;
1403   case 0x08:   /* ADPCM address (LSB) / CD data */
1404      break;
1405   case 0x09:   /* ADPCM address (MSB) */
1406      break;
1407   case 0x0A:   /* ADPCM RAM data port */
1408      pce_cd_set_adpcm_ram_byte(space->machine(), data);
1409      break;
1410   case 0x0B:   /* ADPCM DMA control */
1411      if ( data & 0x03 )
1412      {
1413         /* Start CD to ADPCM transfer */
1414         pce_cd.adpcm_dma_timer->adjust(attotime::from_hz( PCE_CD_DATA_FRAMES_PER_SECOND * 2048 ), 0, attotime::from_hz( PCE_CD_DATA_FRAMES_PER_SECOND * 2048 ) );
1415         pce_cd.regs[0x0c] |= 4;
1416      }
1417      break;
1418   case 0x0C:   /* ADPCM status */
1419      break;
1420   case 0x0D:   /* ADPCM address control */
1421      if ( ( pce_cd.regs[0x0D] & 0x80 ) && ! ( data & 0x80 ) ) // ADPCM reset
1422      {
1423         /* Reset ADPCM hardware */
1424         pce_cd.adpcm_read_ptr = 0;
1425         pce_cd.adpcm_write_ptr = 0;
1426         pce_cd.msm_start_addr = 0;
1427         pce_cd.msm_end_addr = 0;
1428         pce_cd.msm_half_addr = 0;
1429         pce_cd.msm_nibble = 0;
1430         adpcm_stop(space->machine());
1431         msm5205_reset_w( space->machine().device( "msm5205"), 1 );
1432      }
1433
1434      if(data & 0x20)
1435         pce_cd.msm_half_addr = (pce_cd.adpcm_read_ptr + (pce_cd.adpcm_length / ((data & 0x40) ? 2 : 1))) & 0xffff;
1436
1437      if ( ( data & 0x40) && ((pce_cd.regs[0x0D] & 0x40) == 0) ) // ADPCM play
1438      {
1439         pce_cd.msm_start_addr = (pce_cd.adpcm_read_ptr);
1440         pce_cd.msm_end_addr = (pce_cd.adpcm_read_ptr + pce_cd.adpcm_length) & 0xffff;
1441         pce_cd.msm_nibble = 0;
1442         adpcm_play(space->machine());
1443         msm5205_reset_w( space->machine().device( "msm5205"), 0 );
1444
1445         //popmessage("%08x %08x",pce_cd.adpcm_read_ptr,pce_cd.adpcm_length);
1446      }
1447      else if ( (data & 0x40) == 0 )
1448      {
1449         /* used by Buster Bros to cancel an in-flight sample */
1450         adpcm_stop(space->machine());
1451         msm5205_reset_w( space->machine().device( "msm5205"), 1 );
1452      }
1453
1454      if ( data & 0x10 ) //ADPCM set length
1455      {
1456         pce_cd.adpcm_length = ( pce_cd.regs[0x09] << 8 ) | pce_cd.regs[0x08];
1457      }
1458      if ( data & 0x08 ) //ADPCM set read address
1459      {
1460         pce_cd.adpcm_read_ptr = ( pce_cd.regs[0x09] << 8 ) | pce_cd.regs[0x08];
1461         pce_cd.adpcm_read_buf = 2;
1462      }
1463      if ( ( data & 0x02 ) == 0x02 ) //ADPCM set write address
1464      {
1465         pce_cd.adpcm_write_ptr = ( pce_cd.regs[0x09] << 8 ) | pce_cd.regs[0x08];
1466         pce_cd.adpcm_write_buf = data & 1;
1467      }
1468      break;
1469   case 0x0E:   /* ADPCM playback rate */
1470      pce_cd.adpcm_clock_divider = 0x10 - ( data & 0x0F );
1471      msm5205_change_clock_w(space->machine().device("msm5205"), (PCE_CD_CLOCK / 6) / pce_cd.adpcm_clock_divider);
1472      break;
1473   case 0x0F:   /* ADPCM and CD audio fade timer */
1474      /* TODO: timers needs HW tests */
1475      if(pce_cd.regs[0xf] != data)
1476      {
1477         switch(data & 0xf)
1478         {
1479            case 0x00: //CD-DA / ADPCM enable (100 msecs)
1480               pce_cd.cdda_volume = 0.0;
1481               pce_cd.cdda_fadein_timer->adjust(attotime::from_usec(100), 100);
1482               pce_cd.adpcm_volume = 0.0;
1483               pce_cd.adpcm_fadein_timer->adjust(attotime::from_usec(100), 100);
1484               pce_cd.cdda_fadeout_timer->adjust(attotime::never);
1485               pce_cd.adpcm_fadeout_timer->adjust(attotime::never);
1486               break;
1487            case 0x01: //CD-DA enable (100 msecs)
1488               pce_cd.cdda_volume = 0.0;
1489               pce_cd.cdda_fadein_timer->adjust(attotime::from_usec(100), 100);
1490               pce_cd.cdda_fadeout_timer->adjust(attotime::never);
1491               break;
1492            case 0x08: //CD-DA short (1500 msecs) fade out / ADPCM enable
1493               pce_cd.cdda_volume = 100.0;
1494               pce_cd.cdda_fadeout_timer->adjust(attotime::from_usec(1500), 1500);
1495               pce_cd.adpcm_volume = 0.0;
1496               pce_cd.adpcm_fadein_timer->adjust(attotime::from_usec(100), 100);
1497               pce_cd.cdda_fadein_timer->adjust(attotime::never);
1498               pce_cd.adpcm_fadeout_timer->adjust(attotime::never);
1499               break;
1500            case 0x09: //CD-DA long (5000 msecs) fade out
1501               pce_cd.cdda_volume = 100.0;
1502               pce_cd.cdda_fadeout_timer->adjust(attotime::from_usec(5000), 5000);
1503               pce_cd.cdda_fadein_timer->adjust(attotime::never);
1504               break;
1505            case 0x0a: //ADPCM long (5000 msecs) fade out
1506               pce_cd.adpcm_volume = 100.0;
1507               pce_cd.adpcm_fadeout_timer->adjust(attotime::from_usec(5000), 5000);
1508               pce_cd.adpcm_fadein_timer->adjust(attotime::never);
1509               break;
1510            case 0x0c: //CD-DA short (1500 msecs) fade out / ADPCM enable
1511               pce_cd.cdda_volume = 100.0;
1512               pce_cd.cdda_fadeout_timer->adjust(attotime::from_usec(1500), 1500);
1513               pce_cd.adpcm_volume = 0.0;
1514               pce_cd.adpcm_fadein_timer->adjust(attotime::from_usec(100), 100);
1515               pce_cd.cdda_fadein_timer->adjust(attotime::never);
1516               pce_cd.adpcm_fadeout_timer->adjust(attotime::never);
1517               break;
1518            case 0x0d: //CD-DA short (1500 msecs) fade out
1519               pce_cd.cdda_volume = 100.0;
1520               pce_cd.cdda_fadeout_timer->adjust(attotime::from_usec(1500), 1500);
1521               pce_cd.cdda_fadein_timer->adjust(attotime::never);
1522               break;
1523            case 0x0e: //ADPCM short (1500 msecs) fade out
1524               pce_cd.adpcm_volume = 100.0;
1525               pce_cd.adpcm_fadeout_timer->adjust(attotime::from_usec(1500), 1500);
1526               pce_cd.adpcm_fadein_timer->adjust(attotime::never);
1527               break;
1528            default:
1529               popmessage("CD-DA / ADPCM Fade effect mode %02x, contact MESSdev",data & 0x0f);
1530               break;
1531         }
1532      }
1533      break;
1534   default:
1535      return;
1536   }
1537   pce_cd.regs[offset & 0xf] = data;
1538   pce_cd_update(space->machine());
1539}
1540
1541static TIMER_CALLBACK( pce_cd_clear_ack )
1542{
1543   pce_state *state = machine.driver_data<pce_state>();
1544   pce_cd_t &pce_cd = state->m_cd;
1545   pce_cd_update(machine);
1546   pce_cd.scsi_ACK = 0;
1547   pce_cd_update(machine);
1548   if ( pce_cd.scsi_CD )
1549   {
1550      pce_cd.regs[0x0B] &= 0xFE;
1551   }
1552}
1553
1554static UINT8 pce_cd_get_cd_data_byte(running_machine &machine)
1555{
1556   pce_state *state = machine.driver_data<pce_state>();
1557   pce_cd_t &pce_cd = state->m_cd;
1558   UINT8 data = pce_cd.regs[0x01];
1559   if ( pce_cd.scsi_REQ && ! pce_cd.scsi_ACK && ! pce_cd.scsi_CD )
1560   {
1561      if ( pce_cd.scsi_IO )
1562      {
1563         pce_cd.scsi_ACK = 1;
1564         machine.scheduler().timer_set(machine.device<cpu_device>("maincpu")->cycles_to_attotime(15), FUNC(pce_cd_clear_ack));
1565      }
1566   }
1567   return data;
1568}
1569
1570
1571static TIMER_CALLBACK( pce_cd_adpcm_dma_timer_callback )
1572{
1573   pce_state *state = machine.driver_data<pce_state>();
1574   pce_cd_t &pce_cd = state->m_cd;
1575   if ( pce_cd.scsi_REQ && ! pce_cd.scsi_ACK && ! pce_cd.scsi_CD && pce_cd.scsi_IO  )
1576   {
1577      pce_cd.adpcm_ram[pce_cd.adpcm_write_ptr] = pce_cd_get_cd_data_byte(machine);
1578      pce_cd.adpcm_write_ptr = ( pce_cd.adpcm_write_ptr + 1 ) & 0xFFFF;
1579
1580      pce_cd.regs[0x0c] &= ~4;
1581   }
1582}
1583
1584static UINT8 pce_cd_get_adpcm_ram_byte(running_machine &machine)
1585{
1586   pce_state *state = machine.driver_data<pce_state>();
1587   pce_cd_t &pce_cd = state->m_cd;
1588   if(pce_cd.adpcm_read_buf > 0)
1589   {
1590      pce_cd.adpcm_read_buf--;
1591      return 0;
1592   }
1593   else
1594   {
1595      UINT8 res;
1596
1597      res = pce_cd.adpcm_ram[pce_cd.adpcm_read_ptr];
1598      pce_cd.adpcm_read_ptr = ((pce_cd.adpcm_read_ptr + 1) & 0xffff);
1599
1600      return res;
1601   }
1602}
1603
1604READ8_HANDLER( pce_cd_intf_r )
1605{
1606   pce_state *state = space->machine().driver_data<pce_state>();
1607   pce_cd_t &pce_cd = state->m_cd;
1608   UINT8 data = pce_cd.regs[offset & 0x0F];
1609
1610   pce_cd_update(space->machine());
1611
1612   if(offset & 0x200 && state->m_sys3_card && state->m_acard) // route Arcade Card handling ports
1613      return pce_cd_acard_r(space,offset);
1614
1615   logerror("%04X: read from CD interface offset %02X\n", cpu_get_pc(&space->device()), offset );
1616
1617   if((offset & 0xc0) == 0xc0 && state->m_sys3_card) //System 3 Card header handling
1618   {
1619      switch(offset & 0xcf)
1620      {
1621         case 0xc1: return 0xaa;
1622         case 0xc2: return 0x55;
1623         case 0xc3: return 0x00;
1624         case 0xc5: return (state->m_sys3_card & 2) ? 0x55 : 0xaa;
1625         case 0xc6: return (state->m_sys3_card & 2) ? 0xaa : 0x55;
1626         case 0xc7: return 0x03;
1627      }
1628   }
1629
1630   switch( offset & 0xf )
1631   {
1632   case 0x00:   /* CDC status */
1633      data &= 0x07;
1634      data |= pce_cd.scsi_BSY ? 0x80 : 0;
1635      data |= pce_cd.scsi_REQ ? 0x40 : 0;
1636      data |= pce_cd.scsi_MSG ? 0x20 : 0;
1637      data |= pce_cd.scsi_CD  ? 0x10 : 0;
1638      data |= pce_cd.scsi_IO  ? 0x08 : 0;
1639      break;
1640   case 0x01:   /* CDC command / status / data */
1641      break;
1642   case 0x02:   /* ADPCM / CD control */
1643      break;
1644   case 0x03:   /* BRAM lock / CD status */
1645      /* bit 4 set when CD motor is on */
1646      /* bit 2 set when less than half of the ADPCM data is remaining ?? */
1647      pce_cd.bram_locked = 1;
1648      pce_set_cd_bram(space->machine());
1649      data = data & 0x6E;
1650      data |= ( pce_cd.cd_motor_on ? 0x10 : 0 );
1651      pce_cd.regs[0x03] ^= 0x02;         /* TODO: get rid of this hack */
1652      break;
1653   case 0x04:   /* CD reset */
1654      break;
1655   case 0x05:   /* Convert PCM data / PCM data */
1656   case 0x06:   /* PCM data */
1657      break;
1658   case 0x07:   /* BRAM unlock / CD status */
1659      data = ( pce_cd.bram_locked ? ( data & 0x7F ) : ( data | 0x80 ) );
1660      break;
1661   case 0x08:   /* ADPCM address (LSB) / CD data */
1662      data = pce_cd_get_cd_data_byte(space->machine());
1663      break;
1664   case 0x0A:   /* ADPCM RAM data port */
1665      data = pce_cd_get_adpcm_ram_byte(space->machine());
1666      break;
1667   case 0x0B:   /* ADPCM DMA control */
1668      break;
1669   case 0x0C:   /* ADPCM status */
1670      break;
1671   case 0x0D:   /* ADPCM address control */
1672      break;
1673   /* These are read-only registers */
1674   case 0x09:   /* ADPCM address (MSB) */
1675   case 0x0E:   /* ADPCM playback rate */
1676   case 0x0F:   /* ADPCM and CD audio fade timer */
1677      return 0;
1678   default:
1679      data = 0xFF;
1680      break;
1681   }
1682
1683   return data;
1684}
1685
1686
1687/*
1688
1689PC Engine Arcade Card emulation
1690
1691*/
1692
1693READ8_HANDLER( pce_cd_acard_r )
1694{
1695   pce_state *state = space->machine().driver_data<pce_state>();
1696   pce_cd_t &pce_cd = state->m_cd;
1697   UINT8 r_num;
1698
1699   if((offset & 0x2e0) == 0x2e0)
1700   {
1701      switch(offset & 0x2ef)
1702      {
1703         case 0x2e0: return (pce_cd.acard_shift >> 0)  & 0xff;
1704         case 0x2e1: return (pce_cd.acard_shift >> 8)  & 0xff;
1705         case 0x2e2: return (pce_cd.acard_shift >> 16) & 0xff;
1706         case 0x2e3: return (pce_cd.acard_shift >> 24) & 0xff;
1707         case 0x2e4: return (pce_cd.acard_shift_reg);
1708         case 0x2e5: return pce_cd.acard_latch;
1709         case 0x2ee: return 0x10;
1710         case 0x2ef: return 0x51;
1711      }
1712
1713      return 0;
1714   }
1715
1716   r_num = (offset & 0x30) >> 4;
1717
1718   switch(offset & 0x0f)
1719   {
1720      case 0x00:
1721      case 0x01:
1722      {
1723         UINT8 res;
1724         if(pce_cd.acard_ctrl[r_num] & 2)
1725            res = pce_cd.acard_ram[(pce_cd.acard_base_addr[r_num] + pce_cd.acard_addr_offset[r_num]) & 0x1fffff];
1726         else
1727            res = pce_cd.acard_ram[pce_cd.acard_base_addr[r_num] & 0x1fffff];
1728
1729         if(pce_cd.acard_ctrl[r_num] & 0x1)
1730         {
1731            if(pce_cd.acard_ctrl[r_num] & 0x10)
1732            {
1733               pce_cd.acard_base_addr[r_num] += pce_cd.acard_addr_inc[r_num];
1734               pce_cd.acard_base_addr[r_num] &= 0xffffff;
1735            }
1736            else
1737            {
1738               pce_cd.acard_addr_offset[r_num] += pce_cd.acard_addr_inc[r_num];
1739            }
1740         }
1741
1742         return res;
1743      }
1744      case 0x02: return (pce_cd.acard_base_addr[r_num] >> 0) & 0xff;
1745      case 0x03: return (pce_cd.acard_base_addr[r_num] >> 8) & 0xff;
1746      case 0x04: return (pce_cd.acard_base_addr[r_num] >> 16) & 0xff;
1747      case 0x05: return (pce_cd.acard_addr_offset[r_num] >> 0) & 0xff;
1748      case 0x06: return (pce_cd.acard_addr_offset[r_num] >> 8) & 0xff;
1749      case 0x07: return (pce_cd.acard_addr_inc[r_num] >> 0) & 0xff;
1750      case 0x08: return (pce_cd.acard_addr_inc[r_num] >> 8) & 0xff;
1751      case 0x09: return pce_cd.acard_ctrl[r_num];
1752      default:   return 0;
1753   }
1754
1755   return 0;
1756}
1757
1758WRITE8_HANDLER( pce_cd_acard_w )
1759{
1760   pce_state *state = space->machine().driver_data<pce_state>();
1761   pce_cd_t &pce_cd = state->m_cd;
1762   UINT8 w_num;
1763
1764   if((offset & 0x2e0) == 0x2e0)
1765   {
1766      switch(offset & 0x0f)
1767      {
1768         case 0: pce_cd.acard_shift = (data & 0xff) | (pce_cd.acard_shift & 0xffffff00); break;
1769         case 1: pce_cd.acard_shift = (data << 8)   | (pce_cd.acard_shift & 0xffff00ff); break;
1770         case 2: pce_cd.acard_shift = (data << 16)  | (pce_cd.acard_shift & 0xff00ffff); break;
1771         case 3: pce_cd.acard_shift = (data << 24)  | (pce_cd.acard_shift & 0x00ffffff); break;
1772         case 4:
1773            {
1774               pce_cd.acard_shift_reg = data & 0x0f;
1775
1776               if(pce_cd.acard_shift_reg != 0)
1777               {
1778                   pce_cd.acard_shift = (pce_cd.acard_shift_reg < 8) ?
1779                                 (pce_cd.acard_shift << pce_cd.acard_shift_reg)
1780                                 : (pce_cd.acard_shift >> (16 - pce_cd.acard_shift_reg));
1781               }
1782            }
1783            break;
1784         case 5: pce_cd.acard_latch = data; break;
1785      }
1786   }
1787   else
1788   {
1789      w_num = (offset & 0x30) >> 4;
1790
1791      switch(offset & 0x0f)
1792      {
1793         case 0x00:
1794         case 0x01:
1795            if(pce_cd.acard_ctrl[w_num] & 2)
1796               pce_cd.acard_ram[(pce_cd.acard_base_addr[w_num] + pce_cd.acard_addr_offset[w_num]) & 0x1fffff] = data;
1797            else
1798               pce_cd.acard_ram[pce_cd.acard_base_addr[w_num] & 0x1FFFFF] = data;
1799
1800            if(pce_cd.acard_ctrl[w_num] & 0x1)
1801            {
1802               if(pce_cd.acard_ctrl[w_num] & 0x10)
1803               {
1804                  pce_cd.acard_base_addr[w_num] += pce_cd.acard_addr_inc[w_num];
1805                  pce_cd.acard_base_addr[w_num] &= 0xffffff;
1806               }
1807               else
1808               {
1809                  pce_cd.acard_addr_offset[w_num] += pce_cd.acard_addr_inc[w_num];
1810               }
1811            }
1812
1813            break;
1814
1815         case 0x02: pce_cd.acard_base_addr[w_num] = (data & 0xff) | (pce_cd.acard_base_addr[w_num] & 0xffff00);   break;
1816         case 0x03: pce_cd.acard_base_addr[w_num] = (data << 8) | (pce_cd.acard_base_addr[w_num] & 0xff00ff);      break;
1817         case 0x04: pce_cd.acard_base_addr[w_num] = (data << 16) | (pce_cd.acard_base_addr[w_num] & 0x00ffff);   break;
1818         case 0x05: pce_cd.acard_addr_offset[w_num] = (data & 0xff) | (pce_cd.acard_addr_offset[w_num] & 0xff00);   break;
1819         case 0x06:
1820            pce_cd.acard_addr_offset[w_num] = (data << 8) | (pce_cd.acard_addr_offset[w_num] & 0x00ff);
1821
1822            if((pce_cd.acard_ctrl[w_num] & 0x60) == 0x40)
1823            {
1824               pce_cd.acard_base_addr[w_num] += pce_cd.acard_addr_offset[w_num] + ((pce_cd.acard_ctrl[w_num] & 0x08) ? 0xff0000 : 0);
1825               pce_cd.acard_base_addr[w_num] &= 0xffffff;
1826            }
1827            break;
1828         case 0x07: pce_cd.acard_addr_inc[w_num] = (data & 0xff) | (pce_cd.acard_addr_inc[w_num] & 0xff00);      break;
1829         case 0x08: pce_cd.acard_addr_inc[w_num] = (data << 8) | (pce_cd.acard_addr_inc[w_num] & 0x00ff);         break;
1830         case 0x09: pce_cd.acard_ctrl[w_num] = data & 0x7f;                                    break;
1831         case 0x0a:
1832            if((pce_cd.acard_ctrl[w_num] & 0x60) == 0x60)
1833            {
1834               pce_cd.acard_base_addr[w_num] += pce_cd.acard_addr_offset[w_num];
1835               pce_cd.acard_base_addr[w_num] &= 0xffffff;
1836            }
1837            break;
1838      }
1839   }
1840}
1841
1842READ8_HANDLER( pce_cd_acard_wram_r )
1843{
1844   return pce_cd_intf_r(space,0x200 | (offset & 0x6000) >> 9);
1845}
1846
1847WRITE8_HANDLER( pce_cd_acard_wram_w )
1848{
1849   pce_cd_intf_w(space,0x200 | (offset & 0x6000) >> 9,data);
1850}
1851
src/mess/machine/atarifdc.c
r0r11532
1/***************************************************************************
2
3    Atari 400/800
4
5    Floppy Disk Controller code
6
7    Juergen Buchmueller, June 1998
8
9***************************************************************************/
10
11#include <ctype.h>
12
13#include "emu.h"
14#include "cpu/m6502/m6502.h"
15#include "includes/atari.h"
16#include "ataridev.h"
17#include "sound/pokey.h"
18#include "machine/6821pia.h"
19#include "imagedev/flopdrv.h"
20#include "image.h"
21
22#define VERBOSE_SERIAL   0
23#define VERBOSE_CHKSUM   0
24
25typedef struct _atari_drive atari_drive;
26struct _atari_drive
27{
28   UINT8 *image;      /* malloc'd image */
29   int type;         /* type of image (XFD, ATR, DSK) */
30   int mode;         /* 0 read only, != 0 read/write */
31   int density;      /* 0 SD, 1 MD, 2 DD */
32   int header_skip;   /* number of bytes in format header */
33   int tracks;       /* number of tracks (35,40,77,80) */
34   int heads;         /* number of heads (1,2) */
35   int spt;         /* sectors per track (18,26) */
36   int seclen;       /* sector length (128,256) */
37   int bseclen;      /* boot sector length (sectors 1..3) */
38   int sectors;      /* total sectors, ie. tracks x heads x spt */
39};
40
41typedef struct _atari_fdc_t atari_fdc_t;
42struct _atari_fdc_t
43{
44   int  serout_count;
45   int  serout_offs;
46   UINT8 serout_buff[512];
47   UINT8 serout_chksum;
48   int  serout_delay;
49
50   int  serin_count;
51   int  serin_offs;
52   UINT8 serin_buff[512];
53   UINT8 serin_chksum;
54   int  serin_delay;
55
56   atari_drive drv[4];
57};
58
59/*************************************
60 *
61 *  Disk stuff
62 *
63 *************************************/
64
65#define FORMAT_XFD   0
66#define FORMAT_ATR   1
67#define FORMAT_DSK   2
68
69/*****************************************************************************
70    INLINE FUNCTIONS
71*****************************************************************************/
72INLINE atari_fdc_t *get_safe_token(device_t *device)
73{
74   assert(device != NULL);
75   assert(device->type() == ATARI_FDC);
76
77   return (atari_fdc_t *)downcast<legacy_device_base *>(device)->token();
78}
79
80/*****************************************************************************
81 * This is the structure I used in my own Atari 800 emulator some years ago
82 * Though it's a bit overloaded, I used it as it is the maximum of all
83 * supported formats:
84 * XFD no header at all
85 * ATR 16 bytes header
86 * DSK this struct
87 * It is used to determine the format of a XFD image by it's size only
88 *****************************************************************************/
89
90typedef struct _dsk_format dsk_format;
91struct _dsk_format
92{
93   UINT8 density;
94   UINT8 tracks;
95   UINT8 door;
96   UINT8 sta1;
97   UINT8 spt;
98   UINT8 doublesided;
99   UINT8 highdensity;
100   UINT8 seclen_hi;
101   UINT8 seclen_lo;
102   UINT8 status;
103   UINT8 sta2;
104   UINT8 sta3;
105   UINT8 sta4;
106   UINT8 cr;
107   UINT8 info[65+1];
108};
109
110/* combined with the size the image should have */
111typedef struct _xfd_format xfd_format;
112struct _xfd_format
113{
114   int size;
115   dsk_format dsk;
116};
117
118/* here's a table of known xfd formats */
119static const xfd_format xfd_formats[] =
120{
121   {35 * 18 * 1 * 128,             {0,35,1,0,18,0,0,0,128,255,0,0,0,13,"35 SS/SD"}},
122   {35 * 26 * 1 * 128,             {1,35,1,0,26,0,4,0,128,255,0,0,0,13,"35 SS/MD"}},
123   {(35 * 18 * 1 - 3) * 256 + 3 * 128, {2,35,1,0,18,0,4,1,  0,255,0,0,0,13,"35 SS/DD"}},
124   {40 * 18 * 1 * 128,             {0,40,1,0,18,0,0,0,128,255,0,0,0,13,"40 SS/SD"}},
125   {40 * 26 * 1 * 128,             {1,40,1,0,26,0,4,0,128,255,0,0,0,13,"40 SS/MD"}},
126   {(40 * 18 * 1 - 3) * 256 + 3 * 128, {2,40,1,0,18,0,4,1,  0,255,0,0,0,13,"40 SS/DD"}},
127   {40 * 18 * 2 * 128,             {0,40,1,0,18,1,0,0,128,255,0,0,0,13,"40 DS/SD"}},
128   {40 * 26 * 2 * 128,             {1,40,1,0,26,1,4,0,128,255,0,0,0,13,"40 DS/MD"}},
129   {(40 * 18 * 2 - 3) * 256 + 3 * 128, {2,40,1,0,18,1,4,1,  0,255,0,0,0,13,"40 DS/DD"}},
130   {77 * 18 * 1 * 128,             {0,77,1,0,18,0,0,0,128,255,0,0,0,13,"77 SS/SD"}},
131   {77 * 26 * 1 * 128,             {1,77,1,0,26,0,4,0,128,255,0,0,0,13,"77 SS/MD"}},
132   {(77 * 18 * 1 - 3) * 256 + 3 * 128, {2,77,1,0,18,0,4,1,  0,255,0,0,0,13,"77 SS/DD"}},
133   {77 * 18 * 2 * 128,             {0,77,1,0,18,1,0,0,128,255,0,0,0,13,"77 DS/SD"}},
134   {77 * 26 * 2 * 128,             {1,77,1,0,26,1,4,0,128,255,0,0,0,13,"77 DS/MD"}},
135   {(77 * 18 * 2 - 3) * 256 + 3 * 128, {2,77,1,0,18,1,4,1,  0,255,0,0,0,13,"77 DS/DD"}},
136   {80 * 18 * 2 * 128,             {0,80,1,0,18,1,0,0,128,255,0,0,0,13,"80 DS/SD"}},
137   {80 * 26 * 2 * 128,             {1,80,1,0,26,1,4,0,128,255,0,0,0,13,"80 DS/MD"}},
138   {(80 * 18 * 2 - 3) * 256 + 3 * 128, {2,80,1,0,18,1,4,1,  0,255,0,0,0,13,"80 DS/DD"}},
139   {0, {0,}}
140};
141
142/*****************************************************************************
143 *
144 * Open a floppy image for drive 'drive' if it is not yet openend
145 * and a name was given. Determine the image geometry depending on the
146 * type of image and store the results into the global drv[] structure
147 *
148 *****************************************************************************/
149
150#define MAXSIZE 5760 * 256 + 80
151static void atari_load_proc(device_image_interface &image)
152{
153   atari_fdc_t *fdc = get_safe_token(image.device().owner());
154   int id = floppy_get_drive(image);
155   int size, i;
156   const char *ext;
157
158   fdc->drv[id].image = (UINT8*)image.image_malloc(MAXSIZE);
159   if (!fdc->drv[id].image)
160      return;
161
162   /* tell whether the image is writable */
163   fdc->drv[id].mode = !image.is_readonly();
164   /* set up image if it has been created */
165   if (image.has_been_created())
166   {
167      int sector;
168      char buff[256];
169      memset(buff, 0, sizeof(buff));
170      /* default to 720 sectors */
171      for( sector = 0; sector < 720; sector++ )
172         image.fwrite(buff, 256);
173      image.fseek(0, SEEK_SET);
174   }
175
176   size = image.fread(fdc->drv[id].image, MAXSIZE);
177   if( size <= 0 )
178   {
179      fdc->drv[id].image = NULL;
180      return;
181   }
182   /* re allocate the buffer; we don't want to be too lazy ;) */
183    fdc->drv[id].image = (UINT8*)image.image_realloc(fdc->drv[id].image, size);
184
185   ext = image.filetype();
186    /* no extension: assume XFD format (no header) */
187    if (!ext)
188    {
189        fdc->drv[id].type = FORMAT_XFD;
190        fdc->drv[id].header_skip = 0;
191    }
192    else
193    /* XFD extension */
194    if( toupper(ext[0])=='X' && toupper(ext[1])=='F' && toupper(ext[2])=='D' )
195    {
196        fdc->drv[id].type = FORMAT_XFD;
197        fdc->drv[id].header_skip = 0;
198    }
199    else
200    /* ATR extension */
201    if( toupper(ext[0])=='A' && toupper(ext[1])=='T' && toupper(ext[2])=='R' )
202    {
203        fdc->drv[id].type = FORMAT_ATR;
204        fdc->drv[id].header_skip = 16;
205    }
206    else
207    /* DSK extension */
208    if( toupper(ext[0])=='D' && toupper(ext[1])=='S' && toupper(ext[2])=='K' )
209    {
210        fdc->drv[id].type = FORMAT_DSK;
211        fdc->drv[id].header_skip = sizeof(dsk_format);
212    }
213    else
214    {
215      fdc->drv[id].type = FORMAT_XFD;
216        fdc->drv[id].header_skip = 0;
217    }
218
219   if( fdc->drv[id].type == FORMAT_ATR &&
220      (fdc->drv[id].image[0] != 0x96 || fdc->drv[id].image[1] != 0x02) )
221   {
222      fdc->drv[id].type = FORMAT_XFD;
223      fdc->drv[id].header_skip = 0;
224   }
225
226   switch (fdc->drv[id].type)
227   {
228   /* XFD or unknown format: find a matching size from the table */
229   case FORMAT_XFD:
230      for( i = 0; xfd_formats[i].size; i++ )
231      {
232         if( size == xfd_formats[i].size )
233         {
234            fdc->drv[id].density = xfd_formats[i].dsk.density;
235            fdc->drv[id].tracks = xfd_formats[i].dsk.tracks;
236            fdc->drv[id].spt = xfd_formats[i].dsk.spt;
237            fdc->drv[id].heads = (xfd_formats[i].dsk.doublesided) ? 2 : 1;
238            fdc->drv[id].bseclen = 128;
239            fdc->drv[id].seclen = 256 * xfd_formats[i].dsk.seclen_hi + xfd_formats[i].dsk.seclen_lo;
240            fdc->drv[id].sectors = fdc->drv[id].tracks * fdc->drv[id].heads * fdc->drv[id].spt;
241            break;
242         }
243      }
244      break;
245   /* ATR format: find a size including the 16 bytes header */
246   case FORMAT_ATR:
247      {
248         int s;
249
250         fdc->drv[id].bseclen = 128;
251         /* get sectors from ATR header */
252         s = (size - 16) / 128;
253         /* 3 + odd number of sectors ? */
254         if ( fdc->drv[id].image[4] == 128 || (s % 18) == 0 || (s % 26) == 0 || ((s - 3) % 1) != 0 )
255         {
256            fdc->drv[id].sectors = s;
257            fdc->drv[id].seclen = 128;
258            /* sector size 128 or count not evenly dividable by 26 ? */
259            if( fdc->drv[id].seclen == 128 || (s % 26) != 0 )
260            {
261               /* yup! single density */
262               fdc->drv[id].density = 0;
263               fdc->drv[id].spt = 18;
264               fdc->drv[id].heads = 1;
265               fdc->drv[id].tracks = s / 18;
266               if( s % 18 != 0 )
267                  fdc->drv[id].tracks += 1;
268               if( fdc->drv[id].tracks % 2 == 0 && fdc->drv[id].tracks > 80 )
269               {
270                  fdc->drv[id].heads = 2;
271                  fdc->drv[id].tracks /= 2;
272               }
273            }
274            else
275            {
276               /* yes: medium density */
277               fdc->drv[id].density = 0;
278               fdc->drv[id].spt = 26;
279               fdc->drv[id].heads = 1;
280               fdc->drv[id].tracks = s / 26;
281               if( s % 26 != 0 )
282                  fdc->drv[id].tracks += 1;
283               if( fdc->drv[id].tracks % 2 == 0 && fdc->drv[id].tracks > 80 )
284               {
285                  fdc->drv[id].heads = 2;
286                  fdc->drv[id].tracks /= 2;
287               }
288            }
289         }
290         else
291         {
292            /* it's double density */
293            s = (s - 3) / 2 + 3;
294            fdc->drv[id].sectors = s;
295            fdc->drv[id].density = 2;
296            fdc->drv[id].seclen = 256;
297            fdc->drv[id].spt = 18;
298            fdc->drv[id].heads = 1;
299            fdc->drv[id].tracks = s / 18;
300            if( s % 18 != 0 )
301               fdc->drv[id].tracks += 1;
302            if( fdc->drv[id].tracks % 2 == 0 && fdc->drv[id].tracks > 80 )
303            {
304               fdc->drv[id].heads = 2;
305               fdc->drv[id].tracks /= 2;
306            }
307         }
308      }
309      break;
310   /* DSK format: it's all in the header */
311   case FORMAT_DSK:
312      {
313         dsk_format *dsk = (dsk_format *) fdc->drv[id].image;
314
315         fdc->drv[id].tracks = dsk->tracks;
316         fdc->drv[id].spt = dsk->spt;
317         fdc->drv[id].heads = (dsk->doublesided) ? 2 : 1;
318         fdc->drv[id].seclen = 256 * dsk->seclen_hi + dsk->seclen_lo;
319         fdc->drv[id].bseclen = fdc->drv[id].seclen;
320         fdc->drv[id].sectors = fdc->drv[id].tracks * fdc->drv[id].heads * fdc->drv[id].spt;
321      }
322      break;
323   }
324   logerror("atari opened floppy '%s', %d sectors (%d %s%s) %d bytes/sector\n",
325         image.filename(),
326         fdc->drv[id].sectors,
327         fdc->drv[id].tracks,
328         (fdc->drv[id].heads == 1) ? "SS" : "DS",
329         (fdc->drv[id].density == 0) ? "SD" : (fdc->drv[id].density == 1) ? "MD" : "DD",
330         fdc->drv[id].seclen);
331   return;
332}
333
334
335
336/*****************************************************************************
337 *
338 * This is a description of the data flow between Atari (A) and the
339 * Floppy (F) for the supported commands.
340 *
341 * A->F     DEV  CMD  AUX1 AUX2 CKS
342 *          '1'  'S'  00   00                 get status
343 * F->A     ACK  CPL  04   FF   E0   00   CKS
344 *                     ^    ^
345 *                     |    |
346 *                     |    bit 7 : door closed
347 *                     |
348 *                     bit7  : MD 128 bytes/sector, 26 sectors/track
349 *                     bit5  : DD 256 bytes/sector, 18 sectors/track
350 *                     else  : SD 128 bytes/sector, 18 sectors/track
351 *
352 * A->F     DEV  CMD  AUX1 AUX2 CKS
353 *          '1'  'R'  SECL SECH               read sector
354 * F->A     ACK                               command acknowledge
355 *               ***                          now read the sector
356 * F->A              CPL                      complete: sector read
357 * F->A                  128/256 byte CKS
358 *
359 * A->F     DEV  CMD  AUX1 AUX2 CKS
360 *          '1'  'W'  SECL SECH               write with verify
361 * F->A     ACK                               command acknowledge
362 * A->F          128/256 data CKS
363 * F->A                            CPL        complete: CKS okay
364 *          execute writing the sector
365 * F->A                                 CPL   complete: sector written
366 *
367 * A->F     DEV  CMD  AUX1 AUX2 CKS
368 *          '1'  'P'  SECL SECH               put sector
369 * F->A     ACK                               command acknowledge
370 * A->F          128/256 data CKS
371 * F->A                            CPL        complete: CKS okay
372 *          execute writing the sector
373 * F->A                                 CPL   complete: sector written
374 *
375 * A->F     DEV  CMD  AUX1 AUX2 CKS
376 *           '1' '!'  xx   xx                 single density format
377 * F->A     ACK                               command acknowledge
378 *          execute formatting
379 * F->A               CPL                     complete: format
380 * F->A                    128/256 byte CKS   bad sector table
381 *
382 *
383 * A->F     DEV  CMD  AUX1 AUX2 CKS
384 *          '1'  '"'  xx   xx                 double density format
385 * F->A     ACK                               command acknowledge
386 *          execute formatting
387 * F->A               CPL                     complete: format
388 * F->A                    128/256 byte CKS   bad sector table
389 *
390 *****************************************************************************/
391static void make_chksum(UINT8 * chksum, UINT8 data)
392{
393   UINT8 newone;
394   newone= *chksum + data;
395   if (newone < *chksum)
396      newone++;
397
398   if (VERBOSE_CHKSUM)
399      logerror("atari chksum old $%02x + data $%02x -> new $%02x\n", *chksum, data, newone);
400
401   *chksum = newone;
402}
403
404static void clr_serout(device_t *device,int expect_data)
405{
406   atari_fdc_t *fdc = get_safe_token(device);
407
408   fdc->serout_chksum = 0;
409   fdc->serout_offs = 0;
410   fdc->serout_count = expect_data + 1;
411}
412
413static void add_serout(device_t *device,int expect_data)
414{
415   atari_fdc_t *fdc = get_safe_token(device);
416
417   fdc->serout_chksum = 0;
418   fdc->serout_count = expect_data + 1;
419}
420
421static void clr_serin(device_t *device, int ser_delay)
422{
423   atari_fdc_t *fdc = get_safe_token(device);
424   device_t *pokey = device->machine().device("pokey");
425   fdc->serin_chksum = 0;
426   fdc->serin_offs = 0;
427   fdc->serin_count = 0;
428   pokey_serin_ready(pokey, ser_delay * 40);
429}
430
431static void add_serin(device_t *device,UINT8 data, int with_checksum)
432{
433   atari_fdc_t *fdc = get_safe_token(device);
434   fdc->serin_buff[fdc->serin_count++] = data;
435   if (with_checksum)
436      make_chksum(&fdc->serin_chksum, data);
437}
438
439static void ATTR_PRINTF(2,3) atari_set_frame_message(device_t *device,const char *fmt, ...)
440{
441   va_list arg;
442   va_start(arg, fmt);
443
444   vsprintf(atari_frame_message, fmt, arg);
445   atari_frame_counter = 30; /* FIXME */
446
447   va_end(arg);
448}
449
450static void a800_serial_command(device_t *device)
451{
452   int i, drive, sector, offset;
453   atari_fdc_t *fdc = get_safe_token(device);
454
455   if( !fdc->serout_offs )
456   {
457      if (VERBOSE_SERIAL)
458         logerror("atari serout command offset = 0\n");
459      return;
460   }
461   clr_serin(device, 10);
462
463   if (VERBOSE_SERIAL)
464   {
465      logerror("atari serout command %d: %02X %02X %02X %02X %02X : %02X ",
466         fdc->serout_offs,
467         fdc->serout_buff[0], fdc->serout_buff[1], fdc->serout_buff[2],
468         fdc->serout_buff[3], fdc->serout_buff[4], fdc->serout_chksum);
469   }
470
471   if (fdc->serout_chksum == 0)
472   {
473      if (VERBOSE_SERIAL)
474         logerror("OK\n");
475
476      drive = fdc->serout_buff[0] - '1';   /* drive # */
477      /* sector # */
478      if (drive < 0 || drive > 3)          /* ignore unknown drives */
479      {
480         logerror("atari unsupported drive #%d\n", drive+1);
481         atari_set_frame_message(device, "DRIVE #%d not supported", drive+1);
482         return;
483      }
484
485      /* extract sector number from the command buffer */
486      sector = fdc->serout_buff[2] + 256 * fdc->serout_buff[3];
487
488      switch (fdc->serout_buff[1]) /* command ? */
489      {
490         case 'S':   /* status */
491            atari_set_frame_message(device, "DRIVE #%d STATUS", drive+1);
492
493            if (VERBOSE_SERIAL)
494               logerror("atari status\n");
495
496            add_serin(device,'A',0);
497            add_serin(device,'C',0);
498            if (!fdc->drv[drive].mode) /* read only mode ? */
499            {
500               if (fdc->drv[drive].spt == 26)
501                  add_serin(device,0x80,1);   /* MD: 0x80 */
502               else
503               if (fdc->drv[drive].seclen == 128)
504                  add_serin(device,0x00,1);   /* SD: 0x00 */
505               else
506                  add_serin(device,0x20,1);   /* DD: 0x20 */
507            }
508            else
509            {
510               if (fdc->drv[drive].spt == 26)
511                  add_serin(device,0x84,1);   /* MD: 0x84 */
512               else
513               if (fdc->drv[drive].seclen == 128)
514                  add_serin(device,0x04,1);   /* SD: 0x04 */
515               else
516                  add_serin(device,0x24,1);   /* DD: 0x24 */
517            }
518            if (fdc->drv[drive].image)
519               add_serin(device,0xff,1);   /* door closed: 0xff */
520            else
521               add_serin(device,0x7f,1);   /* door open: 0x7f */
522            add_serin(device,0xe0,1);   /* dunno */
523            add_serin(device,0x00,1);   /* dunno */
524            add_serin(device,fdc->serin_chksum,0);
525            break;
526
527         case 'R':   /* read sector */
528            if (VERBOSE_SERIAL)
529               logerror("atari read sector #%d\n", sector);
530
531            if( sector < 1 || sector > fdc->drv[drive].sectors )
532            {
533               atari_set_frame_message(device, "DRIVE #%d READ SECTOR #%3d - ERR", drive+1, sector);
534
535               if (VERBOSE_SERIAL)
536                  logerror("atari bad sector #\n");
537
538               add_serin(device,'E',0);
539               break;
540            }
541            add_serin(device,'A',0);   /* acknowledge */
542            add_serin(device,'C',0);   /* completed */
543            if (sector < 4)    /* sector 1 .. 3 might be different length */
544            {
545               atari_set_frame_message(device, "DRIVE #%d READ SECTOR #%3d - SD", drive+1, sector);
546               offset = (sector - 1) * fdc->drv[drive].bseclen + fdc->drv[drive].header_skip;
547               for (i = 0; i < 128; i++)
548                  add_serin(device,fdc->drv[drive].image[offset++],1);
549            }
550            else
551            {
552               atari_set_frame_message(device, "DRIVE #%d READ SECTOR #%3d - %cD", drive+1, sector, (fdc->drv[drive].seclen == 128) ? 'S' : 'D');
553                    offset = (sector - 1) * fdc->drv[drive].seclen + fdc->drv[drive].header_skip;
554               for (i = 0; i < fdc->drv[drive].seclen; i++)
555                  add_serin(device,fdc->drv[drive].image[offset++],1);
556            }
557            add_serin(device,fdc->serin_chksum,0);
558            break;
559
560         case 'W':   /* write sector with verify */
561            if (VERBOSE_SERIAL)
562               logerror("atari write sector #%d\n", sector);
563
564            add_serin(device,'A',0);
565            if (sector < 4)    /* sector 1 .. 3 might be different length */
566            {
567               add_serout(device,fdc->drv[drive].bseclen);
568               atari_set_frame_message(device, "DRIVE #%d WRITE SECTOR #%3d - SD", drive+1, sector);
569                }
570            else
571            {
572               add_serout(device,fdc->drv[drive].seclen);
573               atari_set_frame_message(device, "DRIVE #%d WRITE SECTOR #%3d - %cD", drive+1, sector, (fdc->drv[drive].seclen == 128) ? 'S' : 'D');
574                }
575            break;
576
577         case 'P':   /* put sector (no verify) */
578            if (VERBOSE_SERIAL)
579               logerror("atari put sector #%d\n", sector);
580
581            add_serin(device,'A',0);
582            if (sector < 4)    /* sector 1 .. 3 might be different length */
583            {
584               add_serout(device,fdc->drv[drive].bseclen);
585               atari_set_frame_message(device, "DRIVE #%d PUT SECTOR #%3d - SD", drive+1, sector);
586                }
587            else
588            {
589               add_serout(device,fdc->drv[drive].seclen);
590               atari_set_frame_message(device, "DRIVE #%d PUT SECTOR #%3d - %cD", drive+1, sector, (fdc->drv[drive].seclen == 128) ? 'S' : 'D');
591                }
592            break;
593
594         case '!':   /* SD format */
595            if (VERBOSE_SERIAL)
596               logerror("atari format SD drive #%d\n", drive+1);
597
598            atari_set_frame_message(device, "DRIVE #%d FORMAT SD", drive+1);
599                add_serin(device,'A',0);   /* acknowledge */
600            add_serin(device,'C',0);   /* completed */
601            for (i = 0; i < 128; i++)
602               add_serin(device,0,1);
603            add_serin(device,fdc->serin_chksum,0);
604            break;
605
606         case '"':   /* DD format */
607            if (VERBOSE_SERIAL)
608               logerror("atari format DD drive #%d\n", drive+1);
609
610            atari_set_frame_message(device, "DRIVE #%d FORMAT DD", drive+1);
611                add_serin(device,'A',0);   /* acknowledge */
612            add_serin(device,'C',0);   /* completed */
613            for (i = 0; i < 256; i++)
614               add_serin(device,0,1);
615            add_serin(device,fdc->serin_chksum,0);
616            break;
617
618         default:
619            if (VERBOSE_SERIAL)
620               logerror("atari unknown command #%c\n", fdc->serout_buff[1]);
621
622            atari_set_frame_message(device, "DRIVE #%d UNKNOWN CMD '%c'", drive+1, fdc->serout_buff[1]);
623                add_serin(device,'N',0);   /* negative acknowledge */
624      }
625   }
626   else
627   {
628      atari_set_frame_message(device, "serial cmd chksum error");
629      if (VERBOSE_SERIAL)
630         logerror("BAD\n");
631
632      add_serin(device,'E',0);
633   }
634   if (VERBOSE_SERIAL)
635      logerror("atari %d bytes to read\n", fdc->serin_count);
636}
637
638static void a800_serial_write(device_t *device)
639{
640   int i, drive, sector, offset;
641   atari_fdc_t *fdc = get_safe_token(device);
642
643   if (VERBOSE_SERIAL)
644   {
645      logerror("atari serout %d bytes written : %02X ",
646         fdc->serout_offs, fdc->serout_chksum);
647   }
648
649   clr_serin(device, 80);
650   if (fdc->serout_chksum == 0)
651   {
652      if (VERBOSE_SERIAL)
653         logerror("OK\n");
654
655      add_serin(device,'C',0);
656      /* write the sector */
657      drive = fdc->serout_buff[0] - '1';   /* drive # */
658      /* not write protected and image available ? */
659      if (fdc->drv[drive].mode && fdc->drv[drive].image)
660      {
661         /* extract sector number from the command buffer */
662         sector = fdc->serout_buff[2] + 256 * fdc->serout_buff[3];
663         if (sector < 4)    /* sector 1 .. 3 might be different length */
664         {
665            offset = (sector - 1) * fdc->drv[drive].bseclen + fdc->drv[drive].header_skip;
666
667            if (VERBOSE_SERIAL)
668               logerror("atari storing 128 byte sector %d at offset 0x%08X", sector, offset );
669
670            for (i = 0; i < 128; i++)
671               fdc->drv[drive].image[offset++] = fdc->serout_buff[5+i];
672            atari_set_frame_message(device, "DRIVE #%d WROTE SECTOR #%3d - SD", drive+1, sector);
673            }
674         else
675         {
676            offset = (sector - 1) * fdc->drv[drive].seclen + fdc->drv[drive].header_skip;
677
678            if (VERBOSE_SERIAL)
679               logerror("atari storing %d byte sector %d at offset 0x%08X", fdc->drv[drive].seclen, sector, offset );
680
681            for (i = 0; i < fdc->drv[drive].seclen; i++)
682               fdc->drv[drive].image[offset++] = fdc->serout_buff[5+i];
683            atari_set_frame_message(device, "DRIVE #%d WROTE SECTOR #%3d - %cD", drive+1, sector, (fdc->drv[drive].seclen == 128) ? 'S' : 'D');
684            }
685         add_serin(device,'C',0);
686      }
687      else
688      {
689         add_serin(device,'E',0);
690      }
691   }
692   else
693   {
694      if (VERBOSE_SERIAL)
695         logerror("BAD\n");
696
697      add_serin(device,'E',0);
698   }
699}
700
701READ8_DEVICE_HANDLER ( atari_serin_r )
702{
703   int data = 0x00;
704   int ser_delay = 0;
705   atari_fdc_t *fdc = get_safe_token(device);
706
707   if (fdc->serin_count)
708   {
709      device_t *pokey = device->machine().device("pokey");
710
711      data = fdc->serin_buff[fdc->serin_offs];
712      ser_delay = 2 * 40;
713      if (fdc->serin_offs < 3)
714      {
715         ser_delay = 4 * 40;
716         if (fdc->serin_offs < 2)
717            ser_delay = 200 * 40;
718      }
719      fdc->serin_offs++;
720      if (--fdc->serin_count == 0)
721         fdc->serin_offs = 0;
722      else
723         pokey_serin_ready(pokey, ser_delay);
724   }
725
726   if (VERBOSE_SERIAL)
727      logerror("atari serin[$%04x] -> $%02x; delay %d\n", fdc->serin_offs, data, ser_delay);
728
729   return data;
730}
731
732WRITE8_DEVICE_HANDLER ( atari_serout_w )
733{
734   pia6821_device *pia = device->machine().device<pia6821_device>( "pia" );
735   atari_fdc_t *fdc = get_safe_token(device);
736
737   /* ignore serial commands if no floppy image is specified */
738   if( !fdc->drv[0].image )
739      return;
740   if (fdc->serout_count)
741   {
742      /* store data */
743      fdc->serout_buff[fdc->serout_offs] = data;
744
745      if (VERBOSE_SERIAL)
746         logerror("atari serout[$%04x] <- $%02x; count %d\n", fdc->serout_offs, data, fdc->serout_count);
747
748      fdc->serout_offs++;
749      if (--fdc->serout_count == 0)
750      {
751         /* exclusive or written checksum with calculated */
752         fdc->serout_chksum ^= data;
753         /* if the attention line is high, this should be data */
754         if (pia->irq_b_state())
755            a800_serial_write(device);
756      }
757      else
758      {
759         make_chksum(&fdc->serout_chksum, data);
760      }
761   }
762}
763
764WRITE_LINE_DEVICE_HANDLER(atarifdc_pia_cb2_w)
765{
766   atari_fdc_t *fdc = get_safe_token(device);
767   if (!state)
768   {
769      clr_serout(device,4); /* expect 4 command bytes + checksum */
770   }
771   else
772   {
773      fdc->serin_delay = 0;
774      a800_serial_command(device);
775   }
776}
777
778static FLOPPY_IDENTIFY( atari_dsk_identify )
779{
780   *vote = 100;
781   return FLOPPY_ERROR_SUCCESS;
782}
783
784
785static FLOPPY_CONSTRUCT( atari_dsk_construct )
786{
787   return FLOPPY_ERROR_SUCCESS;
788}
789
790FLOPPY_OPTIONS_START( atari_only )
791   FLOPPY_OPTION(
792      atari_dsk,
793      "atr,dsk,xfd",
794      "Atari floppy disk image",
795      atari_dsk_identify,
796      atari_dsk_construct,
797      NULL,
798      NULL
799   )
800FLOPPY_OPTIONS_END0
801
802static const floppy_config atari_floppy_config =
803{
804   DEVCB_NULL,
805   DEVCB_NULL,
806   DEVCB_NULL,
807   DEVCB_NULL,
808   DEVCB_NULL,
809   FLOPPY_STANDARD_5_25_DSHD,
810   FLOPPY_OPTIONS_NAME(atari_only),
811   NULL
812};
813
814static MACHINE_CONFIG_FRAGMENT( atari_fdc )
815   MCFG_FLOPPY_4_DRIVES_ADD(atari_floppy_config)
816MACHINE_CONFIG_END
817
818device_t *atari_floppy_get_device_child(device_t *device,int drive)
819{
820   switch(drive) {
821      case 0 : return device->subdevice(FLOPPY_0);
822      case 1 : return device->subdevice(FLOPPY_1);
823      case 2 : return device->subdevice(FLOPPY_2);
824      case 3 : return device->subdevice(FLOPPY_3);
825   }
826   return NULL;
827}
828
829static DEVICE_START(atari_fdc)
830{
831   int id;
832   for(id=0;id<4;id++)
833   {
834      floppy_install_load_proc(atari_floppy_get_device_child(device, id), atari_load_proc);
835   }
836}
837
838static DEVICE_RESET(atari_fdc)
839{
840}
841
842DEVICE_GET_INFO( atari_fdc )
843{
844   switch (state)
845   {
846      /* --- the following bits of info are returned as 64-bit signed integers --- */
847      case DEVINFO_INT_INLINE_CONFIG_BYTES:         info->i = 0;                                    break;
848      case DEVINFO_INT_TOKEN_BYTES:               info->i = sizeof(atari_fdc_t);                        break;
849
850      /* --- the following bits of info are returned as pointers --- */
851      case DEVINFO_PTR_MACHINE_CONFIG:            info->machine_config = MACHINE_CONFIG_NAME(atari_fdc);      break;
852
853      /* --- the following bits of info are returned as pointers to data or functions --- */
854      case DEVINFO_FCT_START:                     info->start = DEVICE_START_NAME(atari_fdc);               break;
855      case DEVINFO_FCT_STOP:                     /* Nothing */                                    break;
856      case DEVINFO_FCT_RESET:                     info->reset = DEVICE_RESET_NAME(atari_fdc);               break;
857
858      /* --- the following bits of info are returned as NULL-terminated strings --- */
859      case DEVINFO_STR_NAME:                     strcpy(info->s, "Atari FDC");                        break;
860      case DEVINFO_STR_FAMILY:                  strcpy(info->s, "Atari FDC");                        break;
861      case DEVINFO_STR_VERSION:                  strcpy(info->s, "1.0");                              break;
862      case DEVINFO_STR_SOURCE_FILE:               strcpy(info->s, __FILE__);                           break;
863      case DEVINFO_STR_CREDITS:                  strcpy(info->s, "Copyright the MESS Team");             break;
864   }
865}
866
867DEFINE_LEGACY_DEVICE(ATARI_FDC, atari_fdc);
src/mess/includes/nes.h
r0r11532
1/*****************************************************************************
2 *
3 * includes/nes.h
4 *
5 * Nintendo Entertainment System (Famicom)
6 *
7 ****************************************************************************/
8
9#ifndef NES_H_
10#define NES_H_
11
12
13/***************************************************************************
14    CONSTANTS
15***************************************************************************/
16
17#define NTSC_CLOCK           N2A03_DEFAULTCLOCK     /* 1.789772 MHz */
18#define PAL_CLOCK              (26601712.0/16)        /* 1.662607 MHz */
19
20#define NES_BATTERY_SIZE 0x2000
21
22
23/***************************************************************************
24    TYPE DEFINITIONS
25***************************************************************************/
26
27struct nes_input
28{
29   UINT32 shift;
30   UINT32 i0, i1, i2;
31};
32
33/*PPU fast banking constants and structures */
34
35#define CHRROM 0
36#define CHRRAM 1
37
38typedef struct
39{
40   int source;   //defines source of base pointer
41   int origin; //defines offset of 0x400 byte segment at base pointer
42   UINT8* access;   //source translated + origin -> valid pointer!
43} chr_bank;
44
45/*PPU nametable fast banking constants and structures */
46
47#define CIRAM 0
48#define ROM 1
49#define EXRAM 2
50#define MMC5FILL 3
51#define CART_NTRAM 4
52
53#define NES_BATTERY 0
54#define NES_WRAM 1
55
56typedef struct
57{
58   int source;      /* defines source of base pointer */
59   int origin;      /* defines offset of 0x400 byte segment at base pointer */
60   int writable;   /* ExRAM, at least, can be write-protected AND used as nametable */
61   UINT8* access;   /* direct access when possible */
62} name_table;
63
64typedef void (*nes_prg_callback)(running_machine &machine, int start, int bank);
65typedef void (*nes_chr_callback)(running_machine &machine, int start, int bank, int source);
66
67class nes_state : public driver_device
68{
69public:
70   nes_state(const machine_config &mconfig, device_type type, const char *tag)
71      : driver_device(mconfig, type, tag) { }
72
73   /* input_related - this part has to be cleaned up (e.g. in_2 and in_3 are not really necessary here...) */
74   nes_input m_in_0, m_in_1, m_in_2, m_in_3;
75   UINT8 m_fck_scan, m_fck_mode;
76
77   int           m_prg_bank[5];
78   chr_bank      m_chr_map[8];  //quick banking structure, because some of this changes multiple times per scanline!
79   name_table    m_nt_page[4];  //quick banking structure for a maximum of 4K of RAM/ROM/ExRAM
80
81   int m_chr_open_bus;
82   int m_prgram_bank5_start, m_battery_bank5_start, m_empty_bank5_start;
83
84   UINT8 m_ce_mask, m_ce_state;
85   UINT8 m_vrc_ls_prg_a, m_vrc_ls_prg_b, m_vrc_ls_chr;
86
87   int m_MMC5_floodtile;
88   int m_MMC5_floodattr;
89   int m_mmc5_vram_control;
90   UINT8 m_mmc5_high_chr;
91   UINT8 m_mmc5_split_scr;
92   UINT8 *m_extended_ntram;
93
94   UINT8 m_mmc5_last_chr_a;
95   UINT16 m_mmc5_vrom_regA[8];
96   UINT16 m_mmc5_vrom_regB[4];
97   UINT8 m_mmc5_prg_regs[4];
98   UINT8 m_mmc5_bank_security;
99   UINT8 m_mmc5_prg_mode;
100   UINT8 m_mmc5_chr_mode;
101   UINT8 m_mmc5_chr_high;
102   UINT8 m_mmc5_split_ctrl;
103   UINT8 m_mmc5_split_yst;
104   UINT8 m_mmc5_split_bank;
105
106   /* video-related */
107   int m_nes_vram_sprite[8]; /* Used only by mmc5 for now */
108   int m_last_frame_flip;
109
110   /* misc */
111   write8_space_func   m_mmc_write_low;
112   const char        *m_mmc_write_low_name;
113   write8_space_func   m_mmc_write_mid;
114   const char        *m_mmc_write_mid_name;
115   write8_space_func   m_mmc_write;
116   const char        *m_mmc_write_name;
117   read8_space_func    m_mmc_read_low;
118   const char        *m_mmc_read_low_name;
119   read8_space_func    m_mmc_read_mid;
120   const char        *m_mmc_read_mid_name;
121   read8_space_func    m_mmc_read;
122   const char        *m_mmc_read_name;
123   emu_timer           *m_irq_timer;
124
125   nes_prg_callback    m_mmc3_prg_cb;   // these are used to simplify a lot emulation of some MMC3 pirate clones
126   nes_chr_callback    m_mmc3_chr_cb;
127
128   /* devices */
129   device_t      *m_maincpu;
130   device_t      *m_ppu;
131   device_t      *m_sound;
132   device_t      *m_cart;
133
134   /* misc region to be allocated at init */
135   // variables which don't change at run-time
136   UINT8      *m_rom;
137   UINT8      *m_vrom;
138   UINT8      *m_vram;
139   UINT8      *m_wram;
140   UINT8      *m_ciram; //PPU nametable RAM - external to PPU!
141   UINT8      *m_battery_ram;
142   UINT8      *m_mapper_ram;
143   UINT8      *m_mapper_bram;
144
145   /***** Mapper-related variables *****/
146
147   // common ones
148   int        m_IRQ_enable, m_IRQ_enable_latch;
149   UINT16     m_IRQ_count, m_IRQ_count_latch;
150   UINT8      m_IRQ_toggle;
151   UINT8      m_IRQ_reset;
152   UINT8      m_IRQ_status;
153   UINT8      m_IRQ_mode;
154   UINT8      m_IRQ_clear;
155   int        m_mult1, m_mult2;
156
157   UINT8 m_mmc_chr_source;         // This is set at init to CHRROM or CHRRAM. a few mappers can swap between
158                           // the two (this is done in the specific handlers).
159
160   UINT8 m_mmc_cmd1, m_mmc_cmd2;      // These represent registers where the mapper writes important values
161   UINT8 m_mmc_count;            // This is used as counter in mappers like 1 and 45
162
163   int m_mmc_prg_base, m_mmc_prg_mask;   // MMC3 based multigame carts select a block of banks by using these (and then act like normal MMC3),
164   int m_mmc_chr_base, m_mmc_chr_mask;   // while MMC3 and clones (mapper 118 & 119) simply set them as 0 and 0xff resp.
165
166   UINT8 m_mmc_prg_bank[6];            // Many mappers writes only some bits of the selected bank (for both PRG and CHR),
167   UINT8 m_mmc_vrom_bank[16];         // hence these are handy to latch bank values.
168
169   UINT16 m_MMC5_vrom_bank[12];         // MMC5 has 10bit wide VROM regs!
170   UINT8 m_mmc_extra_bank[16];         // some MMC3 clone have 2 series of PRG/CHR banks...
171                              // we collect them all here: first 4 elements PRG banks, then 6/8 CHR banks
172
173   UINT8 m_mmc_latch1, m_mmc_latch2;
174   UINT8 m_mmc_reg[16];
175
176   UINT8 m_mmc_dipsetting;
177
178   // misc mapper related variables which should be merged with the above one, where possible
179   int m_mmc1_reg_write_enable;
180   int m_mmc1_latch;
181   int m_mmc1_count;
182
183   int m_mmc3_latch;
184   int m_mmc3_wram_protect;
185   int m_mmc3_alt_irq;
186
187   int m_MMC5_rom_bank_mode;
188   int m_MMC5_vrom_bank_mode;
189   int m_MMC5_vram_protect;
190   int m_MMC5_scanline;
191   int m_vrom_page_a;
192   int m_vrom_page_b;
193   // int vrom_next[4];
194
195   UINT8 m_mmc6_reg;
196
197   // these might be unified in single mmc_reg[] array, together with state->m_mmc_cmd1 & state->m_mmc_cmd2
198   // but be careful that MMC3 clones often use state->m_mmc_cmd1/state->m_mmc_cmd2 (from base MMC3) AND additional regs below!
199   UINT8 m_mapper83_reg[10];
200   UINT8 m_mapper83_low_reg[4];
201   UINT8 m_txc_reg[4];   // used by mappers 132, 172 & 173
202   UINT8 m_subor_reg[4];   // used by mappers 166 & 167
203   UINT8 m_sachen_reg[8];   // used by mappers 137, 138, 139 & 141
204   UINT8 m_map52_reg_written;
205   UINT8 m_map114_reg, m_map114_reg_enabled;
206
207   /***** NES-cart related *****/
208
209   /* load-time cart variables which remain constant */
210   UINT16 m_prg_chunks;      // iNES 2.0 allows for more chunks (a recently dumped multigame cart has 256 chunks of both PRG & CHR!)
211   UINT16 m_chr_chunks;
212   UINT16 m_vram_chunks;
213   UINT8 m_trainer;
214   UINT8 m_battery;         // if there is PRG RAM with battery backup
215   UINT32 m_battery_size;
216   UINT8 m_prg_ram;         // if there is PRG RAM with no backup
217   UINT32 m_wram_size;
218   UINT32 m_mapper_ram_size;
219   UINT32 m_mapper_bram_size;
220
221   /* system variables which don't change at run-time */
222   UINT16 m_mapper;      // for iNES
223   UINT16 m_pcb_id;      // for UNIF & xml
224   UINT8 m_four_screen_vram;
225   UINT8 m_hard_mirroring;
226   UINT8 m_crc_hack;   // this is needed to detect different boards sharing the same Mappers (shame on .nes format)
227   UINT8 m_ines20;
228
229   /***** FDS-floppy related *****/
230
231   int     m_disk_expansion;
232
233   UINT8   m_fds_sides;
234   UINT8   *m_fds_data;   // here, we store a copy of the disk
235   UINT8   *m_fds_ram;   // here, we emulate the RAM adapter
236
237   /* Variables which can change */
238   UINT8   m_fds_motor_on;
239   UINT8   m_fds_door_closed;
240   UINT8   m_fds_current_side;
241   UINT32  m_fds_head_position;
242   UINT8   m_fds_status0;
243   UINT8   m_fds_read_mode;
244   UINT8   m_fds_write_reg;
245
246   /* these are used in the mapper 20 handlers */
247   int     m_fds_last_side;
248   int     m_fds_count;
249};
250
251
252/*----------- defined in machine/nes.c -----------*/
253
254WRITE8_HANDLER ( nes_IN0_w );
255WRITE8_HANDLER ( nes_IN1_w );
256
257/* protos */
258
259DEVICE_IMAGE_LOAD(nes_cart);
260DEVICE_START(nes_disk);
261DEVICE_IMAGE_LOAD(nes_disk);
262DEVICE_IMAGE_UNLOAD(nes_disk);
263
264MACHINE_START( nes );
265MACHINE_RESET( nes );
266
267DRIVER_INIT( famicom );
268
269READ8_HANDLER( nes_IN0_r );
270READ8_HANDLER( nes_IN1_r );
271
272int nes_ppu_vidaccess( device_t *device, int address, int data );
273
274void nes_partialhash(hash_collection &dest, const unsigned char *data, unsigned long length, const char *functions);
275
276/*----------- defined in video/nes.c -----------*/
277
278PALETTE_INIT( nes );
279VIDEO_START( nes );
280SCREEN_UPDATE( nes );
281
282
283#endif /* NES_H_ */
src/mess/includes/pce.h
r0r11532
1/*****************************************************************************
2 *
3 * includes/pce.h
4 *
5 * NEC PC Engine/TurboGrafx16
6 *
7 ****************************************************************************/
8
9#ifndef PCE_H_
10#define PCE_H_
11
12#include "cdrom.h"
13#include "sound/msm5205.h"
14
15#define C6280_TAG         "c6280"
16
17#define   MAIN_CLOCK      21477270
18#define PCE_CD_CLOCK   9216000
19
20#define PCE_HEADER_SIZE      512
21
22#define TG_16_JOY_SIG      0x00
23#define PCE_JOY_SIG         0x40
24#define NO_CD_SIG         0x80
25#define CD_SIG            0x00
26/* these might be used to indicate something, but they always seem to return 1 */
27#define CONST_SIG         0x30
28
29/* the largest possible cartridge image (street fighter 2 - 2.5MB) */
30#define PCE_ROM_MAXSIZE      0x280000
31
32typedef struct
33{
34   UINT8   regs[16];
35   UINT8   *bram;
36   UINT8   *adpcm_ram;
37   int      bram_locked;
38   int      adpcm_read_ptr;
39   UINT8   adpcm_read_buf;
40   int      adpcm_write_ptr;
41   UINT8   adpcm_write_buf;
42   int      adpcm_length;
43   int      adpcm_clock_divider;
44   UINT32  msm_start_addr;
45   UINT32   msm_end_addr;
46   UINT32   msm_half_addr;
47   UINT8   msm_nibble;
48   UINT8   msm_idle;
49
50   /* SCSI signals */
51   int      scsi_BSY;   /* Busy. Bus in use */
52   int      scsi_SEL;   /* Select. Initiator has won arbitration and has selected a target */
53   int      scsi_CD;   /* Control/Data. Target is sending control (data) information */
54   int      scsi_IO;   /* Input/Output. Target is sending (receiving) information */
55   int      scsi_MSG;   /* Message. Target is sending or receiving a message */
56   int      scsi_REQ;   /* Request. Target is requesting a data transfer */
57   int      scsi_ACK;   /* Acknowledge. Initiator acknowledges that it is ready for a data transfer */
58   int      scsi_ATN;   /* Attention. Initiator has a message ready for the target */
59   int      scsi_RST;   /* Reset. Initiator forces all targets and any other initiators to do a warm reset */
60   int      scsi_last_RST;   /* To catch setting of RST signal */
61   int      cd_motor_on;
62   int      selected;
63   UINT8   *command_buffer;
64   int      command_buffer_index;
65   int      status_sent;
66   int      message_after_status;
67   int      message_sent;
68   UINT8   *data_buffer;
69   int      data_buffer_size;
70   int      data_buffer_index;
71   int      data_transferred;
72
73   /* Arcade Card specific */
74   UINT8   *acard_ram;
75   UINT8   acard_latch;
76   UINT8   acard_ctrl[4];
77   UINT32   acard_base_addr[4];
78   UINT16   acard_addr_offset[4];
79   UINT16   acard_addr_inc[4];
80   UINT32   acard_shift;
81   UINT8   acard_shift_reg;
82
83   UINT32   current_frame;
84   UINT32   end_frame;
85   UINT32   last_frame;
86   UINT8   cdda_status;
87   UINT8   cdda_play_mode;
88   UINT8   *subcode_buffer;
89   UINT8   end_mark;
90   cdrom_file   *cd;
91   const cdrom_toc*   toc;
92   emu_timer   *data_timer;
93   emu_timer   *adpcm_dma_timer;
94
95   emu_timer   *cdda_fadeout_timer;
96   emu_timer   *cdda_fadein_timer;
97   double   cdda_volume;
98   emu_timer   *adpcm_fadeout_timer;
99   emu_timer   *adpcm_fadein_timer;
100   double   adpcm_volume;
101} pce_cd_t;
102
103
104class pce_state : public driver_device
105{
106public:
107   pce_state(const machine_config &mconfig, device_type type, const char *tag)
108      : driver_device(mconfig, type, tag) { }
109
110   unsigned char *m_user_ram;
111   UINT8 *m_cd_ram;
112   UINT8 m_io_port_options;
113   UINT8 m_sys3_card;
114   UINT8 m_acard;
115   pce_cd_t m_cd;
116   UINT8 *m_cartridge_ram;
117   int m_joystick_port_select;
118   int m_joystick_data_select;
119   UINT8 m_joy_6b_packet[5];
120};
121
122
123/*----------- defined in machine/pce.c -----------*/
124
125DEVICE_IMAGE_LOAD(pce_cart);
126NVRAM_HANDLER( pce );
127WRITE8_HANDLER ( pce_joystick_w );
128 READ8_HANDLER ( pce_joystick_r );
129
130extern const msm5205_interface pce_cd_msm5205_interface;
131WRITE8_HANDLER( pce_cd_bram_w );
132WRITE8_HANDLER( pce_cd_intf_w );
133READ8_HANDLER( pce_cd_intf_r );
134WRITE8_HANDLER( pce_cd_acard_w );
135READ8_HANDLER( pce_cd_acard_r );
136WRITE8_HANDLER( pce_cd_acard_wram_w );
137READ8_HANDLER( pce_cd_acard_wram_r );
138
139DRIVER_INIT( pce );
140DRIVER_INIT( tg16 );
141DRIVER_INIT( sgx );
142MACHINE_START( pce );
143MACHINE_RESET( pce );
144
145
146#endif /* PCE_H_ */
src/mess/video/nes.c
r0r11532
1/***************************************************************************
2
3  video/nes.c
4
5  Routines to control the unique NES video hardware/PPU.
6
7***************************************************************************/
8
9#include "emu.h"
10#include "video/ppu2c0x.h"
11#include "includes/nes.h"
12#include "machine/nes_mmc.h"
13
14static void nes_vh_reset( running_machine &machine )
15{
16   nes_state *state = machine.driver_data<nes_state>();
17   ppu2c0x_set_vidaccess_callback(machine.device("ppu"), nes_ppu_vidaccess);
18
19   if (state->m_four_screen_vram)
20      set_nt_mirroring(machine, PPU_MIRROR_4SCREEN);
21   else
22   {
23      switch (state->m_hard_mirroring)
24      {
25         case PPU_MIRROR_HORZ:
26         case PPU_MIRROR_VERT:
27         case PPU_MIRROR_HIGH:
28         case PPU_MIRROR_LOW:
29            set_nt_mirroring(machine, state->m_hard_mirroring);
30            break;
31         default:
32            set_nt_mirroring(machine, PPU_MIRROR_NONE);
33            break;
34      }
35   }
36}
37
38VIDEO_START( nes )
39{
40   nes_state *state = machine.driver_data<nes_state>();
41
42   state->m_last_frame_flip =  0;
43
44   machine.add_notifier(MACHINE_NOTIFY_RESET, machine_notify_delegate(FUNC(nes_vh_reset),&machine));
45}
46
47PALETTE_INIT( nes )
48{
49   ppu2c0x_init_palette(machine, 0);
50}
51
52
53/***************************************************************************
54
55  Display refresh
56
57***************************************************************************/
58
59SCREEN_UPDATE( nes )
60{
61   nes_state *state = screen->machine().driver_data<nes_state>();
62
63   /* render the ppu */
64   ppu2c0x_render(state->m_ppu, bitmap, 0, 0, 0, 0);
65
66   /* if this is a disk system game, check for the flip-disk key */
67   if (state->m_disk_expansion && state->m_pcb_id == NO_BOARD)
68   {
69      // latch this input so it doesn't go at warp speed
70      if ((input_port_read(screen->machine(), "FLIPDISK") & 0x01) && (!state->m_last_frame_flip))
71      {
72         state->m_last_frame_flip = 1;
73         state->m_fds_current_side++;
74         if (state->m_fds_current_side > state->m_fds_sides)
75            state->m_fds_current_side = 0;
76
77         if (state->m_fds_current_side == 0)
78            popmessage("No disk inserted.");
79         else
80            popmessage("Disk set to side %d", state->m_fds_current_side);
81      }
82
83      if (!(input_port_read(screen->machine(), "FLIPDISK") & 0x01))
84         state->m_last_frame_flip = 0;
85   }
86   return 0;
87}
src/mess/drivers/a3000.c
r0r11532
1/***************************************************************************
2
3    Commodore Amiga 3000
4
5    Skeleton driver
6
7***************************************************************************/
8
9#include "emu.h"
10#include "cpu/m68000/m68000.h"
11
12
13class a3000_state : public driver_device
14{
15public:
16   a3000_state(const machine_config &mconfig, device_type type, const char *tag)
17      : driver_device(mconfig, type, tag) { }
18
19};
20
21
22
23/***************************************************************************
24    CONSTANTS
25***************************************************************************/
26
27#define XTAL_U104   XTAL_32MHz
28
29
30/***************************************************************************
31    ADDRESS MAPS
32***************************************************************************/
33
34static ADDRESS_MAP_START( a3000_mem, AS_PROGRAM, 32 )
35   ADDRESS_MAP_UNMAP_HIGH
36   AM_RANGE(0x000000, 0x1fffff) AM_RAMBANK("chipram")
37   AM_RANGE(0xf80000, 0xffffff) AM_ROM AM_REGION("kickstart", 0)
38ADDRESS_MAP_END
39
40
41/***************************************************************************
42    INPUT PORTS
43***************************************************************************/
44
45static INPUT_PORTS_START( a3000 )
46INPUT_PORTS_END
47
48
49/***************************************************************************
50    MACHINE DRIVERS
51***************************************************************************/
52
53static MACHINE_CONFIG_START( a3000, a3000_state )
54   MCFG_CPU_ADD("maincpu", M68030, XTAL_U104 / 2)
55   MCFG_CPU_PROGRAM_MAP(a3000_mem)
56
57   MCFG_SCREEN_ADD("screen", RASTER)
58   MCFG_SCREEN_REFRESH_RATE(60)
59   MCFG_SCREEN_VBLANK_TIME(ATTOSECONDS_IN_USEC(0))
60   MCFG_SCREEN_FORMAT(BITMAP_FORMAT_RGB32)
61   MCFG_SCREEN_SIZE(512*2, 312)
62   MCFG_SCREEN_VISIBLE_AREA((129-8-8)*2, (449+8-1+8)*2, 44-8, 300+8-1)
63MACHINE_CONFIG_END
64
65
66/***************************************************************************
67    ROM DEFINITIONS
68***************************************************************************/
69
70/* Note: I think those ROMs are correct, but they should be verified */
71ROM_START( a3000 )
72   ROM_REGION32_BE(0x80000, "kickstart", 0)
73   ROM_DEFAULT_BIOS("kick14")
74   ROM_SYSTEM_BIOS(0, "kick14", "Kickstart 1.4 (36.16)")
75   /* COPYRIGHT 1990 CAI // ALL RIGHTS RESERVED // ALPHA 5 ROM 0 CS=9713 */
76   ROMX_LOAD("390629-02.u182", 0x00000, 0x40000, CRC(58327536) SHA1(d1713d7f31474a5948e6d488e33686061cf3d1e2), ROM_GROUPWORD | ROM_REVERSE | ROM_SKIP(2) | ROM_BIOS(1))
77   /* COPYRIGHT 1990 CAI // ALL RIGHTS RESERVED // ALPHA 5 ROM 1 CS=9B21 */
78   ROMX_LOAD("390630-02.u183", 0x00002, 0x40000, CRC(fe2f7fb9) SHA1(c05c9c52d014c66f9019152b3f2a2adc2c678794), ROM_GROUPWORD | ROM_REVERSE | ROM_SKIP(2) | ROM_BIOS(1))
79   ROM_SYSTEM_BIOS(1, "kick204", "Kickstart 2.04 (37.175)")
80   ROMX_LOAD("390629-03.u182", 0x00000, 0x40000, CRC(a245dbdf) SHA1(83bab8e95d378b55b0c6ae6561385a96f638598f), ROM_GROUPWORD | ROM_REVERSE | ROM_SKIP(2) | ROM_BIOS(2))
81   ROMX_LOAD("390630-03.u183", 0x00002, 0x40000, CRC(7db1332b) SHA1(48f14b31279da6757848df6feb5318818f8f576c), ROM_GROUPWORD | ROM_REVERSE | ROM_SKIP(2) | ROM_BIOS(2))
82   ROM_SYSTEM_BIOS(2, "kick31", "Kickstart 3.1 (40.68)")
83   ROMX_LOAD("kick31.u182",    0x00000, 0x40000, CRC(286b9a0d) SHA1(6763a2258ec493f7408cf663110dae9a17803ad1), ROM_GROUPWORD | ROM_REVERSE | ROM_SKIP(2) | ROM_BIOS(3))
84   ROMX_LOAD("kick31.u183",    0x00002, 0x40000, CRC(0b8cde6a) SHA1(5f02e97b48ebbba87d516a56b0400c6fc3434d8d), ROM_GROUPWORD | ROM_REVERSE | ROM_SKIP(2) | ROM_BIOS(3))
85ROM_END
86
87
88/***************************************************************************
89    GAME DRIVERS
90***************************************************************************/
91
92/*    YEAR  NAME   PARENT  COMPAT  MACHINE  INPUT  INIT  COMPANY      FULLNAME      FLAGS */
93COMP( 1990, a3000, 0,      0,      a3000,   a3000, 0,    "Commodore Business Machines", "Amiga 3000", GAME_NOT_WORKING | GAME_NO_SOUND )
src/mess/drivers/atari400.c
r0r11532
1/******************************************************************************
2    Atari 400/800
3
4    MESS Driver
5
6    Juergen Buchmueller, June 1998
7
8    2009-05 FP changes:
9     Factored out MESS specific code from MAME
10     Added skeleton support for other XL/XE machines (VERY preliminary):
11     - a600xl based on maxaflex emulation in MAME
12     - a1200xl sharing a800xl code without BASIC
13     - a65xe, a65xea, a130xe, a800xe, xegs sharing a800xl code (and this is wrong
14      at least for xegs)
15     Added proper dumps and labels, thanks to Freddy Offenga researches (a few
16     are still marked BAD_DUMP while waiting for crc confirmation, since they
17     have been obtained by splitting whole dumps)
18
19     To Do:
20     - Find out why a600xl and a800xl don't work (xe machines should then follow)
21     - Investigate supported RAM sizes and OS versions in different models
22     - Implement differences between various models (currently most of the
23      XL/XE are exactly an a800xl, but this will change as soon as emulation
24      starts to work)
25     - Fix various keyboard differences
26     - Freddy emulation for 800XLF?
27     - Add support for proto boards and expansions (a1400xl, C/PM board, etc.)
28     - Clean up the whole driver + cart + floppy structure
29
30******************************************************************************/
31
32#include "emu.h"
33#include "deprecat.h"
34#include "cpu/m6502/m6502.h"
35#include "includes/atari.h"
36#include "machine/ataridev.h"
37#include "imagedev/cartslot.h"
38#include "sound/pokey.h"
39#include "machine/6821pia.h"
40#include "video/gtia.h"
41#include "sound/dac.h"
42#include "machine/ram.h"
43
44/******************************************************************************
45    Atari 800 memory map (preliminary)
46
47    ***************** read access *******************
48    range     short   description
49    0000-9FFF RAM     main memory
50    A000-BFFF RAM/ROM RAM or (banked) ROM cartridges
51    C000-CFFF ROM     unused or monitor ROM
52
53    ********* GTIA    ********************************
54
55    D000      m0pf    missile 0 playfield collisions
56    D001      m1pf    missile 1 playfield collisions
57    D002      m2pf    missile 2 playfield collisions
58    D003      m3pf    missile 3 playfield collisions
59    D004      p0pf    player 0 playfield collisions
60    D005      p1pf    player 1 playfield collisions
61    D006      p2pf    player 2 playfield collisions
62    D007      p3pf    player 3 playfield collisions
63    D008      m0pl    missile 0 player collisions
64    D009      m1pl    missile 1 player collisions
65    D00A      m2pl    missile 2 player collisions
66    D00B      m3pl    missile 3 player collisions
67    D00C      p0pl    player 0 player collisions
68    D00D      p1pl    player 1 player collisions
69    D00E      p2pl    player 2 player collisions
70    D00F      p3pl    player 3 player collisions
71    D010      but0    button stick 0
72    D011      but1    button stick 1
73    D012      but2    button stick 2
74    D013      but3    button stick 3
75    D014      xff     unused
76    D015      xff     unused
77    D016      xff     unused
78    D017      xff     unused
79    D018      xff     unused
80    D019      xff     unused
81    D01A      xff     unused
82    D01B      xff     unused
83    D01C      xff     unused
84    D01D      xff     unused
85    D01E      xff     unused
86    D01F      cons    console keys
87    D020-D0FF repeated 7 times
88
89    D100-D1FF xff
90
91    ********* POKEY   ********************************
92    D200      pot0    paddle 0
93    D201      pot1    paddle 1
94    D202      pot2    paddle 2
95    D203      pot3    paddle 3
96    D204      pot4    paddle 4
97    D205      pot5    paddle 5
98    D206      pot6    paddle 6
99    D207      pot7    paddle 7
100    D208      potb    all paddles
101    D209      kbcode  keyboard scan code
102    D20A      random  random number generator
103    D20B      xff     unused
104    D20C      xff     unused
105    D20D      serin   serial input
106    D20E      irqst   IRQ status
107    D20F      skstat  sk status
108    D210-D2FF repeated 15 times
109
110    ********* PIO     ********************************
111    D300      porta   read pio port A
112    D301      portb   read pio port B
113    D302      pactl   read pio port A control
114    D303      pbctl   read pio port B control
115    D304-D3FF repeated 63 times
116
117    ********* ANTIC   ********************************
118    D400      xff     unused
119    D401      xff     unused
120    D402      xff     unused
121    D403      xff     unused
122    D404      xff     unused
123    D405      xff     unused
124    D406      xff     unused
125    D407      xff     unused
126    D408      xff     unused
127    D409      xff     unused
128    D40A      xff     unused
129    D40B      vcount  vertical (scanline) counter
130    D40C      penh    light pen horizontal pos
131    D40D      penv    light pen vertical pos
132    D40E      xff     unused
133    D40F      nmist   NMI status
134
135    D500-D7FF xff     unused memory
136
137    D800-DFFF ROM     floating point ROM
138    E000-FFFF ROM     bios ROM
139
140    ***************** write access *******************
141    range     short   description
142    0000-9FFF RAM     main memory
143    A000-BFFF RAM/ROM RAM or (banked) ROM
144    C000-CFFF ROM     unused or monitor ROM
145
146    ********* GTIA    ********************************
147    D000      hposp0  player 0 horz position
148    D001      hposp1  player 1 horz position
149    D002      hposp2  player 2 horz position
150    D003      hposp3  player 3 horz position
151    D004      hposm0  missile 0 horz position
152    D005      hposm1  missile 0 horz position
153    D006      hposm2  missile 0 horz position
154    D007      hposm3  missile 0 horz position
155    D008      sizep0  size player 0
156    D009      sizep1  size player 0
157    D00A      sizep2  size player 0
158    D00B      sizep3  size player 0
159    D00C      sizem   size missiles
160    D00D      grafp0  graphics data for player 0
161    D00E      grafp1  graphics data for player 1
162    D00F      grafp2  graphics data for player 2
163    D010      grafp3  graphics data for player 3
164    D011      grafm   graphics data for missiles
165    D012      colpm0  color for player/missile 0
166    D013      colpm1  color for player/missile 1
167    D014      colpm2  color for player/missile 2
168    D015      colpm3  color for player/missile 3
169    D016      colpf0  color 0 playfield
170    D017      colpf1  color 1 playfield
171    D018      colpf2  color 2 playfield
172    D019      colpf3  color 3 playfield
173    D01A      colbk   background playfield
174    D01B      prior   priority select
175    D01C      vdelay  delay until vertical retrace
176    D01D      gractl  graphics control
177    D01E      hitclr  clear collisions
178    D01F      wcons   write console (speaker)
179    D020-D0FF repeated 7 times
180
181    D100-D1FF xff     unused
182
183    ********* POKEY   ********************************
184    D200      audf1   frequency audio chan #1
185    D201      audc1   control audio chan #1
186    D202      audf2   frequency audio chan #2
187    D203      audc2   control audio chan #2
188    D204      audf3   frequency audio chan #3
189    D205      audc3   control audio chan #3
190    D206      audf4   frequency audio chan #4
191    D207      audc4   control audio chan #4
192    D208      audctl  audio control
193    D209      stimer  start timer
194    D20A      skres   sk reset
195    D20B      potgo   start pot AD conversion
196    D20C      xff     unused
197    D20D      serout  serial output
198    D20E      irqen   IRQ enable
199    D20F      skctl   sk control
200    D210-D2FF repeated 15 times
201
202    ********* PIO     ********************************
203    D300      porta   write pio port A (output or mask)
204    D301      portb   write pio port B (output or mask)
205    D302      pactl   write pio port A control
206    D303      pbctl   write pio port B control
207    D304-D3FF         repeated
208
209    ********* ANTIC   ********************************
210    D400      dmactl  write DMA control
211    D401      chactl  write character control
212    D402      dlistl  write display list lo
213    D403      dlisth  write display list hi
214    D404      hscrol  write horz scroll
215    D405      vscrol  write vert scroll
216    D406      xff     unused
217    D407      pmbash  player/missile base addr hi
218    D408      xff     unused
219    D409      chbash  character generator base addr hi
220    D40A      wsync   wait for hsync
221    D40B      xff     unused
222    D40C      xff     unused
223    D40D      xff     unused
224    D40E      nmien   NMI enable
225    D40F      nmires  NMI reset
226
227    D500-D7FF xff     unused memory
228
229    D800-DFFF ROM     floating point ROM
230    E000-FFFF ROM     BIOS ROM
231******************************************************************************/
232
233/**************************************************************
234 *
235 * Memory maps
236 *
237 **************************************************************/
238
239
240static ADDRESS_MAP_START(a400_mem, AS_PROGRAM, 8)
241   AM_RANGE(0x0000, 0x9fff) AM_NOP   /* RAM installed at runtime */
242   AM_RANGE(0xa000, 0xbfff) AM_RAMBANK("a000")
243   AM_RANGE(0xc000, 0xcfff) AM_ROM
244   AM_RANGE(0xd000, 0xd0ff) AM_READWRITE(atari_gtia_r, atari_gtia_w)
245   AM_RANGE(0xd100, 0xd1ff) AM_NOP
246   AM_RANGE(0xd200, 0xd2ff) AM_DEVREADWRITE("pokey", pokey_r, pokey_w)
247   AM_RANGE(0xd300, 0xd3ff) AM_DEVREADWRITE_MODERN("pia", pia6821_device, read_alt, write_alt)
248   AM_RANGE(0xd400, 0xd4ff) AM_READWRITE(atari_antic_r, atari_antic_w)
249   AM_RANGE(0xd500, 0xd7ff) AM_NOP
250   AM_RANGE(0xd800, 0xffff) AM_ROM
251ADDRESS_MAP_END
252
253
254static ADDRESS_MAP_START(a800_mem, AS_PROGRAM, 8)
255   AM_RANGE(0x0000, 0x7fff) AM_RAMBANK("0000")
256   AM_RANGE(0x8000, 0x9fff) AM_RAMBANK("8000")
257   AM_RANGE(0xa000, 0xbfff) AM_RAMBANK("a000")
258   AM_RANGE(0xc000, 0xcfff) AM_ROM
259   AM_RANGE(0xd000, 0xd0ff) AM_READWRITE(atari_gtia_r, atari_gtia_w)
260   AM_RANGE(0xd100, 0xd1ff) AM_NOP
261   AM_RANGE(0xd200, 0xd2ff) AM_DEVREADWRITE("pokey", pokey_r, pokey_w)
262   AM_RANGE(0xd300, 0xd3ff) AM_DEVREADWRITE_MODERN("pia", pia6821_device, read_alt, write_alt)
263   AM_RANGE(0xd400, 0xd4ff) AM_READWRITE(atari_antic_r, atari_antic_w)
264   AM_RANGE(0xd500, 0xd7ff) AM_NOP
265   AM_RANGE(0xd800, 0xffff) AM_ROM
266ADDRESS_MAP_END
267
268
269static ADDRESS_MAP_START(a600xl_mem, AS_PROGRAM, 8)
270   AM_RANGE(0x0000, 0x3fff) AM_RAM
271   AM_RANGE(0x5000, 0x57ff) AM_ROM AM_REGION("maincpu", 0x5000)   /* self test */
272   AM_RANGE(0xa000, 0xbfff) AM_ROM   /* BASIC */
273   AM_RANGE(0xc000, 0xcfff) AM_ROM /* OS */
274   AM_RANGE(0xd000, 0xd0ff) AM_READWRITE(atari_gtia_r, atari_gtia_w)
275   AM_RANGE(0xd100, 0xd1ff) AM_NOP
276   AM_RANGE(0xd200, 0xd2ff) AM_DEVREADWRITE("pokey", pokey_r, pokey_w)
277   AM_RANGE(0xd300, 0xd3ff) AM_DEVREADWRITE_MODERN("pia", pia6821_device, read_alt, write_alt)
278   AM_RANGE(0xd400, 0xd4ff) AM_READWRITE(atari_antic_r, atari_antic_w)
279   AM_RANGE(0xd500, 0xd7ff) AM_NOP
280   AM_RANGE(0xd800, 0xffff) AM_ROM /* OS */
281ADDRESS_MAP_END
282
283
284static ADDRESS_MAP_START(a800xl_mem, AS_PROGRAM, 8)
285   AM_RANGE(0x0000, 0x4fff) AM_RAM
286   AM_RANGE(0x5000, 0x57ff) AM_RAMBANK("bank2")
287   AM_RANGE(0x5800, 0x9fff) AM_RAM
288   AM_RANGE(0xa000, 0xbfff) AM_RAMBANK("bank1")
289   AM_RANGE(0xc000, 0xcfff) AM_RAMBANK("bank3")
290   AM_RANGE(0xd000, 0xd0ff) AM_READWRITE(atari_gtia_r, atari_gtia_w)
291   AM_RANGE(0xd100, 0xd1ff) AM_NOP
292   AM_RANGE(0xd200, 0xd2ff) AM_DEVREADWRITE("pokey", pokey_r, pokey_w)
293   AM_RANGE(0xd300, 0xd3ff) AM_DEVREADWRITE_MODERN("pia", pia6821_device, read_alt, write_alt)
294   AM_RANGE(0xd400, 0xd4ff) AM_READWRITE(atari_antic_r, atari_antic_w)
295   AM_RANGE(0xd500, 0xd7ff) AM_NOP
296   AM_RANGE(0xd800, 0xffff) AM_RAMBANK("bank4")
297ADDRESS_MAP_END
298
299static ADDRESS_MAP_START(xegs_mem, AS_PROGRAM, 8)
300   AM_RANGE(0x0000, 0x4fff) AM_RAM
301   AM_RANGE(0x5000, 0x57ff) AM_RAMBANK("bank2")
302   AM_RANGE(0x5800, 0x7fff) AM_RAM
303   AM_RANGE(0x8000, 0x9fff) AM_ROMBANK("bank0")
304   AM_RANGE(0xa000, 0xbfff) AM_ROMBANK("bank1")
305   AM_RANGE(0xc000, 0xcfff) AM_RAMBANK("bank3")
306   AM_RANGE(0xd000, 0xd0ff) AM_READWRITE(atari_gtia_r, atari_gtia_w)
307   AM_RANGE(0xd100, 0xd1ff) AM_NOP
308   AM_RANGE(0xd200, 0xd2ff) AM_DEVREADWRITE("pokey", pokey_r, pokey_w)
309   AM_RANGE(0xd300, 0xd3ff) AM_DEVREADWRITE_MODERN("pia", pia6821_device, read_alt, write_alt)
310   AM_RANGE(0xd400, 0xd4ff) AM_READWRITE(atari_antic_r, atari_antic_w)
311   AM_RANGE(0xd500, 0xd7ff) AM_NOP
312   AM_RANGE(0xd800, 0xffff) AM_RAMBANK("bank4")
313ADDRESS_MAP_END
314
315
316static ADDRESS_MAP_START(a5200_mem, AS_PROGRAM, 8)
317   AM_RANGE(0x0000, 0x3fff) AM_RAM
318   AM_RANGE(0x4000, 0xbfff) AM_ROM
319   AM_RANGE(0xc000, 0xc0ff) AM_READWRITE(atari_gtia_r, atari_gtia_w)
320   AM_RANGE(0xd400, 0xd5ff) AM_READWRITE(atari_antic_r, atari_antic_w)
321   AM_RANGE(0xe800, 0xe8ff) AM_DEVREADWRITE("pokey", pokey_r, pokey_w)
322   AM_RANGE(0xf800, 0xffff) AM_ROM
323ADDRESS_MAP_END
324
325
326#ifdef MESS
327int atari_input_disabled(running_machine &machine)
328{
329   return 0;
330}
331#endif
332
333/**************************************************************
334 *
335 * Input ports
336 *
337 **************************************************************/
338
339
340#define JOYSTICK_DELTA         10
341#define JOYSTICK_SENSITIVITY   200
342
343static INPUT_PORTS_START( atari_artifacting )
344   PORT_START("artifacts")
345   PORT_CONFNAME(0x40, 0x00, "Television Artifacts" )
346   PORT_CONFSETTING(0x00, DEF_STR( Off ) )
347   PORT_CONFSETTING(0x40, DEF_STR( On ) )
348INPUT_PORTS_END
349
350
351
352static INPUT_PORTS_START( atari_console )
353   PORT_START("console")
354   PORT_BIT(0x04, 0x04, IPT_KEYBOARD) PORT_NAME("CONS.2: Option") PORT_CODE(KEYCODE_F3)
355   PORT_BIT(0x02, 0x02, IPT_KEYBOARD) PORT_NAME("CONS.1: Select") PORT_CODE(KEYCODE_F2)
356   PORT_BIT(0x01, 0x01, IPT_KEYBOARD) PORT_NAME("CONS.0: Start") PORT_CODE(KEYCODE_F1)
357INPUT_PORTS_END
358
359
360
361static INPUT_PORTS_START( atari_digital_joystick2 )
362   PORT_START("djoy_0_1")   /* IN1 digital joystick #1 + #2 (PIA port A) */
363   PORT_BIT(0x01, 0x01, IPT_JOYSTICK_UP)    PORT_CODE(KEYCODE_8_PAD) PORT_CODE(JOYCODE_Y_UP_SWITCH)    PORT_PLAYER(1)
364   PORT_BIT(0x02, 0x02, IPT_JOYSTICK_DOWN)  PORT_CODE(KEYCODE_2_PAD) PORT_CODE(JOYCODE_Y_DOWN_SWITCH)  PORT_PLAYER(1)
365   PORT_BIT(0x04, 0x04, IPT_JOYSTICK_LEFT)  PORT_CODE(KEYCODE_4_PAD) PORT_CODE(JOYCODE_X_LEFT_SWITCH)  PORT_PLAYER(1)
366   PORT_BIT(0x08, 0x08, IPT_JOYSTICK_RIGHT) PORT_CODE(KEYCODE_6_PAD) PORT_CODE(JOYCODE_X_RIGHT_SWITCH) PORT_PLAYER(1)
367   PORT_BIT(0x10, 0x10, IPT_JOYSTICK_UP)    PORT_CODE(KEYCODE_8_PAD) PORT_CODE(JOYCODE_Y_UP_SWITCH)    PORT_PLAYER(2)
368   PORT_BIT(0x20, 0x20, IPT_JOYSTICK_DOWN)  PORT_CODE(KEYCODE_2_PAD) PORT_CODE(JOYCODE_Y_DOWN_SWITCH)  PORT_PLAYER(2)
369   PORT_BIT(0x40, 0x40, IPT_JOYSTICK_LEFT)  PORT_CODE(KEYCODE_4_PAD) PORT_CODE(JOYCODE_X_LEFT_SWITCH)  PORT_PLAYER(2)
370   PORT_BIT(0x80, 0x80, IPT_JOYSTICK_RIGHT) PORT_CODE(KEYCODE_6_PAD) PORT_CODE(JOYCODE_X_RIGHT_SWITCH) PORT_PLAYER(2)
371
372   PORT_START("djoy_2_3")   /* IN2 digital joystick #3 + #4 (PIA port B) */
373   PORT_BIT(0x01, 0x01, IPT_UNUSED)
374   PORT_BIT(0x02, 0x02, IPT_UNUSED)
375   PORT_BIT(0x04, 0x04, IPT_UNUSED)
376   PORT_BIT(0x08, 0x08, IPT_UNUSED)
377   PORT_BIT(0x10, 0x10, IPT_UNUSED)
378   PORT_BIT(0x20, 0x20, IPT_UNUSED)
379   PORT_BIT(0x40, 0x40, IPT_UNUSED)
380   PORT_BIT(0x80, 0x80, IPT_UNUSED)
381
382   PORT_START("djoy_b")   /* IN3 digital joystick buttons (GTIA button bits) */
383   PORT_BIT(0x01, 0x01, IPT_BUTTON1) PORT_CODE(KEYCODE_0_PAD) PORT_CODE(JOYCODE_BUTTON1) PORT_PLAYER(1)
384   PORT_BIT(0x02, 0x02, IPT_BUTTON1) PORT_CODE(KEYCODE_0_PAD) PORT_CODE(JOYCODE_BUTTON2) PORT_PLAYER(2)
385   PORT_BIT(0x04, 0x04, IPT_UNUSED)
386   PORT_BIT(0x08, 0x08, IPT_UNUSED)
387   PORT_BIT(0x10, 0x10, IPT_BUTTON2) PORT_CODE(KEYCODE_DEL_PAD) PORT_CODE(JOYCODE_BUTTON1) PORT_PLAYER(1)
388   PORT_BIT(0x20, 0x20, IPT_BUTTON2) PORT_CODE(KEYCODE_DEL_PAD) PORT_CODE(JOYCODE_BUTTON2) PORT_PLAYER(2)
389   PORT_BIT(0x40, 0x40, IPT_UNUSED)
390   PORT_BIT(0x80, 0x80, IPT_UNUSED)
391INPUT_PORTS_END
392
393
394
395static INPUT_PORTS_START( atari_digital_joystick4 )
396   PORT_START("djoy_0_1")   /* digital joystick #1 + #2 (PIA port A) */
397   PORT_BIT(0x01, 0x01, IPT_JOYSTICK_UP)    PORT_CODE(KEYCODE_8_PAD) PORT_CODE(JOYCODE_Y_UP_SWITCH)    PORT_PLAYER(1)
398   PORT_BIT(0x02, 0x02, IPT_JOYSTICK_DOWN)  PORT_CODE(KEYCODE_2_PAD) PORT_CODE(JOYCODE_Y_DOWN_SWITCH)  PORT_PLAYER(1)
399   PORT_BIT(0x04, 0x04, IPT_JOYSTICK_LEFT)  PORT_CODE(KEYCODE_4_PAD) PORT_CODE(JOYCODE_X_LEFT_SWITCH)  PORT_PLAYER(1)
400   PORT_BIT(0x08, 0x08, IPT_JOYSTICK_RIGHT) PORT_CODE(KEYCODE_6_PAD) PORT_CODE(JOYCODE_X_RIGHT_SWITCH) PORT_PLAYER(1)
401   PORT_BIT(0x10, 0x10, IPT_JOYSTICK_UP)    PORT_CODE(KEYCODE_8_PAD) PORT_CODE(JOYCODE_Y_UP_SWITCH)    PORT_PLAYER(2)
402   PORT_BIT(0x20, 0x20, IPT_JOYSTICK_DOWN)  PORT_CODE(KEYCODE_2_PAD) PORT_CODE(JOYCODE_Y_DOWN_SWITCH)  PORT_PLAYER(2)
403   PORT_BIT(0x40, 0x40, IPT_JOYSTICK_LEFT)  PORT_CODE(KEYCODE_4_PAD) PORT_CODE(JOYCODE_X_LEFT_SWITCH)  PORT_PLAYER(2)
404   PORT_BIT(0x80, 0x80, IPT_JOYSTICK_RIGHT) PORT_CODE(KEYCODE_6_PAD) PORT_CODE(JOYCODE_X_RIGHT_SWITCH) PORT_PLAYER(2)
405
406   PORT_START("djoy_2_3")   /* digital joystick #3 + #4 (PIA port B) */
407   PORT_BIT(0x01, 0x01, IPT_JOYSTICK_UP)    PORT_CODE(KEYCODE_8_PAD) PORT_CODE(JOYCODE_Y_UP_SWITCH)    PORT_PLAYER(3)
408   PORT_BIT(0x02, 0x02, IPT_JOYSTICK_DOWN)  PORT_CODE(KEYCODE_2_PAD) PORT_CODE(JOYCODE_Y_DOWN_SWITCH)  PORT_PLAYER(3)
409   PORT_BIT(0x04, 0x04, IPT_JOYSTICK_LEFT)  PORT_CODE(KEYCODE_4_PAD) PORT_CODE(JOYCODE_X_LEFT_SWITCH)  PORT_PLAYER(3)
410   PORT_BIT(0x08, 0x08, IPT_JOYSTICK_RIGHT) PORT_CODE(KEYCODE_6_PAD) PORT_CODE(JOYCODE_X_RIGHT_SWITCH) PORT_PLAYER(3)
411   PORT_BIT(0x10, 0x10, IPT_JOYSTICK_UP)    PORT_CODE(KEYCODE_8_PAD) PORT_CODE(JOYCODE_Y_UP_SWITCH)    PORT_PLAYER(4)
412   PORT_BIT(0x20, 0x20, IPT_JOYSTICK_DOWN)  PORT_CODE(KEYCODE_2_PAD) PORT_CODE(JOYCODE_Y_DOWN_SWITCH)  PORT_PLAYER(4)
413   PORT_BIT(0x40, 0x40, IPT_JOYSTICK_LEFT)  PORT_CODE(KEYCODE_4_PAD) PORT_CODE(JOYCODE_X_LEFT_SWITCH)  PORT_PLAYER(4)
414   PORT_BIT(0x80, 0x80, IPT_JOYSTICK_RIGHT) PORT_CODE(KEYCODE_6_PAD) PORT_CODE(JOYCODE_X_RIGHT_SWITCH) PORT_PLAYER(4)
415
416   PORT_START("djoy_b")   /* digital joystick buttons (GTIA button bits) */
417   PORT_BIT(0x01, 0x01, IPT_BUTTON1) PORT_CODE(KEYCODE_0_PAD) PORT_CODE(JOYCODE_BUTTON1) PORT_PLAYER(1)
418   PORT_BIT(0x02, 0x02, IPT_BUTTON1) PORT_CODE(KEYCODE_0_PAD) PORT_CODE(JOYCODE_BUTTON2) PORT_PLAYER(2)
419   PORT_BIT(0x04, 0x04, IPT_BUTTON1) PORT_CODE(KEYCODE_0_PAD) PORT_CODE(JOYCODE_BUTTON3) PORT_PLAYER(3)
420   PORT_BIT(0x08, 0x08, IPT_BUTTON1) PORT_CODE(KEYCODE_0_PAD) PORT_CODE(JOYCODE_BUTTON4) PORT_PLAYER(4)
421   PORT_BIT(0x10, 0x10, IPT_BUTTON2) PORT_CODE(KEYCODE_DEL_PAD) PORT_CODE(JOYCODE_BUTTON1) PORT_PLAYER(1)
422   PORT_BIT(0x20, 0x20, IPT_BUTTON2) PORT_CODE(KEYCODE_DEL_PAD) PORT_CODE(JOYCODE_BUTTON2) PORT_PLAYER(2)
423   PORT_BIT(0x40, 0x40, IPT_BUTTON2) PORT_CODE(KEYCODE_DEL_PAD) PORT_CODE(JOYCODE_BUTTON3) PORT_PLAYER(3)
424   PORT_BIT(0x80, 0x80, IPT_BUTTON2) PORT_CODE(KEYCODE_DEL_PAD) PORT_CODE(JOYCODE_BUTTON4) PORT_PLAYER(4)
425INPUT_PORTS_END
426
427
428
429/* 2009-04 FP:
430Small note about natural keyboard support: currently,
431- "Break" is mapped to 'F1'
432- "Clear" is mapped to 'F2'
433- "Atari" is mapped to 'F3'                         */
434
435static INPUT_PORTS_START( atari_keyboard )
436   PORT_START("keyboard_0")
437   PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_L) PORT_CHAR('l') PORT_CHAR('L')
438   PORT_BIT(0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_J) PORT_CHAR('j') PORT_CHAR('J')
439   PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_COLON) PORT_CHAR(';') PORT_CHAR(':')
440   PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("Break") PORT_CODE(KEYCODE_BACKSPACE) PORT_CHAR(UCHAR_MAMEKEY(F1))
441   PORT_BIT(0x10, IP_ACTIVE_HIGH, IPT_UNUSED)
442   PORT_BIT(0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_K) PORT_CHAR('k') PORT_CHAR('K')
443   PORT_BIT(0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_QUOTE) PORT_CHAR('+') PORT_CHAR('\\')
444   PORT_BIT(0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_BACKSLASH) PORT_CHAR('*') PORT_CHAR('^')
445
446   PORT_START("keyboard_1")
447   PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_O) PORT_CHAR('o') PORT_CHAR('O')
448   PORT_BIT(0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD) // None!
449   PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_P) PORT_CHAR('p') PORT_CHAR('P')
450   PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_U) PORT_CHAR('u') PORT_CHAR('U')
451   PORT_BIT(0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("Return") PORT_CODE(KEYCODE_ENTER) PORT_CHAR(13)
452   PORT_BIT(0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_I) PORT_CHAR('i') PORT_CHAR('I')
453   PORT_BIT(0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_OPENBRACE) PORT_CHAR('-') PORT_CHAR('_')
454   PORT_BIT(0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_CLOSEBRACE) PORT_CHAR('=') PORT_CHAR('|')
455
456   PORT_START("keyboard_2")
457   PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_V) PORT_CHAR('v') PORT_CHAR('V')
458   PORT_BIT(0x02, IP_ACTIVE_HIGH, IPT_UNUSED)
459   PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_C) PORT_CHAR('c') PORT_CHAR('C')
460   PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_UNUSED)
461   PORT_BIT(0x10, IP_ACTIVE_HIGH, IPT_UNUSED)
462   PORT_BIT(0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_B) PORT_CHAR('b') PORT_CHAR('B')
463   PORT_BIT(0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_X) PORT_CHAR('x') PORT_CHAR('X')
464   PORT_BIT(0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_Z) PORT_CHAR('z') PORT_CHAR('Z')
465
466   PORT_START("keyboard_3")
467   PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_4) PORT_CHAR('4') PORT_CHAR('$')
468   PORT_BIT(0x02, IP_ACTIVE_HIGH, IPT_UNUSED)
469   PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_3) PORT_CHAR('3') PORT_CHAR('#')
470   PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_6) PORT_CHAR('6') PORT_CHAR('&')
471   PORT_BIT(0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("Escape") PORT_CODE(KEYCODE_ESC) PORT_CHAR(27)
472   PORT_BIT(0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_5) PORT_CHAR('5') PORT_CHAR('%')
473   PORT_BIT(0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_2) PORT_CHAR('2') PORT_CHAR('\"')
474   PORT_BIT(0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_1) PORT_CHAR('1') PORT_CHAR('!')
475
476   PORT_START("keyboard_4")
477   PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_COMMA) PORT_CHAR(',') PORT_CHAR('[')
478   PORT_BIT(0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_SPACE) PORT_CHAR(' ')
479   PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_STOP) PORT_CHAR('.') PORT_CHAR(']')
480   PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_N) PORT_CHAR('n') PORT_CHAR('N')
481   PORT_BIT(0x10, IP_ACTIVE_HIGH, IPT_UNUSED)
482   PORT_BIT(0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_M) PORT_CHAR('m') PORT_CHAR('M')
483   PORT_BIT(0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_SLASH) PORT_CHAR('/') PORT_CHAR('?')
484   PORT_BIT(0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("Atari") PORT_CODE(KEYCODE_RCONTROL) PORT_CHAR(UCHAR_MAMEKEY(F3))
485
486   PORT_START("keyboard_5")
487   PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_R) PORT_CHAR('r') PORT_CHAR('R')
488   PORT_BIT(0x02, IP_ACTIVE_HIGH, IPT_UNUSED)
489   PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_E) PORT_CHAR('e') PORT_CHAR('E')
490   PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_Y) PORT_CHAR('y') PORT_CHAR('Y')
491   PORT_BIT(0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_TAB) PORT_CHAR(UCHAR_MAMEKEY(TAB))
492   PORT_BIT(0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_T) PORT_CHAR('t') PORT_CHAR('T')
493   PORT_BIT(0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_W) PORT_CHAR('w') PORT_CHAR('W')
494   PORT_BIT(0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_Q) PORT_CHAR('q') PORT_CHAR('Q')
495
496   PORT_START("keyboard_6")
497   PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_9) PORT_CHAR('9') PORT_CHAR('(')
498   PORT_BIT(0x02, IP_ACTIVE_HIGH, IPT_UNUSED)
499   PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_0) PORT_CHAR('0') PORT_CHAR(')')
500   PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_7) PORT_CHAR('7') PORT_CHAR('\'')
501   PORT_BIT(0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("BackS  Delete") PORT_CODE(KEYCODE_BACKSLASH2) PORT_CHAR(8) PORT_CHAR(UCHAR_MAMEKEY(DEL))
502   PORT_BIT(0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_8) PORT_CHAR('8') PORT_CHAR('@')
503   PORT_BIT(0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("<  Clear") PORT_CODE(KEYCODE_MINUS) PORT_CHAR('<') PORT_CHAR(UCHAR_MAMEKEY(F2))
504   PORT_BIT(0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME(">  Insert") PORT_CODE(KEYCODE_EQUALS) PORT_CHAR('>') PORT_CHAR(UCHAR_MAMEKEY(INSERT))
505
506   PORT_START("keyboard_7")
507   PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_F) PORT_CHAR('f') PORT_CHAR('F')
508   PORT_BIT(0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_H) PORT_CHAR('h') PORT_CHAR('H')
509   PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_D) PORT_CHAR('d') PORT_CHAR('D')
510   PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_UNUSED)
511   PORT_BIT(0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("Caps") PORT_CODE(KEYCODE_CAPSLOCK) PORT_TOGGLE PORT_CHAR(UCHAR_MAMEKEY(CAPSLOCK))
512   PORT_BIT(0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_G) PORT_CHAR('g') PORT_CHAR('G')
513   PORT_BIT(0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_S) PORT_CHAR('s') PORT_CHAR('S')
514   PORT_BIT(0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_A) PORT_CHAR('a') PORT_CHAR('A')
515
516   PORT_START("fake")
517   PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("Shift") PORT_CODE(KEYCODE_LSHIFT) PORT_CODE(KEYCODE_RSHIFT) PORT_CHAR(UCHAR_SHIFT_1)
518   PORT_BIT(0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("Ctrl") PORT_CODE(KEYCODE_LCONTROL) PORT_CHAR(UCHAR_SHIFT_2)
519INPUT_PORTS_END
520
521
522static INPUT_PORTS_START( atari_analog_paddles )
523   PORT_START("analog_0") /* IN8 analog in #1 */
524   PORT_BIT(0xff, 0x74, IPT_PADDLE) PORT_SENSITIVITY(JOYSTICK_SENSITIVITY) PORT_KEYDELTA(JOYSTICK_DELTA) PORT_MINMAX(0x00,0xe4) PORT_PLAYER(1) PORT_REVERSE
525
526   PORT_START("analog_1") /* IN9 analog in #2 */
527   PORT_BIT(0xff, 0x74, IPT_PADDLE) PORT_SENSITIVITY(JOYSTICK_SENSITIVITY) PORT_KEYDELTA(JOYSTICK_DELTA) PORT_MINMAX(0x00,0xe4) PORT_PLAYER(2) PORT_REVERSE
528
529   PORT_START("analog_2") /* IN10 analog in #3 */
530   PORT_BIT(0xff, 0x74, IPT_PADDLE) PORT_SENSITIVITY(JOYSTICK_SENSITIVITY) PORT_KEYDELTA(JOYSTICK_DELTA) PORT_MINMAX(0x00,0xe4) PORT_PLAYER(3) PORT_REVERSE
531
532   PORT_START("analog_3") /* IN11 analog in #4 */
533   PORT_BIT(0xff, 0x74, IPT_PADDLE) PORT_SENSITIVITY(JOYSTICK_SENSITIVITY) PORT_KEYDELTA(JOYSTICK_DELTA) PORT_MINMAX(0x00,0xe4) PORT_PLAYER(4) PORT_REVERSE
534
535   PORT_START("analog_4") /* IN12 analog in #5 */
536   PORT_BIT(0xff, 0x74, IPT_PADDLE) PORT_SENSITIVITY(JOYSTICK_SENSITIVITY) PORT_KEYDELTA(JOYSTICK_DELTA) PORT_MINMAX(0x00,0xe4) PORT_REVERSE /* PORT_PLAYER(5) */
537
538   PORT_START("analog_5") /* IN13 analog in #6 */
539   PORT_BIT(0xff, 0x74, IPT_PADDLE) PORT_SENSITIVITY(JOYSTICK_SENSITIVITY) PORT_KEYDELTA(JOYSTICK_DELTA) PORT_MINMAX(0x00,0xe4) PORT_REVERSE /* PORT_PLAYER(6) */
540
541   PORT_START("analog_6") /* IN14 analog in #7 */
542   PORT_BIT(0xff, 0x74, IPT_PADDLE) PORT_SENSITIVITY(JOYSTICK_SENSITIVITY) PORT_KEYDELTA(JOYSTICK_DELTA) PORT_MINMAX(0x00,0xe4) PORT_REVERSE /* PORT_PLAYER(7) */
543
544   PORT_START("analog_7") /* IN15 analog in #8 */
545   PORT_BIT(0xff, 0x74, IPT_PADDLE) PORT_SENSITIVITY(JOYSTICK_SENSITIVITY) PORT_KEYDELTA(JOYSTICK_DELTA) PORT_MINMAX(0x00,0xe4) PORT_REVERSE /* PORT_PLAYER(8) */
546INPUT_PORTS_END
547
548
549
550static INPUT_PORTS_START( a800 )
551   PORT_INCLUDE( atari_artifacting )
552   PORT_INCLUDE( atari_console )
553   PORT_INCLUDE( atari_digital_joystick4 )
554   PORT_INCLUDE( atari_keyboard )
555   PORT_INCLUDE( atari_analog_paddles )
556INPUT_PORTS_END
557
558
559
560static INPUT_PORTS_START( a800xl )
561   PORT_INCLUDE( atari_artifacting )
562   PORT_INCLUDE( atari_console )
563   PORT_INCLUDE( atari_digital_joystick2 )
564   PORT_INCLUDE( atari_keyboard )
565   PORT_INCLUDE( atari_analog_paddles )
566INPUT_PORTS_END
567
568
569
570static INPUT_PORTS_START( a5200 )
571   PORT_INCLUDE( atari_artifacting )
572
573   PORT_START("djoy_b")   /* lower/upper buttons */
574   PORT_BIT(0x01, 0x01, IPT_BUTTON1) PORT_PLAYER(1)
575   PORT_BIT(0x02, 0x02, IPT_BUTTON1) PORT_PLAYER(2)
576   PORT_BIT(0x04, 0x04, IPT_BUTTON1) PORT_PLAYER(3)
577   PORT_BIT(0x08, 0x08, IPT_BUTTON1) PORT_PLAYER(4)
578   PORT_BIT(0x10, 0x10, IPT_BUTTON2) PORT_PLAYER(1)
579   PORT_BIT(0x20, 0x20, IPT_BUTTON2) PORT_PLAYER(2)
580   PORT_BIT(0x40, 0x40, IPT_BUTTON2) PORT_PLAYER(3)
581   PORT_BIT(0x80, 0x80, IPT_BUTTON2) PORT_PLAYER(4)
582
583   PORT_START("keypad_0")
584   PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_NAME("(Break)") PORT_CODE(KEYCODE_PAUSE)   // is this correct?
585   PORT_BIT(0x02, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_NAME("[#]") PORT_CODE(KEYCODE_ENTER_PAD)
586   PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_NAME("[0]") PORT_CODE(KEYCODE_0_PAD)
587   PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_NAME("[*]") PORT_CODE(KEYCODE_PLUS_PAD)
588   PORT_BIT(0xf0, IP_ACTIVE_HIGH, IPT_UNUSED)
589
590   PORT_START("keypad_1")
591   PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_NAME("Reset") PORT_CODE(KEYCODE_F3)
592   PORT_BIT(0x02, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_NAME("[9]") PORT_CODE(KEYCODE_9_PAD)
593   PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_NAME("[8]") PORT_CODE(KEYCODE_8_PAD)
594   PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_NAME("[7]") PORT_CODE(KEYCODE_7_PAD)
595   PORT_BIT(0xf0, IP_ACTIVE_HIGH, IPT_UNUSED)
596
597   PORT_START("keypad_2")
598   PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_NAME(DEF_STR(Pause)) PORT_CODE(KEYCODE_F2)
599   PORT_BIT(0x02, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_NAME("[6]") PORT_CODE(KEYCODE_6_PAD)
600   PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_NAME("[5]") PORT_CODE(KEYCODE_5_PAD)
601   PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_NAME("[4]") PORT_CODE(KEYCODE_4_PAD)
602   PORT_BIT(0xf0, IP_ACTIVE_HIGH, IPT_UNUSED)
603
604   PORT_START("keypad_3")
605   PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_START)    PORT_NAME("Start")
606   PORT_BIT(0x02, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_NAME("[3]") PORT_CODE(KEYCODE_3_PAD)
607   PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_NAME("[2]") PORT_CODE(KEYCODE_2_PAD)
608   PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_NAME("[1]") PORT_CODE(KEYCODE_1_PAD)
609   PORT_BIT(0xf0, IP_ACTIVE_HIGH, IPT_UNUSED)
610
611   PORT_START("analog_0")
612   PORT_BIT(0xff, 0x72, IPT_AD_STICK_X) PORT_SENSITIVITY(JOYSTICK_SENSITIVITY) PORT_KEYDELTA(JOYSTICK_DELTA) PORT_MINMAX(0x00,0xe4) PORT_PLAYER(1)
613
614   PORT_START("analog_1")
615   PORT_BIT(0xff, 0x72, IPT_AD_STICK_Y) PORT_SENSITIVITY(JOYSTICK_SENSITIVITY) PORT_KEYDELTA(JOYSTICK_DELTA) PORT_MINMAX(0x00,0xe4) PORT_PLAYER(1)
616
617   PORT_START("analog_2")
618   PORT_BIT(0xff, 0x72, IPT_AD_STICK_X) PORT_SENSITIVITY(JOYSTICK_SENSITIVITY) PORT_KEYDELTA(JOYSTICK_DELTA) PORT_MINMAX(0x00,0xe4) PORT_PLAYER(2)
619
620   PORT_START("analog_3")
621   PORT_BIT(0xff, 0x72, IPT_AD_STICK_Y) PORT_SENSITIVITY(JOYSTICK_SENSITIVITY) PORT_KEYDELTA(JOYSTICK_DELTA) PORT_MINMAX(0x00,0xe4) PORT_PLAYER(2)
622
623   PORT_START("analog_4")
624   PORT_BIT(0xff, 0x72, IPT_AD_STICK_X) PORT_SENSITIVITY(JOYSTICK_SENSITIVITY) PORT_KEYDELTA(JOYSTICK_DELTA) PORT_MINMAX(0x00,0xe4) PORT_PLAYER(3)
625
626   PORT_START("analog_5")
627   PORT_BIT(0xff, 0x72, IPT_AD_STICK_Y) PORT_SENSITIVITY(JOYSTICK_SENSITIVITY) PORT_KEYDELTA(JOYSTICK_DELTA) PORT_MINMAX(0x00,0xe4) PORT_PLAYER(3)
628
629   PORT_START("analog_6")
630   PORT_BIT(0xff, 0x72, IPT_AD_STICK_X) PORT_SENSITIVITY(JOYSTICK_SENSITIVITY) PORT_KEYDELTA(JOYSTICK_DELTA) PORT_MINMAX(0x00,0xe4) PORT_PLAYER(4)
631
632   PORT_START("analog_7")
633   PORT_BIT(0xff, 0x72, IPT_AD_STICK_Y) PORT_SENSITIVITY(JOYSTICK_SENSITIVITY) PORT_KEYDELTA(JOYSTICK_DELTA) PORT_MINMAX(0x00,0xe4) PORT_PLAYER(4)
634
635INPUT_PORTS_END
636
637
638/**************************************************************
639 *
640 * Palette
641 *
642 **************************************************************/
643
644static const UINT8 atari_palette[256*3] =
645{
646   /* Grey */
647   0x00,0x00,0x00, 0x25,0x25,0x25, 0x34,0x34,0x34, 0x4e,0x4e,0x4e,
648   0x68,0x68,0x68, 0x75,0x75,0x75, 0x8e,0x8e,0x8e, 0xa4,0xa4,0xa4,
649   0xb8,0xb8,0xb8, 0xc5,0xc5,0xc5, 0xd0,0xd0,0xd0, 0xd7,0xd7,0xd7,
650   0xe1,0xe1,0xe1, 0xea,0xea,0xea, 0xf4,0xf4,0xf4, 0xff,0xff,0xff,
651   /* Gold */
652   0x41,0x20,0x00, 0x54,0x28,0x00, 0x76,0x37,0x00, 0x9a,0x50,0x00,
653   0xc3,0x68,0x06, 0xe4,0x7b,0x07, 0xff,0x91,0x1a, 0xff,0xab,0x1d,
654   0xff,0xc5,0x1f, 0xff,0xd0,0x3b, 0xff,0xd8,0x4c, 0xff,0xe6,0x51,
655   0xff,0xf4,0x56, 0xff,0xf9,0x70, 0xff,0xff,0x90, 0xff,0xff,0xaa,
656   /* Orange */
657   0x45,0x19,0x04, 0x72,0x1e,0x11, 0x9f,0x24,0x1e, 0xb3,0x3a,0x20,
658   0xc8,0x51,0x20, 0xe3,0x69,0x20, 0xfc,0x81,0x20, 0xfd,0x8c,0x25,
659   0xfe,0x98,0x2c, 0xff,0xae,0x38, 0xff,0xb9,0x46, 0xff,0xbf,0x51,
660   0xff,0xc6,0x6d, 0xff,0xd5,0x87, 0xff,0xe4,0x98, 0xff,0xe6,0xab,
661   /* Red-Orange */
662   0x5d,0x1f,0x0c, 0x7a,0x24,0x0d, 0x98,0x2c,0x0e, 0xb0,0x2f,0x0f,
663   0xbf,0x36,0x24, 0xd3,0x4e,0x2a, 0xe7,0x62,0x3e, 0xf3,0x6e,0x4a,
664   0xfd,0x78,0x54, 0xff,0x8a,0x6a, 0xff,0x98,0x7c, 0xff,0xa4,0x8b,
665   0xff,0xb3,0x9e, 0xff,0xc2,0xb2, 0xff,0xd0,0xc3, 0xff,0xda,0xd0,
666   /* Pink */
667   0x4a,0x17,0x00, 0x72,0x1f,0x00, 0xa8,0x13,0x00, 0xc8,0x21,0x0a,
668   0xdf,0x25,0x12, 0xec,0x3b,0x24, 0xfa,0x52,0x36, 0xfc,0x61,0x48,
669   0xff,0x70,0x5f, 0xff,0x7e,0x7e, 0xff,0x8f,0x8f, 0xff,0x9d,0x9e,
670   0xff,0xab,0xad, 0xff,0xb9,0xbd, 0xff,0xc7,0xce, 0xff,0xca,0xde,
671   /* Purple */
672   0x49,0x00,0x36, 0x66,0x00,0x4b, 0x80,0x03,0x5f, 0x95,0x0f,0x74,
673   0xaa,0x22,0x88, 0xba,0x3d,0x99, 0xca,0x4d,0xa9, 0xd7,0x5a,0xb6,
674   0xe4,0x67,0xc3, 0xef,0x72,0xce, 0xfb,0x7e,0xda, 0xff,0x8d,0xe1,
675   0xff,0x9d,0xe5, 0xff,0xa5,0xe7, 0xff,0xaf,0xea, 0xff,0xb8,0xec,
676   /* Purple-Blue */
677   0x48,0x03,0x6c, 0x5c,0x04,0x88, 0x65,0x0d,0x90, 0x7b,0x23,0xa7,
678   0x93,0x3b,0xbf, 0x9d,0x45,0xc9, 0xa7,0x4f,0xd3, 0xb2,0x5a,0xde,
679   0xbd,0x65,0xe9, 0xc5,0x6d,0xf1, 0xce,0x76,0xfa, 0xd5,0x83,0xff,
680   0xda,0x90,0xff, 0xde,0x9c,0xff, 0xe2,0xa9,0xff, 0xe6,0xb6,0xff,
681   /* Blue 1 */
682   0x05,0x1e,0x81, 0x06,0x26,0xa5, 0x08,0x2f,0xca, 0x26,0x3d,0xd4,
683   0x44,0x4c,0xde, 0x4f,0x5a,0xec, 0x5a,0x68,0xff, 0x65,0x75,0xff,
684   0x71,0x83,0xff, 0x80,0x91,0xff, 0x90,0xa0,0xff, 0x97,0xa9,0xff,
685   0x9f,0xb2,0xff, 0xaf,0xbe,0xff, 0xc0,0xcb,0xff, 0xcd,0xd3,0xff,
686   /* Blue 2 */
687   0x0b,0x07,0x79, 0x20,0x1c,0x8e, 0x35,0x31,0xa3, 0x46,0x42,0xb4,
688   0x57,0x53,0xc5, 0x61,0x5d,0xcf, 0x6d,0x69,0xdb, 0x7b,0x77,0xe9,
689   0x89,0x85,0xf7, 0x91,0x8d,0xff, 0x9c,0x98,0xff, 0xa7,0xa4,0xff,
690   0xb2,0xaf,0xff, 0xbb,0xb8,0xff, 0xc3,0xc1,0xff, 0xd3,0xd1,0xff,
691   /* Light-Blue */
692   0x1d,0x29,0x5a, 0x1d,0x38,0x76, 0x1d,0x48,0x92, 0x1d,0x5c,0xac,
693   0x1d,0x71,0xc6, 0x32,0x86,0xcf, 0x48,0x9b,0xd9, 0x4e,0xa8,0xec,
694   0x55,0xb6,0xff, 0x69,0xca,0xff, 0x74,0xcb,0xff, 0x82,0xd3,0xff,
695   0x8d,0xda,0xff, 0x9f,0xd4,0xff, 0xb4,0xe2,0xff, 0xc0,0xeb,0xff,
696   /* Turquoise */
697   0x00,0x4b,0x59, 0x00,0x5d,0x6e, 0x00,0x6f,0x84, 0x00,0x84,0x9c,
698   0x00,0x99,0xbf, 0x00,0xab,0xca, 0x00,0xbc,0xde, 0x00,0xd0,0xf5,
699   0x10,0xdc,0xff, 0x3e,0xe1,0xff, 0x64,0xe7,0xff, 0x76,0xea,0xff,
700   0x8b,0xed,0xff, 0x9a,0xef,0xff, 0xb1,0xf3,0xff, 0xc7,0xf6,0xff,
701   /* Green-Blue */
702   0x00,0x48,0x00, 0x00,0x54,0x00, 0x03,0x6b,0x03, 0x0e,0x76,0x0e,
703   0x18,0x80,0x18, 0x27,0x92,0x27, 0x36,0xa4,0x36, 0x4e,0xb9,0x4e,
704   0x51,0xcd,0x51, 0x72,0xda,0x72, 0x7c,0xe4,0x7c, 0x85,0xed,0x85,
705   0x99,0xf2,0x99, 0xb3,0xf7,0xb3, 0xc3,0xf9,0xc3, 0xcd,0xfc,0xcd,
706   /* Green */
707   0x16,0x40,0x00, 0x1c,0x53,0x00, 0x23,0x66,0x00, 0x28,0x78,0x00,
708   0x2e,0x8c,0x00, 0x3a,0x98,0x0c, 0x47,0xa5,0x19, 0x51,0xaf,0x23,
709   0x5c,0xba,0x2e, 0x71,0xcf,0x43, 0x85,0xe3,0x57, 0x8d,0xeb,0x5f,
710   0x97,0xf5,0x69, 0xa0,0xfe,0x72, 0xb1,0xff,0x8a, 0xbc,0xff,0x9a,
711   /* Yellow-Green */
712   0x2c,0x35,0x00, 0x38,0x44,0x00, 0x44,0x52,0x00, 0x49,0x56,0x00,
713   0x60,0x71,0x00, 0x6c,0x7f,0x00, 0x79,0x8d,0x0a, 0x8b,0x9f,0x1c,
714   0x9e,0xb2,0x2f, 0xab,0xbf,0x3c, 0xb8,0xcc,0x49, 0xc2,0xd6,0x53,
715   0xcd,0xe1,0x53, 0xdb,0xef,0x6c, 0xe8,0xfc,0x79, 0xf2,0xff,0xab,
716   /* Orange-Green */
717   0x46,0x3a,0x09, 0x4d,0x3f,0x09, 0x54,0x45,0x09, 0x6c,0x58,0x09,
718   0x90,0x76,0x09, 0xab,0x8b,0x0a, 0xc1,0xa1,0x20, 0xd0,0xb0,0x2f,
719   0xde,0xbe,0x3d, 0xe6,0xc6,0x45, 0xed,0xcd,0x4c, 0xf5,0xd8,0x62,
720   0xfb,0xe2,0x76, 0xfc,0xee,0x98, 0xfd,0xf3,0xa9, 0xfd,0xf3,0xbe,
721   /* Light-Orange */
722   0x40,0x1a,0x02, 0x58,0x1f,0x05, 0x70,0x24,0x08, 0x8d,0x3a,0x13,
723   0xab,0x51,0x1f, 0xb5,0x64,0x27, 0xbf,0x77,0x30, 0xd0,0x85,0x3a,
724   0xe1,0x93,0x44, 0xed,0xa0,0x4e, 0xf9,0xad,0x58, 0xfc,0xb7,0x5c,
725   0xff,0xc1,0x60, 0xff,0xca,0x69, 0xff,0xcf,0x7e, 0xff,0xda,0x96
726};
727
728
729/* Initialise the palette */
730static PALETTE_INIT( mess_atari )
731{
732   int i;
733
734   for ( i = 0; i < sizeof(atari_palette) / 3; i++ )
735   {
736      palette_set_color_rgb(machine, i, atari_palette[i*3], atari_palette[i*3+1], atari_palette[i*3+2]);
737   }
738}
739
740/**************************************************************
741 *
742 * Memory banking
743 *
744 **************************************************************/
745
746static void a800xl_mmu(running_machine &machine, UINT8 new_mmu)
747{
748   UINT8 *base = machine.region("maincpu")->base();
749   UINT8 *base1, *base2, *base3, *base4;
750
751   /* check if memory C000-FFFF changed */
752   if( new_mmu & 0x01 )
753   {
754      logerror("%s MMU BIOS ROM\n", machine.system().name);
755      base3 = base + 0x14000;  /* 8K lo BIOS */
756      base4 = base + 0x15800;  /* 4K FP ROM + 8K hi BIOS */
757      machine.device("maincpu")->memory().space(AS_PROGRAM)->install_read_bank(0xc000, 0xcfff, "bank3");
758      machine.device("maincpu")->memory().space(AS_PROGRAM)->unmap_write(0xc000, 0xcfff);
759      machine.device("maincpu")->memory().space(AS_PROGRAM)->install_read_bank(0xd800, 0xffff, "bank4");
760      machine.device("maincpu")->memory().space(AS_PROGRAM)->unmap_write(0xd800, 0xffff);
761   }
762   else
763   {
764      logerror("%s MMU BIOS RAM\n", machine.system().name);
765      base3 = base + 0x0c000;  /* 8K RAM */
766      base4 = base + 0x0d800;  /* 4K RAM + 8K RAM */
767      machine.device("maincpu")->memory().space(AS_PROGRAM)->install_readwrite_bank(0xc000, 0xcfff, "bank3");
768      machine.device("maincpu")->memory().space(AS_PROGRAM)->install_readwrite_bank(0xd800, 0xffff, "bank4");
769   }
770   memory_set_bankptr(machine, "bank3", base3);
771   memory_set_bankptr(machine, "bank4", base4);
772
773   /* check if BASIC changed */
774   if( new_mmu & 0x02 )
775   {
776      logerror("%s MMU BASIC RAM\n", machine.system().name);
777      machine.device("maincpu")->memory().space(AS_PROGRAM)->install_readwrite_bank(0xa000, 0xbfff, "bank1");
778      base1 = base + 0x0a000;  /* 8K RAM */
779   }
780   else
781   {
782      logerror("%s MMU BASIC ROM\n", machine.system().name);
783      machine.device("maincpu")->memory().space(AS_PROGRAM)->install_read_bank(0xa000, 0xbfff, "bank1");
784      machine.device("maincpu")->memory().space(AS_PROGRAM)->nop_write(0xa000, 0xbfff);
785      base1 = base + 0x10000;  /* 8K BASIC */
786   }
787
788   memory_set_bankptr(machine, "bank1", base1);
789
790   /* check if self-test ROM changed */
791   if( new_mmu & 0x80 )
792   {
793      logerror("%s MMU SELFTEST RAM\n", machine.system().name);
794      machine.device("maincpu")->memory().space(AS_PROGRAM)->install_readwrite_bank(0x5000, 0x57ff, "bank2");
795      base2 = base + 0x05000;  /* 0x0800 bytes */
796   }
797   else
798   {
799      logerror("%s MMU SELFTEST ROM\n", machine.system().name);
800      machine.device("maincpu")->memory().space(AS_PROGRAM)->install_read_bank(0x5000, 0x57ff, "bank2");
801      machine.device("maincpu")->memory().space(AS_PROGRAM)->nop_write(0x5000, 0x57ff);
802      base2 = base + 0x15000;  /* 0x0800 bytes */
803   }
804   memory_set_bankptr(machine, "bank2", base2);
805}
806
807/* BASIC was available in a separate cart, so we don't test it */
808static void a1200xl_mmu(running_machine &machine, UINT8 new_mmu)
809{
810   UINT8 *base = machine.region("maincpu")->base();
811   UINT8 *base2, *base3, *base4;
812
813   /* check if memory C000-FFFF changed */
814   if( new_mmu & 0x01 )
815   {
816      logerror("%s MMU BIOS ROM\n", machine.system().name);
817      base3 = base + 0x14000;  /* 8K lo BIOS */
818      base4 = base + 0x15800;  /* 4K FP ROM + 8K hi BIOS */
819      machine.device("maincpu")->memory().space(AS_PROGRAM)->install_read_bank(0xc000, 0xcfff, "bank3");
820      machine.device("maincpu")->memory().space(AS_PROGRAM)->unmap_write(0xc000, 0xcfff);
821      machine.device("maincpu")->memory().space(AS_PROGRAM)->install_read_bank(0xd800, 0xffff, "bank4");
822      machine.device("maincpu")->memory().space(AS_PROGRAM)->unmap_write(0xd800, 0xffff);
823   }
824   else
825   {
826      logerror("%s MMU BIOS RAM\n", machine.system().name);
827      base3 = base + 0x0c000;  /* 8K RAM */
828      base4 = base + 0x0d800;  /* 4K RAM + 8K RAM */
829      machine.device("maincpu")->memory().space(AS_PROGRAM)->install_readwrite_bank(0xc000, 0xcfff, "bank3");
830      machine.device("maincpu")->memory().space(AS_PROGRAM)->install_readwrite_bank(0xd800, 0xffff, "bank4");
831   }
832   memory_set_bankptr(machine, "bank3", base3);
833   memory_set_bankptr(machine, "bank4", base4);
834
835   /* check if self-test ROM changed */
836   if( new_mmu & 0x80 )
837   {
838      logerror("%s MMU SELFTEST RAM\n", machine.system().name);
839      base2 = base + 0x05000;  /* 0x0800 bytes */
840      machine.device("maincpu")->memory().space(AS_PROGRAM)->install_readwrite_bank(0x5000, 0x57ff, "bank2");
841   }
842   else
843   {
844      logerror("%s MMU SELFTEST ROM\n", machine.system().name);
845      base2 = base + 0x15000;  /* 0x0800 bytes */
846      machine.device("maincpu")->memory().space(AS_PROGRAM)->install_read_bank(0x5000, 0x57ff, "bank2");
847      machine.device("maincpu")->memory().space(AS_PROGRAM)->unmap_write(0x5000, 0x57ff);
848   }
849   memory_set_bankptr(machine, "bank2", base2);
850}
851
852static void xegs_mmu(running_machine &machine, UINT8 new_mmu)
853{
854   UINT8 *base = machine.region("maincpu")->base();
855   UINT8 *base2, *base3, *base4;
856
857   /* check if memory C000-FFFF changed */
858   if( new_mmu & 0x01 )
859   {
860      logerror("%s MMU BIOS ROM\n", machine.system().name);
861      base3 = base + 0x14000;  /* 8K lo BIOS */
862      base4 = base + 0x15800;  /* 4K FP ROM + 8K hi BIOS */
863      machine.device("maincpu")->memory().space(AS_PROGRAM)->install_read_bank(0xc000, 0xcfff, "bank3");
864      machine.device("maincpu")->memory().space(AS_PROGRAM)->unmap_write(0xc000, 0xcfff);
865      machine.device("maincpu")->memory().space(AS_PROGRAM)->install_read_bank(0xd800, 0xffff, "bank4");
866      machine.device("maincpu")->memory().space(AS_PROGRAM)->unmap_write(0xd800, 0xffff);
867   }
868   else
869   {
870      logerror("%s MMU BIOS RAM\n", machine.system().name);
871      base3 = base + 0x0c000;  /* 8K RAM */
872      base4 = base + 0x0d800;  /* 4K RAM + 8K RAM */
873      machine.device("maincpu")->memory().space(AS_PROGRAM)->install_readwrite_bank(0xc000, 0xcfff, "bank3");
874      machine.device("maincpu")->memory().space(AS_PROGRAM)->install_readwrite_bank(0xd800, 0xffff, "bank4");
875   }
876   memory_set_bankptr(machine, "bank3", base3);
877   memory_set_bankptr(machine, "bank4", base4);
878
879
880   /* check if self-test ROM changed */
881   if( new_mmu & 0x80 )
882   {
883      logerror("%s MMU SELFTEST RAM\n", machine.system().name);
884      machine.device("maincpu")->memory().space(AS_PROGRAM)->install_readwrite_bank(0x5000, 0x57ff, "bank2");
885      base2 = base + 0x05000;  /* 0x0800 bytes */
886   }
887   else
888   {
889      logerror("%s MMU SELFTEST ROM\n", machine.system().name);
890      machine.device("maincpu")->memory().space(AS_PROGRAM)->install_read_bank(0x5000, 0x57ff, "bank2");
891      machine.device("maincpu")->memory().space(AS_PROGRAM)->nop_write(0x5000, 0x57ff);
892      base2 = base + 0x15000;  /* 0x0800 bytes */
893   }
894   memory_set_bankptr(machine, "bank2", base2);
895}
896
897/**************************************************************
898 *
899 * PIA interface
900 *
901 **************************************************************/
902
903static WRITE8_DEVICE_HANDLER(a1200xl_pia_pb_w) { a1200xl_mmu(device->machine(), data); }
904static WRITE8_DEVICE_HANDLER(a800xl_pia_pb_w)
905{
906   if (downcast<pia6821_device *>(device)->port_b_z_mask() != 0xff)
907      a800xl_mmu(device->machine(), data);
908}
909
910static WRITE8_DEVICE_HANDLER(xegs_pia_pb_w)
911{
912   if (downcast<pia6821_device *>(device)->port_b_z_mask() != 0xff)
913      xegs_mmu(device->machine(), data);
914}
915
916static const pokey_interface atari_pokey_interface =
917{
918   {
919      DEVCB_INPUT_PORT("analog_0"),
920      DEVCB_INPUT_PORT("analog_1"),
921      DEVCB_INPUT_PORT("analog_2"),
922      DEVCB_INPUT_PORT("analog_3"),
923      DEVCB_INPUT_PORT("analog_4"),
924      DEVCB_INPUT_PORT("analog_5"),
925      DEVCB_INPUT_PORT("analog_6"),
926      DEVCB_INPUT_PORT("analog_7")
927   },
928   DEVCB_NULL,
929   DEVCB_DEVICE_HANDLER("fdc", atari_serin_r),
930   DEVCB_DEVICE_HANDLER("fdc", atari_serout_w),
931   atari_interrupt_cb,
932};
933
934
935static const pia6821_interface atari_pia_interface =
936{
937   DEVCB_HANDLER(atari_pia_pa_r),      /* port A in */
938   DEVCB_HANDLER(atari_pia_pb_r),   /* port B in */
939   DEVCB_NULL,      /* line CA1 in */
940   DEVCB_NULL,      /* line CB1 in */
941   DEVCB_NULL,      /* line CA2 in */
942   DEVCB_NULL,      /* line CB2 in */
943   DEVCB_NULL,      /* port A out */
944   DEVCB_NULL,      /* port B out */
945   DEVCB_NULL,      /* line CA2 out */
946   DEVCB_DEVICE_LINE("fdc",atarifdc_pia_cb2_w),      /* port CB2 out */
947   DEVCB_NULL,      /* IRQA */
948   DEVCB_NULL      /* IRQB */
949};
950
951static const pia6821_interface a600xl_pia_interface =
952{
953   DEVCB_HANDLER(atari_pia_pa_r),      /* port A in */
954   DEVCB_HANDLER(atari_pia_pb_r),   /* port B in */
955   DEVCB_NULL,      /* line CA1 in */
956   DEVCB_NULL,      /* line CB1 in */
957   DEVCB_NULL,      /* line CA2 in */
958   DEVCB_NULL,      /* line CB2 in */
959   DEVCB_NULL,      /* port A out */
960   DEVCB_HANDLER(a600xl_pia_pb_w),      /* port B out */
961   DEVCB_NULL,      /* line CA2 out */
962   DEVCB_DEVICE_LINE("fdc",atarifdc_pia_cb2_w),      /* port CB2 out */
963   DEVCB_NULL,      /* IRQA */
964   DEVCB_NULL      /* IRQB */
965};
966
967static const pia6821_interface a1200xl_pia_interface =
968{
969   DEVCB_HANDLER(atari_pia_pa_r),      /* port A in */
970   DEVCB_HANDLER(atari_pia_pb_r),   /* port B in */
971   DEVCB_NULL,      /* line CA1 in */
972   DEVCB_NULL,      /* line CB1 in */
973   DEVCB_NULL,      /* line CA2 in */
974   DEVCB_NULL,      /* line CB2 in */
975   DEVCB_NULL,      /* port A out */
976   DEVCB_HANDLER(a1200xl_pia_pb_w),      /* port B out */
977   DEVCB_NULL,      /* line CA2 out */
978   DEVCB_DEVICE_LINE("fdc",atarifdc_pia_cb2_w),      /* port CB2 out */
979   DEVCB_NULL,      /* IRQA */
980   DEVCB_NULL      /* IRQB */
981};
982
983static const pia6821_interface a800xl_pia_interface =
984{
985   DEVCB_HANDLER(atari_pia_pa_r),      /* port A in */
986   DEVCB_HANDLER(atari_pia_pb_r),   /* port B in */
987   DEVCB_NULL,      /* line CA1 in */
988   DEVCB_NULL,      /* line CB1 in */
989   DEVCB_NULL,      /* line CA2 in */
990   DEVCB_NULL,      /* line CB2 in */
991   DEVCB_NULL,      /* port A out */
992   DEVCB_HANDLER(a800xl_pia_pb_w),      /* port B out */
993   DEVCB_NULL,      /* line CA2 out */
994   DEVCB_DEVICE_LINE("fdc",atarifdc_pia_cb2_w),      /* port CB2 out */
995   DEVCB_NULL,      /* IRQA */
996   DEVCB_NULL      /* IRQB */
997};
998
999static const pia6821_interface xegs_pia_interface =
1000{
1001   DEVCB_HANDLER(atari_pia_pa_r),      /* port A in */
1002   DEVCB_HANDLER(atari_pia_pb_r),   /* port B in */
1003   DEVCB_NULL,      /* line CA1 in */
1004   DEVCB_NULL,      /* line CB1 in */
1005   DEVCB_NULL,      /* line CA2 in */
1006   DEVCB_NULL,      /* line CB2 in */
1007   DEVCB_NULL,      /* port A out */
1008   DEVCB_HANDLER(xegs_pia_pb_w),      /* port B out */
1009   DEVCB_NULL,      /* line CA2 out */
1010   DEVCB_DEVICE_LINE("fdc",atarifdc_pia_cb2_w),      /* port CB2 out */
1011   DEVCB_NULL,      /* IRQA */
1012   DEVCB_NULL      /* IRQB */
1013};
1014
1015// FIXME: should there be anything connected where other system have the fdc?
1016static const pokey_interface a5200_pokey_interface =
1017{
1018   {
1019      DEVCB_INPUT_PORT("analog_0"),
1020      DEVCB_INPUT_PORT("analog_1"),
1021      DEVCB_INPUT_PORT("analog_2"),
1022      DEVCB_INPUT_PORT("analog_3"),
1023      DEVCB_INPUT_PORT("analog_4"),
1024      DEVCB_INPUT_PORT("analog_5"),
1025      DEVCB_INPUT_PORT("analog_6"),
1026      DEVCB_INPUT_PORT("analog_7")
1027   },
1028   DEVCB_NULL,
1029   DEVCB_NULL,   // FIXME: is there anything connected here?
1030   DEVCB_NULL,   // FIXME: is there anything connected here?
1031   atari_interrupt_cb,
1032};
1033
1034static const pia6821_interface a5200_pia_interface =
1035{
1036   DEVCB_HANDLER(atari_pia_pa_r),      /* port A in */
1037   DEVCB_HANDLER(atari_pia_pb_r),   /* port B in */
1038   DEVCB_NULL,      /* line CA1 in */
1039   DEVCB_NULL,      /* line CB1 in */
1040   DEVCB_NULL,      /* line CA2 in */
1041   DEVCB_NULL,      /* line CB2 in */
1042   DEVCB_NULL,      /* port A out */
1043   DEVCB_NULL,      /* port B out */
1044   DEVCB_NULL,      /* line CA2 out */
1045   DEVCB_NULL,      /* port CB2 out */   // FIXME: is there anything connected here
1046   DEVCB_NULL,      /* IRQA */
1047   DEVCB_NULL      /* IRQB */
1048};
1049
1050
1051/**************************************************************
1052 *
1053 * Machine drivers
1054 *
1055 **************************************************************/
1056
1057static MACHINE_CONFIG_FRAGMENT( a400_cartslot )
1058   MCFG_CARTSLOT_ADD("cart1")
1059   MCFG_CARTSLOT_EXTENSION_LIST("rom,bin")
1060   MCFG_CARTSLOT_NOT_MANDATORY
1061   MCFG_CARTSLOT_LOAD(a800_cart)
1062   MCFG_CARTSLOT_UNLOAD(a800_cart)
1063   MCFG_CARTSLOT_INTERFACE("a800_cart")
1064MACHINE_CONFIG_END
1065
1066static MACHINE_CONFIG_FRAGMENT( a800_cartslot )
1067   MCFG_CARTSLOT_ADD("cart1")
1068   MCFG_CARTSLOT_EXTENSION_LIST("rom,bin")
1069   MCFG_CARTSLOT_NOT_MANDATORY
1070   MCFG_CARTSLOT_LOAD(a800_cart)
1071   MCFG_CARTSLOT_UNLOAD(a800_cart)
1072   MCFG_CARTSLOT_INTERFACE("a800_cart")
1073
1074   MCFG_CARTSLOT_ADD("cart2")
1075   MCFG_CARTSLOT_EXTENSION_LIST("rom,bin")
1076   MCFG_CARTSLOT_NOT_MANDATORY
1077   MCFG_CARTSLOT_LOAD(a800_cart_right)
1078   MCFG_CARTSLOT_UNLOAD(a800_cart_right)
1079   MCFG_CARTSLOT_INTERFACE("a800_cart")
1080MACHINE_CONFIG_END
1081
1082static MACHINE_CONFIG_START( atari_common_nodac, driver_device )
1083   /* basic machine hardware */
1084   MCFG_CPU_ADD("maincpu", M6502, FREQ_17_EXACT)
1085
1086   /* video hardware */
1087   MCFG_SCREEN_ADD("screen", RASTER)
1088   MCFG_SCREEN_VBLANK_TIME(ATTOSECONDS_IN_USEC(1))
1089   MCFG_SCREEN_FORMAT(BITMAP_FORMAT_INDEXED16)
1090   MCFG_SCREEN_VISIBLE_AREA(MIN_X, MAX_X, MIN_Y, MAX_Y)
1091   MCFG_PALETTE_LENGTH(sizeof(atari_palette) / 3)
1092   MCFG_PALETTE_INIT(mess_atari)
1093   MCFG_SCREEN_UPDATE(atari)
1094
1095   MCFG_VIDEO_START(atari)
1096
1097   MCFG_PIA6821_ADD( "pia", atari_pia_interface )
1098
1099   /* sound hardware */
1100   MCFG_SPEAKER_STANDARD_MONO("mono")
1101   MCFG_SOUND_ADD("pokey", POKEY, FREQ_17_EXACT)
1102   MCFG_SOUND_CONFIG(atari_pokey_interface)
1103   MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 1.00)
1104
1105   /* internal ram */
1106   MCFG_RAM_ADD(RAM_TAG)
1107   MCFG_RAM_DEFAULT_SIZE("40K")
1108MACHINE_CONFIG_END
1109
1110
1111static MACHINE_CONFIG_DERIVED( atari_common, atari_common_nodac )
1112   MCFG_SOUND_ADD("dac", DAC, 0)
1113   MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.50)
1114
1115   MCFG_ATARI_FDC_ADD("fdc")
1116MACHINE_CONFIG_END
1117
1118
1119static MACHINE_CONFIG_DERIVED( a400, atari_common )
1120
1121   MCFG_CPU_MODIFY( "maincpu" )
1122   MCFG_CPU_PROGRAM_MAP(a400_mem)
1123   MCFG_CPU_VBLANK_INT_HACK(a400_interrupt, TOTAL_LINES_60HZ)
1124
1125   MCFG_MACHINE_START( a400 )
1126
1127   MCFG_SCREEN_MODIFY("screen")
1128   MCFG_SCREEN_REFRESH_RATE(FRAME_RATE_60HZ)
1129   MCFG_SCREEN_SIZE(HWIDTH*8, TOTAL_LINES_60HZ)
1130
1131   MCFG_FRAGMENT_ADD(a400_cartslot)
1132
1133   /* software lists */
1134   MCFG_SOFTWARE_LIST_ADD("cart_list","a800")
1135MACHINE_CONFIG_END
1136
1137
1138static MACHINE_CONFIG_DERIVED( a400pal, atari_common )
1139
1140   MCFG_CPU_MODIFY( "maincpu" )
1141   MCFG_CPU_PROGRAM_MAP(a400_mem)
1142   MCFG_CPU_VBLANK_INT_HACK(a400_interrupt, TOTAL_LINES_50HZ)
1143
1144   MCFG_MACHINE_START( a400 )
1145
1146   MCFG_SCREEN_MODIFY("screen")
1147   MCFG_SCREEN_REFRESH_RATE(FRAME_RATE_50HZ)
1148   MCFG_SCREEN_SIZE(HWIDTH*8, TOTAL_LINES_50HZ)
1149
1150   MCFG_FRAGMENT_ADD(a400_cartslot)
1151
1152   /* software lists */
1153   MCFG_SOFTWARE_LIST_ADD("cart_list","a800")
1154MACHINE_CONFIG_END
1155
1156
1157static MACHINE_CONFIG_DERIVED( a800, atari_common )
1158
1159   MCFG_CPU_MODIFY( "maincpu" )
1160   MCFG_CPU_PROGRAM_MAP(a800_mem)
1161   MCFG_CPU_VBLANK_INT_HACK(a800_interrupt, TOTAL_LINES_60HZ)
1162
1163   MCFG_MACHINE_START( a800 )
1164
1165   MCFG_SCREEN_MODIFY("screen")
1166   MCFG_SCREEN_REFRESH_RATE(FRAME_RATE_60HZ)
1167   MCFG_SCREEN_SIZE(HWIDTH*8, TOTAL_LINES_60HZ)
1168
1169   MCFG_FRAGMENT_ADD(a800_cartslot)
1170
1171   /* software lists */
1172   MCFG_SOFTWARE_LIST_ADD("cart_list","a800")
1173MACHINE_CONFIG_END
1174
1175
1176static MACHINE_CONFIG_DERIVED( a800pal, atari_common )
1177
1178   MCFG_CPU_MODIFY( "maincpu" )
1179   MCFG_CPU_PROGRAM_MAP(a800_mem)
1180   MCFG_CPU_VBLANK_INT_HACK(a800_interrupt, TOTAL_LINES_50HZ)
1181
1182   MCFG_MACHINE_START( a800 )
1183
1184   MCFG_SCREEN_MODIFY("screen")
1185   MCFG_SCREEN_REFRESH_RATE(FRAME_RATE_50HZ)
1186   MCFG_SCREEN_SIZE(HWIDTH*8, TOTAL_LINES_50HZ)
1187
1188   MCFG_FRAGMENT_ADD(a800_cartslot)
1189
1190   /* software lists */
1191   MCFG_SOFTWARE_LIST_ADD("cart_list","a800")
1192MACHINE_CONFIG_END
1193
1194
1195static MACHINE_CONFIG_DERIVED( a600xl, atari_common )
1196
1197   MCFG_CPU_MODIFY( "maincpu" )
1198   MCFG_CPU_PROGRAM_MAP(a600xl_mem)   // FIXME?
1199   MCFG_CPU_VBLANK_INT_HACK(a800xl_interrupt, TOTAL_LINES_60HZ)
1200
1201   MCFG_PIA6821_MODIFY( "pia", a600xl_pia_interface )
1202
1203   MCFG_MACHINE_START( a800xl )   // FIXME?
1204
1205   MCFG_SCREEN_MODIFY("screen")
1206   MCFG_SCREEN_REFRESH_RATE(FRAME_RATE_60HZ)
1207   MCFG_SCREEN_SIZE(HWIDTH*8, TOTAL_LINES_60HZ)
1208
1209   MCFG_FRAGMENT_ADD(a400_cartslot)
1210
1211   /* software lists */
1212   MCFG_SOFTWARE_LIST_ADD("cart_list","a800")
1213
1214   /* internal ram */
1215   MCFG_RAM_MODIFY(RAM_TAG)
1216   MCFG_RAM_DEFAULT_SIZE("16K")
1217MACHINE_CONFIG_END
1218
1219
1220static MACHINE_CONFIG_DERIVED( a800xl, atari_common )
1221
1222   MCFG_CPU_MODIFY( "maincpu" )
1223   MCFG_CPU_PROGRAM_MAP(a800xl_mem)
1224   MCFG_CPU_VBLANK_INT_HACK(a800xl_interrupt, TOTAL_LINES_60HZ)
1225
1226   MCFG_PIA6821_MODIFY( "pia", a800xl_pia_interface )
1227
1228   MCFG_MACHINE_START( a800xl )
1229
1230   MCFG_SCREEN_MODIFY("screen")
1231   MCFG_SCREEN_REFRESH_RATE(FRAME_RATE_60HZ)
1232   MCFG_SCREEN_SIZE(HWIDTH*8, TOTAL_LINES_60HZ)
1233
1234   MCFG_FRAGMENT_ADD(a400_cartslot)
1235
1236   /* software lists */
1237   MCFG_SOFTWARE_LIST_ADD("cart_list","a800")
1238MACHINE_CONFIG_END
1239
1240static MACHINE_CONFIG_DERIVED( a800xlpal, a800xl )
1241
1242   MCFG_CPU_MODIFY( "maincpu" )
1243   MCFG_CPU_CLOCK( 1773000 )
1244   MCFG_CPU_VBLANK_INT_HACK(a800xl_interrupt, TOTAL_LINES_50HZ)
1245   MCFG_SCREEN_MODIFY("screen")
1246   MCFG_SCREEN_REFRESH_RATE(FRAME_RATE_50HZ)
1247   MCFG_SCREEN_SIZE(HWIDTH*8, TOTAL_LINES_50HZ)
1248
1249   MCFG_SOUND_MODIFY("pokey")
1250   MCFG_SOUND_CLOCK(1773000)
1251MACHINE_CONFIG_END
1252
1253static MACHINE_CONFIG_DERIVED( a1200xl, a800xl )
1254
1255   MCFG_PIA6821_MODIFY( "pia", a1200xl_pia_interface )
1256MACHINE_CONFIG_END
1257
1258static MACHINE_CONFIG_DERIVED( xegs, a800xl )
1259
1260   MCFG_CPU_MODIFY( "maincpu" )
1261   MCFG_CPU_PROGRAM_MAP(xegs_mem)
1262
1263   MCFG_MACHINE_START( xegs )
1264
1265   MCFG_PIA6821_MODIFY( "pia", xegs_pia_interface )
1266
1267   MCFG_DEVICE_REMOVE("cart1")
1268   MCFG_DEVICE_REMOVE("cart_list")
1269
1270   MCFG_CARTSLOT_ADD("cart1")
1271   MCFG_CARTSLOT_EXTENSION_LIST("rom,bin")
1272   MCFG_CARTSLOT_NOT_MANDATORY
1273   MCFG_CARTSLOT_LOAD(xegs_cart)
1274   MCFG_CARTSLOT_UNLOAD(xegs_cart)
1275   MCFG_CARTSLOT_INTERFACE("xegs_cart")
1276
1277   /* software lists */
1278   MCFG_SOFTWARE_LIST_ADD("cart_list","xegs")
1279MACHINE_CONFIG_END
1280
1281
1282static MACHINE_CONFIG_DERIVED( a5200, atari_common_nodac )
1283
1284   MCFG_CPU_MODIFY( "maincpu" )
1285   MCFG_CPU_PROGRAM_MAP(a5200_mem)
1286   MCFG_CPU_VBLANK_INT_HACK(a5200_interrupt, TOTAL_LINES_60HZ)
1287
1288   MCFG_DEVICE_REMOVE("pokey")
1289   MCFG_SOUND_ADD("pokey", POKEY, FREQ_17_EXACT)
1290   MCFG_SOUND_CONFIG(a5200_pokey_interface)
1291   MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 1.00)
1292
1293   MCFG_PIA6821_MODIFY( "pia", a5200_pia_interface )
1294
1295   MCFG_MACHINE_START( a5200 )
1296
1297   MCFG_SCREEN_MODIFY( "screen" )
1298   MCFG_SCREEN_REFRESH_RATE(FRAME_RATE_60HZ)
1299   MCFG_SCREEN_SIZE(HWIDTH*8, TOTAL_LINES_60HZ)
1300
1301   MCFG_CARTSLOT_ADD("cart")
1302   MCFG_CARTSLOT_EXTENSION_LIST("rom,bin,a52")
1303   MCFG_CARTSLOT_NOT_MANDATORY
1304   MCFG_CARTSLOT_LOAD(a5200_cart)
1305   MCFG_CARTSLOT_UNLOAD(a5200_cart)
1306   MCFG_CARTSLOT_INTERFACE("a5200_cart")
1307
1308   /* Software lists */
1309   MCFG_SOFTWARE_LIST_ADD("cart_list","a5200")
1310
1311   /* internal ram */
1312   MCFG_RAM_MODIFY(RAM_TAG)
1313   MCFG_RAM_DEFAULT_SIZE("16K")
1314MACHINE_CONFIG_END
1315
1316
1317/**************************************************************
1318 *
1319 * ROM loading
1320 *
1321 **************************************************************/
1322
1323ROM_START(a400)
1324   ROM_REGION(0x14000, "maincpu", 0) /* 64K for the CPU + 2 * 8K for cartridges */
1325   ROM_LOAD( "co12399b.rom", 0xd800, 0x0800, CRC(6a5d766e) SHA1(01a6044f7a81d409c938e7dfde0a1af5832229d2) )
1326   ROM_SYSTEM_BIOS(0, "default", "OS Rev. B")
1327   ROMX_LOAD( "co12499b.rom",  0xe000, 0x1000, BAD_DUMP CRC(d818f3e8) SHA1(bcdec2188f6a6a5bfc1df4e383bd828d34b5c4ac), ROM_BIOS(1) )   // CRC and label waiting for confirmation
1328   ROMX_LOAD( "co14599b.rom",  0xf000, 0x1000, BAD_DUMP CRC(c1690a9b) SHA1(c5248e8565574fd39ae1c3f4f356aa4cac07df95), ROM_BIOS(1) )   // CRC and label waiting for confirmation
1329   ROM_SYSTEM_BIOS(1, "reva", "OS Rev. A")
1330   ROMX_LOAD( "co12499a.rom",  0xe000, 0x1000, BAD_DUMP CRC(29f64e17) SHA1(abf7ec488c6b600f1b7f30bdc7f8a2bf6a727675), ROM_BIOS(2) )   // CRC and label waiting for confirmation
1331   ROMX_LOAD( "co14599a.rom",  0xf000, 0x1000, BAD_DUMP CRC(bc533f0c) SHA1(e217148495fa747fe5488132d8d22533e68c7e58), ROM_BIOS(2) )   // CRC and label waiting for confirmation
1332
1333   ROM_REGION(0x10000, "lslot", ROMREGION_ERASEFF)
1334ROM_END
1335
1336ROM_START(a400pal)
1337   ROM_REGION(0x14000, "maincpu", 0) /* 64K for the CPU + 2 * 8K for cartridges */
1338   ROM_LOAD( "co12399b.rom", 0xd800, 0x0800, CRC(6a5d766e) SHA1(01a6044f7a81d409c938e7dfde0a1af5832229d2) )
1339   ROM_LOAD( "co15199.rom", 0xe000, 0x1000, BAD_DUMP CRC(8e547f56) SHA1(1bd746ea798b723bfb18495a7facca113183d713) )   // Rev. A - CRC and label waiting for confirmation
1340   ROM_LOAD( "co15299.rom", 0xf000, 0x1000, BAD_DUMP CRC(be55b413) SHA1(d88afae49b08e75943d0258cb580e5d34756414a) )   // Rev. A - CRC and label waiting for confirmation
1341
1342   ROM_REGION(0x10000, "lslot", ROMREGION_ERASEFF)
1343ROM_END
1344
1345ROM_START(a800)
1346   ROM_REGION(0x14000, "maincpu", 0) /* 64K for the CPU + 2 * 8K for cartridges */
1347   ROM_LOAD( "co12399b.rom", 0xd800, 0x0800, CRC(6a5d766e) SHA1(01a6044f7a81d409c938e7dfde0a1af5832229d2) )
1348   ROM_SYSTEM_BIOS(0, "default", "OS Rev. B")
1349   ROMX_LOAD( "co12499b.rom",  0xe000, 0x1000, BAD_DUMP CRC(d818f3e8) SHA1(bcdec2188f6a6a5bfc1df4e383bd828d34b5c4ac), ROM_BIOS(1) )   // CRC and label waiting for confirmation
1350   ROMX_LOAD( "co14599b.rom",  0xf000, 0x1000, BAD_DUMP CRC(c1690a9b) SHA1(c5248e8565574fd39ae1c3f4f356aa4cac07df95), ROM_BIOS(1) )   // CRC and label waiting for confirmation
1351   ROM_SYSTEM_BIOS(1, "reva", "OS Rev. A")
1352   ROMX_LOAD( "co12499a.rom",  0xe000, 0x1000, BAD_DUMP CRC(29f64e17) SHA1(abf7ec488c6b600f1b7f30bdc7f8a2bf6a727675), ROM_BIOS(2) )   // CRC and label waiting for confirmation
1353   ROMX_LOAD( "co14599a.rom",  0xf000, 0x1000, BAD_DUMP CRC(bc533f0c) SHA1(e217148495fa747fe5488132d8d22533e68c7e58), ROM_BIOS(2) )   // CRC and label waiting for confirmation
1354
1355   ROM_REGION(0x10000, "lslot", ROMREGION_ERASEFF)
1356
1357   ROM_REGION(0x2000, "rslot", ROMREGION_ERASEFF)
1358ROM_END
1359
1360ROM_START(a800pal)
1361   ROM_REGION(0x14000, "maincpu", 0) /* 64K for the CPU + 2 * 8K for cartridges */
1362   ROM_LOAD( "co12399b.rom", 0xd800, 0x0800, CRC(6a5d766e) SHA1(01a6044f7a81d409c938e7dfde0a1af5832229d2) )
1363   ROM_LOAD( "co15199.rom", 0xe000, 0x1000, BAD_DUMP CRC(8e547f56) SHA1(1bd746ea798b723bfb18495a7facca113183d713) )   // Rev. A - CRC and label waiting for confirmation
1364   ROM_LOAD( "co15299.rom", 0xf000, 0x1000, BAD_DUMP CRC(be55b413) SHA1(d88afae49b08e75943d0258cb580e5d34756414a) )   // Rev. A - CRC and label waiting for confirmation
1365
1366   ROM_REGION(0x10000, "lslot", ROMREGION_ERASEFF)
1367
1368   ROM_REGION(0x2000, "rslot", ROMREGION_ERASEFF)
1369ROM_END
1370
1371ROM_START(a1200xl)
1372   ROM_REGION(0x18000, "maincpu", 0)
1373   ROM_SYSTEM_BIOS(0, "default", "OS Rev. 11")
1374   ROMX_LOAD( "co60616b.rom", 0x14000, 0x2000, BAD_DUMP CRC(6e29ec8d) SHA1(3f9c06d6b4d261f3d5bf4354e3cff0c17b9347b9), ROM_BIOS(1) )   // CRC and label waiting for confirmation
1375   ROMX_LOAD( "co60617b.rom", 0x16000, 0x2000, BAD_DUMP CRC(d73ce29a) SHA1(64790242d902643fe0c40dd842749f1fe461831b), ROM_BIOS(1) )   // CRC and label waiting for confirmation
1376   ROM_SYSTEM_BIOS(1, "rev10", "OS Rev. 10")
1377   ROMX_LOAD( "co60616a.rom", 0x14000, 0x2000, BAD_DUMP CRC(0391386b) SHA1(7c176657c88b89b8a69bf021fa8e0939efc0dff2), ROM_BIOS(2) )   // CRC and label waiting for confirmation
1378   ROMX_LOAD( "co60617a.rom", 0x16000, 0x2000, BAD_DUMP CRC(b502f1e7) SHA1(6688db57d97fa570aef5c15cef3e5fb2688879c2), ROM_BIOS(2) )   // CRC and label waiting for confirmation
1379
1380   ROM_REGION(0x10000, "lslot", ROMREGION_ERASEFF)
1381ROM_END
1382
1383ROM_START(a600xl)
1384   ROM_REGION(0x10000, "maincpu", 0)
1385   ROM_LOAD( "co60302a.rom", 0xa000, 0x2000, CRC(f0202fb3) SHA1(7ad88dd99ff4a6ee66f6d162074db6f8bef7a9b6) )   // Rev. B
1386   ROM_LOAD( "co62024.rom",  0xc000, 0x4000, CRC(643bcc98) SHA1(881d030656b40bbe48f15a696b28f22c0b752ab0) )   // Rev. 1
1387
1388   ROM_REGION(0x10000, "lslot", ROMREGION_ERASEFF)
1389ROM_END
1390
1391ROM_START(a800xl)
1392   ROM_REGION(0x18000, "maincpu", 0)
1393   ROM_FILL( 0, 0x10000, 0x00 )
1394   ROM_LOAD( "co60302a.rom", 0x10000, 0x2000, CRC(f0202fb3) SHA1(7ad88dd99ff4a6ee66f6d162074db6f8bef7a9b6) )   // Rev. B
1395   ROM_LOAD( "co61598b.rom", 0x14000, 0x4000, CRC(1f9cd270) SHA1(ae4f523ba08b6fd59f3cae515a2b2410bbd98f55) )   // Rev. 2
1396
1397   ROM_REGION(0x10000, "lslot", ROMREGION_ERASEFF)
1398ROM_END
1399
1400#define rom_a800xlp rom_a800xl
1401
1402ROM_START(a65xe)
1403   ROM_REGION(0x18000, "maincpu", 0)
1404   ROM_LOAD( "co24947a.rom", 0x10000, 0x2000, CRC(7d684184) SHA1(3693c9cb9bf3b41bae1150f7a8264992468fc8c0) )   // Rev. C
1405   ROM_LOAD( "co61598b.rom", 0x14000, 0x4000, CRC(1f9cd270) SHA1(ae4f523ba08b6fd59f3cae515a2b2410bbd98f55) )   // Rev. 2
1406
1407   ROM_REGION(0x10000, "lslot", ROMREGION_ERASEFF)
1408ROM_END
1409
1410ROM_START(a65xea)
1411   ROM_REGION(0x18000, "maincpu", 0)
1412   ROM_LOAD( "basic_ar.rom", 0x10000, 0x2000, CRC(c899f4d6) SHA1(043df191d1fe402e792266a108e147ffcda35130) )   // is this correct? or shall we use Rev. C?
1413//  ROM_LOAD( "c101700.rom",  0x14000, 0x4000, CRC(7f9a76c8) SHA1(57eb6d87850a763f11767f53d4eaede186f831a2) )   // this was from Savetz and has wrong bits!
1414   ROM_LOAD( "c101700.rom",  0x14000, 0x4000, CRC(45f47988) SHA1(a36b8b20f657580f172749bb0625c08706ed824c) )   // Rev. 3B ?
1415
1416   ROM_REGION(0x10000, "lslot", ROMREGION_ERASEFF)
1417ROM_END
1418
1419ROM_START(a130xe)
1420   ROM_REGION(0x18000, "maincpu", 0)
1421   ROM_LOAD( "co24947a.rom", 0x10000, 0x2000, CRC(7d684184) SHA1(3693c9cb9bf3b41bae1150f7a8264992468fc8c0) )   // Rev. C
1422   ROM_LOAD( "co61598b.rom", 0x14000, 0x4000, CRC(1f9cd270) SHA1(ae4f523ba08b6fd59f3cae515a2b2410bbd98f55) )   // Rev. 2
1423
1424   ROM_REGION(0x10000, "lslot", ROMREGION_ERASEFF)
1425ROM_END
1426
1427ROM_START(a800xe)
1428   ROM_REGION(0x18000, "maincpu", 0)
1429   ROM_LOAD( "co24947a.rom", 0x10000, 0x2000, CRC(7d684184) SHA1(3693c9cb9bf3b41bae1150f7a8264992468fc8c0) )   // Rev. C
1430   ROM_LOAD( "c300717.rom",  0x14000, 0x4000, CRC(29f133f7) SHA1(f03b9b93000ee84abb9cf8d6367241006f172182) )   // Rev. 3
1431
1432   ROM_REGION(0x10000, "lslot", ROMREGION_ERASEFF)
1433ROM_END
1434
1435ROM_START(xegs)
1436   ROM_REGION(0x1a000, "maincpu", 0)
1437   ROM_LOAD( "c101687.rom", 0x10000, 0x8000, CRC(d50260d1) SHA1(0e0625ab2473f8431640df3ac8af61925760b9b9) )   // Rev. C + Rev. 4 + Missile Command
1438
1439   ROM_REGION(0x20000, "user1", ROMREGION_ERASE00)
1440ROM_END
1441
1442
1443ROM_START(a5200)
1444   ROM_REGION(0x14000, "maincpu", 0) /* 64K for the CPU + 16K for cartridges */
1445   ROM_SYSTEM_BIOS(0, "default", "a5200")
1446   ROMX_LOAD( "5200.rom",  0xf800, 0x0800, CRC(4248d3e3) SHA1(6ad7a1e8c9fad486fbec9498cb48bf5bc3adc530), ROM_BIOS(1) )
1447   ROM_SYSTEM_BIOS(1, "alt", "a5200 (alt)")
1448   ROMX_LOAD( "5200a.rom", 0xf800, 0x0800, CRC(c2ba2613) SHA1(1d2a3f00109d75d2d79fecb565775eb95b7d04d5), ROM_BIOS(2) )
1449ROM_END
1450
1451/**************************************************************
1452 *
1453 * Driver initializations
1454 *
1455 **************************************************************/
1456
1457static DRIVER_INIT( a800xl )
1458{
1459   a800xl_mmu(machine, 0xff);
1460}
1461
1462static DRIVER_INIT( xegs )
1463{
1464   xegs_mmu(machine, 0xff);
1465}
1466
1467static DRIVER_INIT( a600xl )
1468{
1469   UINT8 *rom = machine.region("maincpu")->base();
1470   memcpy( rom + 0x5000, rom + 0xd000, 0x800 );
1471}
1472
1473/**************************************************************
1474 *
1475 * Game driver(s)
1476 *
1477 **************************************************************/
1478
1479/*     YEAR  NAME      PARENT    COMPAT MACHINE     INPUT    INIT      COMPANY    FULLNAME */
1480COMP ( 1979, a400,     0,        0,     a400,       a800,    0,      "Atari",   "Atari 400 (NTSC)", 0)
1481COMP ( 1979, a400pal,  a400,     0,     a400pal,    a800,    0,      "Atari",   "Atari 400 (PAL)",  0)
1482COMP ( 1979, a800,     0,        0,     a800,       a800,    0,      "Atari",   "Atari 800 (NTSC)", 0)
1483COMP ( 1979, a800pal,  a800,     0,     a800pal,    a800,    0,      "Atari",   "Atari 800 (PAL)",  0)
1484COMP ( 1982, a1200xl,  a800,     0,     a1200xl,    a800xl,  a800xl, "Atari",   "Atari 1200XL",     GAME_NOT_WORKING )      // 64k RAM
1485COMP ( 1983, a600xl,   a800xl,   0,     a600xl,     a800xl,  a600xl, "Atari",   "Atari 600XL",      GAME_NOT_WORKING )      // 16k RAM
1486COMP ( 1983, a800xl,   0,       0,     a800xl,     a800xl,  a800xl, "Atari",   "Atari 800XL (NTSC)",GAME_IMPERFECT_GRAPHICS )      // 64k RAM
1487COMP ( 1983, a800xlp,  a800xl,    0,     a800xlpal,  a800xl,  a800xl, "Atari",   "Atari 800XL (PAL)", GAME_IMPERFECT_GRAPHICS )      // 64k RAM
1488COMP ( 1986, a65xe,    a800xl,   0,     a800xl,     a800xl,  a800xl, "Atari",   "Atari 65XE",       GAME_NOT_WORKING )      // 64k RAM
1489COMP ( 1986, a65xea,   a800xl,   0,     a800xl,     a800xl,  a800xl, "Atari",   "Atari 65XE (Arabic)", GAME_NOT_WORKING )
1490COMP ( 1986, a130xe,   a800xl,   0,     a800xl,     a800xl,  a800xl, "Atari",   "Atari 130XE",      GAME_NOT_WORKING )      // 128k RAM
1491COMP ( 1986, a800xe,   a800xl,   0,     a800xl,     a800xl,  a800xl, "Atari",   "Atari 800XE",      GAME_NOT_WORKING )      // 64k RAM
1492COMP ( 1987, xegs,     0,        0,     xegs,       a800xl,  xegs,   "Atari",   "Atari XE Game System", GAME_NOT_WORKING )   // 64k RAM
1493
1494CONS ( 1982, a5200,    0,        0,     a5200,      a5200,   0,      "Atari",   "Atari 5200",       0)
src/mess/drivers/amiga.c
r0r11532
1/***************************************************************************
2Commodore Amiga - (c) 1985, Commodore Business Machines Co.
3
4Preliminary driver by:
5
6Ernesto Corvi
7
8Note 1: The 'fast-mem' memory detector in Kickstart 1.2 expects to
9see the custom chips at the end of any present fast memory (mapped
10from $C00000 onwards). I assume this is a bug, given that the routine
11was entirely rewritten for Kickstart 1.3. So the strategy is, for
12any machine that can run Kickstart 1.2 (a500,a1000 and a2000), we
13map a mirror of the custom chips right after any fast-mem we mapped.
14If we didn't map any, then we still put a mirror, but where fast-mem
15would commence ($C00000).
16
17***************************************************************************/
18
19/* Core includes */
20#include "emu.h"
21#include "includes/amiga.h"
22
23/* Components */
24#include "cpu/m68000/m68000.h"
25#include "cpu/m6502/m6502.h"
26#include "machine/6525tpi.h"
27#include "machine/6526cia.h"
28#include "machine/amigafdc.h"
29#include "machine/amigakbd.h"
30#include "machine/amigacd.h"
31#include "machine/amigacrt.h"
32#include "machine/msm6242.h"
33#include "machine/ctronics.h"
34#include "machine/nvram.h"
35#include "sound/cdda.h"
36
37/* Devices */
38#include "imagedev/chd_cd.h"
39#include "imagedev/cartslot.h"
40
41
42static READ8_DEVICE_HANDLER( amiga_cia_0_portA_r );
43static READ8_DEVICE_HANDLER( amiga_cia_0_cdtv_portA_r );
44static WRITE8_DEVICE_HANDLER( amiga_cia_0_portA_w );
45
46/***************************************************************************
47  Battery Backed-Up Clock (MSM6264)
48***************************************************************************/
49
50static READ16_HANDLER( amiga_clock_r )
51{
52   device_t *rtc = space->machine().device("rtc");
53   return msm6242_r(rtc, offset / 2);
54}
55
56
57static WRITE16_HANDLER( amiga_clock_w )
58{
59   device_t *rtc = space->machine().device("rtc");
60   msm6242_w(rtc, offset / 2, data);
61}
62
63
64/***************************************************************************
65    CENTRONICS PORT
66***************************************************************************/
67
68static READ8_DEVICE_HANDLER( amiga_cia_1_porta_r )
69{
70   UINT8 result = 0;
71
72   /* centronics status is stored in PA0 to PA2 */
73   result |= centronics_busy_r(device) << 0;
74   result |= !centronics_pe_r(device) << 1;
75   result |= centronics_vcc_r(device) << 2;
76
77   /* PA3 to PA7 store the serial line status (not emulated) */
78
79   return result;
80}
81
82static const centronics_interface amiga_centronics_config =
83{
84   FALSE,
85   DEVCB_DEVICE_LINE("cia_0", mos6526_flag_w),
86   DEVCB_NULL,
87   DEVCB_NULL
88};
89
90
91/***************************************************************************
92  Address maps
93***************************************************************************/
94
95static ADDRESS_MAP_START(amiga_mem, AS_PROGRAM, 16)
96   ADDRESS_MAP_UNMAP_HIGH
97   AM_RANGE(0x000000, 0x07ffff) AM_MIRROR(0x80000) AM_RAMBANK("bank1") AM_BASE_SIZE_MEMBER(amiga_state, m_chip_ram, m_chip_ram_size)
98   AM_RANGE(0xbfd000, 0xbfefff) AM_READWRITE(amiga_cia_r, amiga_cia_w)
99   AM_RANGE(0xc00000, 0xc7ffff) AM_RAM /* slow-mem */
100   AM_RANGE(0xc80000, 0xcfffff) AM_READWRITE(amiga_custom_r, amiga_custom_w)   /* see Note 1 above */
101   AM_RANGE(0xdf0000, 0xdfffff) AM_READWRITE(amiga_custom_r, amiga_custom_w) AM_BASE_MEMBER(amiga_state, m_custom_regs)   /* Custom Chips */
102   AM_RANGE(0xe80000, 0xe8ffff) AM_READWRITE(amiga_autoconfig_r, amiga_autoconfig_w)
103   AM_RANGE(0xf80000, 0xffffff) AM_ROM AM_REGION("user1", 0)   /* System ROM - mirror */
104ADDRESS_MAP_END
105
106static ADDRESS_MAP_START(keyboard_mem, AS_PROGRAM, 8)
107   AM_RANGE(0x0000, 0x003f) AM_RAM /* internal user ram */
108   AM_RANGE(0x0040, 0x007f) AM_NOP /* unassigned */
109   AM_RANGE(0x0080, 0x0080) AM_NOP /* port a */
110   AM_RANGE(0x0081, 0x0081) AM_NOP /* port b */
111   AM_RANGE(0x0082, 0x0082) AM_NOP /* port c */
112   AM_RANGE(0x0083, 0x0083) AM_NOP /* port d */
113   AM_RANGE(0x0084, 0x0085) AM_NOP /* latch */
114   AM_RANGE(0x0086, 0x0087) AM_NOP /* count */
115   AM_RANGE(0x0088, 0x0088) AM_NOP /* upper latch & transfer latch to counter */
116   AM_RANGE(0x0089, 0x0089) AM_NOP /* clear pa0 pos edge detected */
117   AM_RANGE(0x008a, 0x008a) AM_NOP /* clear pa1 neg edge detected */
118   AM_RANGE(0x008b, 0x008e) AM_NOP /* unassigned */
119   AM_RANGE(0x008f, 0x008f) AM_NOP /* control register */
120   AM_RANGE(0x0090, 0x07ff) AM_NOP /* unassigned */
121   AM_RANGE(0x0800, 0x0fff) AM_ROM AM_REGION("keyboard", 0) /* internal mask rom */
122ADDRESS_MAP_END
123
124
125/*
126 * CDTV memory map (source: http://www.l8r.net/technical/cdtv-technical.html)
127 *
128 * 000000-0FFFFF Chip memory
129 * 100000-1FFFFF Space for extra chip memory (Megachip)
130 * 200000-9FFFFF Space for AutoConfig memory
131 * A00000-BFFFFF CIA chips
132 * C00000-C7FFFF Space for slow-fast memory
133 * C80000-DBFFFF Space
134 * DC0000-DC7FFF Power backed-up real time clock
135 * DC8000-DC87FF Non-volatile RAM
136 * DC8800-DCFFFF Space in non-volatile RAM decoded area
137 * DD0000-DEFFFF Space
138 * DF0000-DFFFFF Custom chips
139 * E00000-E7FFFF Memory card address space for front panel memory card
140 * E80000-E8FFFF AutoConfig configuration space
141 * E90000-E9FFFF First AutoConfig device, used by DMAC
142 * EA0000-EFFFFF Space for other AutoConfig devices
143 * F00000-F3FFFF CDTV ROM
144 * F40000-F7FFFF Space in CDTV ROM decoded area
145 * F80000-FBFFFF Space in Kickstart ROM decoded area (used by Kickstart 2)
146 * FC0000-FFFFFF Kickstart ROM
147 *
148 */
149
150static ADDRESS_MAP_START(cdtv_mem, AS_PROGRAM, 16)
151   AM_RANGE(0x000000, 0x0fffff) AM_RAMBANK("bank1") AM_BASE_SIZE_MEMBER(amiga_state, m_chip_ram, m_chip_ram_size)
152   AM_RANGE(0xbfd000, 0xbfefff) AM_READWRITE(amiga_cia_r, amiga_cia_w)
153   AM_RANGE(0xdc0000, 0xdc003f) AM_READWRITE(amiga_clock_r, amiga_clock_w)
154   AM_RANGE(0xdc8000, 0xdc87ff) AM_RAM AM_SHARE("nvram")
155   AM_RANGE(0xdf0000, 0xdfffff) AM_READWRITE(amiga_custom_r, amiga_custom_w) AM_BASE_MEMBER(amiga_state, m_custom_regs)   /* Custom Chips */
156   AM_RANGE(0xe80000, 0xe8ffff) AM_READWRITE(amiga_autoconfig_r, amiga_autoconfig_w)
157   AM_RANGE(0xf00000, 0xffffff) AM_ROM AM_REGION("user1", 0)   /* CDTV & System ROM */
158ADDRESS_MAP_END
159
160static ADDRESS_MAP_START(cdtv_rcmcu_mem, AS_PROGRAM, 8)
161   AM_RANGE(0x0000, 0x003f) AM_RAM /* internal user ram */
162   AM_RANGE(0x0040, 0x007f) AM_NOP /* unassigned */
163   AM_RANGE(0x0080, 0x0080) AM_NOP /* port a */
164   AM_RANGE(0x0081, 0x0081) AM_NOP /* port b */
165   AM_RANGE(0x0082, 0x0082) AM_NOP /* port c */
166   AM_RANGE(0x0083, 0x0083) AM_NOP /* port d */
167   AM_RANGE(0x0084, 0x0085) AM_NOP /* latch */
168   AM_RANGE(0x0086, 0x0087) AM_NOP /* count */
169   AM_RANGE(0x0088, 0x0088) AM_NOP /* upper latch & transfer latch to counter */
170   AM_RANGE(0x0089, 0x0089) AM_NOP /* clear pa0 pos edge detected */
171   AM_RANGE(0x008a, 0x008a) AM_NOP /* clear pa1 neg edge detected */
172   AM_RANGE(0x008b, 0x008e) AM_NOP /* unassigned */
173   AM_RANGE(0x008f, 0x008f) AM_NOP /* control register */
174   AM_RANGE(0x0090, 0x07ff) AM_NOP /* unassigned */
175   AM_RANGE(0x0800, 0x0fff) AM_ROM AM_REGION("rcmcu", 0) /* internal mask rom */
176ADDRESS_MAP_END
177
178static ADDRESS_MAP_START(a1000_mem, AS_PROGRAM, 16)
179   AM_RANGE(0x000000, 0x03ffff) AM_MIRROR(0xc0000) AM_RAMBANK("bank1") AM_BASE_SIZE_MEMBER(amiga_state, m_chip_ram, m_chip_ram_size)
180   AM_RANGE(0xbfd000, 0xbfefff) AM_READWRITE(amiga_cia_r, amiga_cia_w)
181   AM_RANGE(0xc00000, 0xc3ffff) AM_READWRITE(amiga_custom_r, amiga_custom_w) /* See Note 1 above */
182   AM_RANGE(0xdf0000, 0xdfffff) AM_READWRITE(amiga_custom_r, amiga_custom_w) AM_BASE_MEMBER(amiga_state, m_custom_regs)   /* Custom Chips */
183   AM_RANGE(0xe80000, 0xe8ffff) AM_READWRITE(amiga_autoconfig_r, amiga_autoconfig_w)
184   AM_RANGE(0xf80000, 0xfbffff) AM_ROM AM_REGION("user1", 0)   /* Bootstrap ROM */
185   AM_RANGE(0xfc0000, 0xffffff) AM_RAMBANK("bank2")   /* Writable Control Store RAM */
186ADDRESS_MAP_END
187
188
189/***************************************************************************
190  Inputs
191***************************************************************************/
192
193static INPUT_PORTS_START( amiga_common )
194   PORT_START("input")
195   PORT_CONFNAME( 0x20, 0x00, "Input Port 0 Device")
196   PORT_CONFSETTING( 0x00, "Mouse" )
197   PORT_CONFSETTING( 0x20, DEF_STR(Joystick) )
198   PORT_CONFNAME( 0x10, 0x10, "Input Port 1 Device")
199   PORT_CONFSETTING( 0x00, "Mouse" )
200   PORT_CONFSETTING( 0x10, DEF_STR(Joystick) )
201
202   PORT_START("CIA0PORTA")
203   PORT_BIT( 0x3f, IP_ACTIVE_LOW, IPT_SPECIAL )
204   PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_PLAYER(1)
205   PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_PLAYER(2)
206
207   PORT_START("JOY0DAT")
208   PORT_BIT( 0x0303, IP_ACTIVE_HIGH, IPT_SPECIAL ) PORT_CUSTOM(amiga_joystick_convert, "P1JOY")
209   PORT_BIT( 0xfcfc, IP_ACTIVE_HIGH, IPT_UNUSED )
210
211   PORT_START("JOY1DAT")
212   PORT_BIT( 0x0303, IP_ACTIVE_HIGH, IPT_SPECIAL ) PORT_CUSTOM(amiga_joystick_convert, "P2JOY")
213   PORT_BIT( 0xfcfc, IP_ACTIVE_HIGH, IPT_UNUSED )
214
215   PORT_START("POTGO")
216   PORT_BIT( 0x0100, IP_ACTIVE_LOW, IPT_UNUSED )
217   PORT_BIT( 0x0400, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_PLAYER(1)
218   PORT_BIT( 0x1000, IP_ACTIVE_LOW, IPT_UNUSED )
219   PORT_BIT( 0x4000, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_PLAYER(2)
220   PORT_BIT( 0xaaff, IP_ACTIVE_HIGH, IPT_UNUSED )
221
222   PORT_START("P1JOY")
223   PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_JOYSTICK_UP ) PORT_PLAYER(1)
224   PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_JOYSTICK_DOWN ) PORT_PLAYER(1)
225   PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_JOYSTICK_LEFT ) PORT_PLAYER(1)
226   PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_JOYSTICK_RIGHT ) PORT_PLAYER(1)
227
228   PORT_START("P2JOY")
229   PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_JOYSTICK_UP ) PORT_PLAYER(2)
230   PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_JOYSTICK_DOWN ) PORT_PLAYER(2)
231   PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_JOYSTICK_LEFT ) PORT_PLAYER(2)
232   PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_JOYSTICK_RIGHT ) PORT_PLAYER(2)
233
234   PORT_START("P0MOUSEX")
235   PORT_BIT( 0xff, 0x00, IPT_MOUSE_X) PORT_SENSITIVITY(100) PORT_KEYDELTA(5) PORT_MINMAX(0, 255) PORT_PLAYER(1)
236
237   PORT_START("P0MOUSEY")
238   PORT_BIT( 0xff, 0x00, IPT_MOUSE_Y) PORT_SENSITIVITY(100) PORT_KEYDELTA(5) PORT_MINMAX(0, 255) PORT_PLAYER(1)
239
240   PORT_START("P1MOUSEX")
241   PORT_BIT( 0xff, 0x00, IPT_MOUSE_X) PORT_SENSITIVITY(100) PORT_KEYDELTA(5) PORT_MINMAX(0, 255) PORT_PLAYER(2)
242
243   PORT_START("P1MOUSEY")
244   PORT_BIT( 0xff, 0x00, IPT_MOUSE_Y) PORT_SENSITIVITY(100) PORT_KEYDELTA(5) PORT_MINMAX(0, 255) PORT_PLAYER(2)
245
246   PORT_INCLUDE( amiga_us_keyboard )
247
248INPUT_PORTS_END
249
250
251static INPUT_PORTS_START( amiga )
252   PORT_START("hardware")
253   PORT_CONFNAME( 0x08, 0x08, "Battery backed-up RTC")
254   PORT_CONFSETTING( 0x00, "Not Installed" )
255   PORT_CONFSETTING( 0x08, "Installed" )
256
257   PORT_INCLUDE( amiga_common )
258INPUT_PORTS_END
259
260
261/* TODO: Support for the CDTV remote control */
262static INPUT_PORTS_START( cdtv )
263   PORT_INCLUDE( amiga_common )
264INPUT_PORTS_END
265
266/***************************************************************************
267  Machine drivers
268***************************************************************************/
269
270static MACHINE_START( cdtv )
271{
272   MACHINE_START_CALL( amigacd );
273}
274
275
276static MACHINE_RESET( cdtv )
277{
278   MACHINE_RESET_CALL( amiga );
279
280   /* initialize the cdrom controller */
281   MACHINE_RESET_CALL( amigacd );
282}
283
284static const mos6526_interface cia_0_ntsc_intf =
285{
286   60,                                          /* tod_clock */
287   DEVCB_LINE(amiga_cia_0_irq),                     /* irq_func */
288   DEVCB_DEVICE_LINE("centronics", centronics_strobe_w),   /* pc_func */
289   DEVCB_NULL,
290   DEVCB_NULL,
291   DEVCB_HANDLER(amiga_cia_0_portA_r),
292   DEVCB_HANDLER(amiga_cia_0_portA_w),                  /* port A */
293   DEVCB_NULL,
294   DEVCB_DEVICE_HANDLER("centronics", centronics_data_w)   /* port B */
295};
296
297static const mos6526_interface cia_0_pal_intf =
298{
299   50,                                          /* tod_clock */
300   DEVCB_LINE(amiga_cia_0_irq),                     /* irq_func */
301   DEVCB_DEVICE_LINE("centronics", centronics_strobe_w),   /* pc_func */
302   DEVCB_NULL,
303   DEVCB_NULL,
304   DEVCB_HANDLER(amiga_cia_0_portA_r),
305   DEVCB_HANDLER(amiga_cia_0_portA_w),                  /* port A */
306   DEVCB_NULL,
307   DEVCB_DEVICE_HANDLER("centronics", centronics_data_w)   /* port B */
308};
309
310static const mos6526_interface cia_1_intf =
311{
312   0,                                          /* tod_clock */
313   DEVCB_LINE(amiga_cia_1_irq),                     /* irq_func */
314   DEVCB_NULL,                                    /* pc_func */
315   DEVCB_NULL,
316   DEVCB_NULL,
317   DEVCB_DEVICE_HANDLER("centronics", amiga_cia_1_porta_r),
318   DEVCB_NULL,                                    /* port A */
319   DEVCB_NULL,
320   DEVCB_DEVICE_HANDLER("fdc", amiga_fdc_control_w)      /* port B */
321};
322
323static const mos6526_interface cia_0_cdtv_intf =
324{
325   0,                                          /* tod_clock */
326   DEVCB_LINE(amiga_cia_0_irq),                     /* irq_func */
327   DEVCB_DEVICE_LINE("centronics", centronics_strobe_w),   /* pc_func */
328   DEVCB_NULL,
329   DEVCB_NULL,
330   DEVCB_HANDLER(amiga_cia_0_cdtv_portA_r),
331   DEVCB_HANDLER(amiga_cia_0_portA_w),                  /* port A */
332   DEVCB_NULL,
333   DEVCB_DEVICE_HANDLER("centronics", centronics_data_w)   /* port B */
334};
335
336static const mos6526_interface cia_1_cdtv_intf =
337{
338   0,                                          /* tod_clock */
339   DEVCB_LINE(amiga_cia_1_irq),                     /* irq_func */
340   DEVCB_NULL,   /* pc_func */
341   DEVCB_NULL,
342   DEVCB_NULL,
343   DEVCB_DEVICE_HANDLER("centronics", amiga_cia_1_porta_r),
344   DEVCB_NULL,                                    /* port A */
345   DEVCB_NULL,
346   DEVCB_NULL                                    /* port B */
347};
348
349static const tpi6525_interface cdtv_tpi_intf =
350{
351   DEVCB_LINE(amigacd_tpi6525_irq),
352   DEVCB_NULL,
353   DEVCB_NULL,
354   DEVCB_NULL,
355   DEVCB_HANDLER(amigacd_tpi6525_portb_w),
356   DEVCB_HANDLER(amigacd_tpi6525_portc_r),
357   DEVCB_NULL,
358   DEVCB_NULL,
359   DEVCB_NULL
360};
361
362
363static MACHINE_CONFIG_FRAGMENT( amiga_cartslot )
364   MCFG_CARTSLOT_ADD("cart")
365   MCFG_CARTSLOT_EXTENSION_LIST("rom,bin")
366   MCFG_CARTSLOT_NOT_MANDATORY
367MACHINE_CONFIG_END
368
369static MACHINE_CONFIG_START( ntsc, amiga_state )
370   /* basic machine hardware */
371   MCFG_CPU_ADD("maincpu", M68000, AMIGA_68000_NTSC_CLOCK)
372   MCFG_CPU_PROGRAM_MAP(amiga_mem)
373
374   MCFG_CPU_ADD("keyboard", M6502, XTAL_1MHz) /* 1 MHz? */
375   MCFG_CPU_PROGRAM_MAP(keyboard_mem)
376
377   MCFG_SCREEN_ADD("screen", RASTER)
378   MCFG_SCREEN_REFRESH_RATE(59.997)
379   MCFG_SCREEN_VBLANK_TIME(ATTOSECONDS_IN_USEC(0))
380
381   MCFG_MACHINE_RESET( amiga )
382
383    /* video hardware */
384   MCFG_VIDEO_ATTRIBUTES(VIDEO_UPDATE_BEFORE_VBLANK)
385   MCFG_SCREEN_FORMAT(BITMAP_FORMAT_INDEXED16)
386   MCFG_SCREEN_SIZE(228*4, 262)
387   MCFG_SCREEN_VISIBLE_AREA(214, (228*4)-1, 34, 262-1)
388   MCFG_SCREEN_UPDATE(amiga)
389
390   MCFG_PALETTE_LENGTH(4096)
391   MCFG_PALETTE_INIT( amiga )
392
393   MCFG_VIDEO_START(amiga)
394
395   /* devices */
396   MCFG_MSM6242_ADD("rtc")
397   MCFG_CENTRONICS_ADD("centronics", amiga_centronics_config)
398
399   /* sound hardware */
400   MCFG_SPEAKER_STANDARD_STEREO("lspeaker", "rspeaker")
401
402   MCFG_SOUND_ADD("amiga", AMIGA, 3579545)
403   MCFG_SOUND_ROUTE(0, "lspeaker", 0.50)
404   MCFG_SOUND_ROUTE(1, "rspeaker", 0.50)
405   MCFG_SOUND_ROUTE(2, "rspeaker", 0.50)
406   MCFG_SOUND_ROUTE(3, "lspeaker", 0.50)
407
408   /* cia */
409   MCFG_MOS8520_ADD("cia_0", AMIGA_68000_NTSC_CLOCK / 10, cia_0_ntsc_intf)
410   MCFG_MOS8520_ADD("cia_1", AMIGA_68000_NTSC_CLOCK, cia_1_intf)
411
412   MCFG_AMIGA_FDC_ADD("fdc")
413MACHINE_CONFIG_END
414
415static MACHINE_CONFIG_DERIVED( a1000n, ntsc )
416   MCFG_CPU_MODIFY("maincpu")
417   MCFG_CPU_PROGRAM_MAP(a1000_mem)
418MACHINE_CONFIG_END
419
420static MACHINE_CONFIG_DERIVED( a500n, ntsc )
421   MCFG_FRAGMENT_ADD(amiga_cartslot)
422MACHINE_CONFIG_END
423
424
425static MACHINE_CONFIG_DERIVED( cdtv, ntsc )
426   MCFG_CPU_REPLACE("maincpu", M68000, CDTV_CLOCK_X1 / 4)
427   MCFG_CPU_PROGRAM_MAP(cdtv_mem)
428
429   MCFG_DEVICE_REMOVE("keyboard")
430
431   MCFG_CPU_ADD("rcmcu", M6502, XTAL_1MHz) /* 1 MHz? */
432   MCFG_CPU_PROGRAM_MAP(cdtv_rcmcu_mem)
433   MCFG_DEVICE_DISABLE()
434
435//  MCFG_CPU_ADD("lcd", LC6554, XTAL_4MHz) /* 4 MHz? */
436//  MCFG_CPU_PROGRAM_MAP(cdtv_lcd_mem)
437
438   MCFG_MACHINE_START( cdtv )
439   MCFG_MACHINE_RESET( cdtv )
440
441   MCFG_NVRAM_ADD_0FILL("nvram")
442
443   MCFG_SOUND_ADD( "cdda", CDDA, 0 )
444   MCFG_SOUND_ROUTE( 0, "lspeaker", 1.0 )
445   MCFG_SOUND_ROUTE( 1, "rspeaker", 1.0 )
446
447   /* cdrom */
448   MCFG_CDROM_ADD( "cdrom" )
449   MCFG_CDROM_INTERFACE("cdrom")
450   MCFG_SOFTWARE_LIST_ADD("cd_list", "cdtv")
451
452   MCFG_TPI6525_ADD("tpi6525", cdtv_tpi_intf)
453
454   /* cia */
455   MCFG_DEVICE_REMOVE("cia_0")
456   MCFG_DEVICE_REMOVE("cia_1")
457   MCFG_MOS8520_ADD("cia_0", CDTV_CLOCK_X1 / 40, cia_0_cdtv_intf)
458   MCFG_MOS8520_ADD("cia_1", CDTV_CLOCK_X1 / 4, cia_1_cdtv_intf)
459MACHINE_CONFIG_END
460
461
462static MACHINE_CONFIG_DERIVED( pal, ntsc )
463
464   /* adjust for PAL specs */
465   MCFG_CPU_MODIFY("maincpu")
466   MCFG_CPU_CLOCK( AMIGA_68000_PAL_CLOCK)
467
468   MCFG_SCREEN_MODIFY("screen")
469   MCFG_SCREEN_REFRESH_RATE(50)
470   MCFG_SCREEN_SIZE(228*4, 312)
471   MCFG_SCREEN_VISIBLE_AREA(214, (228*4)-1, 34, 312-1)
472
473   /* cia */
474   MCFG_DEVICE_REMOVE("cia_0")
475   MCFG_MOS8520_ADD("cia_0", AMIGA_68000_PAL_CLOCK / 10, cia_0_pal_intf)
476MACHINE_CONFIG_END
477
478static MACHINE_CONFIG_DERIVED( a500p, pal )
479   MCFG_FRAGMENT_ADD(amiga_cartslot)
480MACHINE_CONFIG_END
481
482static MACHINE_CONFIG_DERIVED( a1000p, pal )
483   MCFG_CPU_MODIFY("maincpu")
484   MCFG_CPU_PROGRAM_MAP(a1000_mem)
485MACHINE_CONFIG_END
486
487/***************************************************************************
488
489  Amiga specific stuff
490
491***************************************************************************/
492
493
494static READ8_DEVICE_HANDLER( amiga_cia_0_portA_r )
495{
496   UINT8 ret = input_port_read(device->machine(), "CIA0PORTA") & 0xc0;   /* Gameport 1 and 0 buttons */
497   ret |= amiga_fdc_status_r(device->machine().device("fdc"));
498   return ret;
499}
500
501
502static READ8_DEVICE_HANDLER( amiga_cia_0_cdtv_portA_r )
503{
504   return input_port_read(device->machine(), "CIA0PORTA") & 0xc0;   /* Gameport 1 and 0 buttons */
505}
506
507
508static WRITE8_DEVICE_HANDLER( amiga_cia_0_portA_w )
509{
510   amiga_state *state = device->machine().driver_data<amiga_state>();
511   /* switch banks as appropriate */
512   memory_set_bank(device->machine(), "bank1", data & 1);
513
514   /* swap the write handlers between ROM and bank 1 based on the bit */
515   if ((data & 1) == 0) {
516      UINT32 mirror_mask = state->m_chip_ram_size;
517
518      while( (mirror_mask<<1) < 0x100000 ) {
519         mirror_mask |= ( mirror_mask << 1 );
520      }
521
522      /* overlay disabled, map RAM on 0x000000 */
523      device->machine().device("maincpu")->memory().space(AS_PROGRAM)->install_write_bank(0x000000, state->m_chip_ram_size - 1, 0, mirror_mask, "bank1");
524
525      /* if there is a cart region, check for cart overlay */
526      if (device->machine().region("user2")->base() != NULL)
527         amiga_cart_check_overlay(device->machine());
528   }
529   else
530      /* overlay enabled, map Amiga system ROM on 0x000000 */
531      device->machine().device("maincpu")->memory().space(AS_PROGRAM)->unmap_write(0x000000, state->m_chip_ram_size - 1);
532
533   set_led_status( device->machine(), 0, ( data & 2 ) ? 0 : 1 ); /* bit 2 = Power Led on Amiga */
534   output_set_value("power_led", ( data & 2 ) ? 0 : 1);
535}
536
537static UINT16 amiga_read_joy0dat(running_machine &machine)
538{
539   if ( input_port_read(machine, "input") & 0x20 ) {
540      /* Joystick */
541      return input_port_read_safe(machine, "JOY0DAT", 0xffff);
542   } else {
543      /* Mouse */
544      int input;
545      input  = ( input_port_read(machine, "P0MOUSEX") & 0xff );
546      input |= ( input_port_read(machine, "P0MOUSEY") & 0xff ) << 8;
547      return input;
548   }
549}
550
551static UINT16 amiga_read_joy1dat(running_machine &machine)
552{
553   if ( input_port_read(machine, "input") & 0x10 ) {
554      /* Joystick */
555      return input_port_read_safe(machine, "JOY1DAT", 0xffff);
556   } else {
557      /* Mouse */
558      int input;
559      input  = ( input_port_read(machine, "P1MOUSEX") & 0xff );
560      input |= ( input_port_read(machine, "P1MOUSEY") & 0xff ) << 8;
561      return input;
562   }
563}
564
565static UINT16 amiga_read_dskbytr(running_machine &machine)
566{
567   return amiga_fdc_get_byte(machine.device("fdc"));
568}
569
570static void amiga_write_dsklen(running_machine &machine, UINT16 data)
571{
572   amiga_state *state = machine.driver_data<amiga_state>();
573   if ( data & 0x8000 ) {
574      if ( CUSTOM_REG(REG_DSKLEN) & 0x8000 )
575         amiga_fdc_setup_dma(machine.device("fdc"));
576   }
577}
578
579
580static void amiga_reset(running_machine &machine)
581{
582   if (input_port_read(machine, "hardware") & 0x08)
583   {
584      /* Install RTC */
585      machine.device("maincpu")->memory().space(AS_PROGRAM)->install_legacy_readwrite_handler(0xdc0000, 0xdc003f, FUNC(amiga_clock_r), FUNC(amiga_clock_w));
586   }
587   else
588   {
589      /* No RTC support */
590      machine.device("maincpu")->memory().space(AS_PROGRAM)->unmap_readwrite(0xdc0000, 0xdc003f);
591   }
592}
593
594static DRIVER_INIT( amiga )
595{
596   amiga_state *state = machine.driver_data<amiga_state>();
597   static const amiga_machine_interface amiga_intf =
598   {
599      ANGUS_CHIP_RAM_MASK,
600      amiga_read_joy0dat,   amiga_read_joy1dat,  /* joy0dat_r & joy1dat_r */
601      NULL,                                    /* potgo_w */
602      amiga_read_dskbytr,   amiga_write_dsklen,  /* dskbytr_r & dsklen_w */
603      NULL,                                    /* serdat_w */
604      NULL,                                    /* scanline0_callback */
605      amiga_reset,                             /* reset_callback */
606      amiga_cart_nmi,                          /* nmi_callback */
607      0                                        /* flags */
608   };
609
610   amiga_machine_config(machine, &amiga_intf);
611
612   /* set up memory */
613   memory_configure_bank(machine, "bank1", 0, 1, state->m_chip_ram, 0);
614   memory_configure_bank(machine, "bank1", 1, 1, machine.region("user1")->base(), 0);
615
616   /* initialize cartridge (if present) */
617   amiga_cart_init(machine);
618
619   /* initialize keyboard */
620   amigakbd_init(machine);
621}
622
623#ifdef UNUSED_FUNCTION
624static DRIVER_INIT( amiga_ecs )
625{
626   static const amiga_machine_interface amiga_intf =
627   {
628      ECS_CHIP_RAM_MASK,
629      amiga_cia_0_portA_r, NULL,               /* CIA0 port A & B read */
630      amiga_cia_0_portA_w, NULL,               /* CIA0 port A & B write */
631      NULL, NULL,                              /* CIA1 port A & B read */
632      NULL, amiga_fdc_control_w,               /* CIA1 port A & B write */
633      amiga_read_joy0dat,   amiga_read_joy1dat,  /* joy0dat_r & joy1dat_r */
634      NULL,                                    /* potgo_w */
635      amiga_read_dskbytr,   amiga_write_dsklen,  /* dskbytr_r & dsklen_w */
636      NULL,                                    /* serdat_w */
637      NULL,                                    /* scanline0_callback */
638      amiga_reset,                             /* reset_callback */
639      amiga_cart_nmi,                          /* nmi_callback */
640      0                                        /* flags */
641   };
642
643   amiga_machine_config(machine, &amiga_intf);
644
645   /* set up memory */
646   memory_configure_bank(1, 0, 1, state->m_chip_ram, 0);
647   memory_configure_bank(1, 1, 1, machine.region("user1")->base(), 0);
648
649   /* initialize Action Replay (if present) */
650   amiga_cart_init(machine);
651
652   /* initialize keyboard */
653   amigakbd_init(machine);
654}
655#endif
656
657static DRIVER_INIT( cdtv )
658{
659   amiga_state *state = machine.driver_data<amiga_state>();
660   static const amiga_machine_interface amiga_intf =
661   {
662      ECS_CHIP_RAM_MASK,
663      amiga_read_joy0dat,   amiga_read_joy1dat,  /* joy0dat_r & joy1dat_r */
664      NULL,                                    /* potgo_w */
665      amiga_read_dskbytr,   amiga_write_dsklen,  /* dskbytr_r & dsklen_w */
666      NULL,                                    /* serdat_w */
667      NULL,                                    /* scanline0_callback */
668      NULL,                                    /* reset_callback */
669      NULL,                                    /* nmi_callback */
670      0                                        /* flags */
671   };
672
673   amiga_machine_config(machine, &amiga_intf);
674
675   /* set up memory */
676   memory_configure_bank(machine, "bank1", 0, 1, state->m_chip_ram, 0);
677   memory_configure_bank(machine, "bank1", 1, 1, machine.region("user1")->base(), 0);
678
679   /* initialize keyboard - in cdtv we can use a standard Amiga keyboard*/
680   amigakbd_init(machine);
681}
682
683
684/***************************************************************************
685    ROM DEFINITIONS
686***************************************************************************/
687
688ROM_START( a500n )
689   ROM_REGION16_BE(0x080000, "user1", 0)
690   ROM_DEFAULT_BIOS("kick13")
691   ROM_SYSTEM_BIOS(0, "kick12",  "Kickstart 1.2 (33.180)")
692   ROMX_LOAD("315093-01.u6", 0x000000, 0x040000, CRC(a6ce1636) SHA1(11f9e62cf299f72184835b7b2a70a16333fc0d88), ROM_GROUPWORD | ROM_BIOS(1))
693   ROM_SYSTEM_BIOS(1, "kick13",  "Kickstart 1.3 (34.5)")
694   ROMX_LOAD("315093-02.u6", 0x000000, 0x040000, CRC(c4f0f55f) SHA1(891e9a547772fe0c6c19b610baf8bc4ea7fcb785), ROM_GROUPWORD | ROM_BIOS(2))
695   ROM_COPY("user1", 0x000000, 0x040000, 0x040000)
696   ROM_SYSTEM_BIOS(2, "kick204", "Kickstart 2.04 (37.175)")
697   ROMX_LOAD("390979-01.u6", 0x000000, 0x080000, CRC(c3bdb240) SHA1(c5839f5cb98a7a8947065c3ed2f14f5f42e334a1), ROM_GROUPWORD | ROM_BIOS(3))   /* identical to 363968.01 */
698   ROM_SYSTEM_BIOS(3, "kick31",  "Kickstart 3.1 (40.63)")
699   ROMX_LOAD("kick40063.u6", 0x000000, 0x080000, CRC(fc24ae0d) SHA1(3b7f1493b27e212830f989f26ca76c02049f09ca), ROM_GROUPWORD | ROM_BIOS(4))   /* part number? */
700
701   /* action replay cartridge */
702   ROM_REGION16_BE(0x080000, "user2", ROMREGION_ERASEFF )
703   ROM_CART_LOAD("cart", 0x0000, 0x080000, ROM_NOMIRROR | ROM_OPTIONAL)
704
705   /* keyboard controller, mos 6500/1 mcu */
706   ROM_REGION(0x800, "keyboard", 0)
707   ROM_LOAD("328191-02.ic1", 0x000, 0x800, NO_DUMP)
708ROM_END
709
710#define rom_a500p    rom_a500n
711
712
713ROM_START( a1000n )
714   ROM_REGION16_BE(0x080000, "user1", 0)
715   ROM_LOAD16_BYTE("252179-01.u5n", 0x000000, 0x001000, CRC(42553bc4) SHA1(8855a97f7a44e3f62d1c88d938fee1f4c606af5b))
716   ROM_LOAD16_BYTE("252180-01.u5p", 0x000001, 0x001000, CRC(8e5b9a37) SHA1(d10f1564b99f5ffe108fa042362e877f569de2c3))
717
718   /* keyboard controller, mos 6500/1 mcu */
719   ROM_REGION(0x800, "keyboard", 0)
720   ROM_LOAD("328191-01.bin", 0x000, 0x800, NO_DUMP)
721ROM_END
722
723#define rom_a1000p    rom_a1000n
724
725
726ROM_START( cdtv )
727   ROM_REGION16_BE(0x100000, "user1", 0)
728   ROM_LOAD16_BYTE("391008-01.u34", 0x000000, 0x020000, CRC(791cb14b) SHA1(277a1778924496353ffe56be68063d2a334360e4))
729   ROM_LOAD16_BYTE("391009-01.u35", 0x000001, 0x020000, CRC(accbbc2e) SHA1(41b06d1679c6e6933c3378b7626025f7641ebc5c))
730   ROM_COPY("user1", 0x000000, 0x040000, 0x040000)
731   ROMX_LOAD(      "315093-02.u13", 0x080000, 0x040000, CRC(c4f0f55f) SHA1(891e9a547772fe0c6c19b610baf8bc4ea7fcb785), ROM_GROUPWORD)
732   ROM_COPY("user1", 0x080000, 0x0c0000, 0x040000)
733
734   /* remote control input converter, mos 6500/1 mcu */
735   ROM_REGION(0x800, "rcmcu", 0)
736   ROM_LOAD("252609-02.u75", 0x000, 0x800, NO_DUMP)
737
738   /* lcd controller, sanyo lc6554h */
739   ROM_REGION(0x1000, "lcd", 0)
740   ROM_LOAD("252608-01.u62", 0x000, 0x1000, NO_DUMP)
741ROM_END
742
743/***************************************************************************
744    GAME DRIVERS
745***************************************************************************/
746
747/*    YEAR  NAME    PARENT  COMPAT  MACHINE INPUT   INIT    COMPANY                             FULLNAME                 FLAGS */
748COMP( 1985, a1000n, 0,      0,      a1000n, amiga,  amiga,  "Commodore Business Machines",  "Amiga 1000 (NTSC)",     GAME_IMPERFECT_GRAPHICS )
749COMP( 1985, a1000p, a1000n, 0,      a1000p, amiga,  amiga,  "Commodore Business Machines",  "Amiga 1000 (PAL)",      GAME_IMPERFECT_GRAPHICS )
750COMP( 1987, a500n,  0,      0,      a500n,  amiga,  amiga,  "Commodore Business Machines",  "Amiga 500 (NTSC, OCS)", GAME_IMPERFECT_GRAPHICS )
751COMP( 1987, a500p,  a500n,  0,      a500p,  amiga,  amiga,  "Commodore Business Machines",  "Amiga 500 (PAL, OCS)",  GAME_IMPERFECT_GRAPHICS )
752COMP( 1991, cdtv,   0,      0,      cdtv,   cdtv,   cdtv,   "Commodore Business Machines",  "CDTV (NTSC)",           GAME_IMPERFECT_GRAPHICS )
src/mess/drivers/a7000.c
r0r11532
1/***************************************************************************
2
3    Acorn Archimedes 7000/7000+
4
5    preliminary driver by Angelo Salese,
6    based on work by Tomasz Slanina and Tom Walker
7
8    ???
9    bp (0382827C) (second trigger)
10    do R13 = SR13
11
12****************************************************************************/
13
14#include "emu.h"
15#include "cpu/arm7/arm7.h"
16#include "cpu/arm7/arm7core.h"
17
18
19class a7000_state : public driver_device
20{
21public:
22   a7000_state(const machine_config &mconfig, device_type type, const char *tag)
23      : driver_device(mconfig, type, tag) { }
24
25   UINT8 m_vidc20_pal_index;
26   UINT16 m_vidc20_horz_reg[0x10];
27   UINT16 m_vidc20_vert_reg[0x10];
28   UINT8 m_vidc20_bpp_mode;
29   emu_timer *m_flyback_timer;
30   UINT16 m_timer_in[2];
31   UINT16 m_timer_out[2];
32   int m_timer_counter[2];
33   emu_timer *m_IOMD_timer[2];
34   UINT8 m_IRQ_status_A;
35   UINT8 m_IRQ_mask_A;
36   UINT8 m_IOMD_IO_ctrl;
37   UINT8 m_IOMD_keyb_ctrl;
38   UINT16 m_io_id;
39   UINT8 m_viddma_status;
40   UINT32 m_viddma_addr_start;
41   UINT32 m_viddma_addr_end;
42   UINT8 m_t0readinc;
43   UINT8 m_t1readinc;
44};
45
46
47/*
48 *
49 * VIDC20 chip emulation
50 *
51 */
52
53
54static const char *const vidc20_regnames[] =
55{
56   "Video Palette",               // 0
57   "Video Palette Address",         // 1
58   "RESERVED",                   // 2
59   "LCD offset",                  // 3
60   "Border Colour",               // 4
61   "Cursor Palette Logical Colour 1",   // 5
62   "Cursor Palette Logical Colour 2",   // 6
63   "Cursor Palette Logical Colour 3",   // 7
64   "Horizontal",                  // 8
65   "Vertical",                     // 9
66   "Stereo Image",                  // A
67   "Sound",                     // B
68   "External",                     // C
69   "Frequency Synthesis",            // D
70   "Control",                     // E
71   "Data Control"                  // F
72};
73
74static const char *const vidc20_horz_regnames[] =
75{
76   "Horizontal Cycle",             // 0x80 HCR
77   "Horizontal Sync Width",         // 0x81 HSWR
78   "Horizontal Border Start",         // 0x82 HBSR
79   "Horizontal Display Start",         // 0x83 HDSR
80   "Horizontal Display End",         // 0x84 HDER
81   "Horizontal Border End",         // 0x85 HBER
82   "Horizontal Cursor Start",         // 0x86 HCSR
83   "Horizontal Interlace",          // 0x87 HIR
84   "Horizontal Counter TEST",         // 0x88
85   "Horizontal <UNDEFINED>",         // 0x89
86   "Horizontal <UNDEFINED>",         // 0x8a
87   "Horizontal <UNDEFINED>",         // 0x8b
88   "Horizontal All TEST",            // 0x8c
89   "Horizontal <UNDEFINED>",         // 0x8d
90   "Horizontal <UNDEFINED>",         // 0x8e
91   "Horizontal <UNDEFINED>"         // 0x8f
92};
93
94#define HCR  0
95#define HSWR 1
96#define HBSR 2
97#define HDSR 3
98#define HDER 4
99#define HBER 5
100#define HCSR 6
101#define HIR  7
102
103static const char *const vidc20_vert_regnames[] =
104{
105   "Vertical Cycle",               // 0x90 VCR
106   "Vertical Sync Width",            // 0x91 VSWR
107   "Vertical Border Start",         // 0x92 VBSR
108   "Vertical Display Start",         // 0x93 VDSR
109   "Vertical Display End",          // 0x94 VDER
110   "Vertical Border End",            // 0x95 VBER
111   "Vertical Cursor Start",         // 0x96 VCSR
112   "Vertical Cursor End",            // 0x97 VCER
113   "Vertical Counter TEST",         // 0x98
114   "Horizontal <UNDEFINED>",         // 0x99
115   "Vertical Counter Increment TEST",   // 0x9a
116   "Horizontal <UNDEFINED>",         // 0x9b
117   "Vertical All TEST",            // 0x9c
118   "Horizontal <UNDEFINED>",         // 0x9d
119   "Horizontal <UNDEFINED>",         // 0x9e
120   "Horizontal <UNDEFINED>"         // 0x9f
121};
122
123#define VCR  0
124#define VSWR 1
125#define VBSR 2
126#define VDSR 3
127#define VDER 4
128#define VBER 5
129#define VCSR 6
130#define VCER 7
131
132static void vidc20_dynamic_screen_change(running_machine &machine)
133{
134   a7000_state *state = machine.driver_data<a7000_state>();
135   /* sanity checks - first pass */
136   /*
137    total cycles + border start/end
138    */
139   if(state->m_vidc20_horz_reg[HCR] && state->m_vidc20_horz_reg[HBSR] && state->m_vidc20_horz_reg[HBER] &&
140      state->m_vidc20_vert_reg[VCR] && state->m_vidc20_vert_reg[VBSR] && state->m_vidc20_vert_reg[VBER])
141   {
142      /* sanity checks - second pass */
143      /*
144        total cycles > border end > border start
145        */
146      if((state->m_vidc20_horz_reg[HCR] > state->m_vidc20_horz_reg[HBER]) &&
147         (state->m_vidc20_horz_reg[HBER] > state->m_vidc20_horz_reg[HBSR]) &&
148         (state->m_vidc20_vert_reg[VCR] > state->m_vidc20_vert_reg[VBER]) &&
149         (state->m_vidc20_vert_reg[VBER] > state->m_vidc20_vert_reg[VBSR]))
150      {
151         /* finally ready to change the resolution */
152         int hblank_period,vblank_period;
153         rectangle visarea = machine.primary_screen->visible_area();
154         hblank_period = (state->m_vidc20_horz_reg[HCR] & 0x3ffc);
155         vblank_period = (state->m_vidc20_vert_reg[VCR] & 0x3fff);
156         /* note that we use the border registers as the visible area */
157         visarea.min_x = (state->m_vidc20_horz_reg[HBSR] & 0x3ffe);
158         visarea.max_x = (state->m_vidc20_horz_reg[HBER] & 0x3ffe)-1;
159         visarea.min_y = (state->m_vidc20_vert_reg[VBSR] & 0x1fff);
160         visarea.max_y = (state->m_vidc20_vert_reg[VBER] & 0x1fff)-1;
161
162         machine.primary_screen->configure(hblank_period, vblank_period, visarea, machine.primary_screen->frame_period().attoseconds );
163         logerror("VIDC20: successfully changed the screen to:\n Display Size = %d x %d\n Border Size %d x %d\n Cycle Period %d x %d\n",
164                    (state->m_vidc20_horz_reg[HDER]-state->m_vidc20_horz_reg[HDSR]),(state->m_vidc20_vert_reg[VDER]-state->m_vidc20_vert_reg[VDSR]),
165                    (state->m_vidc20_horz_reg[HBER]-state->m_vidc20_horz_reg[HBSR]),(state->m_vidc20_vert_reg[VBER]-state->m_vidc20_vert_reg[VBSR]),
166                    hblank_period,vblank_period);
167      }
168   }
169}
170
171static WRITE32_HANDLER( a7000_vidc20_w )
172{
173   a7000_state *state = space->machine().driver_data<a7000_state>();
174   int reg = data >> 28;
175
176   switch(reg)
177   {
178      case 0: // Video Palette
179      {
180         int r,g,b;
181
182         r = (data & 0x0000ff) >> 0;
183         g = (data & 0x00ff00) >> 8;
184         b = (data & 0xff0000) >> 16;
185
186         palette_set_color_rgb(space->machine(),state->m_vidc20_pal_index & 0xff,r,g,b);
187
188         /* auto-increment & wrap-around */
189         state->m_vidc20_pal_index++;
190         state->m_vidc20_pal_index &= 0xff;
191      }
192      break;
193      case 1: // Video Palette Address
194      {
195         // according to RPCEmu, these mustn't be set
196         if (data & 0x0fffff00)
197            return;
198
199         state->m_vidc20_pal_index = data & 0xff;
200      }
201      break;
202
203      case 4: // Border Color
204      {
205         int r,g,b;
206
207         r = (data & 0x0000ff) >> 0;
208         g = (data & 0x00ff00) >> 8;
209         b = (data & 0xff0000) >> 16;
210
211         palette_set_color_rgb(space->machine(),0x100,r,g,b);
212      }
213      break;
214      case 5: // Cursor Palette Logical Colour n
215      case 6:
216      case 7:
217      {
218         int r,g,b;
219         int cursor_index = 0x100 + reg - 4; // 0x101,0x102 and 0x103 (plus 0x100 of above, 2bpp)
220
221         r = (data & 0x0000ff) >> 0;
222         g = (data & 0x00ff00) >> 8;
223         b = (data & 0xff0000) >> 16;
224
225         palette_set_color_rgb(space->machine(),cursor_index,r,g,b);
226      }
227      break;
228      case 8: // Horizontal
229      {
230         int horz_reg;
231
232         horz_reg = (data >> 24) & 0xf;
233         state->m_vidc20_horz_reg[horz_reg] = data & 0x3fff;
234         if(horz_reg == 0 || horz_reg == 2 || horz_reg == 5)
235            vidc20_dynamic_screen_change(space->machine());
236
237         // logerror("VIDC20: %s Register write = %08x (%d)\n",vidc20_horz_regnames[horz_reg],val,val);
238      }
239      break;
240      case 9: // Vertical
241      {
242         int vert_reg;
243
244         vert_reg = (data >> 24) & 0xf;
245         state->m_vidc20_vert_reg[vert_reg] = data & 0x1fff;
246         if(vert_reg == 0 || vert_reg == 2 || vert_reg == 5)
247            vidc20_dynamic_screen_change(space->machine());
248
249         if(vert_reg == 4)
250         {
251            if(state->m_vidc20_vert_reg[VDER] != 0)
252               state->m_flyback_timer->adjust(space->machine().primary_screen->time_until_pos(state->m_vidc20_vert_reg[VDER]));
253            else
254               state->m_flyback_timer->adjust(attotime::never);
255         }
256
257         // logerror("VIDC20: %s Register write = %08x (%d)\n",vidc20_vert_regnames[vert_reg],val,val);
258
259      }
260      break;
261      case 0x0e: // Control
262      {
263         state->m_vidc20_bpp_mode = (data & 0xe0) >> 5;
264      }
265      break;
266      default: logerror("VIDC20: %s Register write = %08x\n",vidc20_regnames[reg],data & 0xfffffff);
267   }
268}
269
270static VIDEO_START( a7000 )
271{
272}
273
274static SCREEN_UPDATE( a7000 )
275{
276   a7000_state *state = screen->machine().driver_data<a7000_state>();
277   int x_size,y_size,x_start,y_start;
278   int x,y,xi;
279   UINT32 count;
280   UINT8 *vram = screen->machine().region("vram")->base();
281
282   bitmap_fill(bitmap, cliprect, screen->machine().pens[0x100]);
283
284   x_size = (state->m_vidc20_horz_reg[HDER]-state->m_vidc20_horz_reg[HDSR]);
285   y_size = (state->m_vidc20_vert_reg[VDER]-state->m_vidc20_vert_reg[VDSR]);
286   x_start = state->m_vidc20_horz_reg[HDSR];
287   y_start = state->m_vidc20_vert_reg[VDSR];
288
289   /* check if display is enabled */
290   if(x_size <= 0 || y_size <= 0)
291      return 0;
292
293//  popmessage("%d",state->m_vidc20_bpp_mode);
294
295   count = 0;
296
297   switch(state->m_vidc20_bpp_mode)
298   {
299      case 0: /* 1 bpp */
300      {
301         for(y=0;y<y_size;y++)
302         {
303            for(x=0;x<x_size;x+=8)
304            {
305               for(xi=0;xi<8;xi++)
306                  *BITMAP_ADDR32(bitmap, y+y_start, x+xi+x_start) = screen->machine().pens[(vram[count]>>(xi))&1];
307
308               count++;
309            }
310         }
311      }
312      break;
313      case 1: /* 2 bpp */
314      {
315         for(y=0;y<y_size;y++)
316         {
317            for(x=0;x<x_size;x+=4)
318            {
319               for(xi=0;xi<4;xi++)
320                  *BITMAP_ADDR32(bitmap, y+y_start, x+xi+x_start) = screen->machine().pens[(vram[count]>>(xi*2))&3];
321
322               count++;
323            }
324         }
325      }
326      break;
327      case 2: /* 4 bpp */
328      {
329         for(y=0;y<y_size;y++)
330         {
331            for(x=0;x<x_size;x+=2)
332            {
333               for(xi=0;xi<2;xi++)
334                  *BITMAP_ADDR32(bitmap, y+y_start, x+xi+x_start) = screen->machine().pens[(vram[count]>>(xi*4))&0xf];
335
336               count++;
337            }
338         }
339      }
340      break;
341      case 3: /* 8 bpp */
342      {
343         for(y=0;y<y_size;y++)
344         {
345            for(x=0;x<x_size;x++)
346            {
347               *BITMAP_ADDR32(bitmap, y+y_start, x+x_start) = screen->machine().pens[(vram[count])&0xff];
348
349               count++;
350            }
351         }
352      }
353      break;
354      case 4: /* 16 bpp */
355      {
356         for(y=0;y<y_size;y++)
357         {
358            for(x=0;x<x_size;x++)
359            {
360               int r,g,b,pen;
361
362               pen = ((vram[count]<<8)|(vram[count+1]))&0xffff;
363               r = (pen & 0x000f);
364               g = (pen & 0x00f0) >> 4;
365               b = (pen & 0x0f00) >> 8;
366               r = (r << 4) | (r & 0xf);
367               g = (g << 4) | (g & 0xf);
368               b = (b << 4) | (b & 0xf);
369
370               *BITMAP_ADDR32(bitmap, y+y_start, x+x_start) =  b | g << 8 | r << 16;
371
372               count+=2;
373            }
374         }
375      }
376      break;
377      case 6: /* 32 bpp */
378      {
379         for(y=0;y<y_size;y++)
380         {
381            for(x=0;x<x_size;x++)
382            {
383               int r,g,b,pen;
384
385               pen = ((vram[count]<<24)|(vram[count+1]<<16)|(vram[count+2]<<8)|(vram[count+3]<<0));
386               r = (pen & 0x0000ff);
387               g = (pen & 0x00ff00) >> 8;
388               b = (pen & 0xff0000) >> 16;
389
390               *BITMAP_ADDR32(bitmap, y+y_start, x+x_start) =  b | g << 8 | r << 16;
391
392               count+=4;
393            }
394         }
395      }
396      break;
397      default:
398         //fatalerror("VIDC20 %08x BPP mode not supported\n",state->m_vidc20_bpp_mode);
399         break;
400   }
401
402    return 0;
403}
404
405/*
406*
407* IOMD / ARM7500 / ARM7500FE chip emulation
408*
409*/
410
411/* TODO: some of these registers are actually ARM7500 specific */
412static const char *const iomd_regnames[] =
413{
414   "I/O Control",                  // 0x000 IOCR
415   "Keyboard Data",               // 0x004 KBDDAT
416   "Keyboard Control",               // 0x008 KBDCR
417   "General Purpose I/O Lines",      // 0x00c IOLINES
418   "IRQA Status",                  // 0x010 IRQSTA
419   "IRQA Request/clear",            // 0x014 IRQRQA
420   "IRQA Mask",                  // 0x018 IRQMSKA
421   "Enter SUSPEND Mode",            // 0x01c SUSMODE
422   "IRQB Status",                  // 0x020 IRQSTB
423   "IRQB Request/clear",            // 0x024 IRQRQB
424   "IRQB Mask",                  // 0x028 IRQMSKB
425   "Enter STOP Mode",               // 0x02c STOPMODE
426   "FIQ Status",                  // 0x030 FIQST
427   "FIQ Request/clear",            // 0x034 FIQRQ
428   "FIQ Mask",                     // 0x038 FIQMSK
429   "Clock divider control",         // 0x03c CLKCTL
430   "Timer 0 Low Bits",               // 0x040 T0LOW
431   "Timer 0 High Bits",            // 0x044 T0HIGH
432   "Timer 0 Go Command",            // 0x048 T0GO
433   "Timer 0 Latch Command",         // 0x04c T0LATCH
434   "Timer 1 Low Bits",               // 0x050 T1LOW
435   "Timer 1 High Bits",            // 0x054 T1HIGH
436   "Timer 1 Go Command",            // 0x058 T1GO
437   "Timer 1 Latch Command",         // 0x05c T1LATCH
438   "IRQC Status",                  // 0x060 IRQSTC
439   "IRQC Request/clear",            // 0x064 IRQRQC
440   "IRQC Mask",                  // 0x068 IRQMSKC
441   "LCD and IIS Control Bits",         // 0x06c VIDIMUX
442   "IRQD Status",                  // 0x070 IRQSTD
443   "IRQD Request/clear",            // 0x074 IRQRQD
444   "IRQD Mask",                  // 0x078 IRQMSKD
445   "<RESERVED>",                  // 0x07c
446   "ROM Control Bank 0",            // 0x080 ROMCR0
447   "ROM Control Bank 1",            // 0x084 ROMCR1
448   "DRAM Control (IOMD)",            // 0x088 DRAMCR
449   "VRAM and Refresh Control",         // 0x08c VREFCR
450   "Flyback Line Size",            // 0x090 FSIZE
451   "Chip ID no. Low Byte",            // 0x094 ID0
452   "Chip ID no. High Byte",         // 0x098 ID1
453   "Chip Version Number",            // 0x09c VERSION
454   "Mouse X Position",               // 0x0a0 MOUSEX
455   "Mouse Y Position",               // 0x0a4 MOUSEY
456   "Mouse Data",                  // 0x0a8 MSEDAT
457   "Mouse Control",               // 0x0ac MSECR
458   "<RESERVED>",                  // 0x0b0
459   "<RESERVED>",                  // 0x0b4
460   "<RESERVED>",                  // 0x0b8
461   "<RESERVED>",                  // 0x0bc
462   "DACK Timing Control",            // 0x0c0 DMATCR
463   "I/O Timing Control",            // 0x0c4 IOTCR
464   "Expansion Card Timing",         // 0x0c8 ECTCR
465   "DMA External Control",            // 0x0cc DMAEXT (IOMD) / ASTCR (ARM7500)
466   "DRAM Width Control",            // 0x0d0 DRAMWID
467   "Force CAS/RAS Lines Low",         // 0x0d4 SELFREF
468   "<RESERVED>",                  // 0x0d8
469   "<RESERVED>",                  // 0x0dc
470   "A to D IRQ Control",            // 0x0e0 ATODICR
471   "A to D IRQ Status",            // 0x0e4 ATODCC
472   "A to D IRQ Converter Control",      // 0x0e8 ATODICR
473   "A to D IRQ Counter 1",            // 0x0ec ATODCNT1
474   "A to D IRQ Counter 2",            // 0x0f0 ATODCNT2
475   "A to D IRQ Counter 3",            // 0x0f4 ATODCNT3
476   "A to D IRQ Counter 4",            // 0x0f8 ATODCNT4
477   "<RESERVED>",                  // 0x0fc
478   "I/O DMA 0 CurA",               // 0x100 IO0CURA
479   "I/O DMA 0 EndA",               // 0x104 IO0ENDA
480   "I/O DMA 0 CurB",               // 0x108 IO0CURB
481   "I/O DMA 0 EndB",               // 0x10c IO0ENDB
482   "I/O DMA 0 Control",            // 0x110 IO0CR
483   "I/O DMA 0 Status",               // 0x114 IO0ST
484   "<RESERVED>",                  // 0x118
485   "<RESERVED>",                  // 0x11c
486   "I/O DMA 1 CurA",               // 0x120 IO1CURA
487   "I/O DMA 1 EndA",               // 0x124 IO1ENDA
488   "I/O DMA 1 CurB",               // 0x128 IO1CURB
489   "I/O DMA 1 EndB",               // 0x12c IO1ENDB
490   "I/O DMA 1 Control",            // 0x130 IO1CR
491   "I/O DMA 1 Status",               // 0x134 IO1ST
492   "<RESERVED>",                  // 0x138
493   "<RESERVED>",                  // 0x13c
494   "I/O DMA 2 CurA",               // 0x140 IO2CURA
495   "I/O DMA 2 EndA",               // 0x144 IO2ENDA
496   "I/O DMA 2 CurB",               // 0x148 IO2CURB
497   "I/O DMA 2 EndB",               // 0x14c IO2ENDB
498   "I/O DMA 2 Control",            // 0x150 IO2CR
499   "I/O DMA 2 Status",               // 0x154 IO2ST
500   "<RESERVED>",                  // 0x158
501   "<RESERVED>",                  // 0x15c
502   "I/O DMA 3 CurA",               // 0x160 IO3CURA
503   "I/O DMA 3 EndA",               // 0x164 IO3ENDA
504   "I/O DMA 3 CurB",               // 0x168 IO3CURB
505   "I/O DMA 3 EndB",               // 0x16c IO3ENDB
506   "I/O DMA 3 Control",            // 0x170 IO3CR
507   "I/O DMA 3 Status",               // 0x174 IO3ST
508   "<RESERVED>",                  // 0x178
509   "<RESERVED>",                  // 0x17c
510   "Sound DMA 0 CurA",               // 0x180 SD0CURA
511   "Sound DMA 0 EndA",               // 0x184 SD0ENDA
512   "Sound DMA 0 CurB",               // 0x188 SD0CURB
513   "Sound DMA 0 EndB",               // 0x18c SD0ENDB
514   "Sound DMA 0 Control",            // 0x190 SD0CR
515   "Sound DMA 0 Status",            // 0x194 SD0ST
516   "<RESERVED>",                  // 0x198
517   "<RESERVED>",                  // 0x19c
518   "Sound DMA 1 CurA",               // 0x1a0 SD1CURA
519   "Sound DMA 1 EndA",               // 0x1a4 SD1ENDA
520   "Sound DMA 1 CurB",               // 0x1a8 SD1CURB
521   "Sound DMA 1 EndB",               // 0x1ac SD1ENDB
522   "Sound DMA 1 Control",            // 0x1b0 SD1CR
523   "Sound DMA 1 Status",            // 0x1b4 SD1ST
524   "<RESERVED>",                  // 0x1b8
525   "<RESERVED>",                  // 0x1bc
526   "Cursor DMA Current",            // 0x1c0 CURSCUR
527   "Cursor DMA Init",               // 0x1c4 CURSINIT
528   "Duplex LCD Current B",            // 0x1c8 VIDCURB
529   "<RESERVED>",                  // 0x1cc
530   "Video DMA Current",            // 0x1d0 VIDCUR
531   "Video DMA End",               // 0x1d4 VIDEND
532   "Video DMA Start",               // 0x1d8 VIDSTART
533   "Video DMA Init",               // 0x1dc VIDINIT
534   "Video DMA Control",            // 0x1e0 VIDCR
535   "<RESERVED>",                  // 0x1e4
536   "Duplex LCD Init B",            // 0x1e8 VIDINITB
537   "<RESERVED>",                  // 0x1ec
538   "DMA IRQ Status",               // 0x1f0 DMAST
539   "DMA IRQ Request",               // 0x1f4 DMARQ
540   "DMA IRQ Mask",                  // 0x1f8 DMAMSK
541   "<RESERVED>"                  // 0x1fc
542};
543
544#define IOMD_IOCR      0x000/4
545#define IOMD_KBDDAT      0x004/4
546#define IOMD_KBDCR      0x008/4
547
548#define IOMD_IRQSTA      0x010/4
549#define IOMD_IRQRQA    0x014/4
550#define IOMD_IRQMSKA   0x018/4
551
552#define IOMD_T0LOW      0x040/4
553#define IOMD_T0HIGH    0x044/4
554#define IOMD_T0GO      0x048/4
555#define IOMD_T0LATCH   0x04c/4
556
557#define IOMD_T1LOW      0x050/4
558#define IOMD_T1HIGH    0x054/4
559#define IOMD_T1GO      0x058/4
560#define IOMD_T1LATCH   0x05c/4
561
562#define IOMD_ID0      0x094/4
563#define IOMD_ID1      0x098/4
564#define IOMD_VERSION   0x09c/4
565
566#define IOMD_VIDCUR      0x1d0/4
567#define IOMD_VIDEND      0x1d4/4
568#define IOMD_VIDSTART   0x1d8/4
569#define IOMD_VIDINIT   0x1dc/4
570#define IOMD_VIDCR      0x1e0/4
571
572
573
574static void fire_iomd_timer(a7000_state *state, int timer)
575{
576   int timer_count = state->m_timer_counter[timer];
577   int val = timer_count / 2; // correct?
578
579   if(val==0)
580      state->m_IOMD_timer[timer]->adjust(attotime::never);
581   else
582      state->m_IOMD_timer[timer]->adjust(attotime::from_usec(val), 0, attotime::from_usec(val));
583}
584
585static TIMER_CALLBACK( IOMD_timer0_callback )
586{
587   a7000_state *state = machine.driver_data<a7000_state>();
588   state->m_IRQ_status_A|=0x20;
589   if(state->m_IRQ_mask_A&0x20)
590   {
591      generic_pulse_irq_line(machine.device("maincpu"), ARM7_IRQ_LINE);
592   }
593}
594
595static TIMER_CALLBACK( IOMD_timer1_callback )
596{
597   a7000_state *state = machine.driver_data<a7000_state>();
598   state->m_IRQ_status_A|=0x40;
599   if(state->m_IRQ_mask_A&0x40)
600   {
601      generic_pulse_irq_line(machine.device("maincpu"), ARM7_IRQ_LINE);
602   }
603}
604
605static TIMER_CALLBACK( flyback_timer_callback )
606{
607   a7000_state *state = machine.driver_data<a7000_state>();
608   state->m_IRQ_status_A|=0x08;
609   if(state->m_IRQ_mask_A&0x08)
610   {
611      generic_pulse_irq_line(machine.device("maincpu"), ARM7_IRQ_LINE);
612   }
613
614   state->m_flyback_timer->adjust(machine.primary_screen->time_until_pos(state->m_vidc20_vert_reg[VDER]));
615}
616
617static void viddma_transfer_start(address_space *space)
618{
619   a7000_state *state = space->machine().driver_data<a7000_state>();
620   UINT32 src = state->m_viddma_addr_start;
621   UINT32 dst = 0;
622   UINT32 size = state->m_viddma_addr_end;
623   UINT32 dma_index;
624   UINT8 *vram = space->machine().region("vram")->base();
625
626   /* TODO: this should actually be a qword transfer */
627   for(dma_index = 0;dma_index < size;dma_index++)
628   {
629      vram[dst] = space->read_byte(src);
630
631      src++;
632      dst++;
633   }
634}
635
636static READ32_HANDLER( a7000_iomd_r )
637{
638   a7000_state *state = space->machine().driver_data<a7000_state>();
639//  if(offset != IOMD_KBDCR)
640//      logerror("IOMD: %s Register (%04x) read\n",iomd_regnames[offset & (0x1ff >> 2)],offset*4);
641
642
643   switch(offset)
644   {
645      case IOMD_IOCR:
646      {
647         UINT8 flyback;
648         int vert_pos;
649
650         vert_pos = space->machine().primary_screen->vpos();
651         flyback = (vert_pos <= state->m_vidc20_vert_reg[VDSR] || vert_pos >= state->m_vidc20_vert_reg[VDER]) ? 0x80 : 0x00;
652
653         return state->m_IOMD_IO_ctrl | 0x34 | flyback;
654      }
655      case IOMD_KBDCR:   return state->m_IOMD_keyb_ctrl | 0x80; //IOMD Keyb status
656
657      /*
658        1--- ---- always high
659        -x-- ---- Timer 1
660        --x- ---- Timer 0
661        ---x ---- Power On Reset
662        ---- x--- Flyback
663        ---- -x-- nINT1
664        ---- --0- always low
665        ---- ---x INT2
666        */
667      case IOMD_IRQSTA:   return (state->m_IRQ_status_A & ~2) | 0x80;
668      case IOMD_IRQRQA:   return (state->m_IRQ_status_A & state->m_IRQ_mask_A) | 0x80;
669      case IOMD_IRQMSKA:   return (state->m_IRQ_mask_A);
670
671      case IOMD_T0LOW:   return state->m_timer_out[0] & 0xff;
672      case IOMD_T0HIGH:   return (state->m_timer_out[0] >> 8) & 0xff;
673
674      case IOMD_T1LOW:   return state->m_timer_out[1] & 0xff;
675      case IOMD_T1HIGH:   return (state->m_timer_out[1] >> 8) & 0xff;
676
677      case IOMD_ID0:      return state->m_io_id & 0xff; // IOMD ID low
678      case IOMD_ID1:      return (state->m_io_id >> 8) & 0xff; // IOMD ID high
679      case IOMD_VERSION:   return 0;
680
681      case IOMD_VIDEND:   return (state->m_viddma_addr_end & 0x00fffff8); //bits 31:24 undefined
682      case IOMD_VIDSTART: return (state->m_viddma_addr_start & 0x1ffffff8); //bits 31, 30, 29 undefined
683      case IOMD_VIDCR:   return (state->m_viddma_status & 0xa0) | 0x50; //bit 6 = DRAM mode, bit 4 = QWORD transfer
684
685      default:   logerror("IOMD: %s Register (%04x) read\n",iomd_regnames[offset & (0x1ff >> 2)],offset*4); break;
686   }
687
688   return 0;
689}
690
691static WRITE32_HANDLER( a7000_iomd_w )
692{
693   a7000_state *state = space->machine().driver_data<a7000_state>();
694//  logerror("IOMD: %s Register (%04x) write = %08x\n",iomd_regnames[offset & (0x1ff >> 2)],offset*4,data);
695
696   switch(offset)
697   {
698      case IOMD_IOCR:      state->m_IOMD_IO_ctrl = data & ~0xf4; break;
699
700      case IOMD_KBDCR:
701         state->m_IOMD_keyb_ctrl = data & ~0xf4;
702         //keyboard_ctrl_write(data & 0x08);
703         break;
704
705      case IOMD_IRQRQA:   state->m_IRQ_status_A &= ~data; break;
706      case IOMD_IRQMSKA:   state->m_IRQ_mask_A = (data & ~2) | 0x80; break;
707
708      case IOMD_T0LOW:   state->m_timer_in[0] = (state->m_timer_in[0] & 0xff00) | (data & 0xff); break;
709      case IOMD_T0HIGH:   state->m_timer_in[0] = (state->m_timer_in[0] & 0x00ff) | ((data & 0xff) << 8); break;
710      case IOMD_T0GO:
711         state->m_timer_counter[0] = state->m_timer_in[0];
712         fire_iomd_timer(state,0);
713         break;
714      case IOMD_T0LATCH:
715         {
716            state->m_t0readinc^=1;
717            state->m_timer_out[0] = state->m_timer_counter[0];
718            if(state->m_t0readinc)
719            {
720               state->m_timer_counter[0]--;
721               if(state->m_timer_counter[0] < 0)
722                  state->m_timer_counter[0]+= state->m_timer_in[0];
723            }
724         }
725         break;
726
727      case IOMD_T1LOW:   state->m_timer_in[1] = (state->m_timer_in[1] & 0xff00) | (data & 0xff); break;
728      case IOMD_T1HIGH:   state->m_timer_in[1] = (state->m_timer_in[1] & 0x00ff) | ((data & 0xff) << 8); break;
729      case IOMD_T1GO:
730         state->m_timer_counter[1] = state->m_timer_in[1];
731         fire_iomd_timer(state,1);
732         break;
733      case IOMD_T1LATCH:
734         {
735            state->m_t1readinc^=1;
736            state->m_timer_out[1] = state->m_timer_counter[1];
737            if(state->m_t1readinc)
738            {
739               state->m_timer_counter[1]--;
740               if(state->m_timer_counter[1] < 0)
741                  state->m_timer_counter[1]+= state->m_timer_in[1];
742            }
743         }
744         break;
745
746      case IOMD_VIDEND:   state->m_viddma_addr_end = data & 0x00fffff8; //bits 31:24 unused
747      case IOMD_VIDSTART: state->m_viddma_addr_start = data & 0x1ffffff8; //bits 31, 30, 29 unused
748      case IOMD_VIDCR:
749         state->m_viddma_status = data & 0xa0; if(data & 0x20) { viddma_transfer_start(space); }
750         break;
751
752
753      default: logerror("IOMD: %s Register (%04x) write = %08x\n",iomd_regnames[offset & (0x1ff >> 2)],offset*4,data);
754   }
755}
756
757static ADDRESS_MAP_START( a7000_mem, AS_PROGRAM, 32)
758   AM_RANGE(0x00000000, 0x003fffff) AM_MIRROR(0x00800000) AM_ROM AM_REGION("user1", 0x0)
759//  AM_RANGE(0x01000000, 0x01ffffff) AM_NOP //expansion ROM
760//  AM_RANGE(0x02000000, 0x02ffffff) AM_RAM //VRAM
761//  I/O 03000000 - 033fffff
762//  AM_RANGE(0x03010000, 0x03011fff) //Super IO
763//  AM_RANGE(0x03012000, 0x03029fff) //FDC
764//  AM_RANGE(0x0302b000, 0x0302bfff) //Network podule
765//  AM_RANGE(0x03040000, 0x0304ffff) //podule space 0,1,2,3
766//  AM_RANGE(0x03070000, 0x0307ffff) //podule space 4,5,6,7
767   AM_RANGE(0x03200000, 0x032001ff) AM_READWRITE(a7000_iomd_r,a7000_iomd_w) //IOMD Registers //mirrored at 0x03000000-0x1ff?
768//  AM_RANGE(0x03310000, 0x03310003) //Mouse Buttons
769
770   AM_RANGE(0x03400000, 0x037fffff) AM_WRITE(a7000_vidc20_w)
771//  AM_RANGE(0x08000000, 0x08ffffff) AM_MIRROR(0x07000000) //EASI space
772   AM_RANGE(0x10000000, 0x13ffffff) AM_RAM //SIMM 0 bank 0
773   AM_RANGE(0x14000000, 0x17ffffff) AM_RAM //SIMM 0 bank 1
774//  AM_RANGE(0x18000000, 0x18ffffff) AM_MIRROR(0x03000000) AM_RAM //SIMM 1 bank 0
775//  AM_RANGE(0x1c000000, 0x1cffffff) AM_MIRROR(0x03000000) AM_RAM //SIMM 1 bank 1
776ADDRESS_MAP_END
777
778
779/* Input ports */
780static INPUT_PORTS_START( a7000 )
781INPUT_PORTS_END
782
783static MACHINE_START(a7000)
784{
785   a7000_state *state = machine.driver_data<a7000_state>();
786   state->m_IOMD_timer[0] = machine.scheduler().timer_alloc(FUNC(IOMD_timer0_callback));
787   state->m_IOMD_timer[1] = machine.scheduler().timer_alloc(FUNC(IOMD_timer1_callback));
788   state->m_flyback_timer = machine.scheduler().timer_alloc(FUNC(flyback_timer_callback));
789
790   state->m_io_id = 0xd4e7;
791}
792
793static MACHINE_RESET(a7000)
794{
795   a7000_state *state = machine.driver_data<a7000_state>();
796   state->m_IOMD_IO_ctrl = 0x0b | 0x34; //bit 0,1 and 3 set high on reset plus 2,4,5 always high
797//  state->m_IRQ_status_A = 0x10; // set POR bit ON
798   state->m_IRQ_mask_A = 0x00;
799
800   state->m_IOMD_keyb_ctrl = 0x00;
801
802   state->m_IOMD_timer[0]->adjust( attotime::never);
803   state->m_IOMD_timer[1]->adjust( attotime::never);
804   state->m_flyback_timer->adjust( attotime::never);
805}
806
807static MACHINE_CONFIG_START( a7000, a7000_state )
808
809   /* Basic machine hardware */
810   MCFG_CPU_ADD( "maincpu", ARM7, XTAL_32MHz )
811   MCFG_CPU_PROGRAM_MAP(a7000_mem)
812
813   MCFG_MACHINE_START( a7000 )
814   MCFG_MACHINE_RESET( a7000 )
815
816   /* video hardware */
817   MCFG_SCREEN_ADD("screen", RASTER)
818   MCFG_SCREEN_REFRESH_RATE(60)
819   MCFG_SCREEN_VBLANK_TIME(ATTOSECONDS_IN_USEC(2500)) /* not accurate */
820   MCFG_SCREEN_FORMAT(BITMAP_FORMAT_RGB32)
821   MCFG_SCREEN_SIZE(1900, 1080) //max available size
822   MCFG_SCREEN_VISIBLE_AREA(0, 1900-1, 0, 1080-1)
823   MCFG_SCREEN_UPDATE(a7000)
824   MCFG_PALETTE_LENGTH(0x200)
825//  MCFG_PALETTE_INIT(black_and_white)
826
827   MCFG_VIDEO_START(a7000)
828MACHINE_CONFIG_END
829
830static MACHINE_CONFIG_DERIVED( a7000p, a7000 )
831
832   MCFG_CPU_MODIFY("maincpu")
833   MCFG_CPU_CLOCK(XTAL_48MHz)
834MACHINE_CONFIG_END
835
836ROM_START(a7000)
837   ROM_REGION( 0x800000, "user1", ROMREGION_ERASEFF )
838   ROM_LOAD( "rom1.bin", 0x000000, 0x100000, CRC(ff0e3d12) SHA1(fa489bebede3d13dc43cddec5b5c9b6829a28914) )
839   ROM_LOAD( "rom2.bin", 0x100000, 0x100000, CRC(4ae4fd8b) SHA1(1b30d5905d5364dfa48bad69257b0ef8190e9bf6) )
840   ROM_LOAD( "rom3.bin", 0x200000, 0x100000, CRC(3108fb2b) SHA1(865b01583f3fb5f4ed5e9201676db327cdeb40b3) )
841   ROM_LOAD( "rom4.bin", 0x300000, 0x100000, CRC(55a51980) SHA1(a7191727edd5babf679ebbdea6585833a1fb34e6) )
842
843   ROM_REGION( 0x800000, "vram", ROMREGION_ERASE00 )
844ROM_END
845
846ROM_START(a7000p)
847   ROM_REGION( 0x800000, "user1", ROMREGION_ERASEFF )
848   ROM_LOAD( "riscos-3.71.rom", 0x000000, 0x400000, CRC(211cf888) SHA1(c5fe0645e48894fb4b245abeefdc9a65d659af59))
849
850   ROM_REGION( 0x800000, "vram", ROMREGION_ERASE00 )
851ROM_END
852
853/***************************************************************************
854
855  Game driver(s)
856
857***************************************************************************/
858
859/*    YEAR  NAME        PARENT  COMPAT  MACHINE     INPUT   INIT    COMPANY FULLNAME        FLAGS */
860COMP( 1995, a7000,      0,      0,      a7000,      a7000,   0,      "Acorn",  "Archimedes A7000",   GAME_NOT_WORKING | GAME_NO_SOUND )
861COMP( 1997, a7000p,     a7000,  0,      a7000p,     a7000,   0,      "Acorn",  "Archimedes A7000+",  GAME_NOT_WORKING | GAME_NO_SOUND )
src/mess/drivers/ng_aes.c
r0r11532
1/***************************************************************************
2
3    Neo-Geo AES hardware
4
5    Credits (from MAME neogeo.c, since this is just a minor edit of that driver):
6        * This driver was made possible by the research done by
7          Charles MacDonald.  For a detailed description of the Neo-Geo
8          hardware, please visit his page at:
9          http://cgfm2.emuviews.com/temp/mvstech.txt
10        * Presented to you by the Shin Emu Keikaku team.
11        * The following people have all spent probably far
12          too much time on this:
13          AVDB
14          Bryan McPhail
15          Fuzz
16          Ernesto Corvi
17          Andrew Prime
18          Zsolt Vasvari
19
20    MESS cartridge support by R. Belmont based on work by Michael Zapf
21
22    Current status:
23        - Cartridges run.
24
25    ToDo :
26        - Change input code to allow selection of the mahjong panel in PORT_CATEGORY.
27        - Clean up code, to reduce duplication of MAME source
28
29****************************************************************************/
30
31#include "emu.h"
32#include "cpu/m68000/m68000.h"
33#include "includes/neogeo.h"
34#include "machine/pd4990a.h"
35#include "cpu/z80/z80.h"
36#include "sound/2610intf.h"
37#include "imagedev/aescart.h"
38#include "imagedev/cartslot.h"
39#ifdef MESS
40#include "neogeo.lh"
41#else
42extern const char layout_neogeo[];
43#endif
44
45
46// CD-ROM / DMA control registers
47typedef struct
48{
49   UINT8 area_sel;
50   UINT8 pcm_bank_sel;
51   UINT8 spr_bank_sel;
52   UINT32 addr_source; // target if in fill mode
53   UINT32 addr_target;
54   UINT16 fill_word;
55   UINT32 word_count;
56   UINT16 dma_mode[10];
57} neocd_ctrl_t;
58
59class ng_aes_state : public neogeo_state
60{
61public:
62   ng_aes_state(const machine_config &mconfig, device_type type, const char *tag)
63      : neogeo_state(mconfig, type, tag) { }
64
65   UINT8 *m_memcard_data;
66   neocd_ctrl_t m_neocd_ctrl;
67};
68
69
70
71#define LOG_VIDEO_SYSTEM      (0)
72#define LOG_CPU_COMM         (0)
73#define LOG_MAIN_CPU_BANKING   (1)
74#define LOG_AUDIO_CPU_BANKING   (1)
75
76#define NEOCD_AREA_SPR    0
77#define NEOCD_AREA_PCM    1
78#define NEOCD_AREA_AUDIO  4
79#define NEOCD_AREA_FIX    5
80
81/*************************************
82 *
83 *  Global variables
84 *
85 *************************************/
86
87//static UINT16 *save_ram;
88
89UINT16* neocd_work_ram;
90
91/*************************************
92 *
93 *  Forward declarations
94 *
95 *************************************/
96
97//static void set_output_latch(running_machine &machine, UINT8 data);
98//static void set_output_data(running_machine &machine, UINT8 data);
99
100
101/*************************************
102 *
103 *  Main CPU interrupt generation
104 *
105 *************************************/
106
107#define IRQ2CTRL_ENABLE            (0x10)
108#define IRQ2CTRL_LOAD_RELATIVE      (0x20)
109#define IRQ2CTRL_AUTOLOAD_VBLANK   (0x40)
110#define IRQ2CTRL_AUTOLOAD_REPEAT   (0x80)
111
112
113static void adjust_display_position_interrupt_timer( running_machine &machine )
114{
115   neogeo_state *state = machine.driver_data<neogeo_state>();
116
117   if ((state->m_display_counter + 1) != 0)
118   {
119      attotime period = (attotime::from_hz(NEOGEO_PIXEL_CLOCK) * (state->m_display_counter + 1));
120      if (LOG_VIDEO_SYSTEM) logerror("adjust_display_position_interrupt_timer  current y: %02x  current x: %02x   target y: %x  target x: %x\n", machine.primary_screen->vpos(), machine.primary_screen->hpos(), (state->m_display_counter + 1) / NEOGEO_HTOTAL, (state->m_display_counter + 1) % NEOGEO_HTOTAL);
121
122      state->m_display_position_interrupt_timer->adjust(period);
123   }
124}
125
126#ifdef MESS
127void neogeo_set_display_position_interrupt_control( running_machine &machine, UINT16 data )
128{
129   neogeo_state *state = machine.driver_data<neogeo_state>();
130   state->m_display_position_interrupt_control = data;
131}
132
133
134void neogeo_set_display_counter_msb( address_space *space, UINT16 data )
135{
136   neogeo_state *state = space->machine().driver_data<neogeo_state>();
137
138   state->m_display_counter = (state->m_display_counter & 0x0000ffff) | ((UINT32)data << 16);
139
140   if (LOG_VIDEO_SYSTEM) logerror("PC %06x: set_display_counter %08x\n", cpu_get_pc(&space->device()), state->m_display_counter);
141}
142
143
144void neogeo_set_display_counter_lsb( address_space *space, UINT16 data )
145{
146   neogeo_state *state = space->machine().driver_data<neogeo_state>();
147
148   state->m_display_counter = (state->m_display_counter & 0xffff0000) | data;
149
150   if (LOG_VIDEO_SYSTEM) logerror("PC %06x: set_display_counter %08x\n", cpu_get_pc(&space->device()), state->m_display_counter);
151
152   if (state->m_display_position_interrupt_control & IRQ2CTRL_LOAD_RELATIVE)
153   {
154      if (LOG_VIDEO_SYSTEM) logerror("AUTOLOAD_RELATIVE ");
155      adjust_display_position_interrupt_timer(space->machine());
156   }
157}
158#endif
159
160static void update_interrupts( running_machine &machine )
161{
162   neogeo_state *state = machine.driver_data<neogeo_state>();
163
164   if(strcmp((char*)machine.system().name,"aes") != 0)
165   {  // raster and vblank IRQs are swapped on the NeoCD.
166      cputag_set_input_line(machine, "maincpu", 2, state->m_vblank_interrupt_pending ? ASSERT_LINE : CLEAR_LINE);
167      cputag_set_input_line(machine, "maincpu", 1, state->m_display_position_interrupt_pending ? ASSERT_LINE : CLEAR_LINE);
168      cputag_set_input_line(machine, "maincpu", 3, state->m_irq3_pending ? ASSERT_LINE : CLEAR_LINE);
169   }
170   else
171   {
172      cputag_set_input_line(machine, "maincpu", 1, state->m_vblank_interrupt_pending ? ASSERT_LINE : CLEAR_LINE);
173      cputag_set_input_line(machine, "maincpu", 2, state->m_display_position_interrupt_pending ? ASSERT_LINE : CLEAR_LINE);
174      cputag_set_input_line(machine, "maincpu", 3, state->m_irq3_pending ? ASSERT_LINE : CLEAR_LINE);
175   }
176}
177
178#ifdef MESS
179void neogeo_acknowledge_interrupt( running_machine &machine, UINT16 data )
180{
181   neogeo_state *state = machine.driver_data<neogeo_state>();
182
183   if (data & 0x01)
184      state->m_irq3_pending = 0;
185   if (data & 0x02)
186      state->m_display_position_interrupt_pending = 0;
187   if (data & 0x04)
188      state->m_vblank_interrupt_pending = 0;
189
190   update_interrupts(machine);
191}
192#endif
193
194static TIMER_CALLBACK( display_position_interrupt_callback )
195{
196   neogeo_state *state = machine.driver_data<neogeo_state>();
197
198   if (LOG_VIDEO_SYSTEM) logerror("--- Scanline @ %d,%d\n", machine.primary_screen->vpos(), machine.primary_screen->hpos());
199
200   if (state->m_display_position_interrupt_control & IRQ2CTRL_ENABLE)
201   {
202      if (LOG_VIDEO_SYSTEM) logerror("*** Scanline interrupt (IRQ2) ***  y: %02x  x: %02x\n", machine.primary_screen->vpos(), machine.primary_screen->hpos());
203      state->m_display_position_interrupt_pending = 1;
204
205      update_interrupts(machine);
206   }
207
208   if (state->m_display_position_interrupt_control & IRQ2CTRL_AUTOLOAD_REPEAT)
209   {
210      if (LOG_VIDEO_SYSTEM) logerror("AUTOLOAD_REPEAT ");
211      adjust_display_position_interrupt_timer(machine);
212   }
213}
214
215
216static TIMER_CALLBACK( display_position_vblank_callback )
217{
218   neogeo_state *state = machine.driver_data<neogeo_state>();
219
220   if (state->m_display_position_interrupt_control & IRQ2CTRL_AUTOLOAD_VBLANK)
221   {
222      if (LOG_VIDEO_SYSTEM) logerror("AUTOLOAD_VBLANK ");
223      adjust_display_position_interrupt_timer(machine);
224   }
225
226   /* set timer for next screen */
227   state->m_display_position_vblank_timer->adjust(machine.primary_screen->time_until_pos(NEOGEO_VBSTART, NEOGEO_VBLANK_RELOAD_HPOS));
228}
229
230
231static TIMER_CALLBACK( vblank_interrupt_callback )
232{
233   neogeo_state *state = machine.driver_data<neogeo_state>();
234
235   if (LOG_VIDEO_SYSTEM) logerror("+++ VBLANK @ %d,%d\n", machine.primary_screen->vpos(), machine.primary_screen->hpos());
236
237   /* add a timer tick to the pd4990a */
238   upd4990a_addretrace(state->m_upd4990a);
239
240   state->m_vblank_interrupt_pending = 1;
241
242   update_interrupts(machine);
243
244   /* set timer for next screen */
245   state->m_vblank_interrupt_timer->adjust(machine.primary_screen->time_until_pos(NEOGEO_VBSTART, 0));
246}
247
248
249static void create_interrupt_timers( running_machine &machine )
250{
251   neogeo_state *state = machine.driver_data<neogeo_state>();
252   state->m_display_position_interrupt_timer = machine.scheduler().timer_alloc(FUNC(display_position_interrupt_callback));
253   state->m_display_position_vblank_timer = machine.scheduler().timer_alloc(FUNC(display_position_vblank_callback));
254   state->m_vblank_interrupt_timer = machine.scheduler().timer_alloc(FUNC(vblank_interrupt_callback));
255}
256
257
258static void start_interrupt_timers( running_machine &machine )
259{
260   neogeo_state *state = machine.driver_data<neogeo_state>();
261   state->m_vblank_interrupt_timer->adjust(machine.primary_screen->time_until_pos(NEOGEO_VBSTART, 0));
262   state->m_display_position_vblank_timer->adjust(machine.primary_screen->time_until_pos(NEOGEO_VBSTART, NEOGEO_VBLANK_RELOAD_HPOS));
263}
264
265
266
267/*************************************
268 *
269 *  Audio CPU interrupt generation
270 *
271 *************************************/
272
273static void audio_cpu_irq(device_t *device, int assert)
274{
275   neogeo_state *state = device->machine().driver_data<neogeo_state>();
276   device_set_input_line(state->m_audiocpu, 0, assert ? ASSERT_LINE : CLEAR_LINE);
277}
278
279
280static void audio_cpu_assert_nmi(running_machine &machine)
281{
282   neogeo_state *state = machine.driver_data<neogeo_state>();
283   device_set_input_line(state->m_audiocpu, INPUT_LINE_NMI, ASSERT_LINE);
284}
285
286
287static WRITE8_HANDLER( audio_cpu_clear_nmi_w )
288{
289   neogeo_state *state = space->machine().driver_data<neogeo_state>();
290   device_set_input_line(state->m_audiocpu, INPUT_LINE_NMI, CLEAR_LINE);
291}
292
293
294
295/*************************************
296 *
297 *  Input ports / Controllers
298 *
299 *************************************/
300
301static void select_controller( running_machine &machine, UINT8 data )
302{
303   neogeo_state *state = machine.driver_data<neogeo_state>();
304   state->m_controller_select = data;
305}
306
307
308#if 0
309static CUSTOM_INPUT( multiplexed_controller_r )
310{
311   int port = (FPTR)param;
312
313   static const char *const cntrl[2][2] =
314      {
315         { "IN0-0", "IN0-1" }, { "IN1-0", "IN1-1" }
316      };
317
318   return input_port_read_safe(field.machine(), cntrl[port][controller_select & 0x01], 0x00);
319}
320
321
322static CUSTOM_INPUT( mahjong_controller_r )
323{
324   UINT32 ret;
325
326/*
327cpu #0 (PC=00C18B9A): unmapped memory word write to 00380000 = 0012 & 00FF
328cpu #0 (PC=00C18BB6): unmapped memory word write to 00380000 = 001B & 00FF
329cpu #0 (PC=00C18D54): unmapped memory word write to 00380000 = 0024 & 00FF
330cpu #0 (PC=00C18D6C): unmapped memory word write to 00380000 = 0009 & 00FF
331cpu #0 (PC=00C18C40): unmapped memory word write to 00380000 = 0000 & 00FF
332*/
333   switch (controller_select)
334   {
335   default:
336   case 0x00: ret = 0x0000; break; /* nothing? */
337   case 0x09: ret = input_port_read(field.machine(), "MAHJONG1"); break;
338   case 0x12: ret = input_port_read(field.machine(), "MAHJONG2"); break;
339   case 0x1b: ret = input_port_read(field.machine(), "MAHJONG3"); break; /* player 1 normal inputs? */
340   case 0x24: ret = input_port_read(field.machine(), "MAHJONG4"); break;
341   }
342
343   return ret;
344}
345
346#endif
347
348static WRITE16_HANDLER( io_control_w )
349{
350   neogeo_state *state = space->machine().driver_data<neogeo_state>();
351   switch (offset)
352   {
353   case 0x00: select_controller(space->machine(), data & 0x00ff); break;
354//  case 0x18: set_output_latch(space->machine(), data & 0x00ff); break;
355//  case 0x20: set_output_data(space->machine(), data & 0x00ff); break;
356   case 0x28: upd4990a_control_16_w(state->m_upd4990a, 0, data, mem_mask); break;
357//  case 0x30: break; // coin counters
358//  case 0x31: break; // coin counters
359//  case 0x32: break; // coin lockout
360//  case 0x33: break; // coui lockout
361
362   default:
363      logerror("PC: %x  Unmapped I/O control write.  Offset: %x  Data: %x\n", cpu_get_pc(&space->device()), offset, data);
364      break;
365   }
366}
367
368
369
370/*************************************
371 *
372 *  Unmapped memory access
373 *
374 *************************************/
375#ifdef MESS
376READ16_HANDLER( neogeo_unmapped_r )
377{
378   neogeo_state *state = space->machine().driver_data<neogeo_state>();
379   UINT16 ret;
380
381   /* unmapped memory returns the last word on the data bus, which is almost always the opcode
382       of the next instruction due to prefetch */
383
384   /* prevent recursion */
385   if (state->m_recurse)
386      ret = 0xffff;
387   else
388   {
389      state->m_recurse = 1;
390      ret = space->read_word(cpu_get_pc(&space->device()));
391      state->m_recurse = 0;
392   }
393
394   return ret;
395}
396#endif
397
398
399
400/*************************************
401 *
402 *  uPD4990A calendar chip
403 *
404 *************************************/
405#if 0
406static void calendar_init(running_machine &machine)
407{
408   /* set the celander IC to 'right now' */
409   system_time systime;
410   system_tm time;
411
412   machine.base_datetime(&systime);
413   time = systime.local_time;
414
415   pd4990a.seconds = ((time.second / 10) << 4) + (time.second % 10);
416   pd4990a.minutes = ((time.minute / 10) << 4) + (time.minute % 10);
417   pd4990a.hours = ((time.hour / 10) <<4 ) + (time.hour % 10);
418   pd4990a.days = ((time.mday / 10) << 4) + (time.mday % 10);
419   pd4990a.month = time.month + 1;
420   pd4990a.year = ((((time.year - 1900) % 100) / 10) << 4) + ((time.year - 1900) % 10);
421   pd4990a.weekday = time.weekday;
422}
423
424
425static void calendar_clock(void)
426{
427//  pd4990a_addretrace();
428}
429#endif
430
431static CUSTOM_INPUT( get_calendar_status )
432{
433   neogeo_state *state = field.machine().driver_data<neogeo_state>();
434   return (upd4990a_databit_r(state->m_upd4990a, 0) << 1) | upd4990a_testbit_r(state->m_upd4990a, 0);
435}
436
437
438
439/*************************************
440 *
441 *  NVRAM (Save RAM)
442 *
443 *************************************/
444#if 0
445static NVRAM_HANDLER( neogeo )
446{
447   if (read_or_write)
448      /* save the SRAM settings */
449      mame_fwrite(file, save_ram, 0x2000);
450   else
451   {
452      /* load the SRAM settings */
453      if (file)
454         mame_fread(file, save_ram, 0x2000);
455      else
456         memset(save_ram, 0, 0x10000);
457   }
458}
459
460
461static void set_save_ram_unlock( running_machine &machine, UINT8 data )
462{
463   neogeo_state *state = machine.driver_data<neogeo_state>();
464   state->m_save_ram_unlocked = data;
465}
466
467
468static WRITE16_HANDLER( save_ram_w )
469{
470   neogeo_state *state = space->machine().driver_data<neogeo_state>();
471
472   if (state->m_save_ram_unlocked)
473      COMBINE_DATA(&save_ram[offset]);
474}
475#endif
476
477
478/*************************************
479 *
480 *  Memory card
481 *
482 *************************************/
483
484#define MEMCARD_SIZE   0x0800
485
486static CUSTOM_INPUT( get_memcard_status )
487{
488   /* D0 and D1 are memcard presence indicators, D2 indicates memcard
489       write protect status (we are always write enabled) */
490   if(strcmp((char*)field.machine().system().name,"aes") != 0)
491      return 0x00;  // On the Neo Geo CD, the memory card is internal and therefore always present.
492   else
493      return (memcard_present(field.machine()) == -1) ? 0x07 : 0x00;
494}
495
496static READ16_HANDLER( memcard_r )
497{
498   ng_aes_state *state = space->machine().driver_data<ng_aes_state>();
499   UINT16 ret;
500
501   if (memcard_present(space->machine()) != -1)
502      ret = state->m_memcard_data[offset] | 0xff00;
503   else
504      ret = 0xffff;
505
506   return ret;
507}
508
509
510static WRITE16_HANDLER( memcard_w )
511{
512   ng_aes_state *state = space->machine().driver_data<ng_aes_state>();
513   if (ACCESSING_BITS_0_7)
514   {
515      if (memcard_present(space->machine()) != -1)
516         state->m_memcard_data[offset] = data;
517   }
518}
519
520/* The NeoCD has an 8kB internal memory card, instead of memcard slots like the MVS and AES */
521static READ16_HANDLER( neocd_memcard_r )
522{
523   ng_aes_state *state = space->machine().driver_data<ng_aes_state>();
524   return state->m_memcard_data[offset] | 0xff00;
525}
526
527
528static WRITE16_HANDLER( neocd_memcard_w )
529{
530   ng_aes_state *state = space->machine().driver_data<ng_aes_state>();
531   if (ACCESSING_BITS_0_7)
532   {
533      state->m_memcard_data[offset] = data;
534   }
535}
536
537static MEMCARD_HANDLER( neogeo )
538{
539   ng_aes_state *state = machine.driver_data<ng_aes_state>();
540   switch (action)
541   {
542   case MEMCARD_CREATE:
543      memset(state->m_memcard_data, 0, MEMCARD_SIZE);
544      file.write(state->m_memcard_data, MEMCARD_SIZE);
545      break;
546
547   case MEMCARD_INSERT:
548      file.read(state->m_memcard_data, MEMCARD_SIZE);
549      break;
550
551   case MEMCARD_EJECT:
552      file.write(state->m_memcard_data, MEMCARD_SIZE);
553      break;
554   }
555}
556
557
558
559/*************************************
560 *
561 *  Inter-CPU communications
562 *
563 *************************************/
564
565static WRITE16_HANDLER( audio_command_w )
566{
567   /* accessing the LSB only is not mapped */
568   if (mem_mask != 0x00ff)
569   {
570      soundlatch_w(space, 0, data >> 8);
571
572      audio_cpu_assert_nmi(space->machine());
573
574      /* boost the interleave to let the audio CPU read the command */
575      space->machine().scheduler().boost_interleave(attotime::zero, attotime::from_usec(50));
576
577      if (LOG_CPU_COMM) logerror("MAIN CPU PC %06x: audio_command_w %04x - %04x\n", cpu_get_pc(&space->device()), data, mem_mask);
578   }
579}
580
581
582static READ8_HANDLER( audio_command_r )
583{
584   UINT8 ret = soundlatch_r(space, 0);
585
586   if (LOG_CPU_COMM) logerror(" AUD CPU PC   %04x: audio_command_r %02x\n", cpu_get_pc(&space->device()), ret);
587
588   /* this is a guess */
589   audio_cpu_clear_nmi_w(space, 0, 0);
590
591   return ret;
592}
593
594
595static WRITE8_HANDLER( audio_result_w )
596{
597   neogeo_state *state = space->machine().driver_data<neogeo_state>();
598
599   if (LOG_CPU_COMM && (state->m_audio_result != data)) logerror(" AUD CPU PC   %04x: audio_result_w %02x\n", cpu_get_pc(&space->device()), data);
600
601   state->m_audio_result = data;
602}
603
604
605static CUSTOM_INPUT( get_audio_result )
606{
607   neogeo_state *state = field.machine().driver_data<neogeo_state>();
608   UINT32 ret = state->m_audio_result;
609
610//  if (LOG_CPU_COMM) logerror("MAIN CPU PC %06x: audio_result_r %02x\n", cpu_get_pc(field.machine().device("maincpu")), ret);
611
612   return ret;
613}
614
615
616
617/*************************************
618 *
619 *  Main CPU banking
620 *
621 *************************************/
622
623static void _set_main_cpu_vector_table_source( running_machine &machine )
624{
625   neogeo_state *state = machine.driver_data<neogeo_state>();
626   memory_set_bank(machine, NEOGEO_BANK_VECTORS, state->m_main_cpu_vector_table_source);
627}
628
629
630static void set_main_cpu_vector_table_source( running_machine &machine, UINT8 data )
631{
632   neogeo_state *state = machine.driver_data<neogeo_state>();
633   state->m_main_cpu_vector_table_source = data;
634
635   _set_main_cpu_vector_table_source(machine);
636}
637
638
639static void _set_main_cpu_bank_address( running_machine &machine )
640{
641   neogeo_state *state = machine.driver_data<neogeo_state>();
642   memory_set_bankptr(machine, NEOGEO_BANK_CARTRIDGE, &machine.region("maincpu")->base()[state->m_main_cpu_bank_address]);
643}
644
645#ifdef MESS
646void neogeo_set_main_cpu_bank_address( address_space *space, UINT32 bank_address )
647{
648   neogeo_state *state = space->machine().driver_data<neogeo_state>();
649
650   if (LOG_MAIN_CPU_BANKING) logerror("MAIN CPU PC %06x: neogeo_set_main_cpu_bank_address %06x\n", cpu_get_pc(&space->device()), bank_address);
651
652   state->m_main_cpu_bank_address = bank_address;
653
654   _set_main_cpu_bank_address(space->machine());
655}
656#endif
657
658static WRITE16_HANDLER( main_cpu_bank_select_w )
659{
660   UINT32 bank_address;
661   UINT32 len = space->machine().region("maincpu")->bytes();
662
663   if ((len <= 0x100000) && (data & 0x07))
664      logerror("PC %06x: warning: bankswitch to %02x but no banks available\n", cpu_get_pc(&space->device()), data);
665   else
666   {
667      bank_address = ((data & 0x07) + 1) * 0x100000;
668
669      if (bank_address >= len)
670      {
671         logerror("PC %06x: warning: bankswitch to empty bank %02x\n", cpu_get_pc(&space->device()), data);
672         bank_address = 0x100000;
673      }
674
675      neogeo_set_main_cpu_bank_address(space, bank_address);
676   }
677}
678
679
680static void main_cpu_banking_init( running_machine &machine )
681{
682   address_space *mainspace = machine.device("maincpu")->memory().space(AS_PROGRAM);
683
684   /* create vector banks */
685   memory_configure_bank(machine, NEOGEO_BANK_VECTORS, 0, 1, machine.region("mainbios")->base(), 0);
686   memory_configure_bank(machine, NEOGEO_BANK_VECTORS, 1, 1, machine.region("maincpu")->base(), 0);
687
688   /* set initial main CPU bank */
689   if (machine.region("maincpu")->bytes() > 0x100000)
690      neogeo_set_main_cpu_bank_address(mainspace, 0x100000);
691   else
692      neogeo_set_main_cpu_bank_address(mainspace, 0x000000);
693}
694
695
696
697/*************************************
698 *
699 *  Audio CPU banking
700 *
701 *************************************/
702
703static void set_audio_cpu_banking( running_machine &machine )
704{
705   neogeo_state *state = machine.driver_data<neogeo_state>();
706   int region;
707
708   for (region = 0; region < 4; region++)
709      memory_set_bank(machine, NEOGEO_BANK_AUDIO_CPU_CART_BANK + region, state->m_audio_cpu_banks[region]);
710}
711
712
713static void audio_cpu_bank_select( address_space *space, int region, UINT8 bank )
714{
715   neogeo_state *state = space->machine().driver_data<neogeo_state>();
716
717   if (LOG_AUDIO_CPU_BANKING) logerror("Audio CPU PC %03x: audio_cpu_bank_select: Region: %d   Bank: %02x\n", cpu_get_pc(&space->device()), region, bank);
718
719   state->m_audio_cpu_banks[region] = bank;
720
721   set_audio_cpu_banking(space->machine());
722}
723
724
725static READ8_HANDLER( audio_cpu_bank_select_f000_f7ff_r )
726{
727   audio_cpu_bank_select(space, 0, offset >> 8);
728
729   return 0;
730}
731
732
733static READ8_HANDLER( audio_cpu_bank_select_e000_efff_r )
734{
735   audio_cpu_bank_select(space, 1, offset >> 8);
736
737   return 0;
738}
739
740
741static READ8_HANDLER( audio_cpu_bank_select_c000_dfff_r )
742{
743   audio_cpu_bank_select(space, 2, offset >> 8);
744
745   return 0;
746}
747
748
749static READ8_HANDLER( audio_cpu_bank_select_8000_bfff_r )
750{
751   audio_cpu_bank_select(space, 3, offset >> 8);
752
753   return 0;
754}
755
756
757static void _set_audio_cpu_rom_source( address_space *space )
758{
759   neogeo_state *state = space->machine().driver_data<neogeo_state>();
760
761/*  if (!machine.region("audiobios")->base())   */
762      state->m_audio_cpu_rom_source = 1;
763
764   memory_set_bank(space->machine(), NEOGEO_BANK_AUDIO_CPU_MAIN_BANK, state->m_audio_cpu_rom_source);
765
766   /* reset CPU if the source changed -- this is a guess */
767   if (state->m_audio_cpu_rom_source != state->m_audio_cpu_rom_source_last)
768   {
769      state->m_audio_cpu_rom_source_last = state->m_audio_cpu_rom_source;
770
771      cputag_set_input_line(space->machine(), "audiocpu", INPUT_LINE_RESET, PULSE_LINE);
772
773      if (LOG_AUDIO_CPU_BANKING) logerror("Audio CPU PC %03x: selectign %s ROM\n", cpu_get_pc(&space->device()), state->m_audio_cpu_rom_source ? "CARTRIDGE" : "BIOS");
774   }
775}
776
777
778static void set_audio_cpu_rom_source( address_space *space, UINT8 data )
779{
780   neogeo_state *state = space->machine().driver_data<neogeo_state>();
781   state->m_audio_cpu_rom_source = data;
782
783   _set_audio_cpu_rom_source(space);
784}
785
786
787static void audio_cpu_banking_init( running_machine &machine )
788{
789   neogeo_state *state = machine.driver_data<neogeo_state>();
790   int region;
791   int bank;
792   UINT8 *rgn;
793   UINT32 address_mask;
794
795   /* audio bios/cartridge selection */
796   if (machine.region("audiobios")->base())
797      memory_configure_bank(machine, NEOGEO_BANK_AUDIO_CPU_MAIN_BANK, 0, 1, machine.region("audiobios")->base(), 0);
798   memory_configure_bank(machine, NEOGEO_BANK_AUDIO_CPU_MAIN_BANK, 1, 1, machine.region("audiocpu")->base(), 0);
799
800   /* audio banking */
801   address_mask = machine.region("audiocpu")->bytes() - 0x10000 - 1;
802
803   rgn = machine.region("audiocpu")->base();
804   for (region = 0; region < 4; region++)
805   {
806      for (bank = 0; bank < 0x100; bank++)
807      {
808         UINT32 bank_address = 0x10000 + (((bank << (11 + region)) & 0x3ffff) & address_mask);
809         memory_configure_bank(machine, NEOGEO_BANK_AUDIO_CPU_CART_BANK + region, bank, 1, &rgn[bank_address], 0);
810      }
811   }
812
813   /* set initial audio banks --
814       how does this really work, or is it even neccessary? */
815   state->m_audio_cpu_banks[0] = 0x1e;
816   state->m_audio_cpu_banks[1] = 0x0e;
817   state->m_audio_cpu_banks[2] = 0x06;
818   state->m_audio_cpu_banks[3] = 0x02;
819
820   set_audio_cpu_banking(machine);
821
822   state->m_audio_cpu_rom_source_last = 0;
823   set_audio_cpu_rom_source(machine.device("maincpu")->memory().space(AS_PROGRAM), 0);
824}
825
826
827
828/*************************************
829 *
830 *  System control register
831 *
832 *************************************/
833
834static WRITE16_HANDLER( system_control_w )
835{
836   if (ACCESSING_BITS_0_7)
837   {
838      UINT8 bit = (offset >> 3) & 0x01;
839
840      switch (offset & 0x07)
841      {
842      default:
843      case 0x00: neogeo_set_screen_dark(space->machine(), bit); break;
844      case 0x01: set_main_cpu_vector_table_source(space->machine(), bit);
845               set_audio_cpu_rom_source(space, bit); /* this is a guess */
846               break;
847      case 0x05: neogeo_set_fixed_layer_source(space->machine(), bit); break;
848//      case 0x06: set_save_ram_unlock(space->machine(), bit); break;
849      case 0x07: neogeo_set_palette_bank(space->machine(), bit); break;
850
851      case 0x02: /* unknown - HC32 middle pin 1 */
852      case 0x03: /* unknown - uPD4990 pin ? */
853      case 0x04: /* unknown - HC32 middle pin 10 */
854         logerror("PC: %x  Unmapped system control write.  Offset: %x  Data: %x\n", cpu_get_pc(&space->device()), offset & 0x07, bit);
855         break;
856      }
857
858      if (LOG_VIDEO_SYSTEM && ((offset & 0x07) != 0x06)) logerror("PC: %x  System control write.  Offset: %x  Data: %x\n", cpu_get_pc(&space->device()), offset & 0x07, bit);
859   }
860}
861
862/*
863 *  CD-ROM / DMA control
864 *
865 *  DMA
866
867    FF0061  Write 0x40 means start DMA transfer
868    FF0064  Source address (in copy mode), Target address (in filll mode)
869    FF0068  Target address (in copy mode)
870    FF006C  Fill word
871    FF0070  Words count
872    FF007E  \
873    ......   | DMA programming words?   NeoGeoCD uses Sanyo Puppet LC8359 chip to
874    FF008E  /                           interface with CD, and do DMA transfers
875
876    Memory access control
877
878    FF011C  DIP SWITCH (Region code)
879    FF0105  Area Selector (5 = FIX, 0 = SPR, 4 = Z80, 1 = PCM)
880    FF01A1  Sprite bank selector
881    FF01A3  PCM bank selector
882    FF0120  Prepare sprite area for transfer
883    FF0122  Prepare PCM area for transfer
884    FF0126  Prepare Z80 area for transfer
885    FF0128  Prepare Fix area for transfer
886    FF0140  Terminate work on Spr Area  (Sprites must be decoded here)
887    FF0142  Terminate work on Pcm Area
888    FF0146  Terminate work on Z80 Area  (Z80 needs to be reset)
889    FF0148  Terminate work on Fix Area
890
891    CD-ROM:
892    0xff0102 == 0xF0 start cd transfer
893    int m=bcd(fast_r8(0x10f6c8));
894    int s=bcd(fast_r8(0x10f6c9));
895    int f=bcd(fast_r8(0x10f6ca));
896    int seccount=fast_r16(0x10f688);
897
898    inisec=((m*60)+s)*75+f;
899    inisec-=150;
900    dstaddr=0x111204; // this must come from somewhere
901
902    the value @ 0x10f688 is decremented each time a sector is read until it's 0.
903
904 *
905 */
906
907static void neocd_do_dma(address_space* space)
908{
909   ng_aes_state *state = space->machine().driver_data<ng_aes_state>();
910   // TODO: Proper DMA timing and control
911   int count;
912//  UINT16 word;
913
914   switch(state->m_neocd_ctrl.dma_mode[0])
915   {
916   case 0xffdd:
917      for(count=0;count<state->m_neocd_ctrl.word_count;count++)
918      {
919         //word = space->read_word(state->m_neocd_ctrl.addr_source);
920         space->write_word(state->m_neocd_ctrl.addr_source+(count*2),state->m_neocd_ctrl.fill_word);
921      }
922      logerror("CTRL: DMA word-fill transfer of %i bytes\n",count*2);
923      break;
924   case 0xfef5:
925      for(count=0;count<state->m_neocd_ctrl.word_count;count++)
926      {
927         //word = space->read_word(state->m_neocd_ctrl.addr_source);
928         space->write_word(state->m_neocd_ctrl.addr_source+(count*4),(state->m_neocd_ctrl.addr_source+(count*4)) >> 16);
929         space->write_word(state->m_neocd_ctrl.addr_source+(count*4)+2,(state->m_neocd_ctrl.addr_source+(count*4)) & 0xffff);
930      }
931      logerror("CTRL: DMA mode 2 transfer of %i bytes\n",count*4);
932      break;
933   case 0xcffd:
934      for(count=0;count<state->m_neocd_ctrl.word_count;count++)
935      {
936         //word = space->read_word(state->m_neocd_ctrl.addr_source);
937         space->write_word(state->m_neocd_ctrl.addr_source+(count*8),((state->m_neocd_ctrl.addr_source+(count*8)) >> 24) | 0xff00);
938         space->write_word(state->m_neocd_ctrl.addr_source+(count*8)+2,((state->m_neocd_ctrl.addr_source+(count*8)) >> 16) | 0xff00);
939         space->write_word(state->m_neocd_ctrl.addr_source+(count*8)+4,((state->m_neocd_ctrl.addr_source+(count*8)) >> 8) | 0xff00);
940         space->write_word(state->m_neocd_ctrl.addr_source+(count*8)+6,(state->m_neocd_ctrl.addr_source+(count*8)) | 0xff00);
941      }
942      logerror("CTRL: DMA mode 3 transfer of %i bytes\n",count*8);
943      break;
944   default:
945      logerror("CTRL: Unknown DMA transfer mode %04x\n",state->m_neocd_ctrl.dma_mode[0]);
946   }
947}
948
949static READ16_HANDLER( neocd_control_r )
950{
951   ng_aes_state *state = space->machine().driver_data<ng_aes_state>();
952
953   switch(offset)
954   {
955   case 0x64/2: // source address, high word
956      return (state->m_neocd_ctrl.addr_source >> 16) & 0xffff;
957   case 0x66/2: // source address, low word
958      return state->m_neocd_ctrl.addr_source & 0xffff;
959   case 0x68/2: // target address, high word
960      return (state->m_neocd_ctrl.addr_target >> 16) & 0xffff;
961   case 0x6a/2: // target address, low word
962      return state->m_neocd_ctrl.addr_target & 0xffff;
963   case 0x6c/2: // fill word
964      return state->m_neocd_ctrl.fill_word;
965   case 0x70/2: // word count
966      return (state->m_neocd_ctrl.word_count >> 16) & 0xffff;
967   case 0x72/2:
968      return state->m_neocd_ctrl.word_count & 0xffff;
969   case 0x7e/2:  // DMA parameters
970   case 0x80/2:
971   case 0x82/2:
972   case 0x84/2:
973   case 0x86/2:
974   case 0x88/2:
975   case 0x8a/2:
976   case 0x8c/2:
977   case 0x8e/2:
978      return state->m_neocd_ctrl.dma_mode[offset-(0x7e/2)];
979      break;
980   case 0x105/2:
981      return state->m_neocd_ctrl.area_sel;
982   case 0x11c/2:
983      logerror("CTRL: Read region code.\n");
984      return 0x0600;  // we'll just force USA region for now
985   case 0x1a0/2:
986      return state->m_neocd_ctrl.spr_bank_sel;
987      break;
988   case 0x1a2/2:
989      return state->m_neocd_ctrl.pcm_bank_sel;
990      break;
991   default:
992      logerror("CTRL: Read offset %04x\n",offset);
993   }
994
995   return 0;
996}
997
998static WRITE16_HANDLER( neocd_control_w )
999{
1000   ng_aes_state *state = space->machine().driver_data<ng_aes_state>();
1001   switch(offset)
1002   {
1003   case 0x60/2: // Start DMA transfer
1004      if((data & 0xff) == 0x40)
1005         neocd_do_dma(space);
1006      break;
1007   case 0x64/2: // source address, high word
1008      state->m_neocd_ctrl.addr_source = (state->m_neocd_ctrl.addr_source & 0x0000ffff) | (data << 16);
1009      logerror("CTRL: Set source address to %08x\n",state->m_neocd_ctrl.addr_source);
1010      break;
1011   case 0x66/2: // source address, low word
1012      state->m_neocd_ctrl.addr_source = (state->m_neocd_ctrl.addr_source & 0xffff0000) | data;
1013      logerror("CTRL: Set source address to %08x\n",state->m_neocd_ctrl.addr_source);
1014      break;
1015   case 0x68/2: // target address, high word
1016      state->m_neocd_ctrl.addr_target = (state->m_neocd_ctrl.addr_target & 0x0000ffff) | (data << 16);
1017      logerror("CTRL: Set target address to %08x\n",state->m_neocd_ctrl.addr_target);
1018      break;
1019   case 0x6a/2: // target address, low word
1020      state->m_neocd_ctrl.addr_target = (state->m_neocd_ctrl.addr_target & 0xffff0000) | data;
1021      logerror("CTRL: Set target address to %08x\n",state->m_neocd_ctrl.addr_target);
1022      break;
1023   case 0x6c/2: // fill word
1024      state->m_neocd_ctrl.fill_word = data;
1025      logerror("CTRL: Set fill word to %04x\n",data);
1026      break;
1027   case 0x70/2: // word count
1028      state->m_neocd_ctrl.word_count = (state->m_neocd_ctrl.word_count & 0x0000ffff) | (data << 16);
1029      logerror("CTRL: Set word count to %i\n",state->m_neocd_ctrl.word_count);
1030      break;
1031   case 0x72/2: // word count (low word)
1032      state->m_neocd_ctrl.word_count = (state->m_neocd_ctrl.word_count & 0xffff0000) | data;
1033      logerror("CTRL: Set word count to %i\n",state->m_neocd_ctrl.word_count);
1034      break;
1035   case 0x7e/2:  // DMA parameters
1036   case 0x80/2:
1037   case 0x82/2:
1038   case 0x84/2:
1039   case 0x86/2:
1040   case 0x88/2:
1041   case 0x8a/2:
1042   case 0x8c/2:
1043   case 0x8e/2:
1044      state->m_neocd_ctrl.dma_mode[offset-(0x7e/2)] = data;
1045      logerror("CTRL: DMA parameter %i set to %04x\n",offset-(0x7e/2),data);
1046      break;
1047   case 0x104/2:
1048      state->m_neocd_ctrl.area_sel = data & 0x00ff;
1049      logerror("CTRL: 0xExxxxx set to area %i\n",data & 0xff);
1050      break;
1051   case 0x140/2:  // end sprite transfer
1052      video_reset_neogeo(space->machine());
1053      break;
1054   case 0x142/2:  // end PCM transfer
1055      break;
1056   case 0x146/2:  // end Z80 transfer
1057      cputag_set_input_line(space->machine(),"audiocpu",INPUT_LINE_RESET,PULSE_LINE);
1058      break;
1059   case 0x148/2:  // end FIX transfer
1060      video_reset_neogeo(space->machine());
1061      break;
1062   case 0x1a0/2:
1063      state->m_neocd_ctrl.spr_bank_sel = data & 0xff;
1064      logerror("CTRL: Sprite area set to bank %i\n",data & 0xff);
1065      break;
1066   case 0x1a2/2:
1067      state->m_neocd_ctrl.pcm_bank_sel = data & 0xff;
1068      logerror("CTRL: PCM area set to bank %i\n",data & 0xff);
1069      break;
1070   default:
1071      logerror("CTRL: Write offset %04x, data %04x\n",offset*2,data);
1072   }
1073}
1074
1075/*
1076 *  Handling NeoCD banked RAM
1077 *  When the Z80 space is banked in to 0xe00000, only the low byte of each word is used
1078 */
1079
1080static READ16_HANDLER(neocd_transfer_r)
1081{
1082   ng_aes_state *state = space->machine().driver_data<ng_aes_state>();
1083   UINT16 ret = 0x0000;
1084   UINT8* Z80 = space->machine().region("audiocpu")->base();
1085   UINT8* PCM = space->machine().region("ymsnd")->base();
1086   UINT8* FIX = space->machine().region("fixed")->base();
1087   UINT16* SPR = (UINT16*)space->machine().region("sprites")->base();
1088
1089   switch(state->m_neocd_ctrl.area_sel)
1090   {
1091   case NEOCD_AREA_AUDIO:
1092      ret = Z80[offset & 0xffff] | 0xff00;
1093      break;
1094   case NEOCD_AREA_PCM:
1095      ret = PCM[offset + (0x100000*state->m_neocd_ctrl.pcm_bank_sel)] | 0xff00;
1096      break;
1097   case NEOCD_AREA_SPR:
1098      ret = SPR[offset + (0x80000*state->m_neocd_ctrl.spr_bank_sel)];
1099      break;
1100   case NEOCD_AREA_FIX:
1101      ret = FIX[offset & 0x1ffff] | 0xff00;
1102      break;
1103   }
1104
1105   return ret;
1106}
1107
1108static WRITE16_HANDLER(neocd_transfer_w)
1109{
1110   ng_aes_state *state = space->machine().driver_data<ng_aes_state>();
1111   UINT8* Z80 = space->machine().region("audiocpu")->base();
1112   UINT8* PCM = space->machine().region("ymsnd")->base();
1113   UINT8* FIX = space->machine().region("fixed")->base();
1114   UINT16* SPR = (UINT16*)space->machine().region("sprites")->base();
1115
1116   switch(state->m_neocd_ctrl.area_sel)
1117   {
1118   case NEOCD_AREA_AUDIO:
1119      Z80[offset & 0xffff] = data & 0xff;
1120      break;
1121   case NEOCD_AREA_PCM:
1122      PCM[offset + (0x100000*state->m_neocd_ctrl.pcm_bank_sel)] = data & 0xff;
1123      break;
1124   case NEOCD_AREA_SPR:
1125      COMBINE_DATA(SPR+(offset + (0x80000*state->m_neocd_ctrl.spr_bank_sel)));
1126      break;
1127   case NEOCD_AREA_FIX:
1128      FIX[offset & 0x1ffff] = data & 0xff;
1129      break;
1130   }
1131
1132}
1133
1134/*
1135 * Handling selectable controller types
1136 */
1137
1138static READ16_HANDLER( aes_in0_r )
1139{
1140   neogeo_state *state = space->machine().driver_data<neogeo_state>();
1141   UINT32 ret = 0xffff;
1142   UINT32 ctrl = input_port_read(space->machine(),"CTRLSEL");
1143
1144   switch(ctrl & 0x0f)
1145   {
1146   case 0x00:
1147      ret = 0xffff;
1148      break;
1149   case 0x01:
1150      ret = input_port_read(space->machine(),"IN0");
1151      break;
1152   case 0x02:
1153      switch (state->m_controller_select)
1154      {
1155         case 0x09: ret = input_port_read(space->machine(), "MJ01_P1"); break;
1156         case 0x12: ret = input_port_read(space->machine(), "MJ02_P1"); break;
1157         case 0x1b: ret = input_port_read(space->machine(), "MJ03_P1"); break; /* player 1 normal inputs? */
1158         case 0x24: ret = input_port_read(space->machine(), "MJ04_P1"); break;
1159         default:
1160            ret = input_port_read(space->machine(),"IN0");
1161            break;
1162      }
1163      break;
1164   }
1165
1166   return ret;
1167}
1168
1169static READ16_HANDLER( aes_in1_r )
1170{
1171   neogeo_state *state = space->machine().driver_data<neogeo_state>();
1172   UINT32 ret = 0xffff;
1173   UINT32 ctrl = input_port_read(space->machine(),"CTRLSEL");
1174
1175   switch(ctrl & 0xf0)
1176   {
1177   case 0x00:
1178      ret = 0xffff;
1179      break;
1180   case 0x10:
1181      ret = input_port_read(space->machine(),"IN1");
1182      break;
1183   case 0x20:
1184      switch (state->m_controller_select)
1185      {
1186         case 0x09: ret = input_port_read(space->machine(), "MJ01_P2"); break;
1187         case 0x12: ret = input_port_read(space->machine(), "MJ02_P2"); break;
1188         case 0x1b: ret = input_port_read(space->machine(), "MJ03_P2"); break; /* player 2 normal inputs? */
1189         case 0x24: ret = input_port_read(space->machine(), "MJ04_P2"); break;
1190         default:
1191            ret = input_port_read(space->machine(),"IN1");
1192            break;
1193      }
1194      break;
1195   }
1196
1197   return ret;
1198}
1199
1200
1201static READ16_HANDLER(aes_in2_r)
1202{
1203   UINT32 in2 = input_port_read(space->machine(),"IN2");
1204   UINT32 ret = in2;
1205   UINT32 sel = input_port_read(space->machine(),"CTRLSEL");
1206   neogeo_state *state = space->machine().driver_data<neogeo_state>();
1207
1208   if((sel & 0x02) && (state->m_controller_select == 0x24))
1209      ret ^= 0x0200;
1210
1211   if((sel & 0x20) && (state->m_controller_select == 0x24))
1212      ret ^= 0x0800;
1213
1214   return ret;
1215}
1216
1217
1218/*************************************
1219 *
1220 *  Machine initialization
1221 *
1222 *************************************/
1223
1224static void aes_postload(neogeo_state *state)
1225{
1226   _set_main_cpu_bank_address(state->machine());
1227   _set_main_cpu_vector_table_source(state->machine());
1228   set_audio_cpu_banking(state->machine());
1229   _set_audio_cpu_rom_source(state->machine().device("maincpu")->memory().space(AS_PROGRAM));
1230}
1231
1232static void common_machine_start(running_machine &machine)
1233{
1234   neogeo_state *state = machine.driver_data<neogeo_state>();
1235
1236   /* set the BIOS bank */
1237   memory_set_bankptr(machine, NEOGEO_BANK_BIOS, machine.region("mainbios")->base());
1238
1239   /* set the initial main CPU bank */
1240   main_cpu_banking_init(machine);
1241
1242   /* set the initial audio CPU ROM banks */
1243   audio_cpu_banking_init(machine);
1244
1245   create_interrupt_timers(machine);
1246
1247   /* start with an IRQ3 - but NOT on a reset */
1248   state->m_irq3_pending = 1;
1249
1250   /* get devices */
1251   state->m_maincpu = machine.device("maincpu");
1252   state->m_audiocpu = machine.device("audiocpu");
1253   state->m_upd4990a = machine.device("upd4990a");
1254
1255   /* register state save */
1256   state->save_item(NAME(state->m_display_position_interrupt_control));
1257   state->save_item(NAME(state->m_display_counter));
1258   state->save_item(NAME(state->m_vblank_interrupt_pending));
1259   state->save_item(NAME(state->m_display_position_interrupt_pending));
1260   state->save_item(NAME(state->m_irq3_pending));
1261   state->save_item(NAME(state->m_audio_result));
1262   state->save_item(NAME(state->m_controller_select));
1263   state->save_item(NAME(state->m_main_cpu_bank_address));
1264   state->save_item(NAME(state->m_main_cpu_vector_table_source));
1265   state->save_item(NAME(state->m_audio_cpu_banks));
1266   state->save_item(NAME(state->m_audio_cpu_rom_source));
1267   state->save_item(NAME(state->m_audio_cpu_rom_source_last));
1268   state->save_item(NAME(state->m_save_ram_unlocked));
1269   state->save_item(NAME(state->m_output_data));
1270   state->save_item(NAME(state->m_output_latch));
1271   state->save_item(NAME(state->m_el_value));
1272   state->save_item(NAME(state->m_led1_value));
1273   state->save_item(NAME(state->m_led2_value));
1274   state->save_item(NAME(state->m_recurse));
1275
1276   machine.save().register_postload(save_prepost_delegate(FUNC(aes_postload), state));
1277}
1278
1279static MACHINE_START( neogeo )
1280{
1281   ng_aes_state *state = machine.driver_data<ng_aes_state>();
1282   common_machine_start(machine);
1283
1284   /* initialize the memcard data structure */
1285   state->m_memcard_data = auto_alloc_array_clear(machine, UINT8, MEMCARD_SIZE);
1286   state->save_pointer(NAME(state->m_memcard_data), 0x0800);
1287}
1288
1289static MACHINE_START(neocd)
1290{
1291   ng_aes_state *state = machine.driver_data<ng_aes_state>();
1292   UINT8* ROM = machine.region("mainbios")->base();
1293   UINT8* RAM = machine.region("maincpu")->base();
1294   UINT8* Z80bios = machine.region("audiobios")->base();
1295   UINT8* FIXbios = machine.region("fixedbios")->base();
1296   int x;
1297
1298   common_machine_start(machine);
1299
1300   /* initialize the memcard data structure */
1301   /* NeoCD doesn't have memcard slots, rather, it has a larger internal memory which works the same */
1302   state->m_memcard_data = auto_alloc_array_clear(machine, UINT8, 0x2000);
1303   state->save_pointer(NAME(state->m_memcard_data), 0x2000);
1304
1305   // copy initial 68k vectors into RAM
1306   memcpy(RAM,ROM,0x80);
1307
1308   // copy Z80 code into Z80 space (from 0x20000)
1309   for(x=0;x<0x10000;x+=2)
1310   {
1311      Z80bios[x] = ROM[x+0x20001];
1312      Z80bios[x+1] = ROM[x+0x20000];
1313   }
1314
1315   // copy fixed tiles into FIX space (from 0x70000)
1316   memcpy(FIXbios,ROM+0x70000,0x10000);
1317}
1318
1319//static DEVICE_IMAGE_LOAD(aes_cart)
1320//{
1321//  else
1322//      return IMAGE_INIT_FAIL;
1323
1324//  return IMAGE_INIT_PASS;
1325//}
1326
1327/*************************************
1328 *
1329 *  Machine reset
1330 *
1331 *************************************/
1332
1333static MACHINE_RESET( neogeo )
1334{
1335   neogeo_state *state = machine.driver_data<neogeo_state>();
1336   offs_t offs;
1337   address_space *space = machine.device("maincpu")->memory().space(AS_PROGRAM);
1338
1339   /* reset system control registers */
1340   for (offs = 0; offs < 8; offs++)
1341      system_control_w(space, offs, 0, 0x00ff);
1342
1343   machine.device("maincpu")->reset();
1344
1345   neogeo_reset_rng(machine);
1346
1347   start_interrupt_timers(machine);
1348
1349   /* trigger the IRQ3 that was set by MACHINE_START */
1350   update_interrupts(machine);
1351
1352   state->m_recurse = 0;
1353
1354   /* AES apparently always uses the cartridge's fixed bank mode */
1355   neogeo_set_fixed_layer_source(machine,1);
1356}
1357
1358
1359
1360/*************************************
1361 *
1362 *  Main CPU memory handlers
1363 *
1364 *************************************/
1365
1366static ADDRESS_MAP_START( main_map, AS_PROGRAM, 16 )
1367   AM_RANGE(0x000000, 0x00007f) AM_ROMBANK(NEOGEO_BANK_VECTORS)
1368   AM_RANGE(0x000080, 0x0fffff) AM_ROM
1369   AM_RANGE(0x100000, 0x10ffff) AM_MIRROR(0x0f0000) AM_RAM
1370   /* some games have protection devices in the 0x200000 region, it appears to map to cart space, not surprising, the ROM is read here too */
1371   AM_RANGE(0x200000, 0x2fffff) AM_ROMBANK(NEOGEO_BANK_CARTRIDGE)
1372   AM_RANGE(0x2ffff0, 0x2fffff) AM_WRITE(main_cpu_bank_select_w)
1373   AM_RANGE(0x300000, 0x300001) AM_MIRROR(0x01ff7e) AM_READ(aes_in0_r)
1374   AM_RANGE(0x300080, 0x300081) AM_MIRROR(0x01ff7e) AM_READ_PORT("IN4")
1375   AM_RANGE(0x300000, 0x300001) AM_MIRROR(0x01ffe0) AM_READ(neogeo_unmapped_r) AM_WRITENOP   // AES has no watchdog
1376   AM_RANGE(0x320000, 0x320001) AM_MIRROR(0x01fffe) AM_READ_PORT("IN3") AM_WRITE(audio_command_w)
1377   AM_RANGE(0x340000, 0x340001) AM_MIRROR(0x01fffe) AM_READ(aes_in1_r)
1378   AM_RANGE(0x360000, 0x37ffff) AM_READ(neogeo_unmapped_r)
1379   AM_RANGE(0x380000, 0x380001) AM_MIRROR(0x01fffe) AM_READ(aes_in2_r)
1380   AM_RANGE(0x380000, 0x38007f) AM_MIRROR(0x01ff80) AM_WRITE(io_control_w)
1381   AM_RANGE(0x3a0000, 0x3a001f) AM_MIRROR(0x01ffe0) AM_READWRITE(neogeo_unmapped_r, system_control_w)
1382   AM_RANGE(0x3c0000, 0x3c0007) AM_MIRROR(0x01fff8) AM_READ(neogeo_video_register_r)
1383   AM_RANGE(0x3c0000, 0x3c000f) AM_MIRROR(0x01fff0) AM_WRITE(neogeo_video_register_w)
1384   AM_RANGE(0x3e0000, 0x3fffff) AM_READ(neogeo_unmapped_r)
1385   AM_RANGE(0x400000, 0x401fff) AM_MIRROR(0x3fe000) AM_READWRITE(neogeo_paletteram_r, neogeo_paletteram_w)
1386   AM_RANGE(0x800000, 0x800fff) AM_READWRITE(memcard_r, memcard_w)
1387   AM_RANGE(0xc00000, 0xc1ffff) AM_MIRROR(0x0e0000) AM_ROMBANK(NEOGEO_BANK_BIOS)
1388   AM_RANGE(0xd00000, 0xd0ffff) AM_MIRROR(0x0f0000) AM_READ(neogeo_unmapped_r) //AM_RAM_WRITE(save_ram_w) AM_BASE(&save_ram)
1389   AM_RANGE(0xe00000, 0xffffff) AM_READ(neogeo_unmapped_r)
1390ADDRESS_MAP_END
1391
1392static ADDRESS_MAP_START( neocd_main_map, AS_PROGRAM, 16 )
1393   AM_RANGE(0x000000, 0x00007f) AM_RAMBANK(NEOGEO_BANK_VECTORS)
1394   AM_RANGE(0x000080, 0x0fffff) AM_RAM
1395   AM_RANGE(0x100000, 0x10ffff) AM_MIRROR(0x0f0000) AM_RAM AM_BASE(&neocd_work_ram)
1396   /* some games have protection devices in the 0x200000 region, it appears to map to cart space, not surprising, the ROM is read here too */
1397   AM_RANGE(0x200000, 0x2fffff) AM_ROMBANK(NEOGEO_BANK_CARTRIDGE)
1398   AM_RANGE(0x2ffff0, 0x2fffff) AM_WRITE(main_cpu_bank_select_w)
1399   AM_RANGE(0x300000, 0x300001) AM_MIRROR(0x01ff7e) AM_READ(aes_in0_r)
1400   AM_RANGE(0x300080, 0x300081) AM_MIRROR(0x01ff7e) AM_READ_PORT("IN4")
1401   AM_RANGE(0x300000, 0x300001) AM_MIRROR(0x01ffe0) AM_READ(neogeo_unmapped_r) AM_WRITENOP   // AES has no watchdog
1402   AM_RANGE(0x320000, 0x320001) AM_MIRROR(0x01fffe) AM_READ_PORT("IN3") AM_WRITE(audio_command_w)
1403   AM_RANGE(0x340000, 0x340001) AM_MIRROR(0x01fffe) AM_READ(aes_in1_r)
1404   AM_RANGE(0x360000, 0x37ffff) AM_READ(neogeo_unmapped_r)
1405   AM_RANGE(0x380000, 0x380001) AM_MIRROR(0x01fffe) AM_READ(aes_in2_r)
1406   AM_RANGE(0x380000, 0x38007f) AM_MIRROR(0x01ff80) AM_WRITE(io_control_w)
1407   AM_RANGE(0x3a0000, 0x3a001f) AM_MIRROR(0x01ffe0) AM_READWRITE(neogeo_unmapped_r, system_control_w)
1408   AM_RANGE(0x3c0000, 0x3c0007) AM_MIRROR(0x01fff8) AM_READ(neogeo_video_register_r)
1409   AM_RANGE(0x3c0000, 0x3c000f) AM_MIRROR(0x01fff0) AM_WRITE(neogeo_video_register_w)
1410   AM_RANGE(0x3e0000, 0x3fffff) AM_READ(neogeo_unmapped_r)
1411   AM_RANGE(0x400000, 0x401fff) AM_MIRROR(0x3fe000) AM_READWRITE(neogeo_paletteram_r, neogeo_paletteram_w)
1412   AM_RANGE(0x800000, 0x803fff) AM_READWRITE(neocd_memcard_r, neocd_memcard_w)
1413   AM_RANGE(0xc00000, 0xcfffff) AM_ROMBANK(NEOGEO_BANK_BIOS)
1414   AM_RANGE(0xd00000, 0xd0ffff) AM_MIRROR(0x0f0000) AM_READ(neogeo_unmapped_r) //AM_RAM_WRITE(save_ram_w) AM_BASE(&save_ram)
1415   AM_RANGE(0xe00000, 0xefffff) AM_READWRITE(neocd_transfer_r,neocd_transfer_w)
1416   AM_RANGE(0xf00000, 0xfeffff) AM_READ(neogeo_unmapped_r)
1417   AM_RANGE(0xff0000, 0xff01ff) AM_READWRITE(neocd_control_r, neocd_control_w) // CDROM / DMA
1418   AM_RANGE(0xff0200, 0xffffff) AM_READ(neogeo_unmapped_r)
1419ADDRESS_MAP_END
1420
1421
1422/*************************************
1423 *
1424 *  Audio CPU memory handlers
1425 *
1426 *************************************/
1427
1428static ADDRESS_MAP_START( audio_map, AS_PROGRAM, 8 )
1429   AM_RANGE(0x0000, 0x7fff) AM_ROMBANK(NEOGEO_BANK_AUDIO_CPU_MAIN_BANK)
1430   AM_RANGE(0x8000, 0xbfff) AM_ROMBANK(NEOGEO_BANK_AUDIO_CPU_CART_BANK + 3)
1431   AM_RANGE(0xc000, 0xdfff) AM_ROMBANK(NEOGEO_BANK_AUDIO_CPU_CART_BANK + 2)
1432   AM_RANGE(0xe000, 0xefff) AM_ROMBANK(NEOGEO_BANK_AUDIO_CPU_CART_BANK + 1)
1433   AM_RANGE(0xf000, 0xf7ff) AM_ROMBANK(NEOGEO_BANK_AUDIO_CPU_CART_BANK + 0)
1434   AM_RANGE(0xf800, 0xffff) AM_RAM
1435ADDRESS_MAP_END
1436
1437
1438
1439/*************************************
1440 *
1441 *  Audio CPU port handlers
1442 *
1443 *************************************/
1444
1445static ADDRESS_MAP_START( audio_io_map, AS_IO, 8 )
1446  /*AM_RANGE(0x00, 0x00) AM_MIRROR(0xff00) AM_READWRITE(audio_command_r, audio_cpu_clear_nmi_w);*/  /* may not and NMI clear */
1447   AM_RANGE(0x00, 0x00) AM_MIRROR(0xff00) AM_READ(audio_command_r)
1448   AM_RANGE(0x04, 0x07) AM_MIRROR(0xff00) AM_DEVREADWRITE("ymsnd", ym2610_r, ym2610_w)
1449   AM_RANGE(0x08, 0x08) AM_MIRROR(0xff00) /* write - NMI enable / acknowledge? (the data written doesn't matter) */
1450   AM_RANGE(0x08, 0x08) AM_MIRROR(0xfff0) AM_MASK(0xfff0) AM_READ(audio_cpu_bank_select_f000_f7ff_r)
1451   AM_RANGE(0x09, 0x09) AM_MIRROR(0xfff0) AM_MASK(0xfff0) AM_READ(audio_cpu_bank_select_e000_efff_r)
1452   AM_RANGE(0x0a, 0x0a) AM_MIRROR(0xfff0) AM_MASK(0xfff0) AM_READ(audio_cpu_bank_select_c000_dfff_r)
1453   AM_RANGE(0x0b, 0x0b) AM_MIRROR(0xfff0) AM_MASK(0xfff0) AM_READ(audio_cpu_bank_select_8000_bfff_r)
1454   AM_RANGE(0x0c, 0x0c) AM_MIRROR(0xff00) AM_WRITE(audio_result_w)
1455   AM_RANGE(0x18, 0x18) AM_MIRROR(0xff00) /* write - NMI disable? (the data written doesn't matter) */
1456ADDRESS_MAP_END
1457
1458
1459
1460/*************************************
1461 *
1462 *  Audio interface
1463 *
1464 *************************************/
1465
1466static const ym2610_interface ym2610_config =
1467{
1468   audio_cpu_irq
1469};
1470
1471
1472
1473/*************************************
1474 *
1475 *  Standard Neo-Geo DIPs and
1476 *  input port definition
1477 *
1478 *************************************/
1479
1480#define STANDARD_DIPS                                                      \
1481   PORT_DIPNAME( 0x0001, 0x0001, "Test Switch" ) PORT_DIPLOCATION("SW:1")               \
1482   PORT_DIPSETTING(     0x0001, DEF_STR( Off ) )                                 \
1483   PORT_DIPSETTING(     0x0000, DEF_STR( On ) )                                 \
1484   PORT_DIPNAME( 0x0002, 0x0002, "Coin Chutes?" ) PORT_DIPLOCATION("SW:2")               \
1485   PORT_DIPSETTING(     0x0000, "1?" )                                       \
1486   PORT_DIPSETTING(     0x0002, "2?" )                                       \
1487   PORT_DIPNAME( 0x0004, 0x0004, "Autofire (in some games)" ) PORT_DIPLOCATION("SW:3")      \
1488   PORT_DIPSETTING(     0x0004, DEF_STR( Off ) )                                 \
1489   PORT_DIPSETTING(     0x0000, DEF_STR( On ) )                                 \
1490   PORT_DIPNAME( 0x0018, 0x0018, "COMM Setting (Cabinet No.)" ) PORT_DIPLOCATION("SW:4,5")   \
1491   PORT_DIPSETTING(     0x0018, "1" )                                          \
1492   PORT_DIPSETTING(     0x0008, "2" )                                          \
1493   PORT_DIPSETTING(     0x0010, "3" )                                          \
1494   PORT_DIPSETTING(     0x0000, "4" )                                          \
1495   PORT_DIPNAME( 0x0020, 0x0020, "COMM Setting (Link Enable)" ) PORT_DIPLOCATION("SW:6")   \
1496   PORT_DIPSETTING(     0x0020, DEF_STR( Off ) )                                 \
1497   PORT_DIPSETTING(     0x0000, DEF_STR( On ) )                                 \
1498   PORT_DIPNAME( 0x0040, 0x0040, DEF_STR( Free_Play ) ) PORT_DIPLOCATION("SW:7")         \
1499   PORT_DIPSETTING(     0x0040, DEF_STR( Off ) )                                 \
1500   PORT_DIPSETTING(     0x0000, DEF_STR( On ) )                                 \
1501   PORT_DIPNAME( 0x0080, 0x0080, "Freeze" ) PORT_DIPLOCATION("SW:8")                  \
1502   PORT_DIPSETTING(     0x0080, DEF_STR( Off ) )                                 \
1503   PORT_DIPSETTING(     0x0000, DEF_STR( On ) )
1504
1505#define STANDARD_IN2                                                            \
1506   PORT_START("IN2")                                                            \
1507   PORT_BIT( 0x00ff, IP_ACTIVE_LOW, IPT_UNUSED )                                       \
1508   PORT_BIT( 0x0100, IP_ACTIVE_LOW, IPT_START1 )                           \
1509   PORT_BIT( 0x0200, IP_ACTIVE_LOW, IPT_BUTTON5) PORT_NAME("1P Select") PORT_CODE(KEYCODE_5) PORT_PLAYER(1)   \
1510   PORT_BIT( 0x0400, IP_ACTIVE_LOW, IPT_START2 )                           \
1511   PORT_BIT( 0x0800, IP_ACTIVE_LOW, IPT_BUTTON5) PORT_NAME("2P Select") PORT_CODE(KEYCODE_6) PORT_PLAYER(2)   \
1512   PORT_BIT( 0x7000, IP_ACTIVE_HIGH, IPT_SPECIAL ) PORT_CUSTOM(get_memcard_status, NULL)         \
1513   PORT_BIT( 0x8000, IP_ACTIVE_HIGH, IPT_UNKNOWN )  /* Matrimelee expects this bit to be active high when on an AES */
1514
1515#define STANDARD_IN3                                                            \
1516   PORT_START("IN3")                                                            \
1517   PORT_BIT( 0x0001, IP_ACTIVE_LOW, IPT_UNUSED )  /* Coin 1 - AES has no coin slots, it's a console */   \
1518   PORT_BIT( 0x0002, IP_ACTIVE_LOW, IPT_UNUSED )  /* Coin 2 - AES has no coin slots, it's a console */   \
1519   PORT_BIT( 0x0004, IP_ACTIVE_LOW, IPT_UNUSED )  /* Service Coin - not used, AES is a console */   \
1520   PORT_BIT( 0x0008, IP_ACTIVE_HIGH, IPT_UNKNOWN ) /* having this ACTIVE_HIGH causes you to start with 2 credits using USA bios roms */   \
1521   PORT_BIT( 0x0010, IP_ACTIVE_HIGH, IPT_UNKNOWN ) /* having this ACTIVE_HIGH causes you to start with 2 credits using USA bios roms */   \
1522   PORT_BIT( 0x0020, IP_ACTIVE_LOW, IPT_SPECIAL ) /* what is this? */                        \
1523   PORT_BIT( 0x00c0, IP_ACTIVE_HIGH, IPT_SPECIAL ) PORT_CUSTOM(get_calendar_status, NULL)         \
1524   PORT_BIT( 0xff00, IP_ACTIVE_HIGH, IPT_SPECIAL ) PORT_CUSTOM(get_audio_result, NULL)
1525
1526
1527#define STANDARD_IN4                                                         \
1528   PORT_START("IN4")                                                         \
1529   PORT_BIT( 0x0001, IP_ACTIVE_HIGH, IPT_UNKNOWN )                                    \
1530   PORT_BIT( 0x0002, IP_ACTIVE_HIGH, IPT_UNKNOWN )                                    \
1531   PORT_BIT( 0x0004, IP_ACTIVE_HIGH, IPT_UNKNOWN )                                    \
1532   PORT_BIT( 0x0008, IP_ACTIVE_HIGH, IPT_UNKNOWN )                                    \
1533   PORT_BIT( 0x0010, IP_ACTIVE_HIGH, IPT_UNKNOWN )                                    \
1534   PORT_BIT( 0x0020, IP_ACTIVE_HIGH, IPT_UNKNOWN )                                    \
1535   PORT_BIT( 0x0040, IP_ACTIVE_HIGH, IPT_SPECIAL ) /* what is this? - is 0 for 1 or 2 slot MVS (and AES?)*/                     \
1536   PORT_BIT( 0x0080, IP_ACTIVE_LOW, IPT_OTHER ) PORT_NAME("Enter BIOS") PORT_CODE(KEYCODE_F2)   \
1537   PORT_BIT( 0xff00, IP_ACTIVE_LOW, IPT_UNUSED )
1538
1539static INPUT_PORTS_START( controller )
1540   PORT_START("IN0")
1541   PORT_BIT( 0x00ff, IP_ACTIVE_LOW, IPT_UNUSED )
1542   PORT_BIT( 0x0100, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) PORT_PLAYER(1) PORT_CATEGORY (1)
1543   PORT_BIT( 0x0200, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) PORT_PLAYER(1) PORT_CATEGORY (1)
1544   PORT_BIT( 0x0400, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) PORT_PLAYER(1) PORT_CATEGORY (1)
1545   PORT_BIT( 0x0800, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) PORT_PLAYER(1) PORT_CATEGORY (1)
1546   PORT_BIT( 0x1000, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_PLAYER(1) PORT_CATEGORY (1)
1547   PORT_BIT( 0x2000, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_PLAYER(1) PORT_CATEGORY (1)
1548   PORT_BIT( 0x4000, IP_ACTIVE_LOW, IPT_BUTTON3 ) PORT_PLAYER(1) PORT_CATEGORY (1)
1549   PORT_BIT( 0x8000, IP_ACTIVE_LOW, IPT_BUTTON4 ) PORT_PLAYER(1) PORT_CATEGORY (1)
1550
1551
1552   PORT_START("IN1")
1553   PORT_BIT( 0x00ff, IP_ACTIVE_LOW, IPT_UNUSED )
1554   PORT_BIT( 0x0100, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) PORT_PLAYER(2) PORT_CATEGORY (2)
1555   PORT_BIT( 0x0200, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) PORT_PLAYER(2) PORT_CATEGORY (2)
1556   PORT_BIT( 0x0400, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) PORT_PLAYER(2) PORT_CATEGORY (2)
1557   PORT_BIT( 0x0800, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) PORT_PLAYER(2) PORT_CATEGORY (2)
1558   PORT_BIT( 0x1000, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_PLAYER(2) PORT_CATEGORY (2)
1559   PORT_BIT( 0x2000, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_PLAYER(2) PORT_CATEGORY (2)
1560   PORT_BIT( 0x4000, IP_ACTIVE_LOW, IPT_BUTTON3 ) PORT_PLAYER(2) PORT_CATEGORY (2)
1561   PORT_BIT( 0x8000, IP_ACTIVE_LOW, IPT_BUTTON4 ) PORT_PLAYER(2) PORT_CATEGORY (2)
1562INPUT_PORTS_END
1563
1564static INPUT_PORTS_START( mjpanel )
1565   PORT_START("MJ01_P1")
1566   PORT_BIT( 0x00ff, IP_ACTIVE_HIGH, IPT_UNUSED )
1567   PORT_BIT( 0x0100, IP_ACTIVE_LOW, IPT_MAHJONG_A ) PORT_PLAYER(1) PORT_CATEGORY (3)
1568   PORT_BIT( 0x0200, IP_ACTIVE_LOW, IPT_MAHJONG_B ) PORT_PLAYER(1) PORT_CATEGORY (3)
1569   PORT_BIT( 0x0400, IP_ACTIVE_LOW, IPT_MAHJONG_C ) PORT_PLAYER(1) PORT_CATEGORY (3)
1570   PORT_BIT( 0x0800, IP_ACTIVE_LOW, IPT_MAHJONG_D ) PORT_PLAYER(1) PORT_CATEGORY (3)
1571   PORT_BIT( 0x1000, IP_ACTIVE_LOW, IPT_MAHJONG_E ) PORT_PLAYER(1) PORT_CATEGORY (3)
1572   PORT_BIT( 0x2000, IP_ACTIVE_LOW, IPT_MAHJONG_F ) PORT_PLAYER(1) PORT_CATEGORY (3)
1573   PORT_BIT( 0x4000, IP_ACTIVE_LOW, IPT_MAHJONG_G ) PORT_PLAYER(1) PORT_CATEGORY (3)
1574   PORT_BIT( 0x8000, IP_ACTIVE_LOW, IPT_UNKNOWN )
1575
1576   PORT_START("MJ02_P1")
1577   PORT_BIT( 0x00ff, IP_ACTIVE_HIGH, IPT_UNUSED )
1578   PORT_BIT( 0x0100, IP_ACTIVE_LOW, IPT_MAHJONG_H ) PORT_PLAYER(1) PORT_CATEGORY (3)
1579   PORT_BIT( 0x0200, IP_ACTIVE_LOW, IPT_MAHJONG_I ) PORT_PLAYER(1) PORT_CATEGORY (3)
1580   PORT_BIT( 0x0400, IP_ACTIVE_LOW, IPT_MAHJONG_J ) PORT_PLAYER(1) PORT_CATEGORY (3)
1581   PORT_BIT( 0x0800, IP_ACTIVE_LOW, IPT_MAHJONG_K ) PORT_PLAYER(1) PORT_CATEGORY (3)
1582   PORT_BIT( 0x1000, IP_ACTIVE_LOW, IPT_MAHJONG_L ) PORT_PLAYER(1) PORT_CATEGORY (3)
1583   PORT_BIT( 0x2000, IP_ACTIVE_LOW, IPT_MAHJONG_M ) PORT_PLAYER(1) PORT_CATEGORY (3)
1584   PORT_BIT( 0x4000, IP_ACTIVE_LOW, IPT_MAHJONG_N ) PORT_PLAYER(1) PORT_CATEGORY (3)
1585   PORT_BIT( 0x8000, IP_ACTIVE_LOW, IPT_BUTTON6 ) PORT_PLAYER(1) PORT_CATEGORY (3)
1586
1587   PORT_START("MJ03_P1")
1588   PORT_BIT( 0x00ff, IP_ACTIVE_HIGH, IPT_UNUSED )
1589   PORT_BIT( 0x0100, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) PORT_PLAYER(1) PORT_CATEGORY (3)
1590   PORT_BIT( 0x0200, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) PORT_PLAYER(1) PORT_CATEGORY (3)
1591   PORT_BIT( 0x0400, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) PORT_PLAYER(1) PORT_CATEGORY (3)
1592   PORT_BIT( 0x0800, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) PORT_PLAYER(1) PORT_CATEGORY (3)
1593   PORT_BIT( 0x1000, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_PLAYER(1) PORT_CATEGORY (3)
1594   PORT_BIT( 0x2000, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_PLAYER(1) PORT_CATEGORY (3)
1595   PORT_BIT( 0x4000, IP_ACTIVE_LOW, IPT_BUTTON3 ) PORT_PLAYER(1) PORT_CATEGORY (3)
1596   PORT_BIT( 0x8000, IP_ACTIVE_LOW, IPT_BUTTON4 ) PORT_PLAYER(1) PORT_CATEGORY (3)
1597
1598   PORT_START("MJ04_P1")
1599   PORT_BIT( 0x00ff, IP_ACTIVE_HIGH, IPT_UNUSED )
1600   PORT_BIT( 0x0100, IP_ACTIVE_LOW, IPT_MAHJONG_PON ) PORT_PLAYER(1) PORT_CATEGORY (3)
1601   PORT_BIT( 0x0200, IP_ACTIVE_LOW, IPT_MAHJONG_CHI ) PORT_PLAYER(1) PORT_CATEGORY (3)
1602   PORT_BIT( 0x0400, IP_ACTIVE_LOW, IPT_MAHJONG_KAN ) PORT_PLAYER(1) PORT_CATEGORY (3)
1603   PORT_BIT( 0x0800, IP_ACTIVE_LOW, IPT_MAHJONG_RON ) PORT_PLAYER(1) PORT_CATEGORY (3)
1604   PORT_BIT( 0x1000, IP_ACTIVE_LOW, IPT_MAHJONG_REACH ) PORT_PLAYER(1) PORT_CATEGORY (3)
1605   PORT_BIT( 0x2000, IP_ACTIVE_LOW, IPT_UNKNOWN )
1606   PORT_BIT( 0x4000, IP_ACTIVE_LOW, IPT_UNKNOWN )
1607   PORT_BIT( 0x8000, IP_ACTIVE_LOW, IPT_UNKNOWN )
1608
1609   PORT_START("MJ01_P2")
1610   PORT_BIT( 0x00ff, IP_ACTIVE_HIGH, IPT_UNUSED )
1611   PORT_BIT( 0x0100, IP_ACTIVE_LOW, IPT_MAHJONG_A ) PORT_PLAYER(2) PORT_CATEGORY (4)
1612   PORT_BIT( 0x0200, IP_ACTIVE_LOW, IPT_MAHJONG_B ) PORT_PLAYER(2) PORT_CATEGORY (4)
1613   PORT_BIT( 0x0400, IP_ACTIVE_LOW, IPT_MAHJONG_C ) PORT_PLAYER(2) PORT_CATEGORY (4)
1614   PORT_BIT( 0x0800, IP_ACTIVE_LOW, IPT_MAHJONG_D ) PORT_PLAYER(2) PORT_CATEGORY (4)
1615   PORT_BIT( 0x1000, IP_ACTIVE_LOW, IPT_MAHJONG_E ) PORT_PLAYER(2) PORT_CATEGORY (4)
1616   PORT_BIT( 0x2000, IP_ACTIVE_LOW, IPT_MAHJONG_F ) PORT_PLAYER(2) PORT_CATEGORY (4)
1617   PORT_BIT( 0x4000, IP_ACTIVE_LOW, IPT_MAHJONG_G ) PORT_PLAYER(2) PORT_CATEGORY (4)
1618   PORT_BIT( 0x8000, IP_ACTIVE_LOW, IPT_UNKNOWN )
1619
1620   PORT_START("MJ02_P2")
1621   PORT_BIT( 0x00ff, IP_ACTIVE_HIGH, IPT_UNUSED )
1622   PORT_BIT( 0x0100, IP_ACTIVE_LOW, IPT_MAHJONG_H ) PORT_PLAYER(2) PORT_CATEGORY (4)
1623   PORT_BIT( 0x0200, IP_ACTIVE_LOW, IPT_MAHJONG_I ) PORT_PLAYER(2) PORT_CATEGORY (4)
1624   PORT_BIT( 0x0400, IP_ACTIVE_LOW, IPT_MAHJONG_J ) PORT_PLAYER(2) PORT_CATEGORY (4)
1625   PORT_BIT( 0x0800, IP_ACTIVE_LOW, IPT_MAHJONG_K ) PORT_PLAYER(2) PORT_CATEGORY (4)
1626   PORT_BIT( 0x1000, IP_ACTIVE_LOW, IPT_MAHJONG_L ) PORT_PLAYER(2) PORT_CATEGORY (4)
1627   PORT_BIT( 0x2000, IP_ACTIVE_LOW, IPT_MAHJONG_M ) PORT_PLAYER(2) PORT_CATEGORY (4)
1628   PORT_BIT( 0x4000, IP_ACTIVE_LOW, IPT_MAHJONG_N ) PORT_PLAYER(2) PORT_CATEGORY (4)
1629   PORT_BIT( 0x8000, IP_ACTIVE_LOW, IPT_UNKNOWN )
1630
1631   PORT_START("MJ03_P2")
1632   PORT_BIT( 0x00ff, IP_ACTIVE_HIGH, IPT_UNUSED )
1633   PORT_BIT( 0x0100, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) PORT_PLAYER(2) PORT_CATEGORY (4)
1634   PORT_BIT( 0x0200, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) PORT_PLAYER(2) PORT_CATEGORY (4)
1635   PORT_BIT( 0x0400, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) PORT_PLAYER(2) PORT_CATEGORY (4)
1636   PORT_BIT( 0x0800, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) PORT_PLAYER(2) PORT_CATEGORY (4)
1637   PORT_BIT( 0x1000, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_PLAYER(2) PORT_CATEGORY (4)
1638   PORT_BIT( 0x2000, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_PLAYER(2) PORT_CATEGORY (4)
1639   PORT_BIT( 0x4000, IP_ACTIVE_LOW, IPT_BUTTON3 ) PORT_PLAYER(2) PORT_CATEGORY (4)
1640   PORT_BIT( 0x8000, IP_ACTIVE_LOW, IPT_BUTTON4 ) PORT_PLAYER(2) PORT_CATEGORY (4)
1641
1642   PORT_START("MJ04_P2")
1643   PORT_BIT( 0x00ff, IP_ACTIVE_HIGH, IPT_UNUSED )
1644   PORT_BIT( 0x0100, IP_ACTIVE_LOW, IPT_MAHJONG_PON ) PORT_PLAYER(2) PORT_CATEGORY (4)
1645   PORT_BIT( 0x0200, IP_ACTIVE_LOW, IPT_MAHJONG_CHI ) PORT_PLAYER(2) PORT_CATEGORY (4)
1646   PORT_BIT( 0x0400, IP_ACTIVE_LOW, IPT_MAHJONG_KAN ) PORT_PLAYER(2) PORT_CATEGORY (4)
1647   PORT_BIT( 0x0800, IP_ACTIVE_LOW, IPT_MAHJONG_RON ) PORT_PLAYER(2) PORT_CATEGORY (4)
1648   PORT_BIT( 0x1000, IP_ACTIVE_LOW, IPT_MAHJONG_REACH ) PORT_PLAYER(2) PORT_CATEGORY (4)
1649   PORT_BIT( 0x2000, IP_ACTIVE_LOW, IPT_UNKNOWN )
1650   PORT_BIT( 0x4000, IP_ACTIVE_LOW, IPT_UNKNOWN )
1651   PORT_BIT( 0x8000, IP_ACTIVE_LOW, IPT_UNKNOWN )
1652
1653INPUT_PORTS_END
1654
1655static INPUT_PORTS_START( aes )
1656// was there anyting in place of dipswitch in the home console?
1657/*  PORT_START("IN0")
1658    PORT_BIT( 0x00ff, IP_ACTIVE_LOW, IPT_UNUSED )
1659//  PORT_DIPNAME( 0x0001, 0x0001, "Test Switch" ) PORT_DIPLOCATION("SW:1")
1660//  PORT_DIPSETTING(      0x0001, DEF_STR( Off ) )
1661//  PORT_DIPSETTING(      0x0000, DEF_STR( On ) )
1662//  PORT_DIPNAME( 0x0002, 0x0002, "Coin Chutes?" ) PORT_DIPLOCATION("SW:2")
1663//  PORT_DIPSETTING(      0x0000, "1?" )
1664//  PORT_DIPSETTING(      0x0002, "2?" )
1665//  PORT_DIPNAME( 0x0004, 0x0000, "Mahjong Control Panel (or Auto Fire)" ) PORT_DIPLOCATION("SW:3")
1666//  PORT_DIPSETTING(      0x0004, DEF_STR( Off ) )
1667//  PORT_DIPSETTING(      0x0000, DEF_STR( On ) )
1668//  PORT_DIPNAME( 0x0018, 0x0018, "COMM Setting (Cabinet No.)" ) PORT_DIPLOCATION("SW:4,5")
1669//  PORT_DIPSETTING(      0x0018, "1" )
1670//  PORT_DIPSETTING(      0x0008, "2" )
1671//  PORT_DIPSETTING(      0x0010, "3" )
1672//  PORT_DIPSETTING(      0x0000, "4" )
1673//  PORT_DIPNAME( 0x0020, 0x0020, "COMM Setting (Link Enable)" ) PORT_DIPLOCATION("SW:6")
1674//  PORT_DIPSETTING(      0x0020, DEF_STR( Off ) )
1675//  PORT_DIPSETTING(      0x0000, DEF_STR( On ) )
1676//  PORT_DIPNAME( 0x0040, 0x0040, DEF_STR( Free_Play ) ) PORT_DIPLOCATION("SW:7")
1677//  PORT_DIPSETTING(      0x0040, DEF_STR( Off ) )
1678//  PORT_DIPSETTING(      0x0000, DEF_STR( On ) )
1679//  PORT_DIPNAME( 0x0080, 0x0080, "Freeze" ) PORT_DIPLOCATION("SW:8")
1680//  PORT_DIPSETTING(      0x0080, DEF_STR( Off ) )
1681//  PORT_DIPSETTING(      0x0000, DEF_STR( On ) )
1682    PORT_BIT( 0xff00, IP_ACTIVE_HIGH, IPT_SPECIAL ) PORT_CUSTOM(aes_controller_r, NULL) */
1683
1684   PORT_START("CTRLSEL")  /* Select Controller Type */
1685   PORT_CATEGORY_CLASS( 0x0f, 0x01, "P1 Controller")
1686   PORT_CATEGORY_ITEM(  0x00, "Unconnected",         0 )
1687   PORT_CATEGORY_ITEM(  0x01, "NeoGeo Controller",      1 )
1688   PORT_CATEGORY_ITEM(  0x02, "NeoGeo Mahjong Panel",   3 )
1689   PORT_CATEGORY_CLASS( 0xf0, 0x10, "P2 Controller")
1690   PORT_CATEGORY_ITEM(  0x00, "Unconnected",      0 )
1691   PORT_CATEGORY_ITEM(  0x10, "NeoGeo Controller",      2 )
1692   PORT_CATEGORY_ITEM(  0x20, "NeoGeo Mahjong Panel",   4 )
1693
1694   PORT_INCLUDE( controller )
1695
1696   PORT_INCLUDE( mjpanel )
1697
1698// were some of these present in the AES?!?
1699   STANDARD_IN2
1700
1701   STANDARD_IN3
1702
1703   STANDARD_IN4
1704INPUT_PORTS_END
1705
1706
1707
1708/*************************************
1709 *
1710 *  Machine driver
1711 *
1712 *************************************/
1713
1714static MACHINE_CONFIG_START( neogeo, ng_aes_state )
1715
1716   /* basic machine hardware */
1717   MCFG_CPU_ADD("maincpu", M68000, NEOGEO_MAIN_CPU_CLOCK)
1718   MCFG_CPU_PROGRAM_MAP(main_map)
1719
1720   MCFG_CPU_ADD("audiocpu", Z80, NEOGEO_AUDIO_CPU_CLOCK)
1721   MCFG_CPU_PROGRAM_MAP(audio_map)
1722   MCFG_CPU_IO_MAP(audio_io_map)
1723
1724   MCFG_MACHINE_START(neogeo)
1725   MCFG_MACHINE_RESET(neogeo)
1726
1727   /* video hardware */
1728   MCFG_VIDEO_START(neogeo)
1729   MCFG_VIDEO_RESET(neogeo)
1730   MCFG_DEFAULT_LAYOUT(layout_neogeo)
1731
1732   MCFG_SCREEN_ADD("screen", RASTER)
1733   MCFG_SCREEN_FORMAT(BITMAP_FORMAT_RGB32)
1734   MCFG_SCREEN_RAW_PARAMS(NEOGEO_PIXEL_CLOCK, NEOGEO_HTOTAL, NEOGEO_HBEND, NEOGEO_HBSTART, NEOGEO_VTOTAL, NEOGEO_VBEND, NEOGEO_VBSTART)
1735   MCFG_SCREEN_UPDATE(neogeo)
1736
1737   /* audio hardware */
1738   MCFG_SPEAKER_STANDARD_STEREO("lspeaker", "rspeaker")
1739
1740   MCFG_SOUND_ADD("ymsnd", YM2610, NEOGEO_YM2610_CLOCK)
1741   MCFG_SOUND_CONFIG(ym2610_config)
1742   MCFG_SOUND_ROUTE(0, "lspeaker",  0.60)
1743   MCFG_SOUND_ROUTE(0, "rspeaker", 0.60)
1744   MCFG_SOUND_ROUTE(1, "lspeaker",  1.0)
1745   MCFG_SOUND_ROUTE(2, "rspeaker", 1.0)
1746
1747   /* NEC uPD4990A RTC */
1748   MCFG_UPD4990A_ADD("upd4990a")
1749MACHINE_CONFIG_END
1750
1751static MACHINE_CONFIG_DERIVED( aes, neogeo )
1752
1753   MCFG_MEMCARD_HANDLER(neogeo)
1754
1755   MCFG_AES_CARTRIDGE_ADD("aes_multicart")
1756//  MCFG_CARTSLOT_ADD("cart")
1757//  MCFG_CARTSLOT_MANDATORY
1758
1759//  MCFG_CARTSLOT_LOAD(aes_cart)
1760
1761   MCFG_SOFTWARE_LIST_ADD("cart_list","aes")
1762MACHINE_CONFIG_END
1763
1764static MACHINE_CONFIG_DERIVED( neocd, neogeo )
1765
1766   MCFG_CPU_MODIFY("maincpu")
1767   MCFG_CPU_PROGRAM_MAP(neocd_main_map)
1768
1769   MCFG_MACHINE_START(neocd)
1770MACHINE_CONFIG_END
1771
1772/*************************************
1773 *
1774 *  Driver initalization
1775 *
1776 *************************************/
1777
1778static DRIVER_INIT( neogeo )
1779{
1780}
1781
1782
1783ROM_START( aes )
1784   ROM_REGION16_BE( 0x80000, "mainbios", 0 )
1785   ROM_SYSTEM_BIOS( 0, "jap-aes",   "Japan AES" )
1786   ROMX_LOAD("neo-po.bin",  0x00000, 0x020000, CRC(16d0c132) SHA1(4e4a440cae46f3889d20234aebd7f8d5f522e22c), ROM_GROUPWORD | ROM_REVERSE | ROM_BIOS(1))   /* AES Console (Japan) Bios */
1787   ROM_SYSTEM_BIOS( 1, "asia-aes",   "Asia AES" )
1788   ROMX_LOAD("neo-epo.bin", 0x00000, 0x020000, CRC(d27a71f1) SHA1(1b3b22092f30c4d1b2c15f04d1670eb1e9fbea07), ROM_GROUPWORD | ROM_REVERSE | ROM_BIOS(2))   /* AES Console (Asia?) Bios */
1789//  ROM_SYSTEM_BIOS( 2, "uni-bios_2_3","Universe Bios (Hack, Ver. 2.3)" )
1790//  ROMX_LOAD( "uni-bios_2_3.rom",  0x00000, 0x020000, CRC(27664eb5) SHA1(5b02900a3ccf3df168bdcfc98458136fd2b92ac0), ROM_GROUPWORD | ROM_REVERSE | ROM_BIOS(3) ) /* Universe Bios v2.3 (hack) */
1791
1792   ROM_REGION( 0x200000, "maincpu", ROMREGION_ERASEFF )
1793
1794   ROM_REGION( 0x20000, "audiobios", 0 )
1795   ROM_LOAD( "sm1.sm1", 0x00000, 0x20000, CRC(94416d67) SHA1(42f9d7ddd6c0931fd64226a60dc73602b2819dcf) )
1796
1797   ROM_REGION( 0x90000, "audiocpu", ROMREGION_ERASEFF )
1798
1799   ROM_REGION( 0x20000, "zoomy", 0 )
1800   ROM_LOAD( "000-lo.lo", 0x00000, 0x20000, CRC(5a86cff2) SHA1(5992277debadeb64d1c1c64b0a92d9293eaf7e4a) )
1801
1802   ROM_REGION( 0x20000, "fixedbios", 0 )
1803   ROM_LOAD( "sfix.sfix", 0x000000, 0x20000, CRC(c2ea0cfd) SHA1(fd4a618cdcdbf849374f0a50dd8efe9dbab706c3) )
1804
1805   ROM_REGION( 0x20000, "fixed", ROMREGION_ERASEFF )
1806
1807   ROM_REGION( 0x1000000, "ymsnd", ROMREGION_ERASEFF )
1808
1809   ROM_REGION( 0x1000000, "ymsnd.deltat", ROMREGION_ERASEFF )
1810
1811   ROM_REGION( 0x900000, "sprites", ROMREGION_ERASEFF )
1812ROM_END
1813
1814ROM_START( neocd )
1815   ROM_REGION16_BE( 0x100000, "mainbios", 0 )
1816   ROM_LOAD16_WORD_SWAP( "top-sp1.bin",    0x00000, 0x80000, CRC(19f0ad1a) SHA1(b3e2f8467e9a642c122428d075024a9bd1fe0679) )
1817
1818   ROM_REGION( 0x200000, "maincpu", ROMREGION_ERASEFF )
1819
1820   ROM_REGION( 0x100000, "audiobios", ROMREGION_ERASEFF )
1821
1822   ROM_REGION( 0x10000, "audiocpu", ROMREGION_ERASEFF )
1823
1824   ROM_REGION( 0x20000, "zoomy", 0 )
1825   ROM_LOAD( "000-lo.lo", 0x00000, 0x20000, CRC(5a86cff2) SHA1(5992277debadeb64d1c1c64b0a92d9293eaf7e4a) )
1826
1827   ROM_REGION( 0x20000, "fixedbios", ROMREGION_ERASEFF )
1828
1829   ROM_REGION( 0x20000, "fixed", ROMREGION_ERASEFF )
1830
1831   ROM_REGION( 0x400000, "ymsnd", ROMREGION_ERASEFF )
1832
1833//    NO_DELTAT_REGION
1834
1835   ROM_REGION( 0x400000, "sprites", ROMREGION_ERASEFF )
1836ROM_END
1837
1838ROM_START( neocdz )
1839   ROM_REGION16_BE( 0x100000, "mainbios", 0 )
1840   ROM_LOAD16_WORD_SWAP( "neocd.bin",    0x00000, 0x80000, CRC(df9de490) SHA1(7bb26d1e5d1e930515219cb18bcde5b7b23e2eda) )
1841
1842   ROM_REGION( 0x200000, "maincpu", ROMREGION_ERASEFF )
1843
1844   ROM_REGION( 0x20000, "audiobios", ROMREGION_ERASEFF )
1845
1846   ROM_REGION( 0x10000, "audiocpu", ROMREGION_ERASEFF )
1847
1848   ROM_REGION( 0x20000, "zoomy", 0 )
1849   ROM_LOAD( "000-lo.lo", 0x00000, 0x20000, CRC(5a86cff2) SHA1(5992277debadeb64d1c1c64b0a92d9293eaf7e4a) )
1850
1851   ROM_REGION( 0x20000, "fixedbios", ROMREGION_ERASEFF )
1852
1853   ROM_REGION( 0x20000, "fixed", ROMREGION_ERASEFF )
1854
1855   ROM_REGION( 0x400000, "ymsnd", ROMREGION_ERASEFF )
1856
1857//    NO_DELTAT_REGION
1858
1859   ROM_REGION( 0x400000, "sprites", ROMREGION_ERASEFF )
1860ROM_END
1861
1862/*    YEAR  NAME  PARENT COMPAT MACHINE INPUT  INIT     COMPANY      FULLNAME            FLAGS */
1863CONS( 1990, aes,    0,   0,   aes,      aes,   neogeo,  "SNK", "Neo-Geo AES", 0)
1864CONS( 1994, neocd,  aes, 0,   neocd,    aes,   neogeo,  "SNK", "Neo-Geo CD", GAME_NOT_WORKING )
1865CONS( 1996, neocdz, aes, 0,   neocd,    aes,   neogeo,  "SNK", "Neo-Geo CDZ", GAME_NOT_WORKING )
src/mess/drivers/ami1200.c
r0r11532
1/*
2    Amiga 1200
3
4    Preliminary MAME driver by Mariusz Wojcieszek
5    CD-ROM controller by Ernesto Corvi
6    Borrowed by incog for MESS
7
8    2009-05 Fabio Priuli:
9    Amiga 1200 support is just sketched (I basically took cd32 and removed Akiko). I connected
10    the floppy drive in the same way as in amiga.c but it seems to be not working, since I
11    tried to load WB3.1 with no success. However, this problem may be due to anything: maybe
12    the floppy code must be connected elsewhere, or the .adf image is broken, or I made some
13    stupid mistake in the CIA interfaces.
14    Later, it could be wise to re-factor this source and merge the non-AGA code with
15    mess/drivers/amiga.c
16*/
17
18#include "emu.h"
19#include "cpu/m68000/m68000.h"
20#include "machine/6526cia.h"
21#include "machine/i2cmem.h"
22#include "machine/amigafdc.h"
23#include "machine/amigakbd.h"
24
25#include "includes/amiga.h"
26#include "includes/cd32.h"
27
28
29
30class ami1200_state : public cd32_state
31{
32public:
33   ami1200_state(const machine_config &mconfig, device_type type, const char *tag)
34      : cd32_state(mconfig, type, tag) { }
35
36   UINT16 potgo_value;
37   int cd32_shifter[2];
38   int oldstate[2];
39};
40
41
42
43#define A1200PAL_XTAL_X1  XTAL_28_37516MHz
44#define A1200PAL_XTAL_X2  XTAL_4_433619MHz
45
46
47
48static void handle_cd32_joystick_cia(ami1200_state *state, UINT8 pra, UINT8 dra);
49
50static WRITE32_HANDLER( aga_overlay_w )
51{
52   if (ACCESSING_BITS_16_23)
53   {
54      data = (data >> 16) & 1;
55
56      /* switch banks as appropriate */
57      memory_set_bank(space->machine(), "bank1", data & 1);
58
59      /* swap the write handlers between ROM and bank 1 based on the bit */
60      if ((data & 1) == 0)
61         /* overlay disabled, map RAM on 0x000000 */
62         space->install_write_bank(0x000000, 0x1fffff, "bank1");
63      else
64         /* overlay enabled, map Amiga system ROM on 0x000000 */
65         space->unmap_write(0x000000, 0x1fffff);
66   }
67}
68
69/*************************************
70 *
71 *  CIA-A port A access:
72 *
73 *  PA7 = game port 1, pin 6 (fire)
74 *  PA6 = game port 0, pin 6 (fire)
75 *  PA5 = /RDY (disk ready)
76 *  PA4 = /TK0 (disk track 00)
77 *  PA3 = /WPRO (disk write protect)
78 *  PA2 = /CHNG (disk change)
79 *  PA1 = /LED (LED, 0=bright / audio filter control)
80 *  PA0 = MUTE
81 *
82 *************************************/
83
84static WRITE8_DEVICE_HANDLER( ami1200_cia_0_porta_w )
85{
86   ami1200_state *state = device->machine().driver_data<ami1200_state>();
87
88   /* bit 2 = Power Led on Amiga */
89   set_led_status(device->machine(), 0, !BIT(data, 1));
90
91   handle_cd32_joystick_cia(state, data, mos6526_r(device, 2));
92}
93
94/*************************************
95 *
96 *  CIA-A port B access:
97 *
98 *  PB7 = parallel data 7
99 *  PB6 = parallel data 6
100 *  PB5 = parallel data 5
101 *  PB4 = parallel data 4
102 *  PB3 = parallel data 3
103 *  PB2 = parallel data 2
104 *  PB1 = parallel data 1
105 *  PB0 = parallel data 0
106 *
107 *************************************/
108
109static READ8_DEVICE_HANDLER( ami1200_cia_0_portb_r )
110{
111   /* parallel port */
112   logerror("%s:CIA0_portb_r\n", device->machine().describe_context());
113   return 0xff;
114}
115
116static WRITE8_DEVICE_HANDLER( ami1200_cia_0_portb_w )
117{
118   /* parallel port */
119   logerror("%s:CIA0_portb_w(%02x)\n", device->machine().describe_context(), data);
120}
121
122static ADDRESS_MAP_START( a1200_map, AS_PROGRAM, 32 )
123   ADDRESS_MAP_UNMAP_HIGH
124   AM_RANGE(0x000000, 0x1fffff) AM_RAMBANK("bank1") AM_BASE_SIZE_MEMBER(cd32_state, m_chip_ram, m_chip_ram_size)
125   AM_RANGE(0xbfa000, 0xbfa003) AM_WRITE(aga_overlay_w)
126   AM_RANGE(0xbfd000, 0xbfefff) AM_READWRITE16(amiga_cia_r, amiga_cia_w, 0xffffffff)
127   AM_RANGE(0xc00000, 0xdfffff) AM_READWRITE16(amiga_custom_r, amiga_custom_w, 0xffffffff) AM_BASE_MEMBER(cd32_state, m_custom_regs)
128   AM_RANGE(0xe80000, 0xe8ffff) AM_READWRITE16(amiga_autoconfig_r, amiga_autoconfig_w, 0xffffffff)
129   AM_RANGE(0xf80000, 0xffffff) AM_ROM AM_REGION("user1", 0)   /* Kickstart */
130ADDRESS_MAP_END
131
132
133//int cd32_input_port_val = 0;
134//int cd32_input_select = 0;
135
136static void cd32_potgo_w(running_machine &machine, UINT16 data)
137{
138   ami1200_state *state = machine.driver_data<ami1200_state>();
139   int i;
140
141   state->m_potgo_value = state->m_potgo_value & 0x5500;
142   state->m_potgo_value |= data & 0xaa00;
143
144   for (i = 0; i < 8; i += 2)
145   {
146      UINT16 dir = 0x0200 << i;
147      if (data & dir)
148      {
149         UINT16 d = 0x0100 << i;
150         state->m_potgo_value &= ~d;
151         state->m_potgo_value |= data & d;
152      }
153   }
154   for (i = 0; i < 2; i++)
155   {
156      UINT16 p5dir = 0x0200 << (i * 4); /* output enable P5 */
157      UINT16 p5dat = 0x0100 << (i * 4); /* data P5 */
158      if ((state->m_potgo_value & p5dir) && (state->m_potgo_value & p5dat))
159         state->m_cd32_shifter[i] = 8;
160   }
161}
162
163static void handle_cd32_joystick_cia(ami1200_state *state, UINT8 pra, UINT8 dra)
164{
165   int i;
166
167   for (i = 0; i < 2; i++)
168   {
169      UINT8 but = 0x40 << i;
170      UINT16 p5dir = 0x0200 << (i * 4); /* output enable P5 */
171      UINT16 p5dat = 0x0100 << (i * 4); /* data P5 */
172      if (!(state->m_potgo_value & p5dir) || !(state->m_potgo_value & p5dat))
173      {
174         if ((dra & but) && (pra & but) != state->m_oldstate[i])
175         {
176            if (!(pra & but))
177            {
178               state->m_cd32_shifter[i]--;
179               if (state->m_cd32_shifter[i] < 0)
180                  state->m_cd32_shifter[i] = 0;
181            }
182         }
183      }
184      state->m_oldstate[i] = pra & but;
185   }
186}
187
188
189static INPUT_PORTS_START( a1200 )
190   PORT_START("CIA0PORTA")
191   PORT_BIT( 0x3f, IP_ACTIVE_LOW, IPT_SPECIAL )
192   PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_PLAYER(1)
193   PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_PLAYER(2)
194
195   PORT_START("CIA0PORTB")
196   PORT_BIT( 0xff, IP_ACTIVE_LOW, IPT_UNUSED )
197
198   PORT_START("JOY0DAT")
199   PORT_BIT( 0x0303, IP_ACTIVE_HIGH, IPT_SPECIAL ) PORT_CUSTOM(amiga_joystick_convert, "P1JOY")
200   PORT_BIT( 0xfcfc, IP_ACTIVE_HIGH, IPT_UNUSED )
201
202   PORT_START("JOY1DAT")
203   PORT_BIT( 0x0303, IP_ACTIVE_HIGH, IPT_SPECIAL ) PORT_CUSTOM(amiga_joystick_convert, "P2JOY")
204   PORT_BIT( 0xfcfc, IP_ACTIVE_HIGH, IPT_UNUSED )
205
206   PORT_START("POTGO")
207   PORT_BIT( 0x0100, IP_ACTIVE_LOW, IPT_UNUSED )
208   PORT_BIT( 0x0400, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_PLAYER(1)
209   PORT_BIT( 0x1000, IP_ACTIVE_LOW, IPT_UNUSED )
210   PORT_BIT( 0x4000, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_PLAYER(2)
211   PORT_BIT( 0xaaff, IP_ACTIVE_HIGH, IPT_UNUSED )
212
213   PORT_START("P1JOY")
214   PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_JOYSTICK_UP ) PORT_PLAYER(1)
215   PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_JOYSTICK_DOWN ) PORT_PLAYER(1)
216   PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_JOYSTICK_LEFT ) PORT_PLAYER(1)
217   PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_JOYSTICK_RIGHT ) PORT_PLAYER(1)
218
219   PORT_START("P2JOY")
220   PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_JOYSTICK_UP ) PORT_PLAYER(2)
221   PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_JOYSTICK_DOWN ) PORT_PLAYER(2)
222   PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_JOYSTICK_LEFT ) PORT_PLAYER(2)
223   PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_JOYSTICK_RIGHT ) PORT_PLAYER(2)
224
225   PORT_START("P0MOUSEX")
226   PORT_BIT( 0xff, 0x00, IPT_MOUSE_X) PORT_SENSITIVITY(100) PORT_KEYDELTA(5) PORT_MINMAX(0, 255) PORT_PLAYER(1)
227
228   PORT_START("P0MOUSEY")
229   PORT_BIT( 0xff, 0x00, IPT_MOUSE_Y) PORT_SENSITIVITY(100) PORT_KEYDELTA(5) PORT_MINMAX(0, 255) PORT_PLAYER(1)
230
231   PORT_START("P1MOUSEX")
232   PORT_BIT( 0xff, 0x00, IPT_MOUSE_X) PORT_SENSITIVITY(100) PORT_KEYDELTA(5) PORT_MINMAX(0, 255) PORT_PLAYER(2)
233
234   PORT_START("P1MOUSEY")
235   PORT_BIT( 0xff, 0x00, IPT_MOUSE_Y) PORT_SENSITIVITY(100) PORT_KEYDELTA(5) PORT_MINMAX(0, 255) PORT_PLAYER(2)
236
237   PORT_INCLUDE( amiga_us_keyboard )
238INPUT_PORTS_END
239
240
241/*************************************
242 *
243 *  Sound definitions
244 *
245 *************************************/
246
247static READ8_DEVICE_HANDLER( a1200_cia_0_portA_r )
248{
249   UINT8 ret = input_port_read(device->machine(), "CIA0PORTA") & 0xc0;   /* Gameport 1 and 0 buttons */
250   ret |= amiga_fdc_status_r(device->machine().device("fdc"));
251   return ret;
252}
253
254
255static const mos6526_interface a1200_cia_0_intf =
256{
257   0,                                       /* tod_clock */
258   DEVCB_LINE(amiga_cia_0_irq),                           /* irq_func */
259   DEVCB_NULL,   /* pc_func */
260   DEVCB_NULL,
261   DEVCB_NULL,
262   DEVCB_HANDLER(a1200_cia_0_portA_r),
263   DEVCB_HANDLER(ami1200_cia_0_porta_w),      /* port A */
264   DEVCB_HANDLER(ami1200_cia_0_portb_r),
265   DEVCB_HANDLER(ami1200_cia_0_portb_w)      /* port B */
266};
267
268static const mos6526_interface a1200_cia_1_intf =
269{
270   0,                                       /* tod_clock */
271   DEVCB_LINE(amiga_cia_1_irq),                           /* irq_func */
272   DEVCB_NULL,   /* pc_func */
273   DEVCB_NULL,
274   DEVCB_NULL,
275   DEVCB_NULL,
276   DEVCB_NULL,                           /* port A */
277   DEVCB_NULL,
278   DEVCB_DEVICE_HANDLER("fdc", amiga_fdc_control_w)         /* port B */
279};
280
281
282static MACHINE_CONFIG_START( a1200n, ami1200_state )
283
284   /* basic machine hardware */
285   MCFG_CPU_ADD("maincpu", M68EC020, AMIGA_68EC020_NTSC_CLOCK) /* 14.3 Mhz */
286   MCFG_CPU_PROGRAM_MAP(a1200_map)
287
288//  MCFG_CPU_ADD("keyboard_mpu", MC68HC05)
289
290   MCFG_MACHINE_RESET(amiga)
291
292   /* video hardware */
293   MCFG_VIDEO_ATTRIBUTES(VIDEO_UPDATE_BEFORE_VBLANK)
294
295   MCFG_SCREEN_ADD("screen", RASTER)
296   MCFG_SCREEN_REFRESH_RATE(59.997)
297   MCFG_SCREEN_VBLANK_TIME(ATTOSECONDS_IN_USEC(0))
298   MCFG_SCREEN_FORMAT(BITMAP_FORMAT_RGB32)
299   MCFG_SCREEN_SIZE(512*2, 312)
300   MCFG_SCREEN_VISIBLE_AREA((129-8-8)*2, (449+8-1+8)*2, 44-8, 300+8-1)
301   MCFG_SCREEN_UPDATE(amiga_aga)
302
303   MCFG_VIDEO_START(amiga_aga)
304
305   /* sound hardware */
306   MCFG_SPEAKER_STANDARD_STEREO("lspeaker", "rspeaker")
307
308   MCFG_SOUND_ADD("amiga", AMIGA, XTAL_28_63636MHz/8)
309   MCFG_SOUND_ROUTE(0, "lspeaker", 0.25)
310   MCFG_SOUND_ROUTE(1, "rspeaker", 0.25)
311   MCFG_SOUND_ROUTE(2, "rspeaker", 0.25)
312   MCFG_SOUND_ROUTE(3, "lspeaker", 0.25)
313
314   /* cia */
315   MCFG_MOS8520_ADD("cia_0", AMIGA_68EC020_NTSC_CLOCK / 10, a1200_cia_0_intf)
316   MCFG_MOS8520_ADD("cia_1", AMIGA_68EC020_NTSC_CLOCK / 10, a1200_cia_1_intf)
317
318   MCFG_AMIGA_FDC_ADD("fdc")
319MACHINE_CONFIG_END
320
321static MACHINE_CONFIG_DERIVED( a1200p, a1200n )
322
323   /* adjust for PAL specs */
324   MCFG_CPU_MODIFY("maincpu")
325   MCFG_CPU_CLOCK(A1200PAL_XTAL_X1/2) /* 14.18758 MHz */
326
327   /* video hardware */
328   MCFG_SCREEN_MODIFY("screen")
329   MCFG_SCREEN_REFRESH_RATE(50)
330
331   /* sound hardware */
332   MCFG_SOUND_MODIFY("amiga")
333   MCFG_SOUND_CLOCK(A1200PAL_XTAL_X1/8) /* 3.546895 MHz */
334
335   /* cia */
336   MCFG_DEVICE_MODIFY("cia_0")
337   MCFG_DEVICE_CLOCK(A1200PAL_XTAL_X1/20)
338   MCFG_DEVICE_MODIFY("cia_1")
339   MCFG_DEVICE_CLOCK(A1200PAL_XTAL_X1/20)
340MACHINE_CONFIG_END
341
342
343/***************************************************************************
344    ROM DEFINITIONS
345***************************************************************************/
346
347ROM_START( a1200n )
348   ROM_REGION32_BE(0x080000, "user1", 0)
349   ROM_DEFAULT_BIOS("kick31")
350   ROM_SYSTEM_BIOS(0, "kick30", "Kickstart 3.0 (39.106)")
351   ROMX_LOAD("391523-01.u6a", 0x000000, 0x040000, CRC(c742a412) SHA1(999eb81c65dfd07a71ee19315d99c7eb858ab186), ROM_GROUPWORD | ROM_REVERSE | ROM_SKIP(2) | ROM_BIOS(1))
352   ROMX_LOAD("391524-01.u6b", 0x000002, 0x040000, CRC(d55c6ec6) SHA1(3341108d3a402882b5ef9d3b242cbf3c8ab1a3e9), ROM_GROUPWORD | ROM_REVERSE | ROM_SKIP(2) | ROM_BIOS(1))
353   ROM_SYSTEM_BIOS(1, "kick31", "Kickstart 3.1 (40.068)")
354   ROMX_LOAD("391773-01.u6a", 0x000000, 0x040000, CRC(08dbf275) SHA1(b8800f5f909298109ea69690b1b8523fa22ddb37), ROM_GROUPWORD | ROM_REVERSE | ROM_SKIP(2) | ROM_BIOS(2))   // ROM_LOAD32_WORD_SWAP!
355   ROMX_LOAD("391774-01.u6b", 0x000002, 0x040000, CRC(16c07bf8) SHA1(90e331be1970b0e53f53a9b0390b51b59b3869c2), ROM_GROUPWORD | ROM_REVERSE | ROM_SKIP(2) | ROM_BIOS(2))
356
357   // COMMODORE | 391508-01 REV0 | KEYBOARD MPU
358   ROM_REGION(0x1040, "keyboard_rev0", 0)
359   ROM_LOAD("391508-01.u13", 0x0000, 0x1040, NO_DUMP)
360
361   // Amiga Tech REV1 Keyboard MPU
362   ROM_REGION(0x2f40, "keyboard_rev1", 0)
363   ROM_LOAD("391508-02.u13", 0x0000, 0x2f40, NO_DUMP)
364ROM_END
365
366#define rom_a1200p    rom_a1200n
367
368
369/***************************************************************************************************/
370
371// these come directly from amiga.c
372
373static UINT16 a1200_read_dskbytr(running_machine &machine)
374{
375   return amiga_fdc_get_byte(machine.device("fdc"));
376}
377
378static void a1200_write_dsklen(running_machine &machine, UINT16 data)
379{
380   cd32_state *state = machine.driver_data<cd32_state>();
381   if ( data & 0x8000 )
382   {
383      if ( CUSTOM_REG(REG_DSKLEN) & 0x8000 )
384         amiga_fdc_setup_dma(machine.device("fdc"));
385   }
386}
387
388
389static DRIVER_INIT( a1200 )
390{
391   cd32_state *state = machine.driver_data<cd32_state>();
392   static const amiga_machine_interface cd32_intf =
393   {
394      AGA_CHIP_RAM_MASK,
395      NULL, NULL,         /* joy0dat_r & joy1dat_r */
396      cd32_potgo_w,      /* potgo_w */
397      a1200_read_dskbytr, a1200_write_dsklen, /* dskbytr_r & dsklen_w */
398      NULL,            /* serdat_w */
399      NULL,            /* scanline0_callback */
400      NULL,            /* reset_callback */
401      NULL,            /* nmi_callback */
402      FLAGS_AGA_CHIPSET   /* flags */
403   };
404
405   /* configure our Amiga setup */
406   amiga_machine_config(machine, &cd32_intf);
407
408   /* set up memory */
409   memory_configure_bank(machine, "bank1", 0, 1, state->m_chip_ram, 0);
410   memory_configure_bank(machine, "bank1", 1, 1, machine.region("user1")->base(), 0);
411
412   /* initialize keyboard */
413   amigakbd_init(machine);
414}
415
416
417/***************************************************************************************************/
418
419/*    YEAR  NAME     PARENT   COMPAT  MACHINE INPUT   INIT      COMPANY       FULLNAME */
420COMP( 1992, a1200n,  0,       0,      a1200n, a1200,  a1200,  "Commodore Business Machines",  "Amiga 1200 (NTSC)" , GAME_NOT_WORKING )
421COMP( 1992, a1200p,  a1200n,  0,      a1200p, a1200,  a1200,  "Commodore Business Machines",  "Amiga 1200 (PAL)" , GAME_NOT_WORKING  )
src/mess/drivers/nes.c
r0r11532
1/***************************************************************************
2
3  nes.c
4
5  Driver file to handle emulation of the Nintendo Entertainment System (Famicom).
6
7  MESS driver by Brad Oliver (bradman@pobox.com), NES sound code by Matt Conte.
8  Based in part on the old xNes code, by Nicolas Hamel, Chuck Mason, Brad Oliver,
9  Richard Bannister and Jeff Mitchell.
10
11***************************************************************************/
12
13#include "emu.h"
14#include "video/ppu2c0x.h"
15#include "machine/nes_mmc.h"
16#include "includes/nes.h"
17#include "cpu/m6502/m6502.h"
18#include "imagedev/cartslot.h"
19#include "sound/nes_apu.h"
20#include "imagedev/flopdrv.h"
21#include "formats/nes_dsk.h"
22
23
24static READ8_DEVICE_HANDLER( psg_4015_r )
25{
26   return nes_psg_r(device, 0x15);
27}
28
29static WRITE8_DEVICE_HANDLER( psg_4015_w )
30{
31   nes_psg_w(device, 0x15, data);
32}
33
34static WRITE8_DEVICE_HANDLER( psg_4017_w )
35{
36   nes_psg_w(device, 0x17, data);
37}
38
39static WRITE8_HANDLER(nes_vh_sprite_dma_w)
40{
41   nes_state *state = space->machine().driver_data<nes_state>();
42   ppu2c0x_spriteram_dma(space, state->m_ppu, data);
43}
44
45static ADDRESS_MAP_START( nes_map, AS_PROGRAM, 8 )
46   AM_RANGE(0x0000, 0x07ff) AM_RAM AM_MIRROR(0x1800)               /* RAM */
47   AM_RANGE(0x2000, 0x3fff) AM_DEVREADWRITE("ppu", ppu2c0x_r, ppu2c0x_w)      /* PPU registers */
48   AM_RANGE(0x4000, 0x4013) AM_DEVREADWRITE("nessound", nes_psg_r, nes_psg_w)      /* PSG primary registers */
49   AM_RANGE(0x4014, 0x4014) AM_WRITE(nes_vh_sprite_dma_w)            /* stupid address space hole */
50   AM_RANGE(0x4015, 0x4015) AM_DEVREADWRITE("nessound", psg_4015_r, psg_4015_w)      /* PSG status / first control register */
51   AM_RANGE(0x4016, 0x4016) AM_READWRITE(nes_IN0_r, nes_IN0_w)         /* IN0 - input port 1 */
52   AM_RANGE(0x4017, 0x4017) AM_READ(nes_IN1_r)                     /* IN1 - input port 2 */
53   AM_RANGE(0x4017, 0x4017) AM_DEVWRITE("nessound", psg_4017_w)      /* PSG second control register */
54   AM_RANGE(0x4100, 0x5fff) AM_READWRITE(nes_low_mapper_r, nes_low_mapper_w)   /* Perform unholy acts on the machine */
55ADDRESS_MAP_END
56
57
58static INPUT_PORTS_START( nes_controllers )
59   PORT_START("CTRLSEL")  /* Select Controller Type */
60   PORT_CATEGORY_CLASS( 0x000f, 0x0001, "P1 Controller")
61   PORT_CATEGORY_ITEM(  0x0000, "Unconnected",      0 )
62   PORT_CATEGORY_ITEM(  0x0001, "Gamepad",         1 )
63   PORT_CATEGORY_ITEM(  0x0002, "Zapper",         5 )
64   PORT_CATEGORY_ITEM(  0x0006, "Crazy Climber pad", 10 )
65   PORT_CATEGORY_CLASS( 0x00f0, 0x0010, "P2 Controller")
66   PORT_CATEGORY_ITEM(  0x0000, "Unconnected",      0 )
67   PORT_CATEGORY_ITEM(  0x0010, "Gamepad",         2 )
68   PORT_CATEGORY_ITEM(  0x0030, "Zapper",         6 )
69   PORT_CATEGORY_ITEM(  0x0040, "Arkanoid paddle",   7 )
70//  PORT_CATEGORY_ITEM(  0x0050, "Family Trainer",  11 )
71   PORT_CATEGORY_CLASS( 0x0f00, 0x0000, "P3 Controller")
72   PORT_CATEGORY_ITEM(  0x0000, "Unconnected",      0 )
73   PORT_CATEGORY_ITEM(  0x0100, "Gamepad",         3 )
74   PORT_CATEGORY_CLASS( 0xf000, 0x0000, "P4 Controller")
75   PORT_CATEGORY_ITEM(  0x0000, "Unconnected",      0 )
76   PORT_CATEGORY_ITEM(  0x1000, "Gamepad",         4 )
77
78   PORT_START("PAD1")   /* Joypad 1 */
79   PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_BUTTON1 ) PORT_NAME("P1 A") PORT_CATEGORY(1) PORT_PLAYER(1)
80   PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_BUTTON2 ) PORT_NAME("P1 B") PORT_CATEGORY(1) PORT_PLAYER(1)
81   PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_SELECT ) PORT_CATEGORY(1) PORT_PLAYER(1)
82   PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_START ) PORT_CATEGORY(1) PORT_PLAYER(1)
83   PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_JOYSTICK_UP ) PORT_CATEGORY(1) PORT_PLAYER(1)
84   PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_JOYSTICK_DOWN ) PORT_CATEGORY(1) PORT_PLAYER(1)
85   PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_JOYSTICK_LEFT ) PORT_CATEGORY(1) PORT_PLAYER(1)
86   PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_JOYSTICK_RIGHT ) PORT_CATEGORY(1) PORT_PLAYER(1)
87
88   PORT_START("PAD2")   /* Joypad 2 */
89   PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_BUTTON1 ) PORT_NAME("P2 A") PORT_CATEGORY(2) PORT_PLAYER(2)
90   PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_BUTTON2 ) PORT_NAME("P2 B") PORT_CATEGORY(2) PORT_PLAYER(2)
91   PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_SELECT ) PORT_CATEGORY(2) PORT_PLAYER(2)
92   PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_START ) PORT_CATEGORY(2) PORT_PLAYER(2)
93   PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_JOYSTICK_UP ) PORT_CATEGORY(2) PORT_PLAYER(2)
94   PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_JOYSTICK_DOWN ) PORT_CATEGORY(2) PORT_PLAYER(2)
95   PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_JOYSTICK_LEFT ) PORT_CATEGORY(2) PORT_PLAYER(2)
96   PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_JOYSTICK_RIGHT ) PORT_CATEGORY(2) PORT_PLAYER(2)
97
98   PORT_START("PAD3")   /* Joypad 3 */
99   PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_BUTTON1 ) PORT_NAME("P3 A") PORT_CATEGORY(3) PORT_PLAYER(3)
100   PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_BUTTON2 ) PORT_NAME("P3 B") PORT_CATEGORY(3) PORT_PLAYER(3)
101   PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_SELECT ) PORT_CATEGORY(3) PORT_PLAYER(3)
102   PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_START ) PORT_CATEGORY(3) PORT_PLAYER(3)
103   PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_JOYSTICK_UP ) PORT_CATEGORY(3) PORT_PLAYER(3)
104   PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_JOYSTICK_DOWN ) PORT_CATEGORY(3) PORT_PLAYER(3)
105   PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_JOYSTICK_LEFT ) PORT_CATEGORY(3) PORT_PLAYER(3)
106   PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_JOYSTICK_RIGHT ) PORT_CATEGORY(3) PORT_PLAYER(3)
107
108   PORT_START("PAD4")   /* Joypad 4 */
109   PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_BUTTON1 ) PORT_NAME("P4 A") PORT_CATEGORY(4) PORT_PLAYER(4)
110   PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_BUTTON2 ) PORT_NAME("P4 B") PORT_CATEGORY(4) PORT_PLAYER(4)
111   PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_SELECT ) PORT_CATEGORY(4) PORT_PLAYER(4)
112   PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_START ) PORT_CATEGORY(4) PORT_PLAYER(4)
113   PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_JOYSTICK_UP ) PORT_CATEGORY(4) PORT_PLAYER(4)
114   PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_JOYSTICK_DOWN ) PORT_CATEGORY(4) PORT_PLAYER(4)
115   PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_JOYSTICK_LEFT ) PORT_CATEGORY(4) PORT_PLAYER(4)
116   PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_JOYSTICK_RIGHT ) PORT_CATEGORY(4) PORT_PLAYER(4)
117
118   PORT_START("ZAPPER1_X")  /* P1 zapper */
119   PORT_BIT( 0xff, 0x80, IPT_LIGHTGUN_X) PORT_CROSSHAIR(X, 1.0, 0.0, 0) PORT_SENSITIVITY(70) PORT_KEYDELTA(30) PORT_MINMAX(0,255)                                          PORT_CATEGORY(5) PORT_PLAYER(1)
120   PORT_START("ZAPPER1_Y")  /* P1 zapper */
121   PORT_BIT( 0xff, 0x80, IPT_LIGHTGUN_Y) PORT_CROSSHAIR(Y, 1.0, 0.0, 0) PORT_SENSITIVITY(50) PORT_KEYDELTA(30) PORT_MINMAX(0,255)                                          PORT_CATEGORY(5) PORT_PLAYER(1)
122   PORT_START("ZAPPER1_T")  /* P1 zapper trigger */
123   PORT_BIT( 0x03, IP_ACTIVE_HIGH, IPT_BUTTON1) PORT_NAME("P1 Lightgun Trigger") PORT_CATEGORY(5) PORT_PLAYER(1)
124
125   PORT_START("ZAPPER2_X")  /* P2 zapper */
126   PORT_BIT( 0xff, 0x80, IPT_LIGHTGUN_X) PORT_CROSSHAIR(X, 1.0, 0.0, 0) PORT_SENSITIVITY(70) PORT_KEYDELTA(30) PORT_MINMAX(0,255 )                                          PORT_CATEGORY(6) PORT_PLAYER(2)
127   PORT_START("ZAPPER2_Y")  /* P2 zapper */
128   PORT_BIT( 0xff, 0x80, IPT_LIGHTGUN_Y) PORT_CROSSHAIR(Y, 1.0, 0.0, 0) PORT_SENSITIVITY(50) PORT_KEYDELTA(30) PORT_MINMAX(0,255 )                                          PORT_CATEGORY(6) PORT_PLAYER(2)
129   PORT_START("ZAPPER2_T")  /* P2 zapper trigger */
130   PORT_BIT( 0x03, IP_ACTIVE_HIGH, IPT_BUTTON1) PORT_NAME("P2 Lightgun Trigger") PORT_CATEGORY(6) PORT_PLAYER(2)
131
132   PORT_START("PADDLE")  /* Arkanoid paddle */
133   PORT_BIT( 0xff, 0x7f, IPT_PADDLE) PORT_SENSITIVITY(25) PORT_KEYDELTA(3) PORT_MINMAX(0x62,0xf2)                                                   PORT_CATEGORY(7)
134
135   PORT_START("CC_LEFT")
136   PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_UNUSED ) PORT_CATEGORY(10) PORT_PLAYER(1)
137   PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_UNUSED ) PORT_CATEGORY(10) PORT_PLAYER(1)
138   PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_SELECT ) PORT_CATEGORY(10) PORT_PLAYER(1)
139   PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_START ) PORT_CATEGORY(10) PORT_PLAYER(1)
140   PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_JOYSTICKLEFT_UP ) PORT_CATEGORY(10) PORT_PLAYER(1)
141   PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_JOYSTICKLEFT_DOWN ) PORT_CATEGORY(10) PORT_PLAYER(1)
142   PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_JOYSTICKLEFT_LEFT ) PORT_CATEGORY(10) PORT_PLAYER(1)
143   PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_JOYSTICKLEFT_RIGHT ) PORT_CATEGORY(10) PORT_PLAYER(1)
144
145   PORT_START("CC_RIGHT")
146   PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_UNUSED ) PORT_CATEGORY(10) PORT_PLAYER(1)
147   PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_UNUSED ) PORT_CATEGORY(10) PORT_PLAYER(1)
148   PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_UNUSED ) PORT_CATEGORY(10) PORT_PLAYER(1)
149   PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_UNUSED ) PORT_CATEGORY(10) PORT_PLAYER(1)
150   PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_JOYSTICKRIGHT_UP ) PORT_CATEGORY(10) PORT_PLAYER(1)
151   PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_JOYSTICKRIGHT_DOWN ) PORT_CATEGORY(10) PORT_PLAYER(1)
152   PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_JOYSTICKRIGHT_LEFT ) PORT_CATEGORY(10) PORT_PLAYER(1)
153   PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_JOYSTICKRIGHT_RIGHT ) PORT_CATEGORY(10) PORT_PLAYER(1)
154
155INPUT_PORTS_END
156
157static INPUT_PORTS_START( nes )
158   PORT_INCLUDE( nes_controllers )
159
160   PORT_START("CONFIG")  /* configuration */
161   PORT_CONFNAME( 0x01, 0x00, "Draw Top/Bottom 8 Lines")
162   PORT_CONFSETTING(    0x01, DEF_STR(No) )
163   PORT_CONFSETTING(    0x00, DEF_STR(Yes) )
164   PORT_CONFNAME( 0x02, 0x00, "Enforce 8 Sprites/line")
165   PORT_CONFSETTING(    0x02, DEF_STR(No) )
166   PORT_CONFSETTING(    0x00, DEF_STR(Yes) )
167INPUT_PORTS_END
168
169static INPUT_PORTS_START( famicom )
170   PORT_INCLUDE( nes_controllers )
171
172   PORT_START("FLIPDISK") /* fake keys */
173   PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_BUTTON3) PORT_NAME("Change Disk Side")
174INPUT_PORTS_END
175
176static INPUT_PORTS_START( fc_keyboard )
177   PORT_START("FCKEY0")
178   PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(8) PORT_CODE(KEYCODE_F8) PORT_CHAR(UCHAR_MAMEKEY(F8))
179   PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(8) PORT_CODE(KEYCODE_ENTER) PORT_CHAR(13)
180   PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(8) PORT_CODE(KEYCODE_CLOSEBRACE)   PORT_CHAR('[')
181   PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(8) PORT_CODE(KEYCODE_BACKSLASH)   PORT_CHAR(']')
182   PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(8) PORT_NAME("Kana")
183   PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(8) PORT_CODE(KEYCODE_RSHIFT)
184   PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(8) PORT_CODE(KEYCODE_BACKSLASH2)   PORT_CHAR('\\')
185   PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(8) PORT_NAME("Stop") PORT_CODE(KEYCODE_BACKSPACE)
186
187   PORT_START("FCKEY1")
188   PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(8) PORT_CODE(KEYCODE_F7) PORT_CHAR(UCHAR_MAMEKEY(F7))
189   PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(8) PORT_CODE(KEYCODE_OPENBRACE)   PORT_CHAR('@')
190   PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(8) PORT_CODE(KEYCODE_COLON)   PORT_CHAR(':')
191   PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(8) PORT_CODE(KEYCODE_QUOTE)   PORT_CHAR(';')
192   PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(8) PORT_CHAR('_')
193   PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(8) PORT_CHAR('/')
194   PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(8) PORT_CODE(KEYCODE_MINUS)   PORT_CHAR('-')
195   PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(8) PORT_CODE(KEYCODE_EQUALS)   PORT_CHAR('^')
196
197   PORT_START("FCKEY2")
198   PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(8) PORT_CODE(KEYCODE_F6) PORT_CHAR(UCHAR_MAMEKEY(F6))
199   PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(8) PORT_CODE(KEYCODE_O)   PORT_CHAR('O')
200   PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(8) PORT_CODE(KEYCODE_L)   PORT_CHAR('L')
201   PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(8) PORT_CODE(KEYCODE_K)   PORT_CHAR('K')
202   PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(8) PORT_CODE(KEYCODE_STOP)   PORT_CHAR('.')
203   PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(8) PORT_CODE(KEYCODE_COMMA)   PORT_CHAR(',')
204   PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(8) PORT_CODE(KEYCODE_P)   PORT_CHAR('P')
205   PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(8) PORT_CODE(KEYCODE_0)   PORT_CHAR('0')
206
207   PORT_START("FCKEY3")
208   PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(8) PORT_CODE(KEYCODE_F5) PORT_CHAR(UCHAR_MAMEKEY(F5))
209   PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(8) PORT_CODE(KEYCODE_I)   PORT_CHAR('I')
210   PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(8) PORT_CODE(KEYCODE_U)   PORT_CHAR('U')
211   PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(8) PORT_CODE(KEYCODE_J)   PORT_CHAR('J')
212   PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(8) PORT_CODE(KEYCODE_M)   PORT_CHAR('M')
213   PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(8) PORT_CODE(KEYCODE_N)   PORT_CHAR('N')
214   PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(8) PORT_CODE(KEYCODE_9)   PORT_CHAR('9')
215   PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(8) PORT_CODE(KEYCODE_8)   PORT_CHAR('8')
216
217   PORT_START("FCKEY4")
218   PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(8) PORT_CODE(KEYCODE_F4) PORT_CHAR(UCHAR_MAMEKEY(F4))
219   PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(8) PORT_CODE(KEYCODE_Y)   PORT_CHAR('Y')
220   PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(8) PORT_CODE(KEYCODE_G)   PORT_CHAR('G')
221   PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(8) PORT_CODE(KEYCODE_H)   PORT_CHAR('H')
222   PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(8) PORT_CODE(KEYCODE_B)   PORT_CHAR('B')
223   PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(8) PORT_CODE(KEYCODE_V)   PORT_CHAR('V')
224   PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(8) PORT_CODE(KEYCODE_7)   PORT_CHAR('7')
225   PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(8) PORT_CODE(KEYCODE_6)   PORT_CHAR('6')
226
227   PORT_START("FCKEY5")
228   PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(8) PORT_CODE(KEYCODE_F3) PORT_CHAR(UCHAR_MAMEKEY(F3))
229   PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(8) PORT_CODE(KEYCODE_T)   PORT_CHAR('T')
230   PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(8) PORT_CODE(KEYCODE_R)   PORT_CHAR('R')
231   PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(8) PORT_CODE(KEYCODE_D)   PORT_CHAR('D')
232   PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(8) PORT_CODE(KEYCODE_F)   PORT_CHAR('F')
233   PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(8) PORT_CODE(KEYCODE_C)   PORT_CHAR('C')
234   PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(8) PORT_CODE(KEYCODE_5)   PORT_CHAR('5')
235   PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(8) PORT_CODE(KEYCODE_4)   PORT_CHAR('4')
236
237   PORT_START("FCKEY6")
238   PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(8) PORT_CODE(KEYCODE_F2) PORT_CHAR(UCHAR_MAMEKEY(F2))
239   PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(8) PORT_CODE(KEYCODE_W)   PORT_CHAR('W')
240   PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(8) PORT_CODE(KEYCODE_S)   PORT_CHAR('S')
241   PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(8) PORT_CODE(KEYCODE_A)   PORT_CHAR('A')
242   PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(8) PORT_CODE(KEYCODE_X)   PORT_CHAR('X')
243   PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(8) PORT_CODE(KEYCODE_Z)   PORT_CHAR('Z')
244   PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(8) PORT_CODE(KEYCODE_E)   PORT_CHAR('E')
245   PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(8) PORT_CODE(KEYCODE_3)   PORT_CHAR('3')
246
247   PORT_START("FCKEY7")
248   PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(8) PORT_CODE(KEYCODE_F1) PORT_CHAR(UCHAR_MAMEKEY(F1))
249   PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(8) PORT_CODE(KEYCODE_TAB) PORT_CHAR(UCHAR_MAMEKEY(ESC))
250   PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(8) PORT_CODE(KEYCODE_Q)   PORT_CHAR('Q')
251   PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(8) PORT_CODE(KEYCODE_LCONTROL)      PORT_CHAR(UCHAR_SHIFT_2)
252   PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(8) PORT_CODE(KEYCODE_LSHIFT)      PORT_CHAR(UCHAR_SHIFT_1)
253   PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(8) PORT_NAME("Grph") PORT_CODE(KEYCODE_LALT)
254   PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(8) PORT_CODE(KEYCODE_1)   PORT_CHAR('1')
255   PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(8) PORT_CODE(KEYCODE_2)   PORT_CHAR('2')
256
257   PORT_START("FCKEY8")
258   PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(8) PORT_NAME("Clr")
259   PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(8) PORT_CODE(KEYCODE_UP)   PORT_CHAR(UCHAR_MAMEKEY(UP))
260   PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(8) PORT_CODE(KEYCODE_RIGHT) PORT_CHAR(UCHAR_MAMEKEY(RIGHT))
261   PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(8) PORT_CODE(KEYCODE_LEFT) PORT_CHAR(UCHAR_MAMEKEY(LEFT))
262   PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(8) PORT_CODE(KEYCODE_DOWN) PORT_CHAR(UCHAR_MAMEKEY(DOWN))
263   PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(8) PORT_CODE(KEYCODE_SPACE)      PORT_CHAR(' ')
264   PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(8) PORT_NAME("Del") PORT_CODE(KEYCODE_DEL)
265   PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(8) PORT_NAME("Ins") PORT_CODE(KEYCODE_INSERT)
266
267INPUT_PORTS_END
268
269static INPUT_PORTS_START( subor_keyboard )
270   PORT_START("SUBKEY0")
271   PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(9) PORT_CODE(KEYCODE_4)   PORT_CHAR('4')
272   PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(9) PORT_CODE(KEYCODE_G)   PORT_CHAR('G')
273   PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(9) PORT_CODE(KEYCODE_F)   PORT_CHAR('F')
274   PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(9) PORT_CODE(KEYCODE_C)   PORT_CHAR('C')
275   PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(9) PORT_CODE(KEYCODE_F2) PORT_CHAR(UCHAR_MAMEKEY(F2))
276   PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(9) PORT_CODE(KEYCODE_E)   PORT_CHAR('E')
277   PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(9) PORT_CODE(KEYCODE_5)   PORT_CHAR('5')
278   PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(9) PORT_CODE(KEYCODE_V)   PORT_CHAR('V')
279
280   PORT_START("SUBKEY1")
281   PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(9) PORT_CODE(KEYCODE_2)   PORT_CHAR('2')
282   PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(9) PORT_CODE(KEYCODE_D)   PORT_CHAR('D')
283   PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(9) PORT_CODE(KEYCODE_S)   PORT_CHAR('S')
284   PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(9) PORT_CODE(KEYCODE_END) PORT_CHAR(UCHAR_MAMEKEY(END))
285   PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(9) PORT_CODE(KEYCODE_F1) PORT_CHAR(UCHAR_MAMEKEY(F1))
286   PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(9) PORT_CODE(KEYCODE_W)   PORT_CHAR('W')
287   PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(9) PORT_CODE(KEYCODE_3)   PORT_CHAR('3')
288   PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(9) PORT_CODE(KEYCODE_X)   PORT_CHAR('X')
289
290   PORT_START("SUBKEY2")
291   PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(9) PORT_CODE(KEYCODE_INSERT) PORT_CHAR(UCHAR_MAMEKEY(INSERT))
292   PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(9) PORT_CODE(KEYCODE_BACKSPACE)   PORT_CHAR(8)
293   PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(9) PORT_NAME("NEXT")
294   PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(9) PORT_CODE(KEYCODE_RIGHT) PORT_CHAR(UCHAR_MAMEKEY(RIGHT))
295   PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(9) PORT_CODE(KEYCODE_F8) PORT_CHAR(UCHAR_MAMEKEY(F8))
296   PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(9) PORT_NAME("PRIOR")
297   PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(9) PORT_CODE(KEYCODE_DEL) PORT_CHAR(UCHAR_MAMEKEY(DEL))
298   PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(9) PORT_CODE(KEYCODE_HOME) PORT_CHAR(UCHAR_MAMEKEY(HOME))
299
300   PORT_START("SUBKEY3")
301   PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(9) PORT_CODE(KEYCODE_9)   PORT_CHAR('9')
302   PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(9) PORT_CODE(KEYCODE_I)   PORT_CHAR('I')
303   PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(9) PORT_CODE(KEYCODE_L)   PORT_CHAR('L')
304   PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(9) PORT_CODE(KEYCODE_COMMA)   PORT_CHAR(',')
305   PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(9) PORT_CODE(KEYCODE_F5) PORT_CHAR(UCHAR_MAMEKEY(F5))
306   PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(9) PORT_CODE(KEYCODE_O)   PORT_CHAR('O')
307   PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(9) PORT_CODE(KEYCODE_0)   PORT_CHAR('0')
308   PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(9) PORT_CODE(KEYCODE_STOP)   PORT_CHAR('.')
309
310   PORT_START("SUBKEY4")
311   PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(9) PORT_CODE(KEYCODE_CLOSEBRACE)   PORT_CHAR(']')
312   PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(9) PORT_CODE(KEYCODE_ENTER)   PORT_CHAR(13)
313   PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(9) PORT_CODE(KEYCODE_UP) PORT_CHAR(UCHAR_MAMEKEY(UP))
314   PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(9) PORT_CODE(KEYCODE_LEFT) PORT_CHAR(UCHAR_MAMEKEY(LEFT))
315   PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(9) PORT_CODE(KEYCODE_F7) PORT_CHAR(UCHAR_MAMEKEY(F7))
316   PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(9) PORT_CODE(KEYCODE_OPENBRACE)   PORT_CHAR('[')
317   PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(9) PORT_CODE(KEYCODE_BACKSLASH)   PORT_CHAR('\\')
318   PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(9) PORT_CODE(KEYCODE_DOWN) PORT_CHAR(UCHAR_MAMEKEY(DOWN))
319
320   PORT_START("SUBKEY5")
321   PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(9) PORT_CODE(KEYCODE_Q)   PORT_CHAR('Q')
322   PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(9) PORT_CODE(KEYCODE_CAPSLOCK) PORT_CHAR(UCHAR_MAMEKEY(CAPSLOCK))
323   PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(9) PORT_CODE(KEYCODE_Z)   PORT_CHAR('Z')
324   PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(9) PORT_CODE(KEYCODE_TAB)   PORT_CHAR('\t')
325   PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(9) PORT_CODE(KEYCODE_ESC) PORT_CHAR(UCHAR_MAMEKEY(ESC))
326   PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(9) PORT_CODE(KEYCODE_A)   PORT_CHAR('A')
327   PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(9) PORT_CODE(KEYCODE_1)   PORT_CHAR('1')
328   PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(9) PORT_CODE(KEYCODE_LCONTROL)      PORT_CHAR(UCHAR_SHIFT_2)
329
330   PORT_START("SUBKEY6")
331   PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(9) PORT_CODE(KEYCODE_7)   PORT_CHAR('7')
332   PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(9) PORT_CODE(KEYCODE_Y)   PORT_CHAR('Y')
333   PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(9) PORT_CODE(KEYCODE_K)   PORT_CHAR('K')
334   PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(9) PORT_CODE(KEYCODE_M)   PORT_CHAR('M')
335   PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(9) PORT_CODE(KEYCODE_F4) PORT_CHAR(UCHAR_MAMEKEY(F4))
336   PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(9) PORT_CODE(KEYCODE_U)   PORT_CHAR('U')
337   PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(9) PORT_CODE(KEYCODE_8)   PORT_CHAR('8')
338   PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(9) PORT_CODE(KEYCODE_J)   PORT_CHAR('J')
339
340   PORT_START("SUBKEY7")
341   PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(9) PORT_CODE(KEYCODE_MINUS)   PORT_CHAR('-')
342   PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(9) PORT_CODE(KEYCODE_COLON)   PORT_CHAR(':')
343   PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(9) PORT_CODE(KEYCODE_QUOTE)   PORT_CHAR('\'')
344   PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(9) PORT_CODE(KEYCODE_SLASH)   PORT_CHAR('/')
345   PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(9) PORT_CODE(KEYCODE_F6) PORT_CHAR(UCHAR_MAMEKEY(F6))
346   PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(9) PORT_CODE(KEYCODE_P)      PORT_CHAR('P')
347   PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(9) PORT_CODE(KEYCODE_EQUALS)   PORT_CHAR('=')
348   PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(9) PORT_CODE(KEYCODE_LSHIFT)   PORT_CHAR(UCHAR_SHIFT_1)
349
350   PORT_START("SUBKEY8")
351   PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(9) PORT_CODE(KEYCODE_T)   PORT_CHAR('T')
352   PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(9) PORT_CODE(KEYCODE_H)   PORT_CHAR('H')
353   PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(9) PORT_CODE(KEYCODE_N)   PORT_CHAR('N')
354   PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(9) PORT_CODE(KEYCODE_SPACE)   PORT_CHAR(' ')
355   PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(9) PORT_CODE(KEYCODE_F3) PORT_CHAR(UCHAR_MAMEKEY(F3))
356   PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(9) PORT_CODE(KEYCODE_R)   PORT_CHAR('R')
357   PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(9) PORT_CODE(KEYCODE_6)   PORT_CHAR('6')
358   PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(9) PORT_CODE(KEYCODE_B)   PORT_CHAR('B')
359
360   PORT_START("SUBKEY9")
361   PORT_BIT( 0xff, IP_ACTIVE_HIGH, IPT_UNUSED ) PORT_CATEGORY(9)
362
363   PORT_START("SUBKEY10")
364   PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(9) PORT_NAME("LMENU")
365   PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(9) PORT_CODE(KEYCODE_4_PAD)   PORT_CHAR(UCHAR_MAMEKEY(4_PAD))
366   PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(9) PORT_CODE(KEYCODE_7_PAD)   PORT_CHAR(UCHAR_MAMEKEY(7_PAD))
367   PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(9) PORT_CODE(KEYCODE_F11)      PORT_CHAR(UCHAR_MAMEKEY(F11))
368   PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(9) PORT_CODE(KEYCODE_F12)      PORT_CHAR(UCHAR_MAMEKEY(F12))
369   PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(9) PORT_CODE(KEYCODE_1_PAD)   PORT_CHAR(UCHAR_MAMEKEY(1_PAD))
370   PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(9) PORT_CODE(KEYCODE_2_PAD)   PORT_CHAR(UCHAR_MAMEKEY(2_PAD))
371   PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(9) PORT_CODE(KEYCODE_8_PAD)   PORT_CHAR(UCHAR_MAMEKEY(8_PAD))
372
373   PORT_START("SUBKEY11")
374   PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(9) PORT_CODE(KEYCODE_MINUS_PAD)PORT_CHAR(UCHAR_MAMEKEY(MINUS_PAD))
375   PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(9) PORT_CODE(KEYCODE_PLUS_PAD)   PORT_CHAR(UCHAR_MAMEKEY(PLUS_PAD))
376   PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(9) PORT_CODE(KEYCODE_ASTERISK)   PORT_CHAR(UCHAR_MAMEKEY(ASTERISK))
377   PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(9) PORT_CODE(KEYCODE_9_PAD)   PORT_CHAR(UCHAR_MAMEKEY(9_PAD))
378   PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(9) PORT_CODE(KEYCODE_F10) PORT_CHAR(UCHAR_MAMEKEY(F10))
379   PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(9) PORT_CODE(KEYCODE_5_PAD)   PORT_CHAR(UCHAR_MAMEKEY(5_PAD))
380   PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(9) PORT_CODE(KEYCODE_SLASH_PAD)PORT_CHAR(UCHAR_MAMEKEY(SLASH_PAD))
381   PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(9) PORT_CODE(KEYCODE_NUMLOCK)   PORT_CHAR(UCHAR_MAMEKEY(NUMLOCK))
382
383   PORT_START("SUBKEY12")
384   PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(9) PORT_CODE(KEYCODE_TILDE)   PORT_CHAR('`')
385   PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(9) PORT_CODE(KEYCODE_6_PAD)   PORT_CHAR(UCHAR_MAMEKEY(6_PAD))
386   PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(9) PORT_NAME("PAUSE")
387   PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(9) PORT_NAME("SPACE2")
388   PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(9) PORT_CODE(KEYCODE_F9) PORT_CHAR(UCHAR_MAMEKEY(F9))
389   PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(9) PORT_CODE(KEYCODE_3_PAD)   PORT_CHAR(UCHAR_MAMEKEY(3_PAD))
390   PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(9) PORT_NAME("Keypad .") PORT_CODE(KEYCODE_DEL_PAD)
391   PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CATEGORY(9) PORT_CODE(KEYCODE_0_PAD)   PORT_CHAR(UCHAR_MAMEKEY(0_PAD))
392
393INPUT_PORTS_END
394
395static INPUT_PORTS_START( famikey )
396   PORT_INCLUDE( famicom )
397   PORT_INCLUDE( fc_keyboard )
398   PORT_INCLUDE( subor_keyboard )
399
400   PORT_MODIFY("CTRLSEL")  /* Select Controller Type */
401   PORT_CATEGORY_CLASS( 0x000f, 0x0004, "P1 Controller")
402   PORT_CATEGORY_ITEM(  0x0000, "Unconnected",      0 )
403   PORT_CATEGORY_ITEM(  0x0001, "Gamepad",         1 )
404   PORT_CATEGORY_ITEM(  0x0002, "Zapper",         5 )
405   PORT_CATEGORY_ITEM(  0x0006, "Crazy Climber pad", 10 )
406   PORT_CATEGORY_ITEM(  0x0007, "FC Keyboard",      8 )
407   PORT_CATEGORY_ITEM(  0x0008, "Subor Keyboard",   9 )
408   PORT_CATEGORY_CLASS( 0x00f0, 0x0010, "P2 Controller")
409   PORT_CATEGORY_ITEM(  0x0000, "Unconnected",      0 )
410   PORT_CATEGORY_ITEM(  0x0010, "Gamepad",         2 )
411   PORT_CATEGORY_ITEM(  0x0030, "Zapper",         6 )
412   PORT_CATEGORY_ITEM(  0x0040, "Arkanoid paddle",   7 )
413//  PORT_CATEGORY_ITEM(  0x0050, "Family Trainer",  11 )
414   PORT_CATEGORY_CLASS( 0x0f00, 0x0000, "P3 Controller")
415   PORT_CATEGORY_ITEM(  0x0000, "Unconnected",      0 )
416   PORT_CATEGORY_ITEM(  0x0100, "Gamepad",         3 )
417   PORT_CATEGORY_CLASS( 0xf000, 0x0000, "P4 Controller")
418   PORT_CATEGORY_ITEM(  0x0000, "Unconnected",      0 )
419   PORT_CATEGORY_ITEM(  0x1000, "Gamepad",         4 )
420INPUT_PORTS_END
421
422#ifdef UNUSED_FUNCTION
423/* This layout is not changed at runtime */
424gfx_layout nes_vram_charlayout =
425{
426    8,8,    /* 8*8 characters */
427    512,    /* 512 characters */
428    2,  /* 2 bits per pixel */
429    { 8*8, 0 }, /* the two bitplanes are separated */
430    { 0, 1, 2, 3, 4, 5, 6, 7 },
431    { 0*8, 1*8, 2*8, 3*8, 4*8, 5*8, 6*8, 7*8 },
432    16*8    /* every char takes 16 consecutive bytes */
433};
434#endif
435
436static const nes_interface nes_apu_interface =
437{
438   "maincpu"
439};
440
441
442static void ppu_nmi(device_t *device, int *ppu_regs)
443{
444   cputag_set_input_line(device->machine(), "maincpu", INPUT_LINE_NMI, PULSE_LINE);
445}
446
447
448static const ppu2c0x_interface nes_ppu_interface =
449{
450   0,
451   0,
452   PPU_MIRROR_NONE,
453   ppu_nmi
454};
455
456static const floppy_config nes_floppy_config =
457{
458   DEVCB_NULL,
459   DEVCB_NULL,
460   DEVCB_NULL,
461   DEVCB_NULL,
462   DEVCB_NULL,
463   FLOPPY_STANDARD_5_25_DSHD,
464   FLOPPY_OPTIONS_NAME(nes_only),
465   NULL
466};
467
468
469static MACHINE_CONFIG_START( nes, nes_state )
470   /* basic machine hardware */
471   MCFG_CPU_ADD("maincpu", N2A03, NTSC_CLOCK)
472   MCFG_CPU_PROGRAM_MAP(nes_map)
473
474   MCFG_MACHINE_START( nes )
475   MCFG_MACHINE_RESET( nes )
476
477   MCFG_SCREEN_ADD("screen", RASTER)
478   MCFG_SCREEN_REFRESH_RATE(60.098)
479   // This isn't used so much to calulate the vblank duration (the PPU code tracks that manually) but to determine
480   // the number of cycles in each scanline for the PPU scanline timer. Since the PPU has 20 vblank scanlines + 2
481   // non-rendering scanlines, we compensate. This ends up being 2500 cycles for the non-rendering portion, 2273
482   // cycles for the actual vblank period.
483   MCFG_SCREEN_VBLANK_TIME(ATTOSECONDS_IN_USEC((113.66/(NTSC_CLOCK/1000000)) * (PPU_VBLANK_LAST_SCANLINE_NTSC-PPU_VBLANK_FIRST_SCANLINE+1+2)))
484   MCFG_SCREEN_FORMAT(BITMAP_FORMAT_INDEXED16)
485   MCFG_SCREEN_SIZE(32*8, 262)
486   MCFG_SCREEN_VISIBLE_AREA(0*8, 32*8-1, 0*8, 30*8-1)
487   MCFG_SCREEN_UPDATE(nes)
488
489   MCFG_PALETTE_INIT(nes)
490   MCFG_VIDEO_START(nes)
491
492   MCFG_PALETTE_LENGTH(4*16*8)
493
494   MCFG_PPU2C02_ADD( "ppu", nes_ppu_interface )
495
496   /* sound hardware */
497   MCFG_SPEAKER_STANDARD_MONO("mono")
498   MCFG_SOUND_ADD("nessound", NES, NTSC_CLOCK)
499   MCFG_SOUND_CONFIG(nes_apu_interface)
500   MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.90)
501
502   MCFG_CARTSLOT_ADD("cart")
503   MCFG_CARTSLOT_EXTENSION_LIST("nes,unf")
504   MCFG_CARTSLOT_MANDATORY
505   MCFG_CARTSLOT_INTERFACE("nes_cart")
506   MCFG_CARTSLOT_LOAD(nes_cart)
507   MCFG_CARTSLOT_PARTIALHASH(nes_partialhash)
508   MCFG_SOFTWARE_LIST_ADD("cart_list","nes")
509MACHINE_CONFIG_END
510
511static MACHINE_CONFIG_DERIVED( nespal, nes )
512
513   /* basic machine hardware */
514   MCFG_CPU_MODIFY( "maincpu" )
515   MCFG_CPU_CLOCK( PAL_CLOCK )
516
517   MCFG_DEVICE_REMOVE( "ppu" )
518   MCFG_PPU2C07_ADD( "ppu", nes_ppu_interface )
519
520   /* video hardware */
521   MCFG_SCREEN_MODIFY("screen")
522   MCFG_SCREEN_REFRESH_RATE(53.355)
523   MCFG_SCREEN_VBLANK_TIME(ATTOSECONDS_IN_USEC((106.53/(PAL_CLOCK/1000000)) * (PPU_VBLANK_LAST_SCANLINE_PAL-PPU_VBLANK_FIRST_SCANLINE+1+2)))
524   MCFG_VIDEO_START(nes)
525
526   /* sound hardware */
527   MCFG_SOUND_REPLACE("nessound", NES, PAL_CLOCK)
528   MCFG_SOUND_CONFIG(nes_apu_interface)
529   MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.90)
530MACHINE_CONFIG_END
531
532static MACHINE_CONFIG_DERIVED( dendy, nes )
533
534   /* basic machine hardware */
535   MCFG_CPU_MODIFY( "maincpu" )
536   MCFG_CPU_CLOCK( 26601712/15 ) /* 26.601712MHz / 15 == 1.77344746666... MHz */
537
538   MCFG_DEVICE_REMOVE( "ppu" )
539   MCFG_PPU2C07_ADD( "ppu", nes_ppu_interface )
540
541   /* video hardware */
542   MCFG_SCREEN_MODIFY("screen")
543   MCFG_SCREEN_REFRESH_RATE(50.00697796827)
544   MCFG_SCREEN_VBLANK_TIME(ATTOSECONDS_IN_USEC((106.53/(PAL_CLOCK/1000000)) * (PPU_VBLANK_LAST_SCANLINE_PAL-PPU_VBLANK_FIRST_SCANLINE+1+2)))
545   MCFG_VIDEO_START(nes)
546
547   /* sound hardware */
548   MCFG_SOUND_REPLACE("nessound", NES, 26601712/15) /* 26.601712MHz / 15 == 1.77344746666... MHz */
549   MCFG_SOUND_CONFIG(nes_apu_interface)
550   MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.90)
551MACHINE_CONFIG_END
552
553static MACHINE_CONFIG_DERIVED( famicom, nes )
554
555   MCFG_CARTSLOT_MODIFY("cart")
556   MCFG_CARTSLOT_EXTENSION_LIST("nes,unf")
557   MCFG_CARTSLOT_NOT_MANDATORY
558   MCFG_CARTSLOT_LOAD(nes_cart)
559   MCFG_CARTSLOT_PARTIALHASH(nes_partialhash)
560
561   MCFG_FLOPPY_DRIVE_ADD(FLOPPY_0, nes_floppy_config)
562MACHINE_CONFIG_END
563
564
565/* rom regions are just place-holders: they get removed and re-allocated when a cart is loaded */
566ROM_START( nes )
567   ROM_REGION( 0x10000, "maincpu", ROMREGION_ERASE00 )  /* Main RAM + program banks */
568   ROM_REGION( 0x2000,  "gfx1", ROMREGION_ERASE00 )  /* VROM */
569   ROM_REGION( 0x4000,  "gfx2", ROMREGION_ERASE00 )  /* VRAM */
570   ROM_REGION( 0x800,   "gfx3", ROMREGION_ERASE00 )  /* CI RAM */
571ROM_END
572
573ROM_START( nespal )
574   ROM_REGION( 0x10000, "maincpu", ROMREGION_ERASE00 )  /* Main RAM + program banks */
575   ROM_REGION( 0x2000,  "gfx1", ROMREGION_ERASE00 )  /* VROM */
576   ROM_REGION( 0x4000,  "gfx2", ROMREGION_ERASE00 )  /* VRAM */
577   ROM_REGION( 0x800,   "gfx3", ROMREGION_ERASE00 )  /* CI RAM */
578ROM_END
579
580ROM_START( famicom )
581   ROM_REGION( 0x10000, "maincpu", 0 )  /* Main RAM + program banks */
582   ROM_LOAD_OPTIONAL( "disksys.rom", 0xe000, 0x2000, CRC(5e607dcf) SHA1(57fe1bdee955bb48d357e463ccbf129496930b62) )
583
584   ROM_REGION( 0x2000,  "gfx1", ROMREGION_ERASE00 )  /* VROM */
585   ROM_REGION( 0x4000,  "gfx2", ROMREGION_ERASE00 )  /* VRAM */
586   ROM_REGION( 0x800,   "gfx3", ROMREGION_ERASE00 )  /* CI RAM */
587ROM_END
588
589#define rom_fami_key rom_famicom
590
591ROM_START( famitwin )
592   ROM_REGION( 0x10000, "maincpu", 0 )  /* Main RAM + program banks */
593   ROM_LOAD_OPTIONAL( "disksyst.rom", 0xe000, 0x2000, CRC(4df24a6c) SHA1(e4e41472c454f928e53eb10e0509bf7d1146ecc1) )
594
595   ROM_REGION( 0x2000,  "gfx1", ROMREGION_ERASE00 )  /* VROM */
596   ROM_REGION( 0x4000,  "gfx2", ROMREGION_ERASE00 )  /* VRAM */
597   ROM_REGION( 0x800,   "gfx3", ROMREGION_ERASE00 )  /* CI RAM */
598ROM_END
599
600ROM_START( m82 )
601   ROM_REGION( 0x14000, "maincpu", 0 )  /* Main RAM + program banks */
602   /* Banks to be mapped at 0xe000? More investigations needed... */
603   ROM_LOAD( "m82_v1_0.bin", 0x10000, 0x4000, CRC(7d56840a) SHA1(cbd2d14fa073273ba58367758f40d67fd8a9106d) )
604
605   ROM_REGION( 0x2000,  "gfx1", ROMREGION_ERASE00 )  /* VROM */
606   ROM_REGION( 0x4000,  "gfx2", ROMREGION_ERASE00 )  /* VRAM */
607   ROM_REGION( 0x800,   "gfx3", ROMREGION_ERASE00 )  /* CI RAM */
608ROM_END
609
610// see http://www.disgruntleddesigner.com/chrisc/drpcjr/index.html
611// and http://www.disgruntleddesigner.com/chrisc/drpcjr/DrPCJrMemMap.txt
612ROM_START( drpcjr )
613   ROM_REGION( 0x18000, "maincpu", 0 )  /* Main RAM + program banks */
614   /* 4 banks to be mapped in 0xe000-0xffff (or 8 banks to be mapped in 0xe000-0xefff & 0xf000-0xffff).
615    Banks selected by writing at 0x4180 */
616   ROM_LOAD("drpcjr_bios.bin", 0x10000, 0x8000, CRC(c8fbef89) SHA1(2cb0a817b31400cdf27817d09bae7e69f41b062b) )   // bios vers. 1.0a
617   // Not sure if we should support this: hacked version 1.5a by Chris Covell with bugfixes and GameGenie support
618//  ROM_LOAD("drpcjr_v1_5_gg.bin", 0x10000, 0x8000, CRC(98f2033b) SHA1(93c114da787a19279d1a46667c2f69b49e25d4f1) )
619
620   ROM_REGION( 0x2000,  "gfx1", ROMREGION_ERASE00 )  /* VROM */
621   ROM_REGION( 0x4000,  "gfx2", ROMREGION_ERASE00 )  /* VRAM */
622   ROM_REGION( 0x800,   "gfx3", ROMREGION_ERASE00 )  /* CI RAM */
623ROM_END
624
625ROM_START( dendy )
626   ROM_REGION( 0x10000, "maincpu", ROMREGION_ERASE00 )  /* Main RAM + program banks */
627   ROM_REGION( 0x2000,  "gfx1", ROMREGION_ERASE00 )  /* VROM */
628   ROM_REGION( 0x4000,  "gfx2", ROMREGION_ERASE00 )  /* VRAM */
629   ROM_REGION( 0x800,   "gfx3", ROMREGION_ERASE00 )  /* CI RAM */
630ROM_END
631
632/***************************************************************************
633
634  Game driver(s)
635
636***************************************************************************/
637
638/*     YEAR  NAME      PARENT  COMPAT MACHINE   INPUT    INIT    COMPANY       FULLNAME */
639CONS( 1985, nes,       0,      0,     nes,      nes,     0,       "Nintendo",  "Nintendo Entertainment System / Famicom (NTSC)", GAME_IMPERFECT_GRAPHICS )
640CONS( 1987, nespal,    nes,    0,     nespal,   nes,     0,       "Nintendo",  "Nintendo Entertainment System (PAL)", GAME_IMPERFECT_GRAPHICS )
641CONS( 1983, famicom,   nes,    0,     famicom,  famicom, famicom, "Nintendo",  "Famicom (w/ Disk System add-on)", GAME_IMPERFECT_GRAPHICS )
642CONS( 1983, fami_key,  nes,    0,     famicom,  famikey, famicom, "Nintendo",  "Famicom (w/ Disk System add-on + Keyboard add-on)", GAME_IMPERFECT_GRAPHICS )
643CONS( 1986, famitwin,  nes,    0,     famicom,  famicom, famicom, "Sharp",     "Famicom Twin", GAME_IMPERFECT_GRAPHICS )
644CONS( 198?, m82,       nes,    0,     nes,      nes,     0,       "Nintendo",  "M82 Display Unit", GAME_IMPERFECT_GRAPHICS )
645CONS( 1996, drpcjr,    nes,    0,     famicom,  famicom, famicom, "Bung",      "Doctor PC Jr", GAME_IMPERFECT_GRAPHICS )
646CONS( 1992, dendy,     nes,    0,     dendy,    nes,     0,       "Steepler",  "Dendy Classic", GAME_IMPERFECT_GRAPHICS )
src/mess/drivers/n64.c
r0r11532
1/*
2    Nintendo 64
3
4    Driver by Ville Linde
5    Reformatted to share hardware by R. Belmont
6    Additional work by Ryan Holtz
7    Porting from Mupen64 by Harmony
8*/
9
10#include "emu.h"
11#include "cpu/rsp/rsp.h"
12#include "cpu/mips/mips3.h"
13#include "sound/dmadac.h"
14#include "imagedev/cartslot.h"
15#include "includes/n64.h"
16
17
18static ADDRESS_MAP_START( n64_map, AS_PROGRAM, 32 )
19   AM_RANGE(0x00000000, 0x007fffff) AM_RAM   AM_BASE(&rdram)            // RDRAM
20   AM_RANGE(0x03f00000, 0x03f00027) AM_READWRITE(n64_rdram_reg_r, n64_rdram_reg_w)
21   AM_RANGE(0x04000000, 0x04000fff) AM_RAM AM_SHARE("dmem")               // RSP DMEM
22   AM_RANGE(0x04001000, 0x04001fff) AM_RAM AM_SHARE("imem")               // RSP IMEM
23   AM_RANGE(0x04040000, 0x040fffff) AM_DEVREADWRITE("rsp", n64_sp_reg_r, n64_sp_reg_w)   // RSP
24   AM_RANGE(0x04100000, 0x041fffff) AM_DEVREADWRITE("rsp", n64_dp_reg_r, n64_dp_reg_w)   // RDP
25   AM_RANGE(0x04300000, 0x043fffff) AM_READWRITE(n64_mi_reg_r, n64_mi_reg_w)   // MIPS Interface
26   AM_RANGE(0x04400000, 0x044fffff) AM_READWRITE(n64_vi_reg_r, n64_vi_reg_w)   // Video Interface
27   AM_RANGE(0x04500000, 0x045fffff) AM_READWRITE(n64_ai_reg_r, n64_ai_reg_w)   // Audio Interface
28   AM_RANGE(0x04600000, 0x046fffff) AM_READWRITE(n64_pi_reg_r, n64_pi_reg_w)   // Peripheral Interface
29   AM_RANGE(0x04700000, 0x047fffff) AM_READWRITE(n64_ri_reg_r, n64_ri_reg_w)   // RDRAM Interface
30   AM_RANGE(0x04800000, 0x048fffff) AM_READWRITE(n64_si_reg_r, n64_si_reg_w)   // Serial Interface
31   //AM_RANGE(0x08000000, 0x08007fff) AM_RAM                                   // Cartridge SRAM
32   AM_RANGE(0x10000000, 0x13ffffff) AM_ROM AM_REGION("user2", 0)   // Cartridge
33   AM_RANGE(0x1fc00000, 0x1fc007bf) AM_ROM AM_REGION("user1", 0)   // PIF ROM
34   AM_RANGE(0x1fc007c0, 0x1fc007ff) AM_READWRITE(n64_pif_ram_r, n64_pif_ram_w)
35ADDRESS_MAP_END
36
37static ADDRESS_MAP_START( rsp_map, AS_PROGRAM, 32 )
38   AM_RANGE(0x00000000, 0x00000fff) AM_RAM AM_SHARE("dmem")
39   AM_RANGE(0x00001000, 0x00001fff) AM_RAM AM_SHARE("imem")
40   AM_RANGE(0x04000000, 0x04000fff) AM_RAM AM_BASE(&rsp_dmem) AM_SHARE("dmem")
41   AM_RANGE(0x04001000, 0x04001fff) AM_RAM AM_BASE(&rsp_imem) AM_SHARE("imem")
42ADDRESS_MAP_END
43
44static INPUT_PORTS_START( n64 )
45   PORT_START("P1")
46   PORT_BIT( 0x8000, IP_ACTIVE_HIGH, IPT_BUTTON1 )        PORT_PLAYER(1) PORT_NAME("P1 Button A")
47   PORT_BIT( 0x4000, IP_ACTIVE_HIGH, IPT_BUTTON2 )        PORT_PLAYER(1) PORT_NAME("P1 Button B")
48   PORT_BIT( 0x2000, IP_ACTIVE_HIGH, IPT_BUTTON3 )        PORT_PLAYER(1) PORT_NAME("P1 Button Z")
49   PORT_BIT( 0x1000, IP_ACTIVE_HIGH, IPT_START )          PORT_PLAYER(1) PORT_NAME("P1 Start")
50   PORT_BIT( 0x0800, IP_ACTIVE_HIGH, IPT_JOYSTICK_UP )    PORT_PLAYER(1) PORT_NAME("P1 Joypad \xE2\x86\x91") /* Up */
51   PORT_BIT( 0x0400, IP_ACTIVE_HIGH, IPT_JOYSTICK_DOWN )  PORT_PLAYER(1) PORT_NAME("P1 Joypad \xE2\x86\x93") /* Down */
52   PORT_BIT( 0x0200, IP_ACTIVE_HIGH, IPT_JOYSTICK_LEFT )  PORT_PLAYER(1) PORT_NAME("P1 Joypad \xE2\x86\x90") /* Left */
53   PORT_BIT( 0x0100, IP_ACTIVE_HIGH, IPT_JOYSTICK_RIGHT ) PORT_PLAYER(1) PORT_NAME("P1 Joypad \xE2\x86\x92") /* Right */
54   PORT_BIT( 0x00c0, IP_ACTIVE_HIGH, IPT_UNUSED )
55   PORT_BIT( 0x0020, IP_ACTIVE_HIGH, IPT_BUTTON4 )        PORT_PLAYER(1) PORT_NAME("P1 Button L")
56   PORT_BIT( 0x0010, IP_ACTIVE_HIGH, IPT_BUTTON5 )        PORT_PLAYER(1) PORT_NAME("P1 Button R")
57   PORT_BIT( 0x0008, IP_ACTIVE_HIGH, IPT_BUTTON6 )        PORT_PLAYER(1) PORT_NAME("P1 Button C \xE2\x86\x91") /* Up */
58   PORT_BIT( 0x0004, IP_ACTIVE_HIGH, IPT_BUTTON7 )        PORT_PLAYER(1) PORT_NAME("P1 Button C \xE2\x86\x93") /* Down */
59   PORT_BIT( 0x0002, IP_ACTIVE_HIGH, IPT_BUTTON8 )        PORT_PLAYER(1) PORT_NAME("P1 Button C \xE2\x86\x90") /* Left */
60   PORT_BIT( 0x0001, IP_ACTIVE_HIGH, IPT_BUTTON9 )        PORT_PLAYER(1) PORT_NAME("P1 Button C \xE2\x86\x92") /* Right */
61
62   PORT_START("P1_ANALOG_X")
63   PORT_BIT( 0xff, 0x80, IPT_AD_STICK_X ) PORT_MINMAX(0x00,0xff) PORT_SENSITIVITY(30) PORT_KEYDELTA(30) PORT_PLAYER(1)
64
65   PORT_START("P1_ANALOG_Y")
66   PORT_BIT( 0xff, 0x80, IPT_AD_STICK_Y ) PORT_MINMAX(0x00,0xff) PORT_SENSITIVITY(30) PORT_KEYDELTA(30) PORT_PLAYER(1) PORT_REVERSE
67
68   PORT_START("P2")
69   PORT_BIT( 0x8000, IP_ACTIVE_HIGH, IPT_BUTTON1 )        PORT_PLAYER(2) PORT_NAME("P2 Button A")
70   PORT_BIT( 0x4000, IP_ACTIVE_HIGH, IPT_BUTTON2 )        PORT_PLAYER(2) PORT_NAME("P2 Button B")
71   PORT_BIT( 0x2000, IP_ACTIVE_HIGH, IPT_BUTTON3 )        PORT_PLAYER(2) PORT_NAME("P2 Button Z")
72   PORT_BIT( 0x1000, IP_ACTIVE_HIGH, IPT_START )          PORT_PLAYER(2) PORT_NAME("P2 Start")
73   PORT_BIT( 0x0800, IP_ACTIVE_HIGH, IPT_JOYSTICK_UP )    PORT_PLAYER(2) PORT_NAME("P2 Joypad \xE2\x86\x91") /* Up */
74   PORT_BIT( 0x0400, IP_ACTIVE_HIGH, IPT_JOYSTICK_DOWN )  PORT_PLAYER(2) PORT_NAME("P2 Joypad \xE2\x86\x93") /* Down */
75   PORT_BIT( 0x0200, IP_ACTIVE_HIGH, IPT_JOYSTICK_LEFT )  PORT_PLAYER(2) PORT_NAME("P2 Joypad \xE2\x86\x90") /* Left */
76   PORT_BIT( 0x0100, IP_ACTIVE_HIGH, IPT_JOYSTICK_RIGHT ) PORT_PLAYER(2) PORT_NAME("P2 Joypad \xE2\x86\x92") /* Right */
77   PORT_BIT( 0x00c0, IP_ACTIVE_HIGH, IPT_UNUSED )
78   PORT_BIT( 0x0020, IP_ACTIVE_HIGH, IPT_BUTTON4 )        PORT_PLAYER(2) PORT_NAME("P2 Button L")
79   PORT_BIT( 0x0010, IP_ACTIVE_HIGH, IPT_BUTTON5 )        PORT_PLAYER(2) PORT_NAME("P2 Button R")
80   PORT_BIT( 0x0008, IP_ACTIVE_HIGH, IPT_BUTTON6 )        PORT_PLAYER(2) PORT_NAME("P2 Button C \xE2\x86\x91") /* Up */
81   PORT_BIT( 0x0004, IP_ACTIVE_HIGH, IPT_BUTTON7 )        PORT_PLAYER(2) PORT_NAME("P2 Button C \xE2\x86\x93") /* Down */
82   PORT_BIT( 0x0002, IP_ACTIVE_HIGH, IPT_BUTTON8 )        PORT_PLAYER(2) PORT_NAME("P2 Button C \xE2\x86\x90") /* Left */
83   PORT_BIT( 0x0001, IP_ACTIVE_HIGH, IPT_BUTTON9 )        PORT_PLAYER(2) PORT_NAME("P2 Button C \xE2\x86\x92") /* Right */
84
85   PORT_START("P2_ANALOG_X")
86   PORT_BIT( 0xff, 0x80, IPT_AD_STICK_X ) PORT_MINMAX(0x00,0xff) PORT_SENSITIVITY(30) PORT_KEYDELTA(30) PORT_PLAYER(2)
87
88   PORT_START("P2_ANALOG_Y")
89   PORT_BIT( 0xff, 0x80, IPT_AD_STICK_Y ) PORT_MINMAX(0x00,0xff) PORT_SENSITIVITY(30) PORT_KEYDELTA(30) PORT_PLAYER(2) PORT_REVERSE
90
91INPUT_PORTS_END
92
93/* ?? */
94static const mips3_config config =
95{
96   16384,            /* code cache size */
97   8192,            /* data cache size */
98   62500000         /* system clock */
99};
100
101static INTERRUPT_GEN( n64_vblank )
102{
103   signal_rcp_interrupt(device->machine(), VI_INTERRUPT);
104}
105
106static DEVICE_IMAGE_LOAD(n64_cart)
107{
108   int i, length;
109   UINT8 *cart = image.device().machine().region("user2")->base();
110
111   if (image.software_entry() == NULL)
112   {
113      length = image.fread( cart, 0x4000000);
114   }
115   else
116   {
117      length = image.get_software_region_length("rom");
118      memcpy(cart, image.get_software_region("rom"), length);
119   }
120
121   if (cart[0] == 0x37 && cart[1] == 0x80)
122   {
123      for (i = 0; i < length; i += 4)
124      {
125         UINT8 b1 = cart[i + 0];
126         UINT8 b2 = cart[i + 1];
127         UINT8 b3 = cart[i + 2];
128         UINT8 b4 = cart[i + 3];
129         cart[i + 0] = b3;
130         cart[i + 1] = b4;
131         cart[i + 2] = b1;
132         cart[i + 3] = b2;
133      }
134   }
135   else
136   {
137      for (i = 0; i < length; i += 4)
138      {
139         UINT8 b1 = cart[i + 0];
140         UINT8 b2 = cart[i + 1];
141         UINT8 b3 = cart[i + 2];
142         UINT8 b4 = cart[i + 3];
143         cart[i + 0] = b4;
144         cart[i + 1] = b3;
145         cart[i + 2] = b2;
146         cart[i + 3] = b1;
147      }
148   }
149
150   logerror("cart length = %d\n", length);
151   return IMAGE_INIT_PASS;
152}
153
154static MACHINE_CONFIG_START( n64, _n64_state )
155
156   /* basic machine hardware */
157   MCFG_CPU_ADD("maincpu", VR4300BE, 93750000)
158   MCFG_CPU_CONFIG(config)
159   MCFG_CPU_PROGRAM_MAP(n64_map)
160   MCFG_CPU_VBLANK_INT("screen", n64_vblank)
161
162   MCFG_CPU_ADD("rsp", RSP, 62500000)
163   MCFG_CPU_CONFIG(n64_rsp_config)
164   MCFG_CPU_PROGRAM_MAP(rsp_map)
165
166   MCFG_MACHINE_START( n64 )
167   MCFG_MACHINE_RESET( n64 )
168   MCFG_QUANTUM_TIME(attotime::from_hz(600))
169
170   /* video hardware */
171   MCFG_SCREEN_ADD("screen", RASTER)
172   MCFG_SCREEN_REFRESH_RATE(60)
173   MCFG_SCREEN_VBLANK_TIME(ATTOSECONDS_IN_USEC(0))
174   MCFG_SCREEN_FORMAT(BITMAP_FORMAT_RGB32)
175   MCFG_SCREEN_SIZE(640, 525)
176   MCFG_SCREEN_VISIBLE_AREA(0, 639, 0, 239)
177   MCFG_SCREEN_UPDATE(n64)
178
179   MCFG_PALETTE_LENGTH(0x1000)
180
181   MCFG_VIDEO_START(n64)
182
183   MCFG_SPEAKER_STANDARD_STEREO("lspeaker", "rspeaker")
184
185   MCFG_SOUND_ADD("dac2", DMADAC, 0)
186   MCFG_SOUND_ROUTE(ALL_OUTPUTS, "lspeaker", 1.0)
187   MCFG_SOUND_ADD("dac1", DMADAC, 0)
188   MCFG_SOUND_ROUTE(ALL_OUTPUTS, "rspeaker", 1.0)
189
190   /* cartridge */
191   MCFG_CARTSLOT_ADD("cart")
192   MCFG_CARTSLOT_EXTENSION_LIST("v64,z64,rom,n64,bin")
193   MCFG_CARTSLOT_MANDATORY
194   MCFG_CARTSLOT_INTERFACE("n64_cart")
195   MCFG_CARTSLOT_LOAD(n64_cart)
196
197   /* software lists */
198   MCFG_SOFTWARE_LIST_ADD("cart_list","n64")
199MACHINE_CONFIG_END
200
201ROM_START( n64 )
202   ROM_REGION( 0x800000, "maincpu", ROMREGION_ERASEFF )      /* dummy region for R4300 */
203
204   ROM_REGION32_BE( 0x800, "user1", 0 )
205   ROM_LOAD( "pifdata.bin", 0x0000, 0x0800, CRC(5ec82be9) SHA1(9174eadc0f0ea2654c95fd941406ab46b9dc9bdd) )
206
207   ROM_REGION32_BE( 0x4000000, "user2", ROMREGION_ERASEFF)
208
209   ROM_REGION16_BE( 0x80, "normpoint", 0 )
210   ROM_LOAD( "normpnt.rom", 0x00, 0x80, CRC(e7f2a005) SHA1(c27b4a364a24daeee6e99fd286753fd6216362b4) )
211
212   ROM_REGION16_BE( 0x80, "normslope", 0 )
213   ROM_LOAD( "normslp.rom", 0x00, 0x80, CRC(4f2ae525) SHA1(eab43f8cc52c8551d9cff6fced18ef80eaba6f05) )
214ROM_END
215
216CONS(1996, n64,    0,      0,      n64,   n64,   0,   "Nintendo", "Nintendo 64", GAME_IMPERFECT_GRAPHICS | GAME_IMPERFECT_SOUND )
src/mess/drivers/snes.c
r0r11532
1/***************************************************************************
2
3  snes.c
4
5  Driver file to handle emulation of the Nintendo Super NES.
6
7  R. Belmont
8  Anthony Kruize
9  Angelo Salese
10  Fabio Priuli
11  byuu
12  Based on the original MESS driver by Lee Hammerton (aka Savoury Snax)
13
14  Driver is preliminary right now.
15
16  The memory map included below is setup in a way to make it easier to handle
17  Mode 20 and Mode 21 ROMs.
18
19  Todo (in no particular order):
20    - Fix additional sound bugs
21    - Emulate extra chips - superfx, dsp2, sa-1 etc.
22    - Add horizontal mosaic, hi-res. interlaced etc to video emulation.
23    - Fix support for Mode 7. (In Progress)
24    - Handle interleaved roms (maybe even multi-part roms, but how?)
25    - Add support for running at 3.58 MHz at the appropriate time.
26    - I'm sure there's lots more ...
27
28***************************************************************************/
29
30#include "emu.h"
31#include "audio/snes_snd.h"
32#include "cpu/spc700/spc700.h"
33#include "cpu/superfx/superfx.h"
34#include "cpu/g65816/g65816.h"
35#include "cpu/upd7725/upd7725.h"
36#include "includes/snes.h"
37#include "machine/snescart.h"
38#include "crsshair.h"
39
40#define MAX_SNES_CART_SIZE 0x600000
41
42/*************************************
43 *
44 *  Memory handlers
45 *
46 *************************************/
47
48static READ8_DEVICE_HANDLER( spc_ram_100_r )
49{
50   return spc_ram_r(device, offset + 0x100);
51}
52
53static WRITE8_DEVICE_HANDLER( spc_ram_100_w )
54{
55   spc_ram_w(device, offset + 0x100, data);
56}
57
58/*************************************
59 *
60 *  Address maps
61 *
62 *************************************/
63
64static ADDRESS_MAP_START( snes_map, AS_PROGRAM, 8)
65   AM_RANGE(0x000000, 0x2fffff) AM_READWRITE(snes_r_bank1, snes_w_bank1)   /* I/O and ROM (repeats for each bank) */
66   AM_RANGE(0x300000, 0x3fffff) AM_READWRITE(snes_r_bank2, snes_w_bank2)   /* I/O and ROM (repeats for each bank) */
67   AM_RANGE(0x400000, 0x5fffff) AM_READ(snes_r_bank3)      /* ROM (and reserved in Mode 20) */
68   AM_RANGE(0x600000, 0x6fffff) AM_READWRITE(snes_r_bank4, snes_w_bank4)   /* used by Mode 20 DSP-1 */
69   AM_RANGE(0x700000, 0x7dffff) AM_READWRITE(snes_r_bank5, snes_w_bank5)
70   AM_RANGE(0x7e0000, 0x7fffff) AM_RAM               /* 8KB Low RAM, 24KB High RAM, 96KB Expanded RAM */
71   AM_RANGE(0x800000, 0xbfffff) AM_READWRITE(snes_r_bank6, snes_w_bank6)   /* Mirror and ROM */
72   AM_RANGE(0xc00000, 0xffffff) AM_READWRITE(snes_r_bank7, snes_w_bank7)   /* Mirror and ROM */
73ADDRESS_MAP_END
74
75static ADDRESS_MAP_START( superfx_map, AS_PROGRAM, 8)
76   AM_RANGE(0x000000, 0x3fffff) AM_READWRITE(superfx_r_bank1, superfx_w_bank1)
77   AM_RANGE(0x400000, 0x5fffff) AM_READWRITE(superfx_r_bank2, superfx_w_bank2)
78   AM_RANGE(0x600000, 0x7dffff) AM_READWRITE(superfx_r_bank3, superfx_w_bank3)
79   AM_RANGE(0x800000, 0xbfffff) AM_READWRITE(superfx_r_bank1, superfx_w_bank1)
80   AM_RANGE(0xc00000, 0xdfffff) AM_READWRITE(superfx_r_bank2, superfx_w_bank2)
81   AM_RANGE(0xe00000, 0xffffff) AM_READWRITE(superfx_r_bank3, superfx_w_bank3)
82ADDRESS_MAP_END
83
84static ADDRESS_MAP_START( spc_map, AS_PROGRAM, 8)
85   AM_RANGE(0x0000, 0x00ef) AM_DEVREADWRITE("spc700", spc_ram_r, spc_ram_w)   /* lower 32k ram */
86   AM_RANGE(0x00f0, 0x00ff) AM_DEVREADWRITE("spc700", spc_io_r, spc_io_w)     /* spc io */
87   AM_RANGE(0x0100, 0xffff) AM_DEVWRITE("spc700", spc_ram_100_w)
88   AM_RANGE(0x0100, 0xffbf) AM_DEVREAD("spc700", spc_ram_100_r)
89   AM_RANGE(0xffc0, 0xffff) AM_DEVREAD("spc700", spc_ipl_r)
90ADDRESS_MAP_END
91
92static ADDRESS_MAP_START( dsp_prg_map, AS_PROGRAM, 32 )
93   AM_RANGE(0x0000, 0x07ff) AM_ROM AM_REGION("dspprg", 0)
94ADDRESS_MAP_END
95
96static ADDRESS_MAP_START( dsp_data_map, AS_DATA, 16 )
97   AM_RANGE(0x0000, 0x03ff) AM_ROM AM_REGION("dspdata", 0)
98ADDRESS_MAP_END
99
100static ADDRESS_MAP_START( setadsp_prg_map, AS_PROGRAM, 32 )
101   AM_RANGE(0x0000, 0x3fff) AM_ROM AM_REGION("dspprg", 0)
102ADDRESS_MAP_END
103
104static ADDRESS_MAP_START( setadsp_data_map, AS_DATA, 16 )
105   AM_RANGE(0x0000, 0x07ff) AM_ROM AM_REGION("dspdata", 0)
106ADDRESS_MAP_END
107
108/*************************************
109 *
110 *  Input ports
111 *
112 *************************************/
113
114static CUSTOM_INPUT( snes_mouse_speed_input )
115{
116   snes_state *state = field.machine().driver_data<snes_state>();
117   int port = (FPTR)param;
118
119   if (snes_ram[OLDJOY1] & 0x1)
120   {
121      state->m_mouse[port].speed++;
122      if ((state->m_mouse[port].speed & 0x03) == 0x03)
123         state->m_mouse[port].speed = 0;
124   }
125
126   return state->m_mouse[port].speed;
127}
128
129static CUSTOM_INPUT( snes_superscope_offscreen_input )
130{
131   snes_state *state = field.machine().driver_data<snes_state>();
132   int port = (FPTR)param;
133   static const char *const portnames[2][3] =
134         {
135            { "SUPERSCOPE1", "SUPERSCOPE1_X", "SUPERSCOPE1_Y" },
136            { "SUPERSCOPE2", "SUPERSCOPE2_X", "SUPERSCOPE2_Y" },
137         };
138
139   INT16 x = input_port_read(field.machine(), portnames[port][1]);
140   INT16 y = input_port_read(field.machine(), portnames[port][2]);
141
142   /* these are the theoretical boundaries, but we currently are always onscreen... */
143   if (x < 0 || x >= SNES_SCR_WIDTH || y < 0 || y >= snes_ppu.beam.last_visible_line)
144      state->m_scope[port].offscreen = 1;
145   else
146      state->m_scope[port].offscreen = 0;
147
148   return state->m_scope[port].offscreen;
149}
150
151static TIMER_CALLBACK( lightgun_tick )
152{
153   if ((input_port_read(machine, "CTRLSEL") & 0x0f) == 0x03 || (input_port_read(machine, "CTRLSEL") & 0x0f) == 0x04)
154   {
155      /* enable lightpen crosshair */
156      crosshair_set_screen(machine, 0, CROSSHAIR_SCREEN_ALL);
157   }
158   else
159   {
160      /* disable lightpen crosshair */
161      crosshair_set_screen(machine, 0, CROSSHAIR_SCREEN_NONE);
162   }
163
164   if ((input_port_read(machine, "CTRLSEL") & 0xf0) == 0x30 || (input_port_read(machine, "CTRLSEL") & 0xf0) == 0x40)
165   {
166      /* enable lightpen crosshair */
167      crosshair_set_screen(machine, 1, CROSSHAIR_SCREEN_ALL);
168   }
169   else
170   {
171      /* disable lightpen crosshair */
172      crosshair_set_screen(machine, 1, CROSSHAIR_SCREEN_NONE);
173   }
174}
175
176
177static INPUT_PORTS_START( snes_joypads )
178   PORT_START("SERIAL1_DATA1_L")
179   PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_BUTTON3 ) PORT_NAME("P1 Button A") PORT_PLAYER(1) PORT_CATEGORY(11)
180   PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_BUTTON4 ) PORT_NAME("P1 Button X") PORT_PLAYER(1) PORT_CATEGORY(11)
181   PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_BUTTON5 ) PORT_NAME("P1 Button L") PORT_PLAYER(1) PORT_CATEGORY(11)
182   PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_BUTTON6 ) PORT_NAME("P1 Button R") PORT_PLAYER(1) PORT_CATEGORY(11)
183   PORT_START("SERIAL1_DATA1_H")
184   PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_BUTTON1 ) PORT_NAME("P1 Button B") PORT_PLAYER(1) PORT_CATEGORY(11)
185   PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_BUTTON2 ) PORT_NAME("P1 Button Y") PORT_PLAYER(1) PORT_CATEGORY(11)
186   PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_SELECT ) PORT_PLAYER(1) PORT_CATEGORY(11)
187   PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_START1 ) PORT_PLAYER(1) PORT_CATEGORY(11)
188   PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_JOYSTICK_UP ) PORT_PLAYER(1) PORT_CATEGORY(11)
189   PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_JOYSTICK_DOWN ) PORT_PLAYER(1) PORT_CATEGORY(11)
190   PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_JOYSTICK_LEFT ) PORT_PLAYER(1) PORT_CATEGORY(11)
191   PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_JOYSTICK_RIGHT ) PORT_PLAYER(1) PORT_CATEGORY(11)
192
193   PORT_START("SERIAL2_DATA1_L")
194   PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_BUTTON3 ) PORT_NAME("P2 Button A") PORT_PLAYER(2) PORT_CATEGORY(21)
195   PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_BUTTON4 ) PORT_NAME("P2 Button X") PORT_PLAYER(2) PORT_CATEGORY(21)
196   PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_BUTTON5 ) PORT_NAME("P2 Button L") PORT_PLAYER(2) PORT_CATEGORY(21)
197   PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_BUTTON6 ) PORT_NAME("P2 Button R") PORT_PLAYER(2) PORT_CATEGORY(21)
198   PORT_START("SERIAL2_DATA1_H")
199   PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_BUTTON1 ) PORT_NAME("P2 Button B") PORT_PLAYER(2) PORT_CATEGORY(21)
200   PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_BUTTON2 ) PORT_NAME("P2 Button Y") PORT_PLAYER(2) PORT_CATEGORY(21)
201   PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_SELECT ) PORT_PLAYER(2) PORT_CATEGORY(21)
202   PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_START2 ) PORT_PLAYER(2) PORT_CATEGORY(21)
203   PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_JOYSTICK_UP ) PORT_PLAYER(2) PORT_CATEGORY(21)
204   PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_JOYSTICK_DOWN ) PORT_PLAYER(2) PORT_CATEGORY(21)
205   PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_JOYSTICK_LEFT ) PORT_PLAYER(2) PORT_CATEGORY(21)
206   PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_JOYSTICK_RIGHT ) PORT_PLAYER(2) PORT_CATEGORY(21)
207
208   PORT_START("SERIAL1_DATA2_L")
209   PORT_BIT( 0xff, IP_ACTIVE_HIGH, IPT_UNUSED )
210   PORT_START("SERIAL1_DATA2_H")
211   PORT_BIT( 0xff, IP_ACTIVE_HIGH, IPT_UNUSED )
212
213   PORT_START("SERIAL2_DATA2_L")
214   PORT_BIT( 0xff, IP_ACTIVE_HIGH, IPT_UNUSED )
215   PORT_START("SERIAL2_DATA2_H")
216   PORT_BIT( 0xff, IP_ACTIVE_HIGH, IPT_UNUSED )
217INPUT_PORTS_END
218
219static INPUT_PORTS_START( snes_mouse )
220   PORT_START("MOUSE1")
221   /* bits 0,3 = mouse signature (must be 1) */
222   PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_UNUSED )
223   PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_UNUSED )
224   PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_UNUSED )
225   PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_UNUSED )
226   /* bits 4,5 = mouse speed: 0 = slow, 1 = normal, 2 = fast, 3 = unused */
227   PORT_BIT( 0x30, IP_ACTIVE_HIGH, IPT_SPECIAL ) PORT_CUSTOM(snes_mouse_speed_input, (void *)0)
228   /* bits 6,7 = mouse buttons */
229   PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_BUTTON1 ) PORT_NAME("P1 Mouse Button Left") PORT_PLAYER(1) PORT_CATEGORY(12)
230   PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_BUTTON2 ) PORT_NAME("P1 Mouse Button Right") PORT_PLAYER(1) PORT_CATEGORY(12)
231
232   PORT_START("MOUSE1_X")
233   PORT_BIT( 0xff, 0x00, IPT_TRACKBALL_X) PORT_SENSITIVITY(100) PORT_KEYDELTA(0) PORT_PLAYER(1) PORT_CATEGORY(12)
234
235   PORT_START("MOUSE1_Y")
236   PORT_BIT( 0xff, 0x00, IPT_TRACKBALL_Y) PORT_SENSITIVITY(100) PORT_KEYDELTA(0) PORT_PLAYER(1) PORT_CATEGORY(12)
237
238   PORT_START("MOUSE2")
239   /* bits 0,3 = mouse signature (must be 1) */
240   PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_UNUSED )
241   PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_UNUSED )
242   PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_UNUSED )
243   PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_UNUSED )
244   /* bits 4,5 = mouse speed: 0 = slow, 1 = normal, 2 = fast, 3 = unused */
245   PORT_BIT( 0x30, IP_ACTIVE_HIGH, IPT_SPECIAL ) PORT_CUSTOM(snes_mouse_speed_input, (void *)1)
246   /* bits 6,7 = mouse buttons */
247   PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_BUTTON1 ) PORT_NAME("P2 Mouse Button Left") PORT_PLAYER(2) PORT_CATEGORY(22)
248   PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_BUTTON2 ) PORT_NAME("P2 Mouse Button Right") PORT_PLAYER(2) PORT_CATEGORY(22)
249
250   PORT_START("MOUSE2_X")
251   PORT_BIT( 0xff, 0x00, IPT_TRACKBALL_X) PORT_SENSITIVITY(100) PORT_KEYDELTA(0) PORT_PLAYER(2) PORT_CATEGORY(22)
252
253   PORT_START("MOUSE2_Y")
254   PORT_BIT( 0xff, 0x00, IPT_TRACKBALL_Y) PORT_SENSITIVITY(100) PORT_KEYDELTA(0) PORT_PLAYER(2) PORT_CATEGORY(22)
255INPUT_PORTS_END
256
257static INPUT_PORTS_START( snes_superscope )
258   PORT_START("SUPERSCOPE1")
259   PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_UNUSED )   // Noise
260   PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_SPECIAL ) PORT_CUSTOM(snes_superscope_offscreen_input, (void *)0)
261   PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_UNUSED )
262   PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_UNUSED )
263   PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_BUTTON4 ) PORT_NAME("Port1 Superscope Pause") PORT_PLAYER(1) PORT_CATEGORY(13)
264   PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_BUTTON3 ) PORT_NAME("Port1 Superscope Turbo") PORT_TOGGLE PORT_PLAYER(1) PORT_CATEGORY(13)
265   PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_BUTTON2 ) PORT_NAME("Port1 Superscope Cursor") PORT_PLAYER(1) PORT_CATEGORY(13)
266   PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_BUTTON1 ) PORT_NAME("Port1 Superscope Fire") PORT_PLAYER(1) PORT_CATEGORY(13)
267
268   PORT_START("SUPERSCOPE1_X")
269   PORT_BIT( 0xff, 0x80, IPT_LIGHTGUN_X ) PORT_NAME("Port1 Superscope X Axis") PORT_CROSSHAIR(X, 1.0, 0.0, 0) PORT_SENSITIVITY(25) PORT_KEYDELTA(15) PORT_PLAYER(1) PORT_CATEGORY(13)
270
271   PORT_START("SUPERSCOPE1_Y")
272   PORT_BIT( 0xff, 0x80, IPT_LIGHTGUN_Y) PORT_NAME("Port1 Superscope Y Axis") PORT_CROSSHAIR(Y, 1.0, 0.0, 0) PORT_SENSITIVITY(25) PORT_KEYDELTA(15) PORT_PLAYER(1) PORT_CATEGORY(13)
273
274   PORT_START("SUPERSCOPE2")
275   PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_UNUSED )   // Noise
276   PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_SPECIAL ) PORT_CUSTOM(snes_superscope_offscreen_input, (void *)1)
277   PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_UNUSED )
278   PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_UNUSED )
279   PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_BUTTON4 ) PORT_NAME("Port2 Superscope Pause") PORT_PLAYER(2) PORT_CATEGORY(23)
280   PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_BUTTON3 ) PORT_NAME("Port2 Superscope Turbo") PORT_PLAYER(2) PORT_CATEGORY(23)
281   PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_BUTTON2 ) PORT_NAME("Port2 Superscope Cursor") PORT_PLAYER(2) PORT_CATEGORY(23)
282   PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_BUTTON1 ) PORT_NAME("Port2 Superscope Fire") PORT_PLAYER(2) PORT_CATEGORY(23)
283
284   PORT_START("SUPERSCOPE2_X")
285   PORT_BIT( 0xff, 0x80, IPT_LIGHTGUN_X ) PORT_NAME("Port2 Superscope X Axis") PORT_CROSSHAIR(X, 1.0, 0.0, 0) PORT_SENSITIVITY(25) PORT_KEYDELTA(15) PORT_PLAYER(2) PORT_CATEGORY(23)
286
287   PORT_START("SUPERSCOPE2_Y")
288   PORT_BIT( 0xff, 0x80, IPT_LIGHTGUN_Y) PORT_NAME("Port2 Superscope Y Axis") PORT_CROSSHAIR(Y, 1.0, 0.0, 0) PORT_SENSITIVITY(25) PORT_KEYDELTA(15) PORT_PLAYER(2) PORT_CATEGORY(23)
289INPUT_PORTS_END
290
291static INPUT_PORTS_START( snes )
292   PORT_START("CTRLSEL")  /* Select Controller Type */
293   PORT_CATEGORY_CLASS( 0x0f, 0x01, "P1 Controller")
294   PORT_CATEGORY_ITEM(  0x00, "Unconnected",      10 )
295   PORT_CATEGORY_ITEM(  0x01, "Gamepad",      11 )
296   PORT_CATEGORY_ITEM(  0x02, "Mouse",         12 )
297   PORT_CATEGORY_ITEM(  0x03, "Superscope",      13 )
298//  PORT_CATEGORY_ITEM(  0x04, "Justfier",      14 )
299//  PORT_CATEGORY_ITEM(  0x05, "Multitap",      15 )
300   PORT_CATEGORY_CLASS( 0xf0, 0x10, "P2 Controller")
301   PORT_CATEGORY_ITEM(  0x00, "Unconnected",      20 )
302   PORT_CATEGORY_ITEM(  0x10, "Gamepad",      21 )
303   PORT_CATEGORY_ITEM(  0x20, "Mouse",         22 )
304   PORT_CATEGORY_ITEM(  0x30, "Superscope",      23 )
305//  PORT_CATEGORY_ITEM(  0x40, "Justfier",      24 )
306//  PORT_CATEGORY_ITEM(  0x50, "Multitap",      25 )
307
308   PORT_INCLUDE(snes_joypads)
309   PORT_INCLUDE(snes_mouse)
310   PORT_INCLUDE(snes_superscope)
311
312   PORT_START("OPTIONS")
313   PORT_CONFNAME( 0x01, 0x00, "Hi-Res pixels blurring (TV effect)")
314   PORT_CONFSETTING(    0x00, DEF_STR( Off ) )
315   PORT_CONFSETTING(    0x01, DEF_STR( On ) )
316
317#if SNES_LAYER_DEBUG
318   PORT_START("DEBUG1")
319   PORT_CONFNAME( 0x03, 0x00, "Select BG1 priority" )
320   PORT_CONFSETTING(    0x00, "All" )
321   PORT_CONFSETTING(    0x01, "BG1B (lower) only" )
322   PORT_CONFSETTING(    0x02, "BG1A (higher) only" )
323   PORT_CONFNAME( 0x0c, 0x00, "Select BG2 priority" )
324   PORT_CONFSETTING(    0x00, "All" )
325   PORT_CONFSETTING(    0x04, "BG2B (lower) only" )
326   PORT_CONFSETTING(    0x08, "BG2A (higher) only" )
327   PORT_CONFNAME( 0x30, 0x00, "Select BG3 priority" )
328   PORT_CONFSETTING(    0x00, "All" )
329   PORT_CONFSETTING(    0x10, "BG3B (lower) only" )
330   PORT_CONFSETTING(    0x20, "BG3A (higher) only" )
331   PORT_CONFNAME( 0xc0, 0x00, "Select BG4 priority" )
332   PORT_CONFSETTING(    0x00, "All" )
333   PORT_CONFSETTING(    0x40, "BG4B (lower) only" )
334   PORT_CONFSETTING(    0x80, "BG4A (higher) only" )
335
336   PORT_START("DEBUG2")
337   PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Toggle BG 1") PORT_CODE(KEYCODE_1_PAD) PORT_TOGGLE
338   PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Toggle BG 2") PORT_CODE(KEYCODE_2_PAD) PORT_TOGGLE
339   PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Toggle BG 3") PORT_CODE(KEYCODE_3_PAD) PORT_TOGGLE
340   PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Toggle BG 4") PORT_CODE(KEYCODE_4_PAD) PORT_TOGGLE
341   PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Toggle Objects") PORT_CODE(KEYCODE_5_PAD) PORT_TOGGLE
342   PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Toggle Main/Sub") PORT_CODE(KEYCODE_6_PAD) PORT_TOGGLE
343   PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Toggle Color Math") PORT_CODE(KEYCODE_7_PAD) PORT_TOGGLE
344   PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Toggle Windows") PORT_CODE(KEYCODE_8_PAD) PORT_TOGGLE
345
346   PORT_START("DEBUG3")
347   PORT_BIT( 0x4, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Toggle Mosaic") PORT_CODE(KEYCODE_9_PAD) PORT_TOGGLE
348   PORT_CONFNAME( 0x70, 0x00, "Select OAM priority" )
349   PORT_CONFSETTING(    0x00, "All" )
350   PORT_CONFSETTING(    0x10, "OAM0 only" )
351   PORT_CONFSETTING(    0x20, "OAM1 only" )
352   PORT_CONFSETTING(    0x30, "OAM2 only" )
353   PORT_CONFSETTING(    0x40, "OAM3 only" )
354   PORT_CONFNAME( 0x80, 0x00, "Draw sprite in reverse order" )
355   PORT_CONFSETTING(    0x00, DEF_STR( Off ) )
356   PORT_CONFSETTING(    0x80, DEF_STR( On ) )
357
358   PORT_START("DEBUG4")
359   PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Toggle Mode 0 draw") PORT_TOGGLE
360   PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Toggle Mode 1 draw") PORT_TOGGLE
361   PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Toggle Mode 2 draw") PORT_TOGGLE
362   PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Toggle Mode 3 draw") PORT_TOGGLE
363   PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Toggle Mode 4 draw") PORT_TOGGLE
364   PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Toggle Mode 5 draw") PORT_TOGGLE
365   PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Toggle Mode 6 draw") PORT_TOGGLE
366   PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Toggle Mode 7 draw") PORT_TOGGLE
367#endif
368INPUT_PORTS_END
369
370
371/*************************************
372 *
373 *  Input callbacks
374 *
375 *************************************/
376
377static void snes_gun_latch( running_machine &machine, INT16 x, INT16 y )
378{
379   /* these are the theoretical boundaries */
380   if (x < 0)
381      x = 0;
382   if (x > (SNES_SCR_WIDTH - 1))
383      x = SNES_SCR_WIDTH - 1;
384
385   if (y < 0)
386      y = 0;
387   if (y > (snes_ppu.beam.last_visible_line - 1))
388      y = snes_ppu.beam.last_visible_line - 1;
389
390   snes_ppu.beam.latch_horz = x;
391   snes_ppu.beam.latch_vert = y;
392   snes_ram[STAT78] |= 0x40;
393}
394
395static void snes_input_read_joy( running_machine &machine, int port )
396{
397   snes_state *state = machine.driver_data<snes_state>();
398   static const char *const portnames[2][4] =
399         {
400            { "SERIAL1_DATA1_L", "SERIAL1_DATA1_H", "SERIAL1_DATA2_L", "SERIAL1_DATA2_H" },
401            { "SERIAL2_DATA1_L", "SERIAL2_DATA1_H", "SERIAL2_DATA2_L", "SERIAL2_DATA2_H" },
402         };
403
404   state->m_data1[port] = input_port_read(machine, portnames[port][0]) | (input_port_read(machine, portnames[port][1]) << 8);
405   state->m_data2[port] = input_port_read(machine, portnames[port][2]) | (input_port_read(machine, portnames[port][3]) << 8);
406
407   // avoid sending signals that could crash games
408   // if left, no right
409   if (state->m_data1[port] & 0x200)
410      state->m_data1[port] &= ~0x100;
411   // if up, no down
412   if (state->m_data1[port] & 0x800)
413      state->m_data1[port] &= ~0x400;
414
415   state->m_joypad[port].buttons = state->m_data1[port];
416}
417
418static void snes_input_read_mouse( running_machine &machine, int port )
419{
420   snes_state *state = machine.driver_data<snes_state>();
421   INT16 var;
422   static const char *const portnames[2][3] =
423         {
424            { "MOUSE1", "MOUSE1_X", "MOUSE1_Y" },
425            { "MOUSE2", "MOUSE2_X", "MOUSE2_Y" },
426         };
427
428   state->m_mouse[port].buttons = input_port_read(machine, portnames[port][0]);
429   state->m_mouse[port].x = input_port_read(machine, portnames[port][1]);
430   state->m_mouse[port].y = input_port_read(machine, portnames[port][2]);
431   var = state->m_mouse[port].x - state->m_mouse[port].oldx;
432
433   if (var < -127)
434   {
435      state->m_mouse[port].deltax = 0xff;
436      state->m_mouse[port].oldx -= 127;
437   }
438   else if (var < 0)
439   {
440      state->m_mouse[port].deltax = 0x80 | (-var);
441      state->m_mouse[port].oldx = state->m_mouse[port].x;
442   }
443   else if (var > 127)
444   {
445      state->m_mouse[port].deltax = 0x7f;
446      state->m_mouse[port].oldx += 127;
447   }
448   else
449   {
450      state->m_mouse[port].deltax = var & 0xff;
451      state->m_mouse[port].oldx = state->m_mouse[port].x;
452   }
453
454   var = state->m_mouse[port].y - state->m_mouse[port].oldy;
455
456   if (var < -127)
457   {
458      state->m_mouse[port].deltay = 0xff;
459      state->m_mouse[port].oldy -= 127;
460   }
461   else if (var < 0)
462   {
463      state->m_mouse[port].deltay = 0x80 | (-var);
464      state->m_mouse[port].oldy = state->m_mouse[port].y;
465   }
466   else if (var > 127)
467   {
468      state->m_mouse[port].deltay = 0x7f;
469      state->m_mouse[port].oldy += 127;
470   }
471   else
472   {
473      state->m_mouse[port].deltay = var & 0xff;
474      state->m_mouse[port].oldy = state->m_mouse[port].y;
475   }
476
477   state->m_data1[port] = state->m_mouse[port].buttons | (0x00 << 8);
478   state->m_data2[port] = 0;
479}
480
481static void snes_input_read_superscope( running_machine &machine, int port )
482{
483   snes_state *state = machine.driver_data<snes_state>();
484   static const char *const portnames[2][3] =
485         {
486            { "SUPERSCOPE1", "SUPERSCOPE1_X", "SUPERSCOPE1_Y" },
487            { "SUPERSCOPE2", "SUPERSCOPE2_X", "SUPERSCOPE2_Y" },
488         };
489   UINT8 input;
490
491   /* first read input bits */
492   state->m_scope[port].x = input_port_read(machine, portnames[port][1]);
493   state->m_scope[port].y = input_port_read(machine, portnames[port][2]);
494   input = input_port_read(machine, portnames[port][0]);
495
496   /* then start elaborating input bits: only keep old turbo value */
497   state->m_scope[port].buttons &= 0x20;
498
499   /* set onscreen/offscreen */
500   state->m_scope[port].buttons |= BIT(input, 1);
501
502   /* turbo is a switch; toggle is edge sensitive */
503   if (BIT(input, 5) && !state->m_scope[port].turbo_lock)
504   {
505      state->m_scope[port].buttons ^= 0x20;
506      state->m_scope[port].turbo_lock = 1;
507   }
508   else if (!BIT(input, 5))
509      state->m_scope[port].turbo_lock = 0;
510
511   /* fire is a button; if turbo is active, trigger is level sensitive; otherwise it is edge sensitive */
512   if (BIT(input, 7) && (BIT(state->m_scope[port].buttons, 5) || !state->m_scope[port].fire_lock))
513   {
514      state->m_scope[port].buttons |= 0x80;
515      state->m_scope[port].fire_lock = 1;
516   }
517   else if (!BIT(input, 7))
518      state->m_scope[port].fire_lock = 0;
519
520   /* cursor is a button; it is always level sensitive */
521   state->m_scope[port].buttons |= BIT(input, 6);
522
523   /* pause is a button; it is always edge sensitive */
524   if (BIT(input, 4) && !state->m_scope[port].pause_lock)
525   {
526      state->m_scope[port].buttons |= 0x10;
527      state->m_scope[port].pause_lock = 1;
528   }
529   else if (!BIT(input, 4))
530      state->m_scope[port].pause_lock = 0;
531
532   /* If we have pressed fire or cursor and we are on-screen and SuperScope is in Port2, then latch video signal.
533    Notice that we only latch Port2 because its IOBit pin is connected to bit7 of the IO Port, while Port1 has
534    IOBit pin connected to bit6 of the IO Port, and the latter is not detected by the H/V Counters. In other
535    words, you can connect SuperScope to Port1, but there is no way SNES could detect its on-screen position */
536   if ((state->m_scope[port].buttons & 0xc0) && !(state->m_scope[port].buttons & 0x02) && port == 1)
537      snes_gun_latch(machine, state->m_scope[port].x, state->m_scope[port].y);
538
539   state->m_data1[port] = 0xff | (state->m_scope[port].buttons << 8);
540   state->m_data2[port] = 0;
541}
542
543static void snes_input_read( running_machine &machine )
544{
545   snes_state *state = machine.driver_data<snes_state>();
546   UINT8 ctrl1 = input_port_read(machine, "CTRLSEL") & 0x0f;
547   UINT8 ctrl2 = (input_port_read(machine, "CTRLSEL") & 0xf0) >> 4;
548
549   /* Check if lightgun has been chosen as input: if so, enable crosshair */
550   machine.scheduler().timer_set(attotime::zero, FUNC(lightgun_tick));
551
552   switch (ctrl1)
553   {
554   case 1:   /* SNES joypad */
555      snes_input_read_joy(machine, 0);
556      break;
557   case 2:   /* SNES Mouse */
558      snes_input_read_mouse(machine, 0);
559      break;
560   case 3:   /* SNES Superscope */
561      snes_input_read_superscope(machine, 0);
562      break;
563   case 0:   /* no controller in port1 */
564   default:
565      state->m_data1[0] = 0;
566      state->m_data2[0] = 0;
567      break;
568   }
569
570   switch (ctrl2)
571   {
572   case 1:   /* SNES joypad */
573      snes_input_read_joy(machine, 1);
574      break;
575   case 2:   /* SNES Mouse */
576      snes_input_read_mouse(machine, 1);
577      break;
578   case 3:   /* SNES Superscope */
579      snes_input_read_superscope(machine, 1);
580      break;
581   case 0:   /* no controller in port2 */
582   default:
583      state->m_data1[1] = 0;
584      state->m_data2[1] = 0;
585      break;
586   }
587
588   // is automatic reading on? if so, copy port data1/data2 to joy1l->joy4h
589   // this actually works like reading the first 16bits from oldjoy1/2 in reverse order
590   if (snes_ram[NMITIMEN] & 1)
591   {
592      state->m_joy1l = (state->m_data1[0] & 0x00ff) >> 0;
593      state->m_joy1h = (state->m_data1[0] & 0xff00) >> 8;
594      state->m_joy2l = (state->m_data1[1] & 0x00ff) >> 0;
595      state->m_joy2h = (state->m_data1[1] & 0xff00) >> 8;
596      state->m_joy3l = (state->m_data2[0] & 0x00ff) >> 0;
597      state->m_joy3h = (state->m_data2[0] & 0xff00) >> 8;
598      state->m_joy4l = (state->m_data2[1] & 0x00ff) >> 0;
599      state->m_joy4h = (state->m_data2[1] & 0xff00) >> 8;
600
601      // make sure read_idx starts returning all 1s because the auto-read reads it :-)
602      state->m_read_idx[0] = 16;
603      state->m_read_idx[1] = 16;
604   }
605
606}
607
608static UINT8 snes_oldjoy1_read( running_machine &machine )
609{
610   snes_state *state = machine.driver_data<snes_state>();
611   UINT8 ctrl1 = input_port_read(machine, "CTRLSEL") & 0x0f;
612   UINT8 res = 0;
613
614   switch (ctrl1)
615   {
616   case 1:   /* SNES joypad */
617      if (state->m_read_idx[0] >= 16)
618         res = 0x01;
619      else
620         res = (state->m_joypad[0].buttons >> (15 - state->m_read_idx[0]++)) & 0x01;
621      break;
622   case 2:   /* SNES Mouse */
623      if (state->m_read_idx[0] >= 32)
624         res = 0x01;
625      else if (state->m_read_idx[0] >= 24)
626         res = (state->m_mouse[0].deltax >> (31 - state->m_read_idx[0]++)) & 0x01;
627      else if (state->m_read_idx[0] >= 16)
628         res = (state->m_mouse[0].deltay >> (23 - state->m_read_idx[0]++)) & 0x01;
629      else if (state->m_read_idx[0] >= 8)
630         res = (state->m_mouse[0].buttons >> (15 - state->m_read_idx[0]++)) & 0x01;
631      else
632         res = 0;
633      break;
634   case 3:   /* SNES Superscope */
635      if (state->m_read_idx[0] >= 8)
636         res = 0x01;
637      else
638         res = (state->m_scope[0].buttons >> (7 - state->m_read_idx[0]++)) & 0x01;
639      break;
640   case 0:   /* no controller in port2 */
641   default:
642      break;
643   }
644
645   return res;
646}
647
648static UINT8 snes_oldjoy2_read( running_machine &machine )
649{
650   snes_state *state = machine.driver_data<snes_state>();
651   UINT8 ctrl2 = (input_port_read(machine, "CTRLSEL") & 0xf0) >> 4;
652   UINT8 res = 0;
653
654   switch (ctrl2)
655   {
656   case 1:   /* SNES joypad */
657      if (state->m_read_idx[1] >= 16)
658         res = 0x01;
659      else
660         res = (state->m_joypad[1].buttons >> (15 - state->m_read_idx[1]++)) & 0x01;
661      break;
662   case 2:   /* SNES Mouse */
663      if (state->m_read_idx[1] >= 32)
664         res = 0x01;
665      else if (state->m_read_idx[1] >= 24)
666         res = (state->m_mouse[1].deltax >> (31 - state->m_read_idx[1]++)) & 0x01;
667      else if (state->m_read_idx[1] >= 16)
668         res = (state->m_mouse[1].deltay >> (23 - state->m_read_idx[1]++)) & 0x01;
669      else if (state->m_read_idx[1] >= 8)
670         res = (state->m_mouse[1].buttons >> (15 - state->m_read_idx[1]++)) & 0x01;
671      else
672         res = 0;
673      break;
674   case 3:   /* SNES Superscope */
675      if (state->m_read_idx[1] >= 8)
676         res = 0x01;
677      else
678         res = (state->m_scope[1].buttons >> (7 - state->m_read_idx[1]++)) & 0x01;
679      break;
680   case 0:   /* no controller in port2 */
681   default:
682      break;
683   }
684
685   return res;
686}
687
688/*************************************
689 *
690 *  Machine driver
691 *
692 *************************************/
693
694static MACHINE_RESET( snes_mess )
695{
696   snes_state *state = machine.driver_data<snes_state>();
697
698   MACHINE_RESET_CALL(snes);
699
700   state->m_io_read = snes_input_read;
701   state->m_oldjoy1_read = snes_oldjoy1_read;
702   state->m_oldjoy2_read = snes_oldjoy2_read;
703}
704
705static MACHINE_CONFIG_START( snes_base, snes_state )
706
707   /* basic machine hardware */
708   MCFG_CPU_ADD("maincpu", _5A22, MCLK_NTSC)   /* 2.68 MHz, also 3.58 MHz */
709   MCFG_CPU_PROGRAM_MAP(snes_map)
710
711   MCFG_CPU_ADD("soundcpu", SPC700, 1024000)   /* 1.024 MHz */
712   MCFG_CPU_PROGRAM_MAP(spc_map)
713
714   //MCFG_QUANTUM_TIME(attotime::from_hz(48000))
715   MCFG_QUANTUM_PERFECT_CPU("maincpu")
716
717   MCFG_MACHINE_START(snes_mess)
718   MCFG_MACHINE_RESET(snes_mess)
719
720   /* video hardware */
721   MCFG_VIDEO_START(snes)
722
723   MCFG_SCREEN_ADD("screen", RASTER)
724   MCFG_SCREEN_FORMAT(BITMAP_FORMAT_RGB32)
725   MCFG_SCREEN_RAW_PARAMS(DOTCLK_NTSC, SNES_HTOTAL, 0, SNES_SCR_WIDTH, SNES_VTOTAL_NTSC, 0, SNES_SCR_HEIGHT_NTSC)
726   MCFG_SCREEN_UPDATE(snes)
727
728   /* sound hardware */
729   MCFG_SPEAKER_STANDARD_STEREO("lspeaker", "rspeaker")
730   MCFG_SOUND_ADD("spc700", SNES, 0)
731   MCFG_SOUND_ROUTE(0, "lspeaker", 1.00)
732   MCFG_SOUND_ROUTE(1, "rspeaker", 1.00)
733MACHINE_CONFIG_END
734
735static MACHINE_CONFIG_DERIVED( snes, snes_base )
736
737   MCFG_FRAGMENT_ADD(snes_cartslot)
738MACHINE_CONFIG_END
739
740static SUPERFX_CONFIG( snes_superfx_config )
741{
742   DEVCB_LINE(snes_extern_irq_w)   /* IRQ line from cart */
743};
744
745static MACHINE_CONFIG_DERIVED( snessfx, snes )
746
747   MCFG_CPU_ADD("superfx", SUPERFX, 21480000)   /* 21.48MHz */
748   MCFG_CPU_PROGRAM_MAP(superfx_map)
749   MCFG_CPU_CONFIG(snes_superfx_config)
750MACHINE_CONFIG_END
751
752static MACHINE_CONFIG_DERIVED( snesdsp, snes )
753
754   MCFG_CPU_ADD("dsp", UPD7725, 8000000)
755   MCFG_CPU_PROGRAM_MAP(dsp_prg_map)
756   MCFG_CPU_DATA_MAP(dsp_data_map)
757MACHINE_CONFIG_END
758
759static MACHINE_CONFIG_DERIVED( snesst10, snes )
760
761   MCFG_CPU_ADD("setadsp", UPD96050, 10000000)
762   MCFG_CPU_PROGRAM_MAP(setadsp_prg_map)
763   MCFG_CPU_DATA_MAP(setadsp_data_map)
764MACHINE_CONFIG_END
765
766static MACHINE_CONFIG_DERIVED( snesst11, snes )
767
768   MCFG_CPU_ADD("setadsp", UPD96050, 15000000)
769   MCFG_CPU_PROGRAM_MAP(setadsp_prg_map)
770   MCFG_CPU_DATA_MAP(setadsp_data_map)
771MACHINE_CONFIG_END
772
773static MACHINE_CONFIG_DERIVED( snespal, snes )
774   MCFG_CPU_MODIFY( "maincpu" )
775   MCFG_CPU_CLOCK( MCLK_PAL )
776
777   MCFG_SCREEN_MODIFY("screen")
778   MCFG_SCREEN_RAW_PARAMS(DOTCLK_PAL, SNES_HTOTAL, 0, SNES_SCR_WIDTH, SNES_VTOTAL_PAL, 0, SNES_SCR_HEIGHT_PAL)
779MACHINE_CONFIG_END
780
781static MACHINE_CONFIG_DERIVED( snespsfx, snespal )
782
783   MCFG_CPU_ADD("superfx", SUPERFX, 21480000)   /* 21.48MHz */
784   MCFG_CPU_PROGRAM_MAP(superfx_map)
785   MCFG_CPU_CONFIG(snes_superfx_config)
786MACHINE_CONFIG_END
787
788static MACHINE_CONFIG_DERIVED( snespdsp, snespal )
789
790   MCFG_CPU_ADD("dsp", UPD7725, 8000000)
791   MCFG_CPU_PROGRAM_MAP(dsp_prg_map)
792   MCFG_CPU_DATA_MAP(dsp_data_map)
793MACHINE_CONFIG_END
794
795static MACHINE_CONFIG_DERIVED( snesst, snes_base )
796
797   MCFG_MACHINE_START(snesst)
798
799   MCFG_FRAGMENT_ADD(sufami_cartslot)
800MACHINE_CONFIG_END
801
802static MACHINE_CONFIG_DERIVED( snesbsx, snes_base )
803
804   MCFG_FRAGMENT_ADD(bsx_cartslot)
805MACHINE_CONFIG_END
806
807
808/*************************************
809 *
810 *  ROM definition(s)
811 *
812 *************************************/
813
814ROM_START( snes )
815   ROM_REGION( 0x1000000, "maincpu", ROMREGION_ERASE00 )
816
817   ROM_REGION( 0x100, "user5", 0 )      /* IPL ROM */
818   ROM_LOAD( "spc700.rom", 0, 0x40, CRC(44bb3a40) SHA1(97e352553e94242ae823547cd853eecda55c20f0) )   /* boot rom */
819
820   ROM_REGION( 0x10000, "addons", ROMREGION_ERASE00 )      /* add-on chip ROMs (DSP, SFX, etc) */
821
822   ROM_REGION( MAX_SNES_CART_SIZE, "cart", ROMREGION_ERASE00 )
823   ROM_REGION( 0x2000, "dspprg", ROMREGION_ERASEFF)
824   ROM_REGION( 0x800, "dspdata", ROMREGION_ERASEFF)
825ROM_END
826
827ROM_START( snesdsp )
828   ROM_REGION( 0x1000000, "maincpu", ROMREGION_ERASE00 )
829
830   ROM_REGION( 0x100, "user5", 0 )      /* IPL ROM */
831   ROM_LOAD( "spc700.rom", 0, 0x40, CRC(44bb3a40) SHA1(97e352553e94242ae823547cd853eecda55c20f0) )   /* boot rom */
832
833   ROM_REGION( 0x10000, "addons", 0 )      /* add-on chip ROMs (DSP, SFX, etc) */
834   ROM_LOAD( "dsp1b.bin", SNES_DSP1B_OFFSET, 0x002800, CRC(453557e0) SHA1(3a218b0e4572a8eba6d0121b17fdac9529609220) )
835   ROM_LOAD( "dsp1.bin",  SNES_DSP1_OFFSET,  0x002800, CRC(2838f9f5) SHA1(0a03ccb1fd2bea91151c745a4d1f217ae784f889) )
836   ROM_LOAD( "dsp2.bin",  SNES_DSP2_OFFSET,  0x002800, CRC(8e9fbd9b) SHA1(06dd9fcb118d18f6bbe234e013cb8780e06d6e63) )
837   ROM_LOAD( "dsp3.bin",  SNES_DSP3_OFFSET,  0x002800, CRC(6b86728a) SHA1(1b133741fad810eb7320c21ecfdd427d25a46da1) )
838   ROM_LOAD( "dsp4.bin",  SNES_DSP4_OFFSET,  0x002800, CRC(ce0c7783) SHA1(76fd25f7dc26c3b3f7868a3aa78c7684068713e5) )
839
840   ROM_REGION( MAX_SNES_CART_SIZE, "cart", ROMREGION_ERASE00 )
841   ROM_REGION( 0x2000, "dspprg", ROMREGION_ERASEFF)
842   ROM_REGION( 0x800, "dspdata", ROMREGION_ERASEFF)
843ROM_END
844
845ROM_START( snesst10 )
846   ROM_REGION( 0x1000000, "maincpu", ROMREGION_ERASE00 )
847
848   ROM_REGION( 0x100, "user5", 0 )      /* IPL ROM */
849   ROM_LOAD( "spc700.rom", 0, 0x40, CRC(44bb3a40) SHA1(97e352553e94242ae823547cd853eecda55c20f0) )   /* boot rom */
850
851   ROM_REGION( 0x11000, "addons", 0 )      /* add-on chip ROMs (DSP, SFX, etc) */
852   ROM_LOAD( "st010.bin",    0x000000, 0x011000, CRC(aa11ee2d) SHA1(cc1984e989cb94e3dcbb5f99e085b5414e18a017) )
853
854   ROM_REGION( MAX_SNES_CART_SIZE, "cart", ROMREGION_ERASE00 )
855   ROM_REGION( 0x10000, "dspprg", ROMREGION_ERASEFF)
856   ROM_REGION( 0x1000, "dspdata", ROMREGION_ERASEFF)
857ROM_END
858
859ROM_START( snesst11 )
860   ROM_REGION( 0x1000000, "maincpu", ROMREGION_ERASE00 )
861
862   ROM_REGION( 0x100, "user5", 0 )      /* IPL ROM */
863   ROM_LOAD( "spc700.rom", 0, 0x40, CRC(44bb3a40) SHA1(97e352553e94242ae823547cd853eecda55c20f0) )   /* boot rom */
864
865   ROM_REGION( 0x11000, "addons", 0 )      /* add-on chip ROMs (DSP, SFX, etc) */
866   ROM_LOAD( "st011.bin",    0x000000, 0x011000, CRC(34d2952c) SHA1(1375b8c1efc8cae4962b57dfe22f6b78e1ddacc8) )
867
868   ROM_REGION( MAX_SNES_CART_SIZE, "cart", ROMREGION_ERASE00 )
869   ROM_REGION( 0x10000, "dspprg", ROMREGION_ERASEFF)
870   ROM_REGION( 0x1000, "dspdata", ROMREGION_ERASEFF)
871ROM_END
872
873ROM_START( snessfx )
874   ROM_REGION( 0x1000000, "maincpu", ROMREGION_ERASE00 )
875
876   ROM_REGION( 0x100, "user5", 0 )      /* IPL ROM */
877   ROM_LOAD( "spc700.rom", 0, 0x40, CRC(44bb3a40) SHA1(97e352553e94242ae823547cd853eecda55c20f0) )   /* boot rom */
878
879   ROM_REGION( 0x10000, "addons", ROMREGION_ERASE00 )      /* add-on chip ROMs (DSP, SFX, etc) */
880
881   ROM_REGION( MAX_SNES_CART_SIZE, "cart", ROMREGION_ERASE00 )
882   ROM_REGION( 0x2000, "dspprg", ROMREGION_ERASEFF)
883   ROM_REGION( 0x800, "dspdata", ROMREGION_ERASEFF)
884ROM_END
885
886ROM_START( snespal )
887   ROM_REGION( 0x1000000, "maincpu", ROMREGION_ERASE00 )
888
889   ROM_REGION( 0x100, "user5", 0 )      /* IPL ROM */
890   ROM_LOAD( "spc700.rom", 0, 0x40, CRC(44bb3a40) SHA1(97e352553e94242ae823547cd853eecda55c20f0) )   /* boot rom */
891
892   ROM_REGION( 0x10000, "addons", ROMREGION_ERASE00 )      /* add-on chip ROMs (DSP, SFX, etc) */
893
894   ROM_REGION( MAX_SNES_CART_SIZE, "cart", ROMREGION_ERASE00 )
895   ROM_REGION( 0x2000, "dspprg", ROMREGION_ERASEFF)
896   ROM_REGION( 0x800, "dspdata", ROMREGION_ERASEFF)
897ROM_END
898
899ROM_START( snespdsp )
900   ROM_REGION( 0x1000000, "maincpu", ROMREGION_ERASE00 )
901
902   ROM_REGION( 0x100, "user5", 0 )      /* IPL ROM */
903   ROM_LOAD( "spc700.rom", 0, 0x40, CRC(44bb3a40) SHA1(97e352553e94242ae823547cd853eecda55c20f0) )   /* boot rom */
904
905   ROM_REGION( 0x10000, "addons", 0 )      /* add-on chip ROMs (DSP, SFX, etc) */
906   ROM_LOAD( "dsp1b.bin", SNES_DSP1B_OFFSET, 0x002800, CRC(453557e0) SHA1(3a218b0e4572a8eba6d0121b17fdac9529609220) )
907   ROM_LOAD( "dsp1.bin",  SNES_DSP1_OFFSET,  0x002800, CRC(2838f9f5) SHA1(0a03ccb1fd2bea91151c745a4d1f217ae784f889) )
908   ROM_LOAD( "dsp2.bin",  SNES_DSP2_OFFSET,  0x002800, CRC(8e9fbd9b) SHA1(06dd9fcb118d18f6bbe234e013cb8780e06d6e63) )
909   ROM_LOAD( "dsp3.bin",  SNES_DSP3_OFFSET,  0x002800, CRC(6b86728a) SHA1(1b133741fad810eb7320c21ecfdd427d25a46da1) )
910   ROM_LOAD( "dsp4.bin",  SNES_DSP4_OFFSET,  0x002800, CRC(ce0c7783) SHA1(76fd25f7dc26c3b3f7868a3aa78c7684068713e5) )
911
912   ROM_REGION( MAX_SNES_CART_SIZE, "cart", ROMREGION_ERASE00 )
913   ROM_REGION( 0x2000, "dspprg", ROMREGION_ERASEFF)
914   ROM_REGION( 0x800, "dspdata", ROMREGION_ERASEFF)
915ROM_END
916
917ROM_START( snespsfx )
918   ROM_REGION( 0x1000000, "maincpu", ROMREGION_ERASE00 )
919
920   ROM_REGION( 0x100, "user5", 0 )      /* IPL ROM */
921   ROM_LOAD( "spc700.rom", 0, 0x40, CRC(44bb3a40) SHA1(97e352553e94242ae823547cd853eecda55c20f0) )   /* boot rom */
922
923   ROM_REGION( 0x10000, "addons", ROMREGION_ERASE00 )      /* add-on chip ROMs (DSP, SFX, etc) */
924
925   ROM_REGION( MAX_SNES_CART_SIZE, "cart", ROMREGION_ERASE00 )
926   ROM_REGION( 0x2000, "dspprg", ROMREGION_ERASEFF)
927   ROM_REGION( 0x800, "dspdata", ROMREGION_ERASEFF)
928ROM_END
929
930ROM_START( snesst )
931   ROM_REGION( 0x1000000, "maincpu", ROMREGION_ERASE00 )
932
933   ROM_REGION( 0x100, "user5", 0 )      /* IPL ROM */
934   ROM_LOAD( "spc700.rom", 0, 0x40, CRC(44bb3a40) SHA1(97e352553e94242ae823547cd853eecda55c20f0) )   /* boot rom */
935
936   ROM_REGION( 0x10000, "addons", ROMREGION_ERASE00 )      /* add-on chip ROMs (DSP, SFX, etc) */
937
938   ROM_REGION( 0x40000, "sufami", 0 )      /* add-on chip ROMs (DSP, SFX, etc) */
939   ROM_LOAD( "shvc-qh-0.bin", 0,   0x40000, CRC(9b4ca911) SHA1(ef86ea192eed03d5c413fdbbfd46043be1d7a127) )
940
941   ROM_REGION( MAX_SNES_CART_SIZE, "slot_a", ROMREGION_ERASE00 )
942   ROM_REGION( MAX_SNES_CART_SIZE, "slot_b", ROMREGION_ERASE00 )
943   ROM_REGION( 0x2000, "dspprg", ROMREGION_ERASEFF)
944   ROM_REGION( 0x800, "dspdata", ROMREGION_ERASEFF)
945ROM_END
946
947ROM_START( snesbsx )
948   ROM_REGION( 0x1000000, "maincpu", ROMREGION_ERASE00 )
949
950   ROM_REGION( 0x100, "user5", 0 )      /* IPL ROM */
951   ROM_LOAD( "spc700.rom", 0, 0x40, CRC(44bb3a40) SHA1(97e352553e94242ae823547cd853eecda55c20f0) )   /* boot rom */
952
953   ROM_REGION( 0x10000, "addons", 0 )      /* add-on chip ROMs (DSP, SFX, etc) */
954   ROM_LOAD( "dsp1b.bin", SNES_DSP1B_OFFSET, 0x002800, CRC(453557e0) SHA1(3a218b0e4572a8eba6d0121b17fdac9529609220) )
955   ROM_LOAD( "dsp1.bin",  SNES_DSP1_OFFSET,  0x002800, CRC(2838f9f5) SHA1(0a03ccb1fd2bea91151c745a4d1f217ae784f889) )
956   ROM_LOAD( "dsp2.bin",  SNES_DSP2_OFFSET,  0x002800, CRC(8e9fbd9b) SHA1(06dd9fcb118d18f6bbe234e013cb8780e06d6e63) )
957   ROM_LOAD( "dsp3.bin",  SNES_DSP3_OFFSET,  0x002800, CRC(6b86728a) SHA1(1b133741fad810eb7320c21ecfdd427d25a46da1) )
958   ROM_LOAD( "dsp4.bin",  SNES_DSP4_OFFSET,  0x002800, CRC(ce0c7783) SHA1(76fd25f7dc26c3b3f7868a3aa78c7684068713e5) )
959
960   ROM_REGION( MAX_SNES_CART_SIZE, "cart", ROMREGION_ERASE00 )
961   ROM_REGION( MAX_SNES_CART_SIZE, "flash", ROMREGION_ERASE00 )
962   ROM_REGION( 0x2000, "dspprg", ROMREGION_ERASEFF)
963   ROM_REGION( 0x800, "dspdata", ROMREGION_ERASEFF)
964ROM_END
965
966
967
968/*************************************
969 *
970 *  Game driver(s)
971 *
972 *************************************/
973
974/*    YEAR  NAME      PARENT  COMPAT  MACHINE   INPUT  INIT          COMPANY     FULLNAME                                      FLAGS */
975CONS( 1989, snes,     0,      0,      snes,     snes,  snes_mess,    "Nintendo", "Super Nintendo Entertainment System / Super Famicom (NTSC)", GAME_IMPERFECT_GRAPHICS | GAME_IMPERFECT_SOUND )
976CONS( 1991, snespal,  snes,   0,      snespal,  snes,  snes_mess,    "Nintendo", "Super Nintendo Entertainment System (PAL)",  GAME_IMPERFECT_GRAPHICS | GAME_IMPERFECT_SOUND )
977
978// FIXME: the "hacked" drivers below, currently needed due to limitations in the core device design, should eventually be removed
979
980// These would require CPU to be added/removed depending on the cart which is loaded
981CONS( 1989, snesdsp,  snes,   0,      snesdsp,  snes,  snes_mess,    "Nintendo", "Super Nintendo Entertainment System / Super Famicom (NTSC, w/DSP-x)", GAME_IMPERFECT_GRAPHICS | GAME_IMPERFECT_SOUND )
982CONS( 1991, snespdsp, snes,   0,      snespdsp, snes,  snes_mess,    "Nintendo", "Super Nintendo Entertainment System (PAL, w/DSP-x)",  GAME_IMPERFECT_GRAPHICS | GAME_IMPERFECT_SOUND )
983CONS( 1989, snessfx,  snes,   0,      snessfx,  snes,  snes_mess,    "Nintendo", "Super Nintendo Entertainment System / Super Famicom (NTSC, w/SuperFX)", GAME_IMPERFECT_GRAPHICS | GAME_IMPERFECT_SOUND )
984CONS( 1991, snespsfx, snes,   0,      snespsfx, snes,  snes_mess,    "Nintendo", "Super Nintendo Entertainment System (PAL, w/SuperFX)",  GAME_IMPERFECT_GRAPHICS | GAME_IMPERFECT_SOUND )
985CONS( 1989, snesst10,  snes,   0,      snesst10,  snes,  snes_mess,    "Nintendo", "Super Nintendo Entertainment System / Super Famicom (NTSC, w/ST-010)", GAME_IMPERFECT_GRAPHICS | GAME_IMPERFECT_SOUND )
986CONS( 1989, snesst11,  snes,   0,      snesst11,  snes,  snes_mess,    "Nintendo", "Super Nintendo Entertainment System / Super Famicom (NTSC, w/ST-011)", GAME_IMPERFECT_GRAPHICS | GAME_IMPERFECT_SOUND )
987//CONS( 1989, snessa1,  snes,   0,      snessa1,  snes,  snes_mess,    "Nintendo", "Super Nintendo Entertainment System / Super Famicom (NTSC, w/SA-1)", GAME_IMPERFECT_GRAPHICS | GAME_IMPERFECT_SOUND )
988//CONS( 1991, snespsa1, snes,   0,      snespsa1, snes,  snes_mess,    "Nintendo", "Super Nintendo Entertainment System (PAL, w/SA-1)",  GAME_IMPERFECT_GRAPHICS | GAME_IMPERFECT_SOUND )
989
990// These would require cartslot to be added/removed depending on the cart which is loaded
991CONS( 1989, snesst,   snes,   0,      snesst,  snes,  snesst,       "Nintendo", "Super Nintendo Entertainment System / Super Famicom (NTSC, w/Sufami Turbo)", GAME_NOT_WORKING )
992CONS( 1989, snesbsx,  snes,   0,      snesbsx, snes,  snes_mess,    "Nintendo", "Super Nintendo Entertainment System / Super Famicom (NTSC, w/BS-X Satellaview slotted cart)",  GAME_NOT_WORKING )
src/mess/drivers/a310.c
r0r11532
1/******************************************************************************
2 *
3 *  Acorn Archimedes 310
4 *
5 *  Skeleton: Juergen Buchmueller <pullmoll@t-online.de>, Jul 2000
6 *  Enhanced: R. Belmont, June 2007
7 *  Angelo Salese, August 2010
8 *
9 *  TODO:
10 *  - try to understand why bios 2 was working at some point and now isn't
11 *  - fix RISC OS / Arthur booting, possible causes:
12 *  \- missing reset page size hook-up
13 *  \- some subtle memory paging fault
14 *  \- missing RAM max size
15 *  \- ARM bug?
16 *
17 *
18=======================================================================================
19 *
20 *      Memory map (from http://b-em.bbcmicro.com/arculator/archdocs.txt)
21 *
22 *  0000000 - 1FFFFFF - logical RAM (32 meg)
23 *  2000000 - 2FFFFFF - physical RAM (supervisor only - max 16MB - requires quad MEMCs)
24 *  3000000 - 33FFFFF - IOC (IO controllers - supervisor only)
25 *  3310000 - FDC - WD1772
26 *  33A0000 - Econet - 6854
27 *  33B0000 - Serial - 6551
28 *  3240000 - 33FFFFF - internal expansion cards
29 *  32D0000 - hard disc controller (not IDE) - HD63463
30 *  3350010 - printer
31 *  3350018 - latch A
32 *  3350040 - latch B
33 *  3270000 - external expansion cards
34 *
35 *  3400000 - 3FFFFFF - ROM (read - 12 meg - Arthur and RiscOS 2 512k, RiscOS 3 2MB)
36 *  3400000 - 37FFFFF - Low ROM  (4 meg, I think this is expansion ROMs)
37 *  3800000 - 3FFFFFF - High ROM (main OS ROM)
38 *
39 *  3400000 - 35FFFFF - VICD10 (write - supervisor only)
40 *  3600000 - 3FFFFFF - MEMC (write - supervisor only)
41 *
42 *****************************************************************************/
43/*
44    DASM of code (bios 2 / RISC OS 2)
45    0x380d4e0: MEMC: control to 0x10c (page size 32 kbytes, DRAM ram refresh only during flyback)
46    0x380d4f0: VIDC: params (screen + sound frequency)
47    0x380d51c: IOC: sets control to 0xff, clear IRQA and FIQ masks, sets IRQB mask to 0x80 (keyboard receive full irq)
48    0x380d530: IOC: sets timer 0 to 0x4e20, go command
49        0x380e0a8: work RAM physical check, max size etc.
50    0x380e1f8: IOC: Disables DRAM ram refresh, sets timer 1 to 0x7ffe, go command, then it tests the latch of this timer, enables DRAM refresh
51        0x380d00c: Set up default logical space
52        0x380d16c: Set up case by case logical space
53
54
55*/
56
57
58#include "emu.h"
59#include "machine/wd17xx.h"
60#include "imagedev/flopdrv.h"
61#include "cpu/arm/arm.h"
62#include "sound/dac.h"
63#include "includes/archimds.h"
64#include "machine/i2cmem.h"
65#include "machine/ram.h"
66
67
68class a310_state : public driver_device
69{
70public:
71   a310_state(const machine_config &mconfig, device_type type, const char *tag)
72      : driver_device(mconfig, type, tag) { }
73
74};
75
76
77static WRITE_LINE_DEVICE_HANDLER( a310_wd177x_intrq_w )
78{
79   if (state)
80      archimedes_request_fiq(device->machine(), ARCHIMEDES_FIQ_FLOPPY);
81   else
82      archimedes_clear_fiq(device->machine(), ARCHIMEDES_FIQ_FLOPPY);
83}
84
85static WRITE_LINE_DEVICE_HANDLER( a310_wd177x_drq_w )
86{
87   if (state)
88      archimedes_request_fiq(device->machine(), ARCHIMEDES_FIQ_FLOPPY_DRQ);
89   else
90      archimedes_clear_fiq(device->machine(), ARCHIMEDES_FIQ_FLOPPY_DRQ);
91}
92
93static READ32_HANDLER( a310_psy_wram_r )
94{
95   return archimedes_memc_physmem[offset];
96}
97
98static WRITE32_HANDLER( a310_psy_wram_w )
99{
100   COMBINE_DATA(&archimedes_memc_physmem[offset]);
101}
102
103
104static DRIVER_INIT(a310)
105{
106   UINT32 ram_size = ram_get_size(machine.device(RAM_TAG));
107
108   archimedes_memc_physmem = auto_alloc_array(machine, UINT32, 0x01000000);
109
110   machine.device("maincpu")->memory().space(AS_PROGRAM)->install_legacy_readwrite_handler( 0x02000000, 0x02000000+(ram_size-1), FUNC(a310_psy_wram_r), FUNC(a310_psy_wram_w) );
111
112   archimedes_driver_init(machine);
113}
114
115static MACHINE_START( a310 )
116{
117   archimedes_init(machine);
118
119   // reset the DAC to centerline
120   //dac_signed_data_w(machine.device("dac"), 0x80);
121}
122
123static MACHINE_RESET( a310 )
124{
125   archimedes_reset(machine);
126}
127
128static ADDRESS_MAP_START( a310_mem, AS_PROGRAM, 32 )
129   AM_RANGE(0x00000000, 0x01ffffff) AM_READWRITE(archimedes_memc_logical_r, archimedes_memc_logical_w)
130//  AM_RANGE(0x02000000, 0x02ffffff) AM_RAM AM_BASE(&archimedes_memc_physmem) /* physical RAM - 16 MB for now, should be 512k for the A310 */
131   AM_RANGE(0x03000000, 0x033fffff) AM_READWRITE(archimedes_ioc_r, archimedes_ioc_w)
132   AM_RANGE(0x03400000, 0x035fffff) AM_READWRITE(archimedes_vidc_r, archimedes_vidc_w)
133   AM_RANGE(0x03600000, 0x037fffff) AM_READWRITE(archimedes_memc_r, archimedes_memc_w)
134   AM_RANGE(0x03800000, 0x03ffffff) AM_ROM AM_REGION("maincpu", 0) AM_WRITE(archimedes_memc_page_w)
135ADDRESS_MAP_END
136
137
138static INPUT_PORTS_START( a310 )
139   PORT_START("dip") /* DIP switches */
140   PORT_BIT(0xfd, 0xfd, IPT_UNUSED)
141
142   PORT_START("key0") /* KEY ROW 0 */
143   PORT_BIT(0x01, 0x00, IPT_KEYBOARD) PORT_NAME("ESC") PORT_CODE(KEYCODE_ESC)
144   PORT_BIT(0x02, 0x00, IPT_KEYBOARD) PORT_NAME("1  !") PORT_CODE(KEYCODE_1)
145   PORT_BIT(0x04, 0x00, IPT_KEYBOARD) PORT_NAME("2  \"") PORT_CODE(KEYCODE_2)
146   PORT_BIT(0x08, 0x00, IPT_KEYBOARD) PORT_NAME("3  #") PORT_CODE(KEYCODE_3)
147   PORT_BIT(0x10, 0x00, IPT_KEYBOARD) PORT_NAME("4  $") PORT_CODE(KEYCODE_4)
148   PORT_BIT(0x20, 0x00, IPT_KEYBOARD) PORT_NAME("5  %") PORT_CODE(KEYCODE_5)
149   PORT_BIT(0x40, 0x00, IPT_KEYBOARD) PORT_NAME("6  &") PORT_CODE(KEYCODE_6)
150   PORT_BIT(0x80, 0x00, IPT_KEYBOARD) PORT_NAME("7  '") PORT_CODE(KEYCODE_7)
151
152   PORT_START("key1") /* KEY ROW 1 */
153   PORT_BIT(0x01, 0x00, IPT_KEYBOARD) PORT_NAME("8  *") PORT_CODE(KEYCODE_8)
154   PORT_BIT(0x02, 0x00, IPT_KEYBOARD) PORT_NAME("9  (") PORT_CODE(KEYCODE_9)
155   PORT_BIT(0x04, 0x00, IPT_KEYBOARD) PORT_NAME("0  )") PORT_CODE(KEYCODE_0)
156   PORT_BIT(0x08, 0x00, IPT_KEYBOARD) PORT_NAME("-  _") PORT_CODE(KEYCODE_MINUS)
157   PORT_BIT(0x10, 0x00, IPT_KEYBOARD) PORT_NAME("=  +") PORT_CODE(KEYCODE_EQUALS)
158   PORT_BIT(0x20, 0x00, IPT_KEYBOARD) PORT_NAME("`  ~") PORT_CODE(KEYCODE_TILDE)
159   PORT_BIT(0x40, 0x00, IPT_KEYBOARD) PORT_NAME("BACK SPACE") PORT_CODE(KEYCODE_BACKSPACE)
160   PORT_BIT(0x80, 0x00, IPT_KEYBOARD) PORT_NAME("TAB") PORT_CODE(KEYCODE_TAB)
161
162   PORT_START("key2") /* KEY ROW 2 */
163   PORT_BIT(0x01, 0x00, IPT_KEYBOARD) PORT_NAME("q  Q") PORT_CODE(KEYCODE_Q)
164   PORT_BIT(0x02, 0x00, IPT_KEYBOARD) PORT_NAME("w  W") PORT_CODE(KEYCODE_W)
165   PORT_BIT(0x04, 0x00, IPT_KEYBOARD) PORT_NAME("e  E") PORT_CODE(KEYCODE_E)
166   PORT_BIT(0x08, 0x00, IPT_KEYBOARD) PORT_NAME("r  R") PORT_CODE(KEYCODE_R)
167   PORT_BIT(0x10, 0x00, IPT_KEYBOARD) PORT_NAME("t  T") PORT_CODE(KEYCODE_T)
168   PORT_BIT(0x20, 0x00, IPT_KEYBOARD) PORT_NAME("y  Y") PORT_CODE(KEYCODE_Y)
169   PORT_BIT(0x40, 0x00, IPT_KEYBOARD) PORT_NAME("u  U") PORT_CODE(KEYCODE_U)
170   PORT_BIT(0x80, 0x00, IPT_KEYBOARD) PORT_NAME("i  I") PORT_CODE(KEYCODE_I)
171
172   PORT_START("key3") /* KEY ROW 3 */
173   PORT_BIT(0x01, 0x00, IPT_KEYBOARD) PORT_NAME("o  O") PORT_CODE(KEYCODE_O)
174   PORT_BIT(0x02, 0x00, IPT_KEYBOARD) PORT_NAME("p  P") PORT_CODE(KEYCODE_P)
175   PORT_BIT(0x04, 0x00, IPT_KEYBOARD) PORT_NAME("[  {") PORT_CODE(KEYCODE_OPENBRACE)
176   PORT_BIT(0x08, 0x00, IPT_KEYBOARD) PORT_NAME("]  }") PORT_CODE(KEYCODE_CLOSEBRACE)
177   PORT_BIT(0x10, 0x00, IPT_KEYBOARD) PORT_NAME("RETURN") PORT_CODE(KEYCODE_ENTER)
178   PORT_BIT(0x20, 0x00, IPT_KEYBOARD) PORT_NAME("DEL") PORT_CODE(KEYCODE_DEL)
179   PORT_BIT(0x40, 0x00, IPT_KEYBOARD) PORT_NAME("CTRL") PORT_CODE(KEYCODE_LCONTROL)
180   PORT_BIT(0x80, 0x80, IPT_KEYBOARD) PORT_NAME("CAPS LOCK") PORT_CODE(KEYCODE_CAPSLOCK) PORT_TOGGLE
181
182   PORT_START("key4") /* KEY ROW 4 */
183   PORT_BIT(0x01, 0x00, IPT_KEYBOARD) PORT_NAME("a  A") PORT_CODE(KEYCODE_A)
184   PORT_BIT(0x02, 0x00, IPT_KEYBOARD) PORT_NAME("s  S") PORT_CODE(KEYCODE_S)
185   PORT_BIT(0x04, 0x00, IPT_KEYBOARD) PORT_NAME("d  D") PORT_CODE(KEYCODE_D)
186   PORT_BIT(0x08, 0x00, IPT_KEYBOARD) PORT_NAME("f  F") PORT_CODE(KEYCODE_F)
187   PORT_BIT(0x10, 0x00, IPT_KEYBOARD) PORT_NAME("g  G") PORT_CODE(KEYCODE_G)
188   PORT_BIT(0x20, 0x00, IPT_KEYBOARD) PORT_NAME("h  H") PORT_CODE(KEYCODE_H)
189   PORT_BIT(0x40, 0x00, IPT_KEYBOARD) PORT_NAME("j  J") PORT_CODE(KEYCODE_J)
190   PORT_BIT(0x80, 0x00, IPT_KEYBOARD) PORT_NAME("k  K") PORT_CODE(KEYCODE_K)
191
192   PORT_START("key5") /* KEY ROW 5 */
193   PORT_BIT(0x01, 0x00, IPT_KEYBOARD) PORT_NAME("l  L") PORT_CODE(KEYCODE_L)
194   PORT_BIT(0x02, 0x00, IPT_KEYBOARD) PORT_NAME(";  :") PORT_CODE(KEYCODE_COLON)
195   PORT_BIT(0x04, 0x00, IPT_KEYBOARD) PORT_NAME("'  \"") PORT_CODE(KEYCODE_QUOTE)
196   PORT_BIT(0x08, 0x00, IPT_KEYBOARD) PORT_NAME("\\  |") PORT_CODE(KEYCODE_ASTERISK)
197   PORT_BIT(0x10, 0x00, IPT_KEYBOARD) PORT_NAME("SHIFT (L)") PORT_CODE(KEYCODE_LSHIFT)
198   PORT_BIT(0x20, 0x00, IPT_KEYBOARD) PORT_NAME("z  Z") PORT_CODE(KEYCODE_Z)
199   PORT_BIT(0x40, 0x00, IPT_KEYBOARD) PORT_NAME("x  X") PORT_CODE(KEYCODE_X)
200   PORT_BIT(0x80, 0x00, IPT_KEYBOARD) PORT_NAME("c  C") PORT_CODE(KEYCODE_C)
201
202   PORT_START("key6") /* KEY ROW 6 */
203   PORT_BIT(0x01, 0x00, IPT_KEYBOARD) PORT_NAME("v  V") PORT_CODE(KEYCODE_V)
204   PORT_BIT(0x02, 0x00, IPT_KEYBOARD) PORT_NAME("b  B") PORT_CODE(KEYCODE_B)
205   PORT_BIT(0x04, 0x00, IPT_KEYBOARD) PORT_NAME("n  N") PORT_CODE(KEYCODE_N)
206   PORT_BIT(0x08, 0x00, IPT_KEYBOARD) PORT_NAME("m  M") PORT_CODE(KEYCODE_M)
207   PORT_BIT(0x10, 0x00, IPT_KEYBOARD) PORT_NAME(",  <") PORT_CODE(KEYCODE_COMMA)
208   PORT_BIT(0x20, 0x00, IPT_KEYBOARD) PORT_NAME(".  >") PORT_CODE(KEYCODE_STOP)
209   PORT_BIT(0x40, 0x00, IPT_KEYBOARD) PORT_NAME("/  ?") PORT_CODE(KEYCODE_SLASH)
210   PORT_BIT(0x80, 0x00, IPT_KEYBOARD) PORT_NAME("SHIFT (R)") PORT_CODE(KEYCODE_RSHIFT)
211
212   PORT_START("key7") /* KEY ROW 7 */
213   PORT_BIT(0x01, 0x00, IPT_KEYBOARD) PORT_NAME("LINE FEED")
214   PORT_BIT(0x02, 0x00, IPT_KEYBOARD) PORT_NAME("SPACE") PORT_CODE(KEYCODE_SPACE)
215   PORT_BIT(0x04, 0x00, IPT_KEYBOARD) PORT_NAME("- (KP)") PORT_CODE(KEYCODE_MINUS_PAD)
216   PORT_BIT(0x08, 0x00, IPT_KEYBOARD) PORT_NAME(", (KP)") PORT_CODE(KEYCODE_PLUS_PAD)
217   PORT_BIT(0x10, 0x00, IPT_KEYBOARD) PORT_NAME("ENTER (KP)") PORT_CODE(KEYCODE_ENTER_PAD)
218   PORT_BIT(0x20, 0x00, IPT_KEYBOARD) PORT_NAME(". (KP)") PORT_CODE(KEYCODE_DEL_PAD)
219   PORT_BIT(0x40, 0x00, IPT_KEYBOARD) PORT_NAME("0 (KP)") PORT_CODE(KEYCODE_0_PAD)
220   PORT_BIT(0x80, 0x00, IPT_KEYBOARD) PORT_NAME("1 (KP)") PORT_CODE(KEYCODE_1_PAD)
221
222   PORT_START("key8") /* KEY ROW 8 */
223   PORT_BIT(0x01, 0x00, IPT_KEYBOARD) PORT_NAME("2 (KP)") PORT_CODE(KEYCODE_2_PAD)
224   PORT_BIT(0x02, 0x00, IPT_KEYBOARD) PORT_NAME("3 (KP)") PORT_CODE(KEYCODE_3_PAD)
225   PORT_BIT(0x04, 0x00, IPT_KEYBOARD) PORT_NAME("4 (KP)") PORT_CODE(KEYCODE_4_PAD)
226   PORT_BIT(0x08, 0x00, IPT_KEYBOARD) PORT_NAME("5 (KP)") PORT_CODE(KEYCODE_5_PAD)
227   PORT_BIT(0x10, 0x00, IPT_KEYBOARD) PORT_NAME("6 (KP)") PORT_CODE(KEYCODE_6_PAD)
228   PORT_BIT(0x20, 0x00, IPT_KEYBOARD) PORT_NAME("7 (KP)") PORT_CODE(KEYCODE_7_PAD)
229   PORT_BIT(0x40, 0x00, IPT_KEYBOARD) PORT_NAME("8 (KP)") PORT_CODE(KEYCODE_8_PAD)
230   PORT_BIT(0x80, 0x00, IPT_KEYBOARD) PORT_NAME("9 (KP)") PORT_CODE(KEYCODE_9_PAD)
231
232   PORT_START("via1a") /* VIA #1 PORT A */
233   PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_START) PORT_PLAYER(1)
234   PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_START) PORT_PLAYER(2)
235   PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_BUTTON1                )
236   PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_BUTTON2                )
237   PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT) PORT_4WAY
238   PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_JOYSTICK_UP) PORT_4WAY
239   PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT) PORT_4WAY
240   PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN) PORT_4WAY
241
242   PORT_START("tape")/* tape control */
243   PORT_BIT(0x01, 0x00, IPT_KEYBOARD) PORT_NAME("TAPE STOP") PORT_CODE(KEYCODE_F5)
244   PORT_BIT(0x02, 0x00, IPT_KEYBOARD) PORT_NAME("TAPE PLAY") PORT_CODE(KEYCODE_F6)
245   PORT_BIT(0x04, 0x00, IPT_KEYBOARD) PORT_NAME("TAPE REW") PORT_CODE(KEYCODE_F7)
246   PORT_BIT (0xf8, 0x80, IPT_UNUSED)
247INPUT_PORTS_END
248
249static const wd17xx_interface a310_wd17xx_interface =
250{
251   DEVCB_NULL,
252   DEVCB_LINE(a310_wd177x_intrq_w),
253   DEVCB_LINE(a310_wd177x_drq_w),
254   {FLOPPY_0, FLOPPY_1, FLOPPY_2, FLOPPY_3}
255};
256
257static const i2cmem_interface i2cmem_interface =
258{
259   I2CMEM_SLAVE_ADDRESS, 0, 0x100
260};
261
262static MACHINE_CONFIG_START( a310, a310_state )
263   /* basic machine hardware */
264   MCFG_CPU_ADD("maincpu", ARM, 8000000)        /* 8 MHz */
265   MCFG_CPU_PROGRAM_MAP(a310_mem)
266
267   MCFG_MACHINE_START( a310 )
268   MCFG_MACHINE_RESET( a310 )
269
270   MCFG_I2CMEM_ADD("i2cmem",i2cmem_interface)
271
272   /* video hardware */
273   MCFG_SCREEN_ADD("screen", RASTER)
274   MCFG_SCREEN_REFRESH_RATE(60)
275   MCFG_SCREEN_VBLANK_TIME(ATTOSECONDS_IN_USEC(2500)) /* not accurate */
276   MCFG_SCREEN_FORMAT(BITMAP_FORMAT_RGB32)
277   MCFG_SCREEN_SIZE(1280, 1024) //TODO: default screen size
278   MCFG_SCREEN_VISIBLE_AREA(0*8, 1280 - 1, 0*16, 1024 - 1)
279   MCFG_SCREEN_UPDATE(archimds_vidc)
280
281   MCFG_PALETTE_LENGTH(32768)
282
283   MCFG_VIDEO_START(archimds_vidc)
284
285   MCFG_RAM_ADD(RAM_TAG)
286   MCFG_RAM_DEFAULT_SIZE("2M")
287   MCFG_RAM_EXTRA_OPTIONS("512K, 1M, 4M, 8M, 16M")
288
289   MCFG_WD1772_ADD("wd1772", a310_wd17xx_interface )
290
291   //MCFG_FLOPPY_4_DRIVES_ADD(a310_floppy_config)
292
293   MCFG_SPEAKER_STANDARD_MONO("mono")
294   MCFG_SOUND_ADD("dac0", DAC, 0)
295   MCFG_SOUND_ROUTE(0, "mono", 0.10)
296
297   MCFG_SOUND_ADD("dac1", DAC, 0)
298   MCFG_SOUND_ROUTE(0, "mono", 0.10)
299
300   MCFG_SOUND_ADD("dac2", DAC, 0)
301   MCFG_SOUND_ROUTE(0, "mono", 0.10)
302
303   MCFG_SOUND_ADD("dac3", DAC, 0)
304   MCFG_SOUND_ROUTE(0, "mono", 0.10)
305
306   MCFG_SOUND_ADD("dac4", DAC, 0)
307   MCFG_SOUND_ROUTE(0, "mono", 0.10)
308
309   MCFG_SOUND_ADD("dac5", DAC, 0)
310   MCFG_SOUND_ROUTE(0, "mono", 0.10)
311
312   MCFG_SOUND_ADD("dac6", DAC, 0)
313   MCFG_SOUND_ROUTE(0, "mono", 0.10)
314
315   MCFG_SOUND_ADD("dac7", DAC, 0)
316   MCFG_SOUND_ROUTE(0, "mono", 0.10)
317MACHINE_CONFIG_END
318
319ROM_START(a310)
320   ROM_REGION( 0x800000, "maincpu", 0 )
321   ROM_SYSTEM_BIOS( 0, "311", "RiscOS 3.11 (29 Sep 1992)" )
322   ROMX_LOAD( "ic24.rom", 0x000000, 0x80000, CRC(c1adde84) SHA1(12d060e0401dd0523d44453f947bdc55dd2c3240), ROM_BIOS(1) )
323   ROMX_LOAD( "ic25.rom", 0x080000, 0x80000, CRC(15d89664) SHA1(78f5d0e6f1e8ee603317807f53ff8fe65a3b3518), ROM_BIOS(1) )
324   ROMX_LOAD( "ic26.rom", 0x100000, 0x80000, CRC(a81ceb7c) SHA1(46b870876bc1f68f242726415f0c49fef7be0c72), ROM_BIOS(1) )
325   ROMX_LOAD( "ic27.rom", 0x180000, 0x80000, CRC(707b0c6c) SHA1(345199a33fed23996374b9db8170a52ab63f0380), ROM_BIOS(1) )
326   ROM_SYSTEM_BIOS( 1, "120", "Arthur/RiscOS 1.20 (25 Sep 1987)" )
327   ROMX_LOAD( "arthur.bin",   0x000000, 0x080000, CRC(eb3fda57) SHA1(1181ff9c2c2f3d6d414054ec33b2260404bafc81), ROM_BIOS(2) )
328   ROM_SYSTEM_BIOS( 2, "200", "RiscOS 2.0 (05 Oct 1988)" )
329   ROMX_LOAD( "riscos2.bin",  0x000000, 0x080000, CRC(89c4ad36) SHA1(b82a78830dac386f9b649b6d32a34f9c6910546d), ROM_BIOS(3) )
330
331   ROM_REGION( 0x200000, "vram", ROMREGION_ERASE00 )
332
333   ROM_REGION( 0x100, "i2cmem", ROMREGION_ERASE00 )
334ROM_END
335
336/*    YEAR  NAME  PARENT  COMPAT  MACHINE  INPUT  INIT   COMPANY  FULLNAME */
337COMP( 1988, a310, 0,      0,      a310,    a310,  a310,   "Acorn", "Archimedes 310", GAME_NOT_WORKING)
src/mess/drivers/pce.c
r0r11532
1/****************************************************************************
2
3 PC-Engine / Turbo Grafx 16 driver
4 by Charles Mac Donald
5 E-Mail: cgfm2@hooked.net
6
7 Thanks to David Shadoff and Brian McPhail for help with the driver.
8
9****************************************************************************/
10
11/**********************************************************************
12          To-Do List:
13- convert h6280-based drivers to internal memory map for the I/O region
14- test sprite collision and overflow interrupts
15- sprite precaching
16- rewrite the base renderer loop
17- Add CD support
18- Add 6 button joystick support
19- Add 263 line mode
20- Sprite DMA should use vdc VRAM functions
21- properly implement the pixel clocks instead of the simple scaling we do now
22
23Banking
24=======
25
26Normally address spacebanks 00-F6 are assigned to regular HuCard ROM space. There
27are a couple of special situations:
28
29Street Fighter II:
30  - address space banks 40-7F switchable by writing to 1FF0-1FF3
31    1FF0 - select rom banks 40-7F
32    1FF1 - select rom banks 80-BF
33    1FF2 - select rom banks C0-FF
34    1FF3 - select rom banks 100-13F
35
36Populous:
37  - address space banks 40-43 contains 32KB RAM
38
39CDRom units:
40  - address space banks 80-87 contains 64KB RAM
41
42Super System Card:
43  - address space banks 68-7F contains 192KB RAM
44
45**********************************************************************/
46
47/**********************************************************************
48                          Known Bugs
49***********************************************************************
50- Benkei Gaiden: hangs after a few Sunsoft logo spins.
51- Busou Keiji Cyber Cross: hangs on attract mode
52- Cadash: After choosing character and name, the game starts and the display 'jiggles' like tracking if off a VCR
53- Fighting Run: has color and sprite issues during gameplay;
54- Hisou Kihei - Xserd: black screen;
55**********************************************************************/
56
57#include "emu.h"
58#include "deprecat.h"
59#include "video/vdc.h"
60#include "cpu/h6280/h6280.h"
61#include "includes/pce.h"
62#include "imagedev/cartslot.h"
63#include "imagedev/chd_cd.h"
64#include "sound/c6280.h"
65#include "sound/cdda.h"
66#include "sound/msm5205.h"
67#include "hash.h"
68
69
70static ADDRESS_MAP_START( pce_mem , AS_PROGRAM, 8)
71   AM_RANGE( 0x000000, 0x07FFFF) AM_ROMBANK("bank1")
72   AM_RANGE( 0x080000, 0x087FFF) AM_ROMBANK("bank2")
73   AM_RANGE( 0x088000, 0x0CFFFF) AM_ROMBANK("bank3")
74   AM_RANGE( 0x0D0000, 0x0FFFFF) AM_ROMBANK("bank4")
75   AM_RANGE( 0x100000, 0x10FFFF) AM_RAM AM_BASE_MEMBER( pce_state, m_cd_ram )
76   AM_RANGE( 0x110000, 0x1EDFFF) AM_NOP
77   AM_RANGE( 0x1EE000, 0x1EE7FF) AM_ROMBANK("bank10") AM_WRITE( pce_cd_bram_w )
78   AM_RANGE( 0x1EE800, 0x1EFFFF) AM_NOP
79   AM_RANGE( 0x1F0000, 0x1F1FFF) AM_RAM AM_MIRROR(0x6000) AM_BASE_MEMBER( pce_state, m_user_ram )
80   AM_RANGE( 0x1FE000, 0x1FE3FF) AM_READWRITE( vdc_0_r, vdc_0_w )
81   AM_RANGE( 0x1FE400, 0x1FE7FF) AM_READWRITE( vce_r, vce_w )
82   AM_RANGE( 0x1FE800, 0x1FEBFF) AM_DEVREADWRITE(C6280_TAG, c6280_r, c6280_w )
83   AM_RANGE( 0x1FEC00, 0x1FEFFF) AM_READWRITE( h6280_timer_r, h6280_timer_w )
84   AM_RANGE( 0x1FF000, 0x1FF3FF) AM_READWRITE( pce_joystick_r, pce_joystick_w )
85   AM_RANGE( 0x1FF400, 0x1FF7FF) AM_READWRITE( h6280_irq_status_r, h6280_irq_status_w )
86   AM_RANGE( 0x1FF800, 0x1FFBFF) AM_READWRITE( pce_cd_intf_r, pce_cd_intf_w )
87ADDRESS_MAP_END
88
89static ADDRESS_MAP_START( pce_io , AS_IO, 8)
90   AM_RANGE( 0x00, 0x03) AM_READWRITE( vdc_0_r, vdc_0_w )
91ADDRESS_MAP_END
92
93static ADDRESS_MAP_START( sgx_mem , AS_PROGRAM, 8)
94   AM_RANGE( 0x000000, 0x07FFFF) AM_ROMBANK("bank1")
95   AM_RANGE( 0x080000, 0x087FFF) AM_ROMBANK("bank2")
96   AM_RANGE( 0x088000, 0x0CFFFF) AM_ROMBANK("bank3")
97   AM_RANGE( 0x0D0000, 0x0FFFFF) AM_ROMBANK("bank4")
98   AM_RANGE( 0x100000, 0x10FFFF) AM_RAM AM_BASE_MEMBER( pce_state, m_cd_ram )
99   AM_RANGE( 0x110000, 0x1EDFFF) AM_NOP
100   AM_RANGE( 0x1EE000, 0x1EE7FF) AM_ROMBANK("bank10") AM_WRITE( pce_cd_bram_w )
101   AM_RANGE( 0x1EE800, 0x1EFFFF) AM_NOP
102   AM_RANGE( 0x1F0000, 0x1F7FFF) AM_RAM AM_BASE_MEMBER( pce_state, m_user_ram )
103   AM_RANGE( 0x1FE000, 0x1FE007) AM_READWRITE( vdc_0_r, vdc_0_w ) AM_MIRROR(0x03E0)
104   AM_RANGE( 0x1FE008, 0x1FE00F) AM_READWRITE( vpc_r, vpc_w ) AM_MIRROR(0x03E0)
105   AM_RANGE( 0x1FE010, 0x1FE017) AM_READWRITE( vdc_1_r, vdc_1_w ) AM_MIRROR(0x03E0)
106   AM_RANGE( 0x1FE400, 0x1FE7FF) AM_READWRITE( vce_r, vce_w )
107   AM_RANGE( 0x1FE800, 0x1FEBFF) AM_DEVREADWRITE(C6280_TAG, c6280_r, c6280_w )
108   AM_RANGE( 0x1FEC00, 0x1FEFFF) AM_READWRITE( h6280_timer_r, h6280_timer_w )
109   AM_RANGE( 0x1FF000, 0x1FF3FF) AM_READWRITE( pce_joystick_r, pce_joystick_w )
110   AM_RANGE( 0x1FF400, 0x1FF7FF) AM_READWRITE( h6280_irq_status_r, h6280_irq_status_w )
111   AM_RANGE( 0x1FF800, 0x1FFBFF) AM_READWRITE( pce_cd_intf_r, pce_cd_intf_w )
112ADDRESS_MAP_END
113
114static ADDRESS_MAP_START( sgx_io , AS_IO, 8)
115   AM_RANGE( 0x00, 0x03) AM_READWRITE( sgx_vdc_r, sgx_vdc_w )
116ADDRESS_MAP_END
117
118/* todo: alternate forms of input (multitap, mouse, etc.) */
119static INPUT_PORTS_START( pce )
120
121   PORT_START("JOY_P1")
122   /* II is left of I on the original pad so we map them in reverse order */
123   PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_NAME("P1 Button I") PORT_PLAYER(1) PORT_CATEGORY(10)
124   PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_NAME("P1 Button II") PORT_PLAYER(1) PORT_CATEGORY(10)
125   PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_SELECT  ) PORT_NAME("P1 Select") PORT_PLAYER(1) PORT_CATEGORY(10)
126   PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_START   ) PORT_NAME("P1 Run") PORT_PLAYER(1) PORT_CATEGORY(10)
127   PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) PORT_PLAYER(1) PORT_CATEGORY(10)
128   PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) PORT_PLAYER(1) PORT_CATEGORY(10)
129   PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) PORT_PLAYER(1) PORT_CATEGORY(10)
130   PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) PORT_PLAYER(1) PORT_CATEGORY(10)
131
132   PORT_START("JOY_P2")
133   /* II is left of I on the original pad so we map them in reverse order */
134   PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_NAME("P2 Button I") PORT_PLAYER(2) PORT_CATEGORY(20)
135   PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_NAME("P2 Button II") PORT_PLAYER(2) PORT_CATEGORY(20)
136   PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_SELECT  ) PORT_NAME("P2 Select") PORT_PLAYER(2) PORT_CATEGORY(20)
137   PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_START   ) PORT_NAME("P2 Run") PORT_PLAYER(2) PORT_CATEGORY(20)
138   PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) PORT_PLAYER(2) PORT_CATEGORY(20)
139   PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) PORT_PLAYER(2) PORT_CATEGORY(20)
140   PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) PORT_PLAYER(2) PORT_CATEGORY(20)
141   PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) PORT_PLAYER(2) PORT_CATEGORY(20)
142
143   PORT_START("JOY_P3")
144   /* II is left of I on the original pad so we map them in reverse order */
145   PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_NAME("P3 Button I") PORT_PLAYER(3) PORT_CATEGORY(30)
146   PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_NAME("P3 Button II") PORT_PLAYER(3) PORT_CATEGORY(30)
147   PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_SELECT  ) PORT_NAME("P3 Select") PORT_PLAYER(3) PORT_CATEGORY(30)
148   PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_START   ) PORT_NAME("P3 Run") PORT_PLAYER(3) PORT_CATEGORY(30)
149   PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) PORT_PLAYER(3) PORT_CATEGORY(30)
150   PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) PORT_PLAYER(3) PORT_CATEGORY(30)
151   PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) PORT_PLAYER(3) PORT_CATEGORY(30)
152   PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) PORT_PLAYER(3) PORT_CATEGORY(30)
153
154   PORT_START("JOY_P4")
155   /* II is left of I on the original pad so we map them in reverse order */
156   PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_NAME("P4 Button I") PORT_PLAYER(4) PORT_CATEGORY(40)
157   PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_NAME("P4 Button II") PORT_PLAYER(4) PORT_CATEGORY(40)
158   PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_SELECT  ) PORT_NAME("P4 Select") PORT_PLAYER(4) PORT_CATEGORY(40)
159   PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_START   ) PORT_NAME("P4 Run") PORT_PLAYER(4) PORT_CATEGORY(40)
160   PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) PORT_PLAYER(4) PORT_CATEGORY(40)
161   PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) PORT_PLAYER(4) PORT_CATEGORY(40)
162   PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) PORT_PLAYER(4) PORT_CATEGORY(40)
163   PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) PORT_PLAYER(4) PORT_CATEGORY(40)
164
165   PORT_START("JOY_P5")
166   /* II is left of I on the original pad so we map them in reverse order */
167   PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_NAME("P5 Button I") PORT_PLAYER(5) PORT_CATEGORY(50)
168   PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_NAME("P5 Button II") PORT_PLAYER(5) PORT_CATEGORY(50)
169   PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_SELECT  ) PORT_NAME("P5 Select") PORT_PLAYER(5) PORT_CATEGORY(50)
170   PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_START   ) PORT_NAME("P5 Run") PORT_PLAYER(5) PORT_CATEGORY(50)
171   PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) PORT_PLAYER(5) PORT_CATEGORY(50)
172   PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) PORT_PLAYER(5) PORT_CATEGORY(50)
173   PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) PORT_PLAYER(5) PORT_CATEGORY(50)
174   PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) PORT_PLAYER(5) PORT_CATEGORY(50)
175
176   PORT_START("JOY6B_P1")
177   /* II is left of I on the original pad so we map them in reverse order */
178   PORT_BIT( 0x0001, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_NAME("P1 Button I") PORT_PLAYER(1) PORT_CATEGORY(11)
179   PORT_BIT( 0x0002, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_NAME("P1 Button II") PORT_PLAYER(1) PORT_CATEGORY(11)
180   PORT_BIT( 0x0004, IP_ACTIVE_LOW, IPT_SELECT  ) PORT_NAME("P1 Select") PORT_PLAYER(1) PORT_CATEGORY(11)
181   PORT_BIT( 0x0008, IP_ACTIVE_LOW, IPT_START   ) PORT_NAME("P1 Run") PORT_PLAYER(1) PORT_CATEGORY(11)
182   PORT_BIT( 0x0010, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) PORT_PLAYER(1) PORT_CATEGORY(11)
183   PORT_BIT( 0x0040, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) PORT_PLAYER(1) PORT_CATEGORY(11)
184   PORT_BIT( 0x0080, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) PORT_PLAYER(1) PORT_CATEGORY(11)
185   PORT_BIT( 0x0020, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) PORT_PLAYER(1) PORT_CATEGORY(11)
186   PORT_BIT( 0x0100, IP_ACTIVE_LOW, IPT_BUTTON3 ) PORT_NAME("P1 Button III") PORT_PLAYER(1) PORT_CATEGORY(11)
187   PORT_BIT( 0x0200, IP_ACTIVE_LOW, IPT_BUTTON4 ) PORT_NAME("P1 Button IV") PORT_PLAYER(1) PORT_CATEGORY(11)
188   PORT_BIT( 0x0400, IP_ACTIVE_LOW, IPT_BUTTON5 ) PORT_NAME("P1 Button V") PORT_PLAYER(1) PORT_CATEGORY(11)
189   PORT_BIT( 0x0800, IP_ACTIVE_LOW, IPT_BUTTON6 ) PORT_NAME("P1 Button VI") PORT_PLAYER(1) PORT_CATEGORY(11)
190   PORT_BIT( 0xf000, IP_ACTIVE_HIGH,IPT_UNUSED ) //6-button pad header
191
192   PORT_START("JOY6B_P2")  /* Player 2 controls */
193   /* II is left of I on the original pad so we map them in reverse order */
194   PORT_BIT( 0x0001, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_NAME("P2 Button I") PORT_PLAYER(2) PORT_CATEGORY(21)
195   PORT_BIT( 0x0002, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_NAME("P2 Button II") PORT_PLAYER(2) PORT_CATEGORY(21)
196   PORT_BIT( 0x0004, IP_ACTIVE_LOW, IPT_SELECT  ) PORT_NAME("P2 Select") PORT_PLAYER(2) PORT_CATEGORY(21)
197   PORT_BIT( 0x0008, IP_ACTIVE_LOW, IPT_START   ) PORT_NAME("P2 Run") PORT_PLAYER(2) PORT_CATEGORY(21)
198   PORT_BIT( 0x0010, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) PORT_PLAYER(2) PORT_CATEGORY(21)
199   PORT_BIT( 0x0040, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) PORT_PLAYER(2) PORT_CATEGORY(21)
200   PORT_BIT( 0x0080, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) PORT_PLAYER(2) PORT_CATEGORY(21)
201   PORT_BIT( 0x0020, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) PORT_PLAYER(2) PORT_CATEGORY(21)
202   PORT_BIT( 0x0100, IP_ACTIVE_LOW, IPT_BUTTON3 ) PORT_NAME("P2 Button III") PORT_PLAYER(2) PORT_CATEGORY(21)
203   PORT_BIT( 0x0200, IP_ACTIVE_LOW, IPT_BUTTON4 ) PORT_NAME("P2 Button IV") PORT_PLAYER(2) PORT_CATEGORY(21)
204   PORT_BIT( 0x0400, IP_ACTIVE_LOW, IPT_BUTTON5 ) PORT_NAME("P2 Button V") PORT_PLAYER(2) PORT_CATEGORY(21)
205   PORT_BIT( 0x0800, IP_ACTIVE_LOW, IPT_BUTTON6 ) PORT_NAME("P2 Button VI") PORT_PLAYER(2) PORT_CATEGORY(21)
206   PORT_BIT( 0xf000, IP_ACTIVE_HIGH,IPT_UNUSED ) //6-button pad header
207
208   PORT_START("JOY6B_P3")  /* Player 3 controls */
209   /* II is left of I on the original pad so we map them in reverse order */
210   PORT_BIT( 0x0001, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_NAME("P3 Button I") PORT_PLAYER(3) PORT_CATEGORY(31)
211   PORT_BIT( 0x0002, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_NAME("P3 Button II") PORT_PLAYER(3) PORT_CATEGORY(31)
212   PORT_BIT( 0x0004, IP_ACTIVE_LOW, IPT_SELECT  ) PORT_NAME("P3 Select") PORT_PLAYER(3) PORT_CATEGORY(31)
213   PORT_BIT( 0x0008, IP_ACTIVE_LOW, IPT_START   ) PORT_NAME("P3 Run") PORT_PLAYER(3) PORT_CATEGORY(31)
214   PORT_BIT( 0x0010, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) PORT_PLAYER(3) PORT_CATEGORY(31)
215   PORT_BIT( 0x0040, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) PORT_PLAYER(3) PORT_CATEGORY(31)
216   PORT_BIT( 0x0080, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) PORT_PLAYER(3) PORT_CATEGORY(31)
217   PORT_BIT( 0x0020, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) PORT_PLAYER(3) PORT_CATEGORY(31)
218   PORT_BIT( 0x0100, IP_ACTIVE_LOW, IPT_BUTTON3 ) PORT_NAME("P3 Button III") PORT_PLAYER(3) PORT_CATEGORY(31)
219   PORT_BIT( 0x0200, IP_ACTIVE_LOW, IPT_BUTTON4 ) PORT_NAME("P3 Button IV") PORT_PLAYER(3) PORT_CATEGORY(31)
220   PORT_BIT( 0x0400, IP_ACTIVE_LOW, IPT_BUTTON5 ) PORT_NAME("P3 Button V") PORT_PLAYER(3) PORT_CATEGORY(31)
221   PORT_BIT( 0x0800, IP_ACTIVE_LOW, IPT_BUTTON6 ) PORT_NAME("P3 Button VI") PORT_PLAYER(3) PORT_CATEGORY(31)
222   PORT_BIT( 0xf000, IP_ACTIVE_HIGH,IPT_UNUSED ) //6-button pad header
223
224   PORT_START("JOY6B_P4")  /* Player 4 controls */
225   /* II is left of I on the original pad so we map them in reverse order */
226   PORT_BIT( 0x0001, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_NAME("P4 Button I") PORT_PLAYER(4) PORT_CATEGORY(41)
227   PORT_BIT( 0x0002, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_NAME("P4 Button II") PORT_PLAYER(4) PORT_CATEGORY(41)
228   PORT_BIT( 0x0004, IP_ACTIVE_LOW, IPT_SELECT  ) PORT_NAME("P4 Select") PORT_PLAYER(4) PORT_CATEGORY(41)
229   PORT_BIT( 0x0008, IP_ACTIVE_LOW, IPT_START   ) PORT_NAME("P4 Run") PORT_PLAYER(4) PORT_CATEGORY(41)
230   PORT_BIT( 0x0010, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) PORT_PLAYER(4) PORT_CATEGORY(41)
231   PORT_BIT( 0x0040, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) PORT_PLAYER(4) PORT_CATEGORY(41)
232   PORT_BIT( 0x0080, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) PORT_PLAYER(4) PORT_CATEGORY(41)
233   PORT_BIT( 0x0020, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) PORT_PLAYER(4) PORT_CATEGORY(41)
234   PORT_BIT( 0x0100, IP_ACTIVE_LOW, IPT_BUTTON3 ) PORT_NAME("P3 Button III") PORT_PLAYER(4) PORT_CATEGORY(41)
235   PORT_BIT( 0x0200, IP_ACTIVE_LOW, IPT_BUTTON4 ) PORT_NAME("P3 Button IV") PORT_PLAYER(4) PORT_CATEGORY(41)
236   PORT_BIT( 0x0400, IP_ACTIVE_LOW, IPT_BUTTON5 ) PORT_NAME("P3 Button V") PORT_PLAYER(4) PORT_CATEGORY(41)
237   PORT_BIT( 0x0800, IP_ACTIVE_LOW, IPT_BUTTON6 ) PORT_NAME("P3 Button VI") PORT_PLAYER(4) PORT_CATEGORY(41)
238   PORT_BIT( 0xf000, IP_ACTIVE_HIGH,IPT_UNUSED ) //6-button pad header
239
240   PORT_START("JOY6B_P5")  /* Player 5 controls */
241   /* II is left of I on the original pad so we map them in reverse order */
242   PORT_BIT( 0x0001, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_NAME("P5 Button I") PORT_PLAYER(5) PORT_CATEGORY(51)
243   PORT_BIT( 0x0002, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_NAME("P5 Button II") PORT_PLAYER(5) PORT_CATEGORY(51)
244   PORT_BIT( 0x0004, IP_ACTIVE_LOW, IPT_SELECT  ) PORT_NAME("P5 Select") PORT_PLAYER(5) PORT_CATEGORY(51)
245   PORT_BIT( 0x0008, IP_ACTIVE_LOW, IPT_START   ) PORT_NAME("P5 Run") PORT_PLAYER(5) PORT_CATEGORY(51)
246   PORT_BIT( 0x0010, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) PORT_PLAYER(5) PORT_CATEGORY(51)
247   PORT_BIT( 0x0040, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) PORT_PLAYER(5) PORT_CATEGORY(51)
248   PORT_BIT( 0x0080, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) PORT_PLAYER(5) PORT_CATEGORY(51)
249   PORT_BIT( 0x0020, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) PORT_PLAYER(5) PORT_CATEGORY(51)
250   PORT_BIT( 0x0100, IP_ACTIVE_LOW, IPT_BUTTON3 ) PORT_NAME("P5 Button III") PORT_PLAYER(5) PORT_CATEGORY(51)
251   PORT_BIT( 0x0200, IP_ACTIVE_LOW, IPT_BUTTON4 ) PORT_NAME("P5 Button IV") PORT_PLAYER(5) PORT_CATEGORY(51)
252   PORT_BIT( 0x0400, IP_ACTIVE_LOW, IPT_BUTTON5 ) PORT_NAME("P5 Button V") PORT_PLAYER(5) PORT_CATEGORY(51)
253   PORT_BIT( 0x0800, IP_ACTIVE_LOW, IPT_BUTTON6 ) PORT_NAME("P5 Button VI") PORT_PLAYER(5) PORT_CATEGORY(51)
254   PORT_BIT( 0xf000, IP_ACTIVE_HIGH,IPT_UNUSED ) //6-button pad header
255
256   PORT_START("JOY_TYPE")
257   PORT_CATEGORY_CLASS(0x0003,0x0000,"Joystick Type Player 1")
258   PORT_CATEGORY_ITEM( 0x0000,"2-buttons", 10)
259//  PORT_CATEGORY_ITEM( 0x0001,"3-buttons", xx)
260   PORT_CATEGORY_ITEM( 0x0002,"6-buttons", 11)
261//  PORT_CATEGORY_ITEM( 0x0003,"Mouse",     xx)
262   PORT_CATEGORY_CLASS(0x000c,0x0000,"Joystick Type Player 2")
263   PORT_CATEGORY_ITEM( 0x0000,"2-buttons", 20)
264//  PORT_CATEGORY_ITEM( 0x0004,"3-buttons", xx)
265   PORT_CATEGORY_ITEM( 0x0008,"6-buttons", 21)
266//  PORT_CATEGORY_ITEM( 0x000c,"Mouse",     xx)
267   PORT_CATEGORY_CLASS(0x0030,0x0000,"Joystick Type Player 3")
268   PORT_CATEGORY_ITEM( 0x0000,"2-buttons", 30)
269//  PORT_CATEGORY_ITEM( 0x0010,"3-buttons", xx)
270   PORT_CATEGORY_ITEM( 0x0020,"6-buttons", 31)
271//  PORT_CATEGORY_ITEM( 0x0030,"Mouse",     xx)
272   PORT_CATEGORY_CLASS(0x00c0,0x0000,"Joystick Type Player 4")
273   PORT_CATEGORY_ITEM( 0x0000,"2-buttons", 40)
274//  PORT_CATEGORY_ITEM( 0x0040,"3-buttons", xx)
275   PORT_CATEGORY_ITEM( 0x0080,"6-buttons", 41)
276//  PORT_CATEGORY_ITEM( 0x00c0,"Mouse",     xx)
277   PORT_CATEGORY_CLASS(0x0300,0x0000,"Joystick Type Player 5")
278   PORT_CATEGORY_ITEM( 0x0000,"2-buttons", 50)
279//  PORT_CATEGORY_ITEM( 0x0100,"3-buttons", xx)
280   PORT_CATEGORY_ITEM( 0x0200,"6-buttons", 51)
281//  PORT_CATEGORY_ITEM( 0x0300,"Mouse",     xx)
282
283   PORT_START("A_CARD")
284   PORT_CONFNAME( 0x01, 0x01, "Arcade Card" )
285   PORT_CONFSETTING(    0x00, DEF_STR( Off ) )
286   PORT_CONFSETTING(    0x01, DEF_STR( On ) )
287INPUT_PORTS_END
288
289
290static void pce_partialhash(hash_collection &dest, const unsigned char *data,
291   unsigned long length, const char *functions)
292{
293   if ( ( length <= PCE_HEADER_SIZE ) || ( length & PCE_HEADER_SIZE ) ) {
294         dest.compute(&data[PCE_HEADER_SIZE], length - PCE_HEADER_SIZE, functions);
295   } else {
296      dest.compute(data, length, functions);
297   }
298}
299
300static const c6280_interface c6280_config =
301{
302   "maincpu"
303};
304static MACHINE_CONFIG_FRAGMENT( pce_cdslot )
305   MCFG_CDROM_ADD( "cdrom" )
306   MCFG_CDROM_INTERFACE("pce_cdrom")
307
308   MCFG_SOFTWARE_LIST_ADD("cd_list","pcecd")
309MACHINE_CONFIG_END
310
311static MACHINE_CONFIG_FRAGMENT( pce_cartslot )
312   MCFG_CARTSLOT_ADD("cart")
313   MCFG_CARTSLOT_EXTENSION_LIST("pce,bin")
314   MCFG_CARTSLOT_MANDATORY
315   MCFG_CARTSLOT_INTERFACE("pce_cart")
316   MCFG_CARTSLOT_LOAD(pce_cart)
317   MCFG_CARTSLOT_PARTIALHASH(pce_partialhash)
318   MCFG_SOFTWARE_LIST_ADD("cart_list","pce")
319MACHINE_CONFIG_END
320
321static MACHINE_CONFIG_FRAGMENT( tg16_cartslot )
322   MCFG_CARTSLOT_ADD("cart")
323   MCFG_CARTSLOT_EXTENSION_LIST("pce,bin")
324   MCFG_CARTSLOT_MANDATORY
325   MCFG_CARTSLOT_INTERFACE("tg16_cart")
326   MCFG_CARTSLOT_LOAD(pce_cart)
327   MCFG_CARTSLOT_PARTIALHASH(pce_partialhash)
328   MCFG_SOFTWARE_LIST_ADD("cart_list","tg16")
329MACHINE_CONFIG_END
330
331static MACHINE_CONFIG_FRAGMENT( sgx_cartslot )
332   MCFG_CARTSLOT_ADD("cart")
333   MCFG_CARTSLOT_EXTENSION_LIST("pce,bin")
334   MCFG_CARTSLOT_MANDATORY
335   MCFG_CARTSLOT_INTERFACE("pce_cart")
336   MCFG_CARTSLOT_LOAD(pce_cart)
337   MCFG_CARTSLOT_PARTIALHASH(pce_partialhash)
338   MCFG_SOFTWARE_LIST_ADD("cart_list","sgx")
339MACHINE_CONFIG_END
340
341static MACHINE_CONFIG_START( pce_common, pce_state )
342   /* basic machine hardware */
343   MCFG_CPU_ADD("maincpu", H6280, MAIN_CLOCK/3)
344   MCFG_CPU_PROGRAM_MAP(pce_mem)
345   MCFG_CPU_IO_MAP(pce_io)
346   MCFG_CPU_VBLANK_INT_HACK(pce_interrupt, VDC_LPF)
347   MCFG_QUANTUM_TIME(attotime::from_hz(60))
348
349   MCFG_MACHINE_START( pce )
350   MCFG_MACHINE_RESET( pce )
351
352    /* video hardware */
353   MCFG_SCREEN_ADD("screen", RASTER)
354   MCFG_SCREEN_REFRESH_RATE(60)
355   MCFG_SCREEN_VBLANK_TIME(ATTOSECONDS_IN_USEC(2500)) /* not accurate */
356   MCFG_SCREEN_FORMAT(BITMAP_FORMAT_INDEXED16)
357   MCFG_SCREEN_RAW_PARAMS(MAIN_CLOCK/2, VDC_WPF, 70, 70 + 512 + 32, VDC_LPF, 14, 14+242)
358   MCFG_SCREEN_UPDATE( pce )
359
360   /* MCFG_GFXDECODE( pce ) */
361   MCFG_PALETTE_LENGTH(1024)
362   MCFG_PALETTE_INIT( vce )
363
364   MCFG_VIDEO_START( pce )
365
366   MCFG_NVRAM_HANDLER( pce )
367   MCFG_SPEAKER_STANDARD_STEREO("lspeaker", "rspeaker")
368   MCFG_SOUND_ADD(C6280_TAG, C6280, MAIN_CLOCK/6)
369   MCFG_SOUND_CONFIG(c6280_config)
370   MCFG_SOUND_ROUTE( 0, "lspeaker", 1.00 )
371   MCFG_SOUND_ROUTE( 1, "rspeaker", 1.00 )
372
373   MCFG_SOUND_ADD( "msm5205", MSM5205, PCE_CD_CLOCK / 6 )
374   MCFG_SOUND_CONFIG( pce_cd_msm5205_interface )
375   MCFG_SOUND_ROUTE( ALL_OUTPUTS, "lspeaker", 0.50 )
376   MCFG_SOUND_ROUTE( ALL_OUTPUTS, "rspeaker", 0.50 )
377
378   MCFG_SOUND_ADD( "cdda", CDDA, 0 )
379   MCFG_SOUND_ROUTE( 0, "lspeaker", 1.00 )
380   MCFG_SOUND_ROUTE( 1, "rspeaker", 1.00 )
381MACHINE_CONFIG_END
382
383static MACHINE_CONFIG_DERIVED( pce, pce_common )
384   MCFG_FRAGMENT_ADD( pce_cartslot )
385   MCFG_FRAGMENT_ADD( pce_cdslot )
386MACHINE_CONFIG_END
387
388static MACHINE_CONFIG_DERIVED( tg16, pce_common )
389   MCFG_FRAGMENT_ADD( tg16_cartslot )
390   MCFG_FRAGMENT_ADD( pce_cdslot )
391MACHINE_CONFIG_END
392
393static MACHINE_CONFIG_START( sgx, pce_state )
394   /* basic machine hardware */
395   MCFG_CPU_ADD("maincpu", H6280, MAIN_CLOCK/3)
396   MCFG_CPU_PROGRAM_MAP(sgx_mem)
397   MCFG_CPU_IO_MAP(sgx_io)
398   MCFG_CPU_VBLANK_INT_HACK(sgx_interrupt, VDC_LPF)
399   MCFG_QUANTUM_TIME(attotime::from_hz(60))
400
401   MCFG_MACHINE_START( pce )
402   MCFG_MACHINE_RESET( pce )
403
404   /* video hardware */
405   MCFG_SCREEN_ADD("screen", RASTER)
406   MCFG_SCREEN_REFRESH_RATE(60)
407   MCFG_SCREEN_VBLANK_TIME(ATTOSECONDS_IN_USEC(2500)) /* not accurate */
408   MCFG_SCREEN_FORMAT(BITMAP_FORMAT_INDEXED16)
409   MCFG_SCREEN_RAW_PARAMS(MAIN_CLOCK/2, VDC_WPF, 70, 70 + 512 + 32, VDC_LPF, 14, 14+242)
410   MCFG_SCREEN_UPDATE( pce )
411
412   MCFG_PALETTE_LENGTH(1024)
413   MCFG_PALETTE_INIT( vce )
414
415   MCFG_VIDEO_START( pce )
416
417   MCFG_NVRAM_HANDLER( pce )
418   MCFG_SPEAKER_STANDARD_STEREO("lspeaker", "rspeaker")
419   MCFG_SOUND_ADD(C6280_TAG, C6280, MAIN_CLOCK/6)
420   MCFG_SOUND_CONFIG(c6280_config)
421   MCFG_SOUND_ROUTE(0, "lspeaker", 1.00)
422   MCFG_SOUND_ROUTE(1, "rspeaker", 1.00)
423
424   MCFG_SOUND_ADD( "msm5205", MSM5205, PCE_CD_CLOCK / 6 )
425   MCFG_SOUND_CONFIG( pce_cd_msm5205_interface )
426   MCFG_SOUND_ROUTE( ALL_OUTPUTS, "lspeaker", 0.00 )
427   MCFG_SOUND_ROUTE( ALL_OUTPUTS, "rspeaker", 0.00 )
428
429   MCFG_SOUND_ADD( "cdda", CDDA, 0 )
430   MCFG_SOUND_ROUTE( 0, "lspeaker", 1.00 )
431   MCFG_SOUND_ROUTE( 1, "rspeaker", 1.00 )
432
433   MCFG_FRAGMENT_ADD( sgx_cartslot )
434   MCFG_FRAGMENT_ADD( pce_cdslot )
435MACHINE_CONFIG_END
436
437/***************************************************************************
438
439  Game driver(s)
440
441***************************************************************************/
442
443ROM_START( pce )
444   ROM_REGION( PCE_ROM_MAXSIZE, "user1", 0 )      /* Cartridge ROM area */
445   ROM_FILL( 0, PCE_ROM_MAXSIZE, 0xFF )
446ROM_END
447
448#define rom_tg16 rom_pce
449#define rom_sgx rom_pce
450
451/*    YEAR  NAME    PARENT  COMPAT  MACHINE INPUT    INIT   COMPANY  FULLNAME */
452CONS( 1987, pce,    0,      0,      pce,    pce,     pce,   "Nippon Electronic Company", "PC Engine", GAME_IMPERFECT_SOUND)
453CONS( 1989, tg16,   pce,    0,      tg16,   pce,     tg16,  "Nippon Electronic Company", "TurboGrafx 16", GAME_IMPERFECT_SOUND)
454CONS( 1989, sgx,    pce,    0,      sgx,    pce,     sgx,   "Nippon Electronic Company", "SuperGrafx", GAME_IMPERFECT_SOUND)
src/mess/mess.mak
r11531r11532
498498   $(MAME_DRIVERS)/segasms.o   \
499499   $(MAME_DRIVERS)/sg1000.o   \
500500   $(MAME_MACHINE)/gdrom.o    \
501   $(MAME_DRIVERS)/a310.o      \
502   $(MAME_DRIVERS)/a7000.o      \
503   $(MAME_MACHINE)/amigafdc.o   \
504   $(MAME_MACHINE)/amigacrt.o   \
505   $(MAME_MACHINE)/amigacd.o   \
506   $(MAME_MACHINE)/amigakbd.o   \
507   $(MAME_DRIVERS)/amiga.o      \
508   $(MAME_DRIVERS)/a3000.o      \
509   $(MAME_DRIVERS)/ami1200.o   \
510   $(MAME_MACHINE)/ataricrt.o   \
511   $(MAME_MACHINE)/atarifdc.o   \
512   $(MAME_DRIVERS)/atari400.o   \
513   $(MAME_MACHINE)/pce.o      \
514   $(MAME_DRIVERS)/pce.o      \
515   $(MAME_MACHINE)/nes_mmc.o   \
516   $(MAME_VIDEO)/nes.o         \
517   $(MAME_MACHINE)/nes.o      \
518   $(MAME_DRIVERS)/nes.o      \
519   $(MAME_MACHINE)/snescart.o   \
520   $(MAME_DRIVERS)/snes.o      \
521   $(MAME_DRIVERS)/n64.o      \
522   $(MAME_MACHINE)/aescart.o   \
523   $(MAME_DRIVERS)/ng_aes.o   \
501   $(MESS_DRIVERS)/a310.o      \
502   $(MESS_DRIVERS)/a7000.o      \
503   $(MESS_MACHINE)/amigafdc.o   \
504   $(MESS_MACHINE)/amigacrt.o   \
505   $(MESS_MACHINE)/amigacd.o   \
506   $(MESS_MACHINE)/amigakbd.o   \
507   $(MESS_DRIVERS)/amiga.o      \
508   $(MESS_DRIVERS)/a3000.o      \
509   $(MESS_DRIVERS)/ami1200.o   \
510   $(MESS_MACHINE)/ataricrt.o   \
511   $(MESS_MACHINE)/atarifdc.o   \
512   $(MESS_DRIVERS)/atari400.o   \
513   $(MESS_MACHINE)/pce.o      \
514   $(MESS_DRIVERS)/pce.o      \
515   $(MESS_MACHINE)/nes_mmc.o   \
516   $(MESS_VIDEO)/nes.o         \
517   $(MESS_MACHINE)/nes.o      \
518   $(MESS_DRIVERS)/nes.o      \
519   $(MESS_MACHINE)/snescart.o   \
520   $(MESS_DRIVERS)/snes.o      \
521   $(MESS_DRIVERS)/n64.o      \
522   $(MESS_DRIVERS)/ng_aes.o   \
524523   $(MESS_DRIVERS)/psx.o      \
525524   $(MESS_MACHINE)/psxcd.o      \
526525   $(MESS_MACHINE)/psxcddrv.o   \
527526   $(MESS_MACHINE)/psxcard.o   \
527   $(MESS_DEVICES)/aescart.o       \
528528   $(MAME_DRIVERS)/saturn.o   \
529529   $(MAME_DRIVERS)/cps1.o   \
530530   $(MAME_VIDEO)/cps1.o   \
r11531r11532
18021802$(MESS_DRIVERS)/mmd1.o:      $(MESS_LAYOUT)/mmd1.lh \
18031803               $(MESS_LAYOUT)/mmd2.lh
18041804$(MESS_VIDEO)/newbrain.o:   $(MESS_LAYOUT)/newbrain.lh
1805$(MAME_DRIVERS)/ng_aes.o:   $(MESS_LAYOUT)/neogeo.lh
1805$(MESS_DRIVERS)/ng_aes.o:   $(MESS_LAYOUT)/neogeo.lh
18061806$(MESS_DRIVERS)/poly880.o:   $(MESS_LAYOUT)/poly880.lh
18071807$(MESS_DRIVERS)/pc1500.o:   $(MESS_LAYOUT)/pc1500.lh
18081808$(MESS_VIDEO)/pc8401a.o:   $(MESS_LAYOUT)/pc8500.lh

Previous 15994 Revisions Next


© 1998-2018 The MESS Team