Previous 199869 Revisions Next

r20588 Monday 28th January, 2013 at 20:31:49 UTC by Curt Coder
(MESS) c64: Renamed legacy file. (nw)
[src/mess]mess.mak
[src/mess/machine]c64.c c64_legacy.c*

trunk/src/mess/mess.mak
r20587r20588
827827   $(MESS_DRIVERS)/pet.o       \
828828   $(MESS_MACHINE)/pet.o       \
829829   $(MESS_DRIVERS)/c64.o       \
830   $(MESS_MACHINE)/c64.o       \
830   $(MESS_MACHINE)/c64_legacy.o       \
831831   $(MESS_DRIVERS)/c64dtv.o    \
832832   $(MESS_MACHINE)/c64exp.o    \
833833   $(MESS_MACHINE)/c64user.o   \
trunk/src/mess/machine/c64.c
r20587r20588
1/***************************************************************************
2    commodore c64 home computer
3
4    peter.trauner@jk.uni-linz.ac.at
5    documentation
6     www.funet.fi
7***************************************************************************/
8
9/*
10    2008-09-06: Tape status for C64 & C128 [FP & RZ]
11    - tape loading works
12    - tap files are supported
13    - tape writing works
14*/
15
16#include "emu.h"
17
18#include "cpu/m6502/m6510.h"
19#include "cpu/z80/z80.h"
20#include "sound/sid6581.h"
21#include "machine/6526cia.h"
22#include "machine/cbmiec.h"
23
24#include "includes/cbm.h"
25#include "includes/c64_legacy.h"
26
27#include "imagedev/cassette.h"
28#include "imagedev/cartslot.h"
29
30#define VERBOSE_LEVEL 0
31#define DBG_LOG( MACHINE, N, M, A ) \
32   do { \
33      if(VERBOSE_LEVEL >= N) \
34      { \
35         if( M ) \
36            logerror("%11.6f: %-24s", MACHINE.time().as_double(), (char*) M ); \
37         logerror A; \
38      } \
39   } while (0)
40
41#define log_cart 0
42
43/* Info from http://unusedino.de/ec64/technical/misc/c64/64doc.html */
44/*
45
46  The leftmost column of the table contains addresses in hexadecimal
47notation. The columns aside it introduce all possible memory
48configurations. The default mode is on the left, and the absolutely
49most rarely used Ultimax game console configuration is on the right.
50(Has anybody ever seen any Ultimax games?) Each memory configuration
51column has one or more four-digit binary numbers as a title. The bits,
52from left to right, represent the state of the -LORAM, -HIRAM, -GAME
53and -EXROM lines, respectively. The bits whose state does not matter
54are marked with "x". For instance, when the Ultimax video game
55configuration is active (the -GAME line is shorted to ground), the
56-LORAM and -HIRAM lines have no effect.
57
58      default                      001x                       Ultimax
59       1111   101x   1000   011x   00x0   1110   0100   1100   xx01
6010000
61----------------------------------------------------------------------
62 F000
63       Kernal RAM    RAM    Kernal RAM    Kernal Kernal Kernal ROMH(*
64 E000
65----------------------------------------------------------------------
66 D000  IO/C   IO/C   IO/RAM IO/C   RAM    IO/C   IO/C   IO/C   I/O
67----------------------------------------------------------------------
68 C000  RAM    RAM    RAM    RAM    RAM    RAM    RAM    RAM     -
69----------------------------------------------------------------------
70 B000
71       BASIC  RAM    RAM    RAM    RAM    BASIC  ROMH   ROMH    -
72 A000
73----------------------------------------------------------------------
74 9000
75       RAM    RAM    RAM    RAM    RAM    ROML   RAM    ROML   ROML(*
76 8000
77----------------------------------------------------------------------
78 7000
79
80 6000
81       RAM    RAM    RAM    RAM    RAM    RAM    RAM    RAM     -
82 5000
83
84 4000
85----------------------------------------------------------------------
86 3000
87
88 2000  RAM    RAM    RAM    RAM    RAM    RAM    RAM    RAM     -
89
90 1000
91----------------------------------------------------------------------
92 0000  RAM    RAM    RAM    RAM    RAM    RAM    RAM    RAM    RAM
93----------------------------------------------------------------------
94
95   *) Internal memory does not respond to write accesses to these
96       areas.
97
98
99    Legend: Kernal      E000-FFFF       Kernal ROM.
100
101            IO/C        D000-DFFF       I/O address space or Character
102                                        generator ROM, selected by
103                                        -CHAREN. If the CHAREN bit is
104                                        clear, the character generator
105                                        ROM will be selected. If it is
106                                        set, the I/O chips are
107                                        accessible.
108
109            IO/RAM      D000-DFFF       I/O address space or RAM,
110                                        selected by -CHAREN. If the
111                                        CHAREN bit is clear, the
112                                        character generator ROM will
113                                        be selected. If it is set, the
114                                        internal RAM is accessible.
115
116            I/O         D000-DFFF       I/O address space.
117                                        The -CHAREN line has no effect.
118
119            BASIC       A000-BFFF       BASIC ROM.
120
121            ROMH        A000-BFFF or    External ROM with the -ROMH line
122                        E000-FFFF       connected to its -CS line.
123
124            ROML        8000-9FFF       External ROM with the -ROML line
125                                        connected to its -CS line.
126
127            RAM         various ranges  Commodore 64's internal RAM.
128
129            -           1000-7FFF and   Open address space.
130                        A000-CFFF       The Commodore 64's memory chips
131                                        do not detect any memory accesses
132                                        to this area except the VIC-II's
133                                        DMA and memory refreshes.
134
135    NOTE:   Whenever the processor tries to write to any ROM area
136            (Kernal, BASIC, CHAROM, ROML, ROMH), the data will get
137            "through the ROM" to the C64's internal RAM.
138
139            For this reason, you can easily copy data from ROM to RAM,
140            without any bank switching. But implementing external
141            memory expansions without DMA is very hard, as you have to
142            use a 256 byte window on the I/O1 or I/O2 area, like
143            GEORAM, or the Ultimax memory configuration, if you do not
144            want the data to be written both to internal and external
145            RAM.
146
147            However, this is not true for the Ultimax video game
148            configuration. In that mode, the internal RAM ignores all
149            memory accesses outside the area $0000-$0FFF, unless they
150            are performed by the VIC, and you can write to external
151            memory at $1000-$CFFF and $E000-$FFFF, if any, without
152            changing the contents of the internal RAM.
153
154*/
155
156static void c64_bankswitch( running_machine &machine, int reset )
157{
158   legacy_c64_state *state = machine.driver_data<legacy_c64_state>();
159   int loram, hiram, charen;
160   int ultimax_mode = 0;
161   int data = machine.device<m6510_device>("maincpu")->get_port() & 0x07;
162
163   /* Are we in Ultimax mode? */
164   if (!state->m_game && state->m_exrom)
165      ultimax_mode = 1;
166
167   DBG_LOG(machine, 1, "bankswitch", ("%d\n", data & 7));
168   loram  = (data & 1) ? 1 : 0;
169   hiram  = (data & 2) ? 1 : 0;
170   charen = (data & 4) ? 1 : 0;
171   //logerror("Bankswitch mode || charen, state->m_ultimax\n");
172   //logerror("%d, %d, %d, %d  ||   %d,      %d  \n", loram, hiram, state->m_game, state->m_exrom, charen, ultimax_mode);
173
174   if (ultimax_mode)
175   {
176         state->m_io_enabled = 1;        // charen has no effect in ultimax_mode
177
178         state->membank("bank1")->set_base(state->m_roml);
179         state->membank("bank3")->set_base(state->m_memory + 0xa000);
180         state->membank("bank4")->set_base(state->m_romh);
181         machine.device("maincpu")->memory().space(AS_PROGRAM).nop_write(0xe000, 0xffff);
182   }
183   else
184   {
185      /* 0x8000-0x9000 */
186      if (loram && hiram && !state->m_exrom)
187      {
188         state->membank("bank1")->set_base(state->m_roml);
189      }
190      else
191      {
192         state->membank("bank1")->set_base(state->m_memory + 0x8000);
193      }
194
195      /* 0xa000 */
196      if (hiram && !state->m_game && !state->m_exrom)
197         state->membank("bank3")->set_base(state->m_romh);
198
199      else if (loram && hiram && state->m_game)
200         state->membank("bank3")->set_base(state->m_basic);
201
202      else
203         state->membank("bank3")->set_base(state->m_memory + 0xa000);
204
205      /* 0xd000 */
206      // RAM
207      if (!loram && !hiram && (state->m_game || !state->m_exrom))
208      {
209         state->m_io_enabled = 0;
210         state->m_io_ram_r_ptr = state->m_memory + 0xd000;
211         state->m_io_ram_w_ptr = state->m_memory + 0xd000;
212      }
213      // IO/RAM
214      else if (loram && !hiram && !state->m_game) // remember we cannot be in ultimax_mode, no need of !state->m_exrom
215      {
216         state->m_io_enabled = 1;
217         state->m_io_ram_r_ptr = (!charen) ? state->m_chargen : state->m_memory + 0xd000;
218         state->m_io_ram_w_ptr = state->m_memory + 0xd000;
219      }
220      // IO/C
221      else
222      {
223         state->m_io_enabled = charen ? 1 : 0;
224
225         if (!charen)
226         {
227         state->m_io_ram_r_ptr = state->m_chargen;
228         state->m_io_ram_w_ptr = state->m_memory + 0xd000;
229         }
230      }
231
232      /* 0xe000-0xf000 */
233      state->membank("bank4")->set_base(hiram ? state->m_kernal : state->m_memory + 0xe000);
234      state->membank("bank5")->set_base(state->m_memory + 0xe000);
235   }
236
237   /* make sure the opbase function gets called each time */
238   /* NPW 15-May-2008 - Another hack in the C64 drivers broken! */
239   /* opbase->mem_max = 0xcfff; */
240
241   state->m_old_game = state->m_game;
242   state->m_old_exrom = state->m_exrom;
243   state->m_old_data = data;
244}
245
246int c64_paddle_read( device_t *device, address_space &space, int which )
247{
248   running_machine &machine = device->machine();
249   int pot1 = 0xff, pot2 = 0xff, pot3 = 0xff, pot4 = 0xff, temp;
250   UINT8 cia0porta = mos6526_pa_r(machine.device("cia_0"), space, 0);
251   int controller1 = machine.root_device().ioport("CTRLSEL")->read() & 0x07;
252   int controller2 = machine.root_device().ioport("CTRLSEL")->read() & 0x70;
253   /* Notice that only a single input is defined for Mouse & Lightpen in both ports */
254   switch (controller1)
255   {
256      case 0x01:
257         if (which)
258            pot2 = machine.root_device().ioport("PADDLE2")->read();
259         else
260            pot1 = machine.root_device().ioport("PADDLE1")->read();
261         break;
262
263      case 0x02:
264         if (which)
265            pot2 = machine.root_device().ioport("TRACKY")->read();
266         else
267            pot1 = machine.root_device().ioport("TRACKX")->read();
268         break;
269
270      case 0x03:
271         if (which && (machine.root_device().ioport("JOY1_2B")->read() & 0x20))  /* Joy1 Button 2 */
272            pot1 = 0x00;
273         break;
274
275      case 0x04:
276         if (which)
277            pot2 = machine.root_device().ioport("LIGHTY")->read();
278         else
279            pot1 = machine.root_device().ioport("LIGHTX")->read();
280         break;
281
282      case 0x06:
283         if (which && (machine.root_device().ioport("OTHER")->read() & 0x04))    /* Lightpen Signal */
284            pot2 = 0x00;
285         break;
286
287      case 0x00:
288      case 0x07:
289         break;
290
291      default:
292         logerror("Invalid Controller Setting %d\n", controller1);
293         break;
294   }
295
296   switch (controller2)
297   {
298      case 0x10:
299         if (which)
300            pot4 = machine.root_device().ioport("PADDLE4")->read();
301         else
302            pot3 = machine.root_device().ioport("PADDLE3")->read();
303         break;
304
305      case 0x20:
306         if (which)
307            pot4 = machine.root_device().ioport("TRACKY")->read();
308         else
309            pot3 = machine.root_device().ioport("TRACKX")->read();
310         break;
311
312      case 0x30:
313         if (which && (machine.root_device().ioport("JOY2_2B")->read() & 0x20))  /* Joy2 Button 2 */
314            pot4 = 0x00;
315         break;
316
317      case 0x40:
318         if (which)
319            pot4 = machine.root_device().ioport("LIGHTY")->read();
320         else
321            pot3 = machine.root_device().ioport("LIGHTX")->read();
322         break;
323
324      case 0x60:
325         if (which && (machine.root_device().ioport("OTHER")->read() & 0x04))    /* Lightpen Signal */
326            pot4 = 0x00;
327         break;
328
329      case 0x00:
330      case 0x70:
331         break;
332
333      default:
334         logerror("Invalid Controller Setting %d\n", controller1);
335         break;
336   }
337
338   if (machine.root_device().ioport("CTRLSEL")->read() & 0x80)     /* Swap */
339   {
340      temp = pot1; pot1 = pot3; pot3 = temp;
341      temp = pot2; pot2 = pot4; pot4 = temp;
342   }
343
344   switch (cia0porta & 0xc0)
345   {
346      case 0x40:
347         return which ? pot2 : pot1;
348
349      case 0x80:
350         return which ? pot4 : pot3;
351
352      case 0xc0:
353         return which ? pot2 : pot1;
354
355      default:
356         return 0;
357   }
358}
359
360READ8_HANDLER( c64_colorram_read )
361{
362   legacy_c64_state *state = space.machine().driver_data<legacy_c64_state>();
363   return state->m_colorram[offset & 0x3ff];
364}
365
366WRITE8_HANDLER( c64_colorram_write )
367{
368   legacy_c64_state *state = space.machine().driver_data<legacy_c64_state>();
369   state->m_colorram[offset & 0x3ff] = data | 0xf0;
370}
371
372/***********************************************
373
374    C64 Cartridges
375
376***********************************************/
377
378/* Info based on http://ist.uwaterloo.ca/~schepers/formats/CRT.TXT      */
379/* Please refer to the webpage for the latest version and for a very
380   complete listing of various cart types and their bankswitch tricks   */
381/*
382  Cartridge files were introduced in the CCS64  emulator,  written  by  Per
383Hakan Sundell, and use the ".CRT" file extension. This format  was  created
384to handle the various ROM cartridges that exist, such as Action Replay, the
385Power cartridge, and the Final Cartridge.
386
387  Normal game cartridges can load  into  several  different  memory  ranges
388($8000-9FFF,  $A000-BFFF  or  $E000-FFFF).  Newer   utility   and   freezer
389cartridges were less intrusive, hiding themselves until  called  upon,  and
390still others used bank-switching techniques to allow much larger ROM's than
391normal. Because of these "stealthing" and bank-switching methods, a special
392cartridge format  was  necessary,  to  let  the  emulator  know  where  the
393cartridge should reside, the control line  states  to  enable  it  and  any
394special hardware features it uses.
395
396(...)
397
398[ A .CRT file consists of
399
400    $0000-0040 :    Header of the whole .crt files
401    $0040-EOF :     Blocks of data
402
403  Each block of data, called 'CHIP', can be of variable size. The first
4040x10 bytes of each CHIP block is the block header, and it contains various
405informations on the block itself, as its size (both with and without the
406header), the loading address and an index to identify which memory bank
407the data must be loaded to.  FP ]
408
409.CRT header description
410-----------------------
411
412 Bytes: $0000-000F - 16-byte cartridge signature  "C64  CARTRIDGE"  (padded
413                     with space characters)
414         0010-0013 - File header length  ($00000040,  in  high/low  format,
415                     calculated from offset $0000). The default  (also  the
416                     minimum) value is $40.  Some  cartridges  exist  which
417                     show a value of $00000020 which is wrong.
418         0014-0015 - Cartridge version (high/low, presently 01.00)
419         0016-0017 - Cartridge hardware type ($0000, high/low)
420              0018 - Cartridge port EXROM line status
421                      0 - inactive
422                      1 - active
423              0019 - Cartridge port GAME line status
424                      0 - inactive
425                      1 - active
426         001A-001F - Reserved for future use
427         0020-003F - 32-byte cartridge  name  "CCSMON"  (uppercase,  padded
428                     with null characters)
429         0040-xxxx - Cartridge contents (called CHIP PACKETS, as there  can
430                     be more than one  per  CRT  file).  See  below  for  a
431                     breakdown of the CHIP format.
432
433CHIP content description
434------------------------
435
436[ Addresses shifted back to $0000.  FP ]
437
438 Bytes: $0000-0003 - Contained ROM signature "CHIP" (note there can be more
439                     than one image in a .CRT file)
440         0004-0007 - Total packet length (ROM  image  size  and
441                     header combined) (high/low format)
442         0008-0009 - Chip type
443                      0 - ROM
444                      1 - RAM, no ROM data
445                      2 - Flash ROM
446         000A-000B - Bank number
447         000C-000D - Starting load address (high/low format)
448         000E-000F - ROM image size in bytes  (high/low  format,  typically
449                     $2000 or $4000)
450         0010-xxxx - ROM data
451
452
453*/
454
455
456/* Hardware Types for C64 carts */
457enum {
458   GENERIC_CRT = 0,        /* 00 - Normal cartridge                    */
459   ACTION_REPLAY,      /* 01 - Action Replay                       */
460   KCS_PC,         /* 02 - KCS Power Cartridge                 */
461   FINAL_CART_III,     /* 03 - Final Cartridge III                 */
462   SIMONS_BASIC,       /* 04 - Simons Basic                        */
463   OCEAN_1,            /* 05 - Ocean type 1 (1)                    */
464   EXPERT,         /* 06 - Expert Cartridge                    */
465   FUN_PLAY,           /* 07 - Fun Play, Power Play                */
466   SUPER_GAMES,        /* 08 - Super Games                         */
467   ATOMIC_POWER,       /* 09 - Atomic Power                        */
468   EPYX_FASTLOAD,      /* 10 - Epyx Fastload                       */
469   WESTERMANN,         /* 11 - Westermann Learning                 */
470   REX,                /* 12 - Rex Utility                         */
471   FINAL_CART_I,       /* 13 - Final Cartridge I                   */
472   MAGIC_FORMEL,       /* 14 - Magic Formel                        */
473   C64GS,          /* 15 - C64 Game System, System 3           */
474   WARPSPEED,          /* 16 - WarpSpeed                           */
475   DINAMIC,            /* 17 - Dinamic (2)                         */
476   ZAXXON,         /* 18 - Zaxxon, Super Zaxxon (SEGA)         */
477   DOMARK,         /* 19 - Magic Desk, Domark, HES Australia   */
478   SUPER_SNAP_5,       /* 20 - Super Snapshot 5                    */
479   COMAL_80,           /* 21 - Comal-80                            */
480   STRUCT_BASIC,       /* 22 - Structured Basic                    */
481   ROSS,               /* 23 - Ross                                */
482   DELA_EP64,          /* 24 - Dela EP64                           */
483   DELA_EP7X8,         /* 25 - Dela EP7x8                          */
484   DELA_EP256,         /* 26 - Dela EP256                          */
485   REX_EP256,          /* 27 - Rex EP256                           */
486   MIKRO_ASSMBLR,      /* 28 - Mikro Assembler                     */
487   REAL_FC_I,          /* 29 - (3)                                 */
488   ACTION_REPLAY_4,        /* 30 - Action Replay 4                     */
489   STARDOS,            /* 31 - StarDOS                             */
490   /*
491   (1) Ocean type 1 includes Navy Seals, Robocop 2 & 3,  Shadow  of
492   the Beast, Toki, Terminator 2 and more. Both 256 and 128 Kb images.
493   (2) Dinamic includes Narco Police and more.
494   (3) Type 29 is reserved for the real Final Cartridge I, the one
495   above (Type 13) will become Final Cartridge II.                 */
496   /****************************************
497   Vice also defines the following types:
498   #define CARTRIDGE_ACTION_REPLAY3    -29
499   #define CARTRIDGE_IEEE488           -11
500   #define CARTRIDGE_IDE64             -7
501   #define CARTRIDGE_RETRO_REPLAY      -5
502   #define CARTRIDGE_SUPER_SNAPSHOT    -4
503
504   Can we support these as well?
505   *****************************************/
506};
507
508static DEVICE_IMAGE_UNLOAD( c64_cart )
509{
510   legacy_c64_state *state = image.device().machine().driver_data<legacy_c64_state>();
511   int i;
512
513   for (i = 0; i < C64_MAX_ROMBANK; i++)
514   {
515      state->m_cart.bank[i].size = 0;
516      state->m_cart.bank[i].addr = 0;
517      state->m_cart.bank[i].index = 0;
518      state->m_cart.bank[i].start = 0;
519   }
520}
521
522
523static DEVICE_START( c64_cart )
524{
525   legacy_c64_state *state = device->machine().driver_data<legacy_c64_state>();
526   /* In the first slot we can load a .crt file. In this case we want
527       to use game & exrom values from the header, not the default ones. */
528   state->m_cart.game = -1;
529   state->m_cart.exrom = -1;
530   state->m_cart.mapper = GENERIC_CRT;
531   state->m_cart.n_banks = 0;
532}
533
534static int c64_crt_load( device_image_interface &image )
535{
536   legacy_c64_state *state = image.device().machine().driver_data<legacy_c64_state>();
537   int size = image.length(), test, i = 0, ii;
538   int _80_loaded = 0, _90_loaded = 0, a0_loaded = 0, b0_loaded = 0, e0_loaded = 0, f0_loaded = 0;
539   const char *filetype = image.filetype();
540   int address = 0, new_start = 0;
541   // int lbank_end_addr = 0, hbank_end_addr = 0;
542   UINT8 *cart_cpy = state->memregion("user1")->base();
543
544   /* We support .crt files */
545   if (!mame_stricmp(filetype, "crt"))
546   {
547      int j;
548      unsigned short c64_cart_type;
549
550      if (i >= C64_MAX_ROMBANK)
551         return IMAGE_INIT_FAIL;
552
553      /* Start to parse the .crt header */
554      /* 0x16-0x17 is Hardware type */
555      image.fseek(0x16, SEEK_SET);
556      image.fread(&c64_cart_type, 2);
557      state->m_cart.mapper = BIG_ENDIANIZE_INT16(c64_cart_type);
558
559      /* If it is unsupported cart type, warn the user */
560      switch (state->m_cart.mapper)
561      {
562         case SIMONS_BASIC:  /* Type #  4 */
563         case OCEAN_1:       /* Type #  5 */
564         case FUN_PLAY:      /* Type #  7 */
565         case SUPER_GAMES:       /* Type #  8 */
566         case EPYX_FASTLOAD: /* Type # 10 */
567         case REX:           /* Type # 12 */
568         case C64GS:         /* Type # 15 */
569         case DINAMIC:       /* Type # 17 */
570         case ZAXXON:        /* Type # 18 */
571         case DOMARK:        /* Type # 19 */
572         case COMAL_80:      /* Type # 21 */
573         case GENERIC_CRT:       /* Type #  0 */
574            printf("Currently supported cart type (Type %d)\n", state->m_cart.mapper);
575            break;
576
577         default:
578         case ACTION_REPLAY: /* Type #  1 */
579         case KCS_PC:        /* Type #  2 */
580         case FINAL_CART_III:    /* Type #  3 */
581         case EXPERT:        /* Type #  6 */
582         case ATOMIC_POWER:  /* Type #  9 */
583         case WESTERMANN:        /* Type # 11 */
584         case FINAL_CART_I:  /* Type # 13 */
585         case MAGIC_FORMEL:  /* Type # 14 */
586         case SUPER_SNAP_5:  /* Type # 20 */
587            printf("Currently unsupported cart type (Type %d)\n", state->m_cart.mapper);
588            break;
589      }
590
591      /* 0x18 is EXROM */
592      image.fseek(0x18, SEEK_SET);
593      image.fread(&state->m_cart.exrom, 1);
594
595      /* 0x19 is GAME */
596      image.fread(&state->m_cart.game, 1);
597
598      /* We can pass to the data: it starts from 0x40 */
599      image.fseek(0x40, SEEK_SET);
600      j = 0x40;
601
602      logerror("Loading cart %s size:%.4x\n", image.filename(), size);
603      logerror("Header info: EXROM %d, GAME %d, Cart Type %d \n", state->m_cart.exrom, state->m_cart.game, c64_cart_type);
604
605
606      /* Data in a .crt image are organized in blocks called 'CHIP':
607         each 'CHIP' consists of a 0x10 header, which contains the
608         actual size of the block, the loading address and info on
609         the bankswitch, followed by the actual data                  */
610      while (j < size)
611      {
612         unsigned short chip_size, chip_bank_index, chip_data_size;
613         unsigned char buffer[10];
614
615         /* Start to parse the CHIP header */
616         /* First 4 bytes are the string 'CHIP' */
617         image.fread(buffer, 6);
618
619         /* 0x06-0x07 is the size of the CHIP block (header + data) */
620         image.fread(&chip_size, 2);
621         chip_size = BIG_ENDIANIZE_INT16(chip_size);
622
623         /* 0x08-0x09 chip type (ROM, RAM + no ROM, Flash ROM) */
624         image.fread(buffer + 6, 2);
625
626         /* 0x0a-0x0b is the bank number of the CHIP block */
627         image.fread(&chip_bank_index, 2);
628         chip_bank_index = BIG_ENDIANIZE_INT16(chip_bank_index);
629
630         /* 0x0c-0x0d is the loading address of the CHIP block */
631         image.fread(&address, 2);
632         address = BIG_ENDIANIZE_INT16(address);
633
634         /* 0x0e-0x0f is the data size of the CHIP block (without header) */
635         image.fread(&chip_data_size, 2);
636         chip_data_size = BIG_ENDIANIZE_INT16(chip_data_size);
637
638         /* Print out the CHIP header! */
639         logerror("%.4s %.2x %.2x %.4x %.2x %.2x %.4x %.4x:%.4x\n",
640            buffer, buffer[4], buffer[5], chip_size,
641            buffer[6], buffer[7], chip_bank_index,
642            address, chip_data_size);
643         logerror("Loading CHIP data at %.4x size:%.4x\n", address, chip_data_size);
644
645         /* Store data, address & size of the CHIP block */
646         state->m_cart.bank[i].addr = address;
647         state->m_cart.bank[i].index = chip_bank_index;
648         state->m_cart.bank[i].size = chip_data_size;
649         state->m_cart.bank[i].start = new_start;
650
651         test = image.fread(cart_cpy + new_start, state->m_cart.bank[i].size);
652         new_start += state->m_cart.bank[i].size;
653
654         /* Does CHIP contain any data? */
655         if (test != state->m_cart.bank[i].size)
656            return IMAGE_INIT_FAIL;
657
658         /* Advance to the next CHIP block */
659         i++;
660         j += chip_size;
661      }
662   }
663   else /* We also support .80 files for c64 & .e0/.f0 for max */
664   {
665      /* Assign loading address according to extension */
666      if (!mame_stricmp(filetype, "80"))
667         address = 0x8000;
668
669      if (!mame_stricmp(filetype, "e0"))
670         address = 0xe000;
671
672      if (!mame_stricmp(filetype, "f0"))
673         address = 0xf000;
674
675      logerror("loading %s rom at %.4x size:%.4x\n", image.filename(), address, size);
676
677      /* Store data, address & size */
678      state->m_cart.bank[0].addr = address;
679      state->m_cart.bank[0].size = size;
680      state->m_cart.bank[0].start = new_start;
681
682      test = image.fread(cart_cpy + new_start, state->m_cart.bank[0].size);
683      new_start += state->m_cart.bank[0].size;
684
685      /* Does cart contain any data? */
686      if (test != state->m_cart.bank[0].size)
687         return IMAGE_INIT_FAIL;
688   }
689
690   state->m_cart.n_banks = i; // this is also needed so that we only set mappers if a cart is present!
691
692   /* If we load a .crt file, use EXROM & GAME from the header! */
693   if ((state->m_cart.exrom != -1) && (state->m_cart.game != -1))
694   {
695      state->m_exrom = state->m_cart.exrom;
696      state->m_game  = state->m_cart.game;
697   }
698
699   /* Finally load the cart */
700   state->m_roml = state->m_c64_roml;
701   state->m_romh = state->m_c64_romh;
702
703   memset(state->m_roml, 0, 0x2000);
704   memset(state->m_romh, 0, 0x2000);
705
706   switch (state->m_cart.mapper)
707   {
708   default:
709      if (!state->m_game && state->m_exrom && (state->m_cart.n_banks == 1))
710      {
711         memcpy(state->m_romh, cart_cpy, 0x2000);
712      }
713      else
714      {
715         // we first attempt to load the first 'CHIPs' with address 0x8000-0xb000 and 0xe000-0xf000, otherwise we load the first (or first two) 'CHIPs' of the image
716         for (ii = 0; ii < state->m_cart.n_banks; ii++)
717         {
718            if (state->m_cart.bank[ii].addr == 0x8000 && !_80_loaded)
719            {
720               memcpy(state->m_roml, cart_cpy + state->m_cart.bank[ii].start, state->m_cart.bank[ii].size);
721               _80_loaded = 1;
722               if (state->m_cart.bank[ii].size > 0x1000)
723                  _90_loaded = 1;
724               if (state->m_cart.bank[ii].size > 0x2000)
725                  a0_loaded = 1;
726               if (state->m_cart.bank[ii].size > 0x3000)
727                  b0_loaded = 1;
728//                  printf("addr 0x8000: 80 %d, 90 %d, a0 %d, b0 %d\n", _80_loaded, _90_loaded, a0_loaded, b0_loaded);
729            }
730
731            if (state->m_cart.bank[ii].addr == 0x9000 && !_90_loaded)
732            {
733               memcpy(state->m_roml + 0x1000, cart_cpy + state->m_cart.bank[ii].start, state->m_cart.bank[ii].size);
734               _90_loaded = 1;
735               if (state->m_cart.bank[ii].size > 0x1000)
736                  a0_loaded = 1;
737               if (state->m_cart.bank[ii].size > 0x2000)
738                  b0_loaded = 1;
739//                  printf("addr 0x9000: 80 %d, 90 %d, a0 %d, b0 %d\n", _80_loaded, _90_loaded, a0_loaded, b0_loaded);
740            }
741
742            if (state->m_cart.bank[ii].addr == 0xa000 && !a0_loaded)
743            {
744               memcpy(state->m_roml + 0x2000, cart_cpy + state->m_cart.bank[ii].start, state->m_cart.bank[ii].size);
745               a0_loaded = 1;
746               if (state->m_cart.bank[ii].size > 0x1000)
747                  b0_loaded = 1;
748//                  printf("addr 0xa000: 80 %d, 90 %d, a0 %d, b0 %d\n", _80_loaded, _90_loaded, a0_loaded, b0_loaded);
749            }
750
751            if (state->m_cart.bank[ii].addr == 0xb000 && !b0_loaded)
752            {
753               memcpy(state->m_roml + 0x3000, cart_cpy + state->m_cart.bank[ii].start, state->m_cart.bank[ii].size);
754               b0_loaded = 1;
755//                  printf("addr 0xb000: 80 %d, 90 %d, a0 %d, b0 %d\n", _80_loaded, _90_loaded, a0_loaded, b0_loaded);
756            }
757
758            if (state->m_cart.bank[ii].addr == 0xe000 && !e0_loaded)
759            {
760               memcpy(state->m_romh, cart_cpy + state->m_cart.bank[ii].start, state->m_cart.bank[ii].size);
761               e0_loaded = 1;
762               if (state->m_cart.bank[ii].size > 0x1000)
763                  f0_loaded = 1;
764//                  printf("addr 0xe000: e0 %d, f0 %d\n", e0_loaded, f0_loaded);
765            }
766
767            if (state->m_cart.bank[ii].addr == 0xf000 && !f0_loaded)
768            {
769               memcpy(state->m_romh + 0x1000, cart_cpy + state->m_cart.bank[ii].start, state->m_cart.bank[ii].size);
770               f0_loaded = 1;
771//                  printf("addr 0xe000: e0 %d, f0 %d\n", e0_loaded, f0_loaded);
772            }
773         }
774      }
775   }
776
777   return IMAGE_INIT_PASS;
778}
779
780/***************************************************************************
781    SOFTWARE LIST CARTRIDGE HANDLING
782***************************************************************************/
783
784#define install_write_handler(_start, _end, _handler) \
785   image.device().machine().firstcpu->space(AS_PROGRAM).install_legacy_write_handler(_start, _end, FUNC(_handler));
786
787#define install_io1_handler(_handler) \
788   image.device().machine().firstcpu->space(AS_PROGRAM).install_legacy_write_handler(0xde00, 0xde00, 0, 0xff, FUNC(_handler));
789
790#define install_io2_handler(_handler) \
791   image.device().machine().firstcpu->space(AS_PROGRAM).install_legacy_write_handler(0xdf00, 0xdf00, 0, 0xff, FUNC(_handler));
792
793#define allocate_cartridge_timer(_period, _func) \
794   legacy_c64_state *state = image.device().machine().driver_data<legacy_c64_state>(); \
795   state->m_cartridge_timer = image.device().machine().scheduler().timer_alloc(FUNC(_func)); \
796   state->m_cartridge_timer->adjust(_period, 0);
797
798#define set_game_line(_machine, _state) \
799   _machine.driver_data<legacy_c64_state>()->m_game = _state; \
800   c64_bankswitch(_machine, 0);
801
802INLINE void load_cartridge_region(device_image_interface &image, const char *name, offs_t offset, size_t size)
803{
804   UINT8 *cart = image.device().machine().root_device().memregion("user1")->base();
805   UINT8 *rom = image.get_software_region(name);
806   memcpy(cart + offset, rom, size);
807}
808
809INLINE void map_cartridge_roml(running_machine &machine, offs_t offset)
810{
811   legacy_c64_state *state = machine.driver_data<legacy_c64_state>();
812   UINT8 *cart = state->memregion("user1")->base();
813   memcpy(state->m_roml, cart + offset, 0x2000);
814}
815
816INLINE void map_cartridge_romh(running_machine &machine, offs_t offset)
817{
818   legacy_c64_state *state = machine.driver_data<legacy_c64_state>();
819   UINT8 *cart = state->memregion("user1")->base();
820   memcpy(state->m_romh, cart + offset, 0x2000);
821}
822
823static void load_standard_c64_cartridge(device_image_interface &image)
824{
825   legacy_c64_state *state = image.device().machine().driver_data<legacy_c64_state>();
826   UINT32 size;
827
828   // is there anything to load at 0x8000?
829   size = image.get_software_region_length("roml");
830
831   if (size)
832   {
833      memcpy(state->m_roml, image.get_software_region("roml"), MIN(0x2000, size));
834
835      if (size == 0x4000)
836      {
837         // continue loading to ROMH region
838         memcpy(state->m_romh, image.get_software_region("roml") + 0x2000, 0x2000);
839      }
840   }
841
842   // is there anything to load at 0xa000?
843   size = image.get_software_region_length("romh");
844   if (size)
845      memcpy(state->m_romh, image.get_software_region("romh"), size);
846}
847
848static TIMER_CALLBACK( vizawrite_timer )
849{
850   map_cartridge_roml(machine, 0x2000);
851   set_game_line(machine, 1);
852}
853
854static void load_vizawrite_cartridge(device_image_interface &image)
855{
856   #define VW64_DECRYPT_ADDRESS(_offset) \
857      BITSWAP16(_offset,15,14,13,12,7,8,6,9,5,11,4,3,2,10,1,0)
858
859   #define VW64_DECRYPT_DATA(_data) \
860      BITSWAP8(_data,7,6,0,5,1,4,2,3)
861
862   UINT8 *roml = image.get_software_region("roml");
863   UINT8 *romh = image.get_software_region("romh");
864   UINT8 *decrypted = image.device().machine().root_device().memregion("user1")->base();
865
866   // decrypt ROMs
867   for (offs_t offset = 0; offset < 0x2000; offset++)
868   {
869      offs_t address = VW64_DECRYPT_ADDRESS(offset);
870      decrypted[address] = VW64_DECRYPT_DATA(roml[offset]);
871      decrypted[address + 0x2000] = VW64_DECRYPT_DATA(roml[offset + 0x2000]);
872      decrypted[address + 0x4000] = VW64_DECRYPT_DATA(romh[offset]);
873   }
874
875   // map cartridge ROMs
876   map_cartridge_roml(image.device().machine(), 0x0000);
877   map_cartridge_romh(image.device().machine(), 0x4000);
878
879   // allocate GAME changing timer
880   allocate_cartridge_timer(attotime::from_msec(1184), vizawrite_timer);
881}
882
883static WRITE8_HANDLER( hugo_bank_w )
884{
885   /*
886
887       bit     description
888
889       0
890       1
891       2
892       3
893       4       A14
894       5       A15
895       6       A16
896       7       A13
897
898   */
899
900   int bank = ((data >> 3) & 0x0e) | BIT(data, 7);
901
902   map_cartridge_roml(space.machine(), bank * 0x2000);
903}
904
905static void load_hugo_cartridge(device_image_interface &image)
906{
907   #define HUGO_DECRYPT_ADDRESS(_offset) \
908      BITSWAP16(_offset,15,14,13,12,7,6,5,4,3,2,1,0,8,9,11,10)
909
910   #define HUGO_DECRYPT_DATA(_data) \
911      BITSWAP8(_data,7,6,5,4,0,1,2,3)
912
913   UINT8 *roml = image.get_software_region("roml");
914   UINT8 *decrypted = image.device().machine().root_device().memregion("user1")->base();
915
916   // decrypt ROMs
917   for (offs_t offset = 0; offset < 0x20000; offset++)
918   {
919      offs_t address = (offset & 0x10000) | HUGO_DECRYPT_ADDRESS(offset);
920      decrypted[address] = HUGO_DECRYPT_DATA(roml[offset]);
921   }
922
923   // map cartridge ROMs
924   map_cartridge_roml(image.device().machine(), 0x0000);
925
926   // install bankswitch handler
927   install_io1_handler(hugo_bank_w);
928}
929
930static WRITE8_HANDLER( easy_calc_result_bank_w )
931{
932   map_cartridge_romh(space.machine(), 0x2000 + (!offset * 0x2000));
933}
934
935static void load_easy_calc_result_cartridge(device_image_interface &image)
936{
937   load_cartridge_region(image, "roml", 0x0000, 0x2000);
938   load_cartridge_region(image, "romh", 0x2000, 0x4000);
939
940   map_cartridge_roml(image.device().machine(), 0x0000);
941   map_cartridge_romh(image.device().machine(), 0x2000);
942
943   install_write_handler(0xde00, 0xde01, easy_calc_result_bank_w);
944}
945
946static WRITE8_HANDLER( pagefox_bank_w )
947{
948   /*
949
950       Die 96KB des Moduls belegen in 6 16K-Banken den Modulbereich von $8000- $c000.
951       Die Umschaltung erfolgt mit einem Register in $DE80 (-$DEFF, nicht voll decodiert),
952       welches nur beschrieben und nicht gelesen werden kann. Durch Schreiben der Werte
953       $08 oder $0A selektiert man eine der beiden RAM-Banke, $FF deselektiert das Modul.
954
955       Zusatzlich muss Adresse 1 entsprechend belegt werden :$37 fur Lesezugriffe auf das
956       Modul, $35 oder $34 fur Lesezugriffe auf das Ram des C64. Schreibzugriffe lenkt
957       der C64 grundsatzlich ins eigene RAM, weshalb zum Beschreiben des Modulrams ein
958       Trick notwendig ist: Man schaltet das Ram-Modul parallel zum C64-Ram, rettet vor
959       dem Schreiben den C64-Ram-Inhalt und stellt ihn nachher wieder her...
960
961       Ldy#0
962       Lda#$35
963       Sta 1
964       Loop Lda (Ptr),y
965       Pha
966       Lda#$08
967       Sta $DE80
968       Lda (Quell),y
969       Sta (Ptr),y
970       Lda#$FF
971       Sta $DE80
972       Pla
973       Sta (Ptr),y
974       Iny
975       Bne Loop
976
977   */
978
979   legacy_c64_state *state = space.machine().driver_data<legacy_c64_state>();
980   UINT8 *cart = state->memregion("user1")->base();
981
982   if (data == 0xff)
983   {
984      // hide cartridge
985      state->m_game = 1;
986      state->m_exrom = 1;
987   }
988   else
989   {
990      if (state->m_game)
991      {
992         // enable cartridge
993         state->m_game = 0;
994         state->m_exrom = 0;
995      }
996
997      int bank = (data >> 1) & 0x07;
998      int ram = BIT(data, 3);
999      offs_t address = bank * 0x4000;
1000
1001      state->m_roml_writable = ram;
1002
1003      if (ram)
1004      {
1005         state->m_roml = cart + address;
1006      }
1007      else
1008      {
1009         state->m_roml = state->m_c64_roml;
1010
1011         map_cartridge_roml(space.machine(), address);
1012         map_cartridge_romh(space.machine(), address + 0x2000);
1013      }
1014   }
1015
1016   c64_bankswitch(space.machine(), 0);
1017}
1018
1019static void load_pagefox_cartridge(device_image_interface &image)
1020{
1021   load_cartridge_region(image, "rom", 0x0000, 0x10000);
1022
1023   map_cartridge_roml(image.device().machine(), 0x0000);
1024   map_cartridge_romh(image.device().machine(), 0x2000);
1025
1026   install_write_handler(0xde80, 0xdeff, pagefox_bank_w);
1027}
1028
1029static WRITE8_HANDLER( multiscreen_bank_w )
1030{
1031   legacy_c64_state *state = space.machine().driver_data<legacy_c64_state>();
1032   UINT8 *cart = state->memregion("user1")->base();
1033   int bank = data & 0x0f;
1034   offs_t address = bank * 0x4000;
1035
1036   if (bank == 0x0d)
1037   {
1038      // RAM
1039      state->m_roml = cart + address;
1040      state->m_roml_writable = 1;
1041
1042      map_cartridge_romh(space.machine(), 0x2000);
1043   }
1044   else
1045   {
1046      // ROM
1047      state->m_roml = state->m_c64_roml;
1048      state->m_roml_writable = 0;
1049
1050      map_cartridge_roml(space.machine(), address);
1051      map_cartridge_romh(space.machine(), address + 0x2000);
1052   }
1053
1054   c64_bankswitch(space.machine(), 0);
1055}
1056
1057static void load_multiscreen_cartridge(device_image_interface &image)
1058{
1059   load_cartridge_region(image, "roml", 0x0000, 0x4000);
1060   load_cartridge_region(image, "rom", 0x4000, 0x30000);
1061
1062   map_cartridge_roml(image.device().machine(), 0x0000);
1063   map_cartridge_romh(image.device().machine(), 0x2000);
1064
1065   install_write_handler(0xdfff, 0xdfff, multiscreen_bank_w);
1066}
1067
1068static WRITE8_HANDLER( simons_basic_bank_w )
1069{
1070   set_game_line(space.machine(), !BIT(data, 0));
1071}
1072
1073static void load_simons_basic_cartridge(device_image_interface &image)
1074{
1075   load_cartridge_region(image, "roml", 0x0000, 0x2000);
1076   load_cartridge_region(image, "romh", 0x2000, 0x2000);
1077
1078   map_cartridge_roml(image.device().machine(), 0x0000);
1079   map_cartridge_romh(image.device().machine(), 0x2000);
1080
1081   install_io1_handler(simons_basic_bank_w);
1082}
1083
1084static READ8_HANDLER( super_explode_r )
1085{
1086   legacy_c64_state *state = space.machine().driver_data<legacy_c64_state>();
1087
1088   return state->m_roml[0x1f00 | offset];
1089}
1090
1091static WRITE8_HANDLER( super_explode_bank_w )
1092{
1093   map_cartridge_roml(space.machine(), BIT(data, 7) * 0x2000);
1094}
1095
1096static void load_super_explode_cartridge(device_image_interface &image)
1097{
1098   load_cartridge_region(image, "roml", 0x0000, 0x4000);
1099
1100   map_cartridge_roml(image.device().machine(), 0x0000);
1101
1102   address_space &space = image.device().machine().firstcpu->space(AS_PROGRAM);
1103   space.install_legacy_read_handler(0xdf00, 0xdfff, FUNC(super_explode_r));
1104
1105   install_io2_handler(super_explode_bank_w);
1106}
1107
1108static void c64_software_list_cartridge_load(device_image_interface &image)
1109{
1110   legacy_c64_state *state = image.device().machine().driver_data<legacy_c64_state>();
1111
1112   // initialize ROML and ROMH pointers
1113   state->m_roml = state->m_c64_roml;
1114   state->m_romh = state->m_c64_romh;
1115
1116   // clear ROML and ROMH areas
1117   memset(state->m_roml, 0, 0x2000);
1118   memset(state->m_romh, 0, 0x2000);
1119
1120   // set GAME and EXROM
1121   state->m_game = atol(image.get_feature("game"));
1122   state->m_exrom = atol(image.get_feature("exrom"));
1123
1124   // determine cartridge type
1125   const char *cart_type = image.get_feature("cart_type");
1126
1127   if (cart_type == NULL)
1128   {
1129      load_standard_c64_cartridge(image);
1130   }
1131   else
1132   {
1133      if (!strcmp(cart_type, "vizawrite"))
1134         load_vizawrite_cartridge(image);
1135
1136      else if (!strcmp(cart_type, "hugo"))
1137         load_hugo_cartridge(image);
1138
1139      else if (!strcmp(cart_type, "easy_calc_result"))
1140         load_easy_calc_result_cartridge(image);
1141
1142      else if (!strcmp(cart_type, "pagefox"))
1143         load_pagefox_cartridge(image);
1144
1145      else if (!strcmp(cart_type, "multiscreen"))
1146         /*
1147
1148             TODO: crashes on protection check after cartridge RAM test
1149
1150             805A: lda  $01
1151             805C: and  #$FE
1152             805E: sta  $01
1153             8060: m6502_brk#$00 <-- BOOM!
1154
1155         */
1156         load_multiscreen_cartridge(image);
1157
1158      else if (!strcmp(cart_type, "simons_basic"))
1159         load_simons_basic_cartridge(image);
1160
1161      else if (!strcmp(cart_type, "super_explode"))
1162         load_super_explode_cartridge(image);
1163
1164      else
1165         load_standard_c64_cartridge(image);
1166   }
1167}
1168
1169static DEVICE_IMAGE_LOAD( c64_cart )
1170{
1171   int result = IMAGE_INIT_PASS;
1172
1173   if (image.software_entry() != NULL)
1174   {
1175      c64_software_list_cartridge_load(image);
1176   }
1177   else
1178      result = c64_crt_load(image);
1179
1180   return result;
1181}
1182MACHINE_CONFIG_FRAGMENT( c64_cartslot )
1183   MCFG_CARTSLOT_ADD("cart1")
1184   MCFG_CARTSLOT_EXTENSION_LIST("crt,80")
1185   MCFG_CARTSLOT_NOT_MANDATORY
1186   MCFG_CARTSLOT_INTERFACE("c64_cart")
1187   MCFG_CARTSLOT_START(c64_cart)
1188   MCFG_CARTSLOT_LOAD(c64_cart)
1189   MCFG_CARTSLOT_UNLOAD(c64_cart)
1190
1191   MCFG_CARTSLOT_ADD("cart2")
1192   MCFG_CARTSLOT_EXTENSION_LIST("crt,80")
1193   MCFG_CARTSLOT_NOT_MANDATORY
1194   MCFG_CARTSLOT_START(c64_cart)
1195   MCFG_CARTSLOT_LOAD(c64_cart)
1196   MCFG_CARTSLOT_UNLOAD(c64_cart)
1197
1198   MCFG_SOFTWARE_LIST_ADD("cart_list_c64", "c64_cart")
1199MACHINE_CONFIG_END
trunk/src/mess/machine/c64_legacy.c
r0r20588
1/***************************************************************************
2    commodore c64 home computer
3
4    peter.trauner@jk.uni-linz.ac.at
5    documentation
6     www.funet.fi
7***************************************************************************/
8
9/*
10    2008-09-06: Tape status for C64 & C128 [FP & RZ]
11    - tape loading works
12    - tap files are supported
13    - tape writing works
14*/
15
16#include "emu.h"
17
18#include "cpu/m6502/m6510.h"
19#include "cpu/z80/z80.h"
20#include "sound/sid6581.h"
21#include "machine/6526cia.h"
22#include "machine/cbmiec.h"
23
24#include "includes/cbm.h"
25#include "includes/c64_legacy.h"
26
27#include "imagedev/cassette.h"
28#include "imagedev/cartslot.h"
29
30#define VERBOSE_LEVEL 0
31#define DBG_LOG( MACHINE, N, M, A ) \
32   do { \
33      if(VERBOSE_LEVEL >= N) \
34      { \
35         if( M ) \
36            logerror("%11.6f: %-24s", MACHINE.time().as_double(), (char*) M ); \
37         logerror A; \
38      } \
39   } while (0)
40
41#define log_cart 0
42
43/* Info from http://unusedino.de/ec64/technical/misc/c64/64doc.html */
44/*
45
46  The leftmost column of the table contains addresses in hexadecimal
47notation. The columns aside it introduce all possible memory
48configurations. The default mode is on the left, and the absolutely
49most rarely used Ultimax game console configuration is on the right.
50(Has anybody ever seen any Ultimax games?) Each memory configuration
51column has one or more four-digit binary numbers as a title. The bits,
52from left to right, represent the state of the -LORAM, -HIRAM, -GAME
53and -EXROM lines, respectively. The bits whose state does not matter
54are marked with "x". For instance, when the Ultimax video game
55configuration is active (the -GAME line is shorted to ground), the
56-LORAM and -HIRAM lines have no effect.
57
58      default                      001x                       Ultimax
59       1111   101x   1000   011x   00x0   1110   0100   1100   xx01
6010000
61----------------------------------------------------------------------
62 F000
63       Kernal RAM    RAM    Kernal RAM    Kernal Kernal Kernal ROMH(*
64 E000
65----------------------------------------------------------------------
66 D000  IO/C   IO/C   IO/RAM IO/C   RAM    IO/C   IO/C   IO/C   I/O
67----------------------------------------------------------------------
68 C000  RAM    RAM    RAM    RAM    RAM    RAM    RAM    RAM     -
69----------------------------------------------------------------------
70 B000
71       BASIC  RAM    RAM    RAM    RAM    BASIC  ROMH   ROMH    -
72 A000
73----------------------------------------------------------------------
74 9000
75       RAM    RAM    RAM    RAM    RAM    ROML   RAM    ROML   ROML(*
76 8000
77----------------------------------------------------------------------
78 7000
79
80 6000
81       RAM    RAM    RAM    RAM    RAM    RAM    RAM    RAM     -
82 5000
83
84 4000
85----------------------------------------------------------------------
86 3000
87
88 2000  RAM    RAM    RAM    RAM    RAM    RAM    RAM    RAM     -
89
90 1000
91----------------------------------------------------------------------
92 0000  RAM    RAM    RAM    RAM    RAM    RAM    RAM    RAM    RAM
93----------------------------------------------------------------------
94
95   *) Internal memory does not respond to write accesses to these
96       areas.
97
98
99    Legend: Kernal      E000-FFFF       Kernal ROM.
100
101            IO/C        D000-DFFF       I/O address space or Character
102                                        generator ROM, selected by
103                                        -CHAREN. If the CHAREN bit is
104                                        clear, the character generator
105                                        ROM will be selected. If it is
106                                        set, the I/O chips are
107                                        accessible.
108
109            IO/RAM      D000-DFFF       I/O address space or RAM,
110                                        selected by -CHAREN. If the
111                                        CHAREN bit is clear, the
112                                        character generator ROM will
113                                        be selected. If it is set, the
114                                        internal RAM is accessible.
115
116            I/O         D000-DFFF       I/O address space.
117                                        The -CHAREN line has no effect.
118
119            BASIC       A000-BFFF       BASIC ROM.
120
121            ROMH        A000-BFFF or    External ROM with the -ROMH line
122                        E000-FFFF       connected to its -CS line.
123
124            ROML        8000-9FFF       External ROM with the -ROML line
125                                        connected to its -CS line.
126
127            RAM         various ranges  Commodore 64's internal RAM.
128
129            -           1000-7FFF and   Open address space.
130                        A000-CFFF       The Commodore 64's memory chips
131                                        do not detect any memory accesses
132                                        to this area except the VIC-II's
133                                        DMA and memory refreshes.
134
135    NOTE:   Whenever the processor tries to write to any ROM area
136            (Kernal, BASIC, CHAROM, ROML, ROMH), the data will get
137            "through the ROM" to the C64's internal RAM.
138
139            For this reason, you can easily copy data from ROM to RAM,
140            without any bank switching. But implementing external
141            memory expansions without DMA is very hard, as you have to
142            use a 256 byte window on the I/O1 or I/O2 area, like
143            GEORAM, or the Ultimax memory configuration, if you do not
144            want the data to be written both to internal and external
145            RAM.
146
147            However, this is not true for the Ultimax video game
148            configuration. In that mode, the internal RAM ignores all
149            memory accesses outside the area $0000-$0FFF, unless they
150            are performed by the VIC, and you can write to external
151            memory at $1000-$CFFF and $E000-$FFFF, if any, without
152            changing the contents of the internal RAM.
153
154*/
155
156static void c64_bankswitch( running_machine &machine, int reset )
157{
158   legacy_c64_state *state = machine.driver_data<legacy_c64_state>();
159   int loram, hiram, charen;
160   int ultimax_mode = 0;
161   int data = machine.device<m6510_device>("maincpu")->get_port() & 0x07;
162
163   /* Are we in Ultimax mode? */
164   if (!state->m_game && state->m_exrom)
165      ultimax_mode = 1;
166
167   DBG_LOG(machine, 1, "bankswitch", ("%d\n", data & 7));
168   loram  = (data & 1) ? 1 : 0;
169   hiram  = (data & 2) ? 1 : 0;
170   charen = (data & 4) ? 1 : 0;
171   //logerror("Bankswitch mode || charen, state->m_ultimax\n");
172   //logerror("%d, %d, %d, %d  ||   %d,      %d  \n", loram, hiram, state->m_game, state->m_exrom, charen, ultimax_mode);
173
174   if (ultimax_mode)
175   {
176         state->m_io_enabled = 1;        // charen has no effect in ultimax_mode
177
178         state->membank("bank1")->set_base(state->m_roml);
179         state->membank("bank3")->set_base(state->m_memory + 0xa000);
180         state->membank("bank4")->set_base(state->m_romh);
181         machine.device("maincpu")->memory().space(AS_PROGRAM).nop_write(0xe000, 0xffff);
182   }
183   else
184   {
185      /* 0x8000-0x9000 */
186      if (loram && hiram && !state->m_exrom)
187      {
188         state->membank("bank1")->set_base(state->m_roml);
189      }
190      else
191      {
192         state->membank("bank1")->set_base(state->m_memory + 0x8000);
193      }
194
195      /* 0xa000 */
196      if (hiram && !state->m_game && !state->m_exrom)
197         state->membank("bank3")->set_base(state->m_romh);
198
199      else if (loram && hiram && state->m_game)
200         state->membank("bank3")->set_base(state->m_basic);
201
202      else
203         state->membank("bank3")->set_base(state->m_memory + 0xa000);
204
205      /* 0xd000 */
206      // RAM
207      if (!loram && !hiram && (state->m_game || !state->m_exrom))
208      {
209         state->m_io_enabled = 0;
210         state->m_io_ram_r_ptr = state->m_memory + 0xd000;
211         state->m_io_ram_w_ptr = state->m_memory + 0xd000;
212      }
213      // IO/RAM
214      else if (loram && !hiram && !state->m_game) // remember we cannot be in ultimax_mode, no need of !state->m_exrom
215      {
216         state->m_io_enabled = 1;
217         state->m_io_ram_r_ptr = (!charen) ? state->m_chargen : state->m_memory + 0xd000;
218         state->m_io_ram_w_ptr = state->m_memory + 0xd000;
219      }
220      // IO/C
221      else
222      {
223         state->m_io_enabled = charen ? 1 : 0;
224
225         if (!charen)
226         {
227         state->m_io_ram_r_ptr = state->m_chargen;
228         state->m_io_ram_w_ptr = state->m_memory + 0xd000;
229         }
230      }
231
232      /* 0xe000-0xf000 */
233      state->membank("bank4")->set_base(hiram ? state->m_kernal : state->m_memory + 0xe000);
234      state->membank("bank5")->set_base(state->m_memory + 0xe000);
235   }
236
237   /* make sure the opbase function gets called each time */
238   /* NPW 15-May-2008 - Another hack in the C64 drivers broken! */
239   /* opbase->mem_max = 0xcfff; */
240
241   state->m_old_game = state->m_game;
242   state->m_old_exrom = state->m_exrom;
243   state->m_old_data = data;
244}
245
246int c64_paddle_read( device_t *device, address_space &space, int which )
247{
248   running_machine &machine = device->machine();
249   int pot1 = 0xff, pot2 = 0xff, pot3 = 0xff, pot4 = 0xff, temp;
250   UINT8 cia0porta = mos6526_pa_r(machine.device("cia_0"), space, 0);
251   int controller1 = machine.root_device().ioport("CTRLSEL")->read() & 0x07;
252   int controller2 = machine.root_device().ioport("CTRLSEL")->read() & 0x70;
253   /* Notice that only a single input is defined for Mouse & Lightpen in both ports */
254   switch (controller1)
255   {
256      case 0x01:
257         if (which)
258            pot2 = machine.root_device().ioport("PADDLE2")->read();
259         else
260            pot1 = machine.root_device().ioport("PADDLE1")->read();
261         break;
262
263      case 0x02:
264         if (which)
265            pot2 = machine.root_device().ioport("TRACKY")->read();
266         else
267            pot1 = machine.root_device().ioport("TRACKX")->read();
268         break;
269
270      case 0x03:
271         if (which && (machine.root_device().ioport("JOY1_2B")->read() & 0x20))  /* Joy1 Button 2 */
272            pot1 = 0x00;
273         break;
274
275      case 0x04:
276         if (which)
277            pot2 = machine.root_device().ioport("LIGHTY")->read();
278         else
279            pot1 = machine.root_device().ioport("LIGHTX")->read();
280         break;
281
282      case 0x06:
283         if (which && (machine.root_device().ioport("OTHER")->read() & 0x04))    /* Lightpen Signal */
284            pot2 = 0x00;
285         break;
286
287      case 0x00:
288      case 0x07:
289         break;
290
291      default:
292         logerror("Invalid Controller Setting %d\n", controller1);
293         break;
294   }
295
296   switch (controller2)
297   {
298      case 0x10:
299         if (which)
300            pot4 = machine.root_device().ioport("PADDLE4")->read();
301         else
302            pot3 = machine.root_device().ioport("PADDLE3")->read();
303         break;
304
305      case 0x20:
306         if (which)
307            pot4 = machine.root_device().ioport("TRACKY")->read();
308         else
309            pot3 = machine.root_device().ioport("TRACKX")->read();
310         break;
311
312      case 0x30:
313         if (which && (machine.root_device().ioport("JOY2_2B")->read() & 0x20))  /* Joy2 Button 2 */
314            pot4 = 0x00;
315         break;
316
317      case 0x40:
318         if (which)
319            pot4 = machine.root_device().ioport("LIGHTY")->read();
320         else
321            pot3 = machine.root_device().ioport("LIGHTX")->read();
322         break;
323
324      case 0x60:
325         if (which && (machine.root_device().ioport("OTHER")->read() & 0x04))    /* Lightpen Signal */
326            pot4 = 0x00;
327         break;
328
329      case 0x00:
330      case 0x70:
331         break;
332
333      default:
334         logerror("Invalid Controller Setting %d\n", controller1);
335         break;
336   }
337
338   if (machine.root_device().ioport("CTRLSEL")->read() & 0x80)     /* Swap */
339   {
340      temp = pot1; pot1 = pot3; pot3 = temp;
341      temp = pot2; pot2 = pot4; pot4 = temp;
342   }
343
344   switch (cia0porta & 0xc0)
345   {
346      case 0x40:
347         return which ? pot2 : pot1;
348
349      case 0x80:
350         return which ? pot4 : pot3;
351
352      case 0xc0:
353         return which ? pot2 : pot1;
354
355      default:
356         return 0;
357   }
358}
359
360READ8_HANDLER( c64_colorram_read )
361{
362   legacy_c64_state *state = space.machine().driver_data<legacy_c64_state>();
363   return state->m_colorram[offset & 0x3ff];
364}
365
366WRITE8_HANDLER( c64_colorram_write )
367{
368   legacy_c64_state *state = space.machine().driver_data<legacy_c64_state>();
369   state->m_colorram[offset & 0x3ff] = data | 0xf0;
370}
371
372/***********************************************
373
374    C64 Cartridges
375
376***********************************************/
377
378/* Info based on http://ist.uwaterloo.ca/~schepers/formats/CRT.TXT      */
379/* Please refer to the webpage for the latest version and for a very
380   complete listing of various cart types and their bankswitch tricks   */
381/*
382  Cartridge files were introduced in the CCS64  emulator,  written  by  Per
383Hakan Sundell, and use the ".CRT" file extension. This format  was  created
384to handle the various ROM cartridges that exist, such as Action Replay, the
385Power cartridge, and the Final Cartridge.
386
387  Normal game cartridges can load  into  several  different  memory  ranges
388($8000-9FFF,  $A000-BFFF  or  $E000-FFFF).  Newer   utility   and   freezer
389cartridges were less intrusive, hiding themselves until  called  upon,  and
390still others used bank-switching techniques to allow much larger ROM's than
391normal. Because of these "stealthing" and bank-switching methods, a special
392cartridge format  was  necessary,  to  let  the  emulator  know  where  the
393cartridge should reside, the control line  states  to  enable  it  and  any
394special hardware features it uses.
395
396(...)
397
398[ A .CRT file consists of
399
400    $0000-0040 :    Header of the whole .crt files
401    $0040-EOF :     Blocks of data
402
403  Each block of data, called 'CHIP', can be of variable size. The first
4040x10 bytes of each CHIP block is the block header, and it contains various
405informations on the block itself, as its size (both with and without the
406header), the loading address and an index to identify which memory bank
407the data must be loaded to.  FP ]
408
409.CRT header description
410-----------------------
411
412 Bytes: $0000-000F - 16-byte cartridge signature  "C64  CARTRIDGE"  (padded
413                     with space characters)
414         0010-0013 - File header length  ($00000040,  in  high/low  format,
415                     calculated from offset $0000). The default  (also  the
416                     minimum) value is $40.  Some  cartridges  exist  which
417                     show a value of $00000020 which is wrong.
418         0014-0015 - Cartridge version (high/low, presently 01.00)
419         0016-0017 - Cartridge hardware type ($0000, high/low)
420              0018 - Cartridge port EXROM line status
421                      0 - inactive
422                      1 - active
423              0019 - Cartridge port GAME line status
424                      0 - inactive
425                      1 - active
426         001A-001F - Reserved for future use
427         0020-003F - 32-byte cartridge  name  "CCSMON"  (uppercase,  padded
428                     with null characters)
429         0040-xxxx - Cartridge contents (called CHIP PACKETS, as there  can
430                     be more than one  per  CRT  file).  See  below  for  a
431                     breakdown of the CHIP format.
432
433CHIP content description
434------------------------
435
436[ Addresses shifted back to $0000.  FP ]
437
438 Bytes: $0000-0003 - Contained ROM signature "CHIP" (note there can be more
439                     than one image in a .CRT file)
440         0004-0007 - Total packet length (ROM  image  size  and
441                     header combined) (high/low format)
442         0008-0009 - Chip type
443                      0 - ROM
444                      1 - RAM, no ROM data
445                      2 - Flash ROM
446         000A-000B - Bank number
447         000C-000D - Starting load address (high/low format)
448         000E-000F - ROM image size in bytes  (high/low  format,  typically
449                     $2000 or $4000)
450         0010-xxxx - ROM data
451
452
453*/
454
455
456/* Hardware Types for C64 carts */
457enum {
458   GENERIC_CRT = 0,        /* 00 - Normal cartridge                    */
459   ACTION_REPLAY,      /* 01 - Action Replay                       */
460   KCS_PC,         /* 02 - KCS Power Cartridge                 */
461   FINAL_CART_III,     /* 03 - Final Cartridge III                 */
462   SIMONS_BASIC,       /* 04 - Simons Basic                        */
463   OCEAN_1,            /* 05 - Ocean type 1 (1)                    */
464   EXPERT,         /* 06 - Expert Cartridge                    */
465   FUN_PLAY,           /* 07 - Fun Play, Power Play                */
466   SUPER_GAMES,        /* 08 - Super Games                         */
467   ATOMIC_POWER,       /* 09 - Atomic Power                        */
468   EPYX_FASTLOAD,      /* 10 - Epyx Fastload                       */
469   WESTERMANN,         /* 11 - Westermann Learning                 */
470   REX,                /* 12 - Rex Utility                         */
471   FINAL_CART_I,       /* 13 - Final Cartridge I                   */
472   MAGIC_FORMEL,       /* 14 - Magic Formel                        */
473   C64GS,          /* 15 - C64 Game System, System 3           */
474   WARPSPEED,          /* 16 - WarpSpeed                           */
475   DINAMIC,            /* 17 - Dinamic (2)                         */
476   ZAXXON,         /* 18 - Zaxxon, Super Zaxxon (SEGA)         */
477   DOMARK,         /* 19 - Magic Desk, Domark, HES Australia   */
478   SUPER_SNAP_5,       /* 20 - Super Snapshot 5                    */
479   COMAL_80,           /* 21 - Comal-80                            */
480   STRUCT_BASIC,       /* 22 - Structured Basic                    */
481   ROSS,               /* 23 - Ross                                */
482   DELA_EP64,          /* 24 - Dela EP64                           */
483   DELA_EP7X8,         /* 25 - Dela EP7x8                          */
484   DELA_EP256,         /* 26 - Dela EP256                          */
485   REX_EP256,          /* 27 - Rex EP256                           */
486   MIKRO_ASSMBLR,      /* 28 - Mikro Assembler                     */
487   REAL_FC_I,          /* 29 - (3)                                 */
488   ACTION_REPLAY_4,        /* 30 - Action Replay 4                     */
489   STARDOS,            /* 31 - StarDOS                             */
490   /*
491   (1) Ocean type 1 includes Navy Seals, Robocop 2 & 3,  Shadow  of
492   the Beast, Toki, Terminator 2 and more. Both 256 and 128 Kb images.
493   (2) Dinamic includes Narco Police and more.
494   (3) Type 29 is reserved for the real Final Cartridge I, the one
495   above (Type 13) will become Final Cartridge II.                 */
496   /****************************************
497   Vice also defines the following types:
498   #define CARTRIDGE_ACTION_REPLAY3    -29
499   #define CARTRIDGE_IEEE488           -11
500   #define CARTRIDGE_IDE64             -7
501   #define CARTRIDGE_RETRO_REPLAY      -5
502   #define CARTRIDGE_SUPER_SNAPSHOT    -4
503
504   Can we support these as well?
505   *****************************************/
506};
507
508static DEVICE_IMAGE_UNLOAD( c64_cart )
509{
510   legacy_c64_state *state = image.device().machine().driver_data<legacy_c64_state>();
511   int i;
512
513   for (i = 0; i < C64_MAX_ROMBANK; i++)
514   {
515      state->m_cart.bank[i].size = 0;
516      state->m_cart.bank[i].addr = 0;
517      state->m_cart.bank[i].index = 0;
518      state->m_cart.bank[i].start = 0;
519   }
520}
521
522
523static DEVICE_START( c64_cart )
524{
525   legacy_c64_state *state = device->machine().driver_data<legacy_c64_state>();
526   /* In the first slot we can load a .crt file. In this case we want
527       to use game & exrom values from the header, not the default ones. */
528   state->m_cart.game = -1;
529   state->m_cart.exrom = -1;
530   state->m_cart.mapper = GENERIC_CRT;
531   state->m_cart.n_banks = 0;
532}
533
534static int c64_crt_load( device_image_interface &image )
535{
536   legacy_c64_state *state = image.device().machine().driver_data<legacy_c64_state>();
537   int size = image.length(), test, i = 0, ii;
538   int _80_loaded = 0, _90_loaded = 0, a0_loaded = 0, b0_loaded = 0, e0_loaded = 0, f0_loaded = 0;
539   const char *filetype = image.filetype();
540   int address = 0, new_start = 0;
541   // int lbank_end_addr = 0, hbank_end_addr = 0;
542   UINT8 *cart_cpy = state->memregion("user1")->base();
543
544   /* We support .crt files */
545   if (!mame_stricmp(filetype, "crt"))
546   {
547      int j;
548      unsigned short c64_cart_type;
549
550      if (i >= C64_MAX_ROMBANK)
551         return IMAGE_INIT_FAIL;
552
553      /* Start to parse the .crt header */
554      /* 0x16-0x17 is Hardware type */
555      image.fseek(0x16, SEEK_SET);
556      image.fread(&c64_cart_type, 2);
557      state->m_cart.mapper = BIG_ENDIANIZE_INT16(c64_cart_type);
558
559      /* If it is unsupported cart type, warn the user */
560      switch (state->m_cart.mapper)
561      {
562         case SIMONS_BASIC:  /* Type #  4 */
563         case OCEAN_1:       /* Type #  5 */
564         case FUN_PLAY:      /* Type #  7 */
565         case SUPER_GAMES:       /* Type #  8 */
566         case EPYX_FASTLOAD: /* Type # 10 */
567         case REX:           /* Type # 12 */
568         case C64GS:         /* Type # 15 */
569         case DINAMIC:       /* Type # 17 */
570         case ZAXXON:        /* Type # 18 */
571         case DOMARK:        /* Type # 19 */
572         case COMAL_80:      /* Type # 21 */
573         case GENERIC_CRT:       /* Type #  0 */
574            printf("Currently supported cart type (Type %d)\n", state->m_cart.mapper);
575            break;
576
577         default:
578         case ACTION_REPLAY: /* Type #  1 */
579         case KCS_PC:        /* Type #  2 */
580         case FINAL_CART_III:    /* Type #  3 */
581         case EXPERT:        /* Type #  6 */
582         case ATOMIC_POWER:  /* Type #  9 */
583         case WESTERMANN:        /* Type # 11 */
584         case FINAL_CART_I:  /* Type # 13 */
585         case MAGIC_FORMEL:  /* Type # 14 */
586         case SUPER_SNAP_5:  /* Type # 20 */
587            printf("Currently unsupported cart type (Type %d)\n", state->m_cart.mapper);
588            break;
589      }
590
591      /* 0x18 is EXROM */
592      image.fseek(0x18, SEEK_SET);
593      image.fread(&state->m_cart.exrom, 1);
594
595      /* 0x19 is GAME */
596      image.fread(&state->m_cart.game, 1);
597
598      /* We can pass to the data: it starts from 0x40 */
599      image.fseek(0x40, SEEK_SET);
600      j = 0x40;
601
602      logerror("Loading cart %s size:%.4x\n", image.filename(), size);
603      logerror("Header info: EXROM %d, GAME %d, Cart Type %d \n", state->m_cart.exrom, state->m_cart.game, c64_cart_type);
604
605
606      /* Data in a .crt image are organized in blocks called 'CHIP':
607         each 'CHIP' consists of a 0x10 header, which contains the
608         actual size of the block, the loading address and info on
609         the bankswitch, followed by the actual data                  */
610      while (j < size)
611      {
612         unsigned short chip_size, chip_bank_index, chip_data_size;
613         unsigned char buffer[10];
614
615         /* Start to parse the CHIP header */
616         /* First 4 bytes are the string 'CHIP' */
617         image.fread(buffer, 6);
618
619         /* 0x06-0x07 is the size of the CHIP block (header + data) */
620         image.fread(&chip_size, 2);
621         chip_size = BIG_ENDIANIZE_INT16(chip_size);
622
623         /* 0x08-0x09 chip type (ROM, RAM + no ROM, Flash ROM) */
624         image.fread(buffer + 6, 2);
625
626         /* 0x0a-0x0b is the bank number of the CHIP block */
627         image.fread(&chip_bank_index, 2);
628         chip_bank_index = BIG_ENDIANIZE_INT16(chip_bank_index);
629
630         /* 0x0c-0x0d is the loading address of the CHIP block */
631         image.fread(&address, 2);
632         address = BIG_ENDIANIZE_INT16(address);
633
634         /* 0x0e-0x0f is the data size of the CHIP block (without header) */
635         image.fread(&chip_data_size, 2);
636         chip_data_size = BIG_ENDIANIZE_INT16(chip_data_size);
637
638         /* Print out the CHIP header! */
639         logerror("%.4s %.2x %.2x %.4x %.2x %.2x %.4x %.4x:%.4x\n",
640            buffer, buffer[4], buffer[5], chip_size,
641            buffer[6], buffer[7], chip_bank_index,
642            address, chip_data_size);
643         logerror("Loading CHIP data at %.4x size:%.4x\n", address, chip_data_size);
644
645         /* Store data, address & size of the CHIP block */
646         state->m_cart.bank[i].addr = address;
647         state->m_cart.bank[i].index = chip_bank_index;
648         state->m_cart.bank[i].size = chip_data_size;
649         state->m_cart.bank[i].start = new_start;
650
651         test = image.fread(cart_cpy + new_start, state->m_cart.bank[i].size);
652         new_start += state->m_cart.bank[i].size;
653
654         /* Does CHIP contain any data? */
655         if (test != state->m_cart.bank[i].size)
656            return IMAGE_INIT_FAIL;
657
658         /* Advance to the next CHIP block */
659         i++;
660         j += chip_size;
661      }
662   }
663   else /* We also support .80 files for c64 & .e0/.f0 for max */
664   {
665      /* Assign loading address according to extension */
666      if (!mame_stricmp(filetype, "80"))
667         address = 0x8000;
668
669      if (!mame_stricmp(filetype, "e0"))
670         address = 0xe000;
671
672      if (!mame_stricmp(filetype, "f0"))
673         address = 0xf000;
674
675      logerror("loading %s rom at %.4x size:%.4x\n", image.filename(), address, size);
676
677      /* Store data, address & size */
678      state->m_cart.bank[0].addr = address;
679      state->m_cart.bank[0].size = size;
680      state->m_cart.bank[0].start = new_start;
681
682      test = image.fread(cart_cpy + new_start, state->m_cart.bank[0].size);
683      new_start += state->m_cart.bank[0].size;
684
685      /* Does cart contain any data? */
686      if (test != state->m_cart.bank[0].size)
687         return IMAGE_INIT_FAIL;
688   }
689
690   state->m_cart.n_banks = i; // this is also needed so that we only set mappers if a cart is present!
691
692   /* If we load a .crt file, use EXROM & GAME from the header! */
693   if ((state->m_cart.exrom != -1) && (state->m_cart.game != -1))
694   {
695      state->m_exrom = state->m_cart.exrom;
696      state->m_game  = state->m_cart.game;
697   }
698
699   /* Finally load the cart */
700   state->m_roml = state->m_c64_roml;
701   state->m_romh = state->m_c64_romh;
702
703   memset(state->m_roml, 0, 0x2000);
704   memset(state->m_romh, 0, 0x2000);
705
706   switch (state->m_cart.mapper)
707   {
708   default:
709      if (!state->m_game && state->m_exrom && (state->m_cart.n_banks == 1))
710      {
711         memcpy(state->m_romh, cart_cpy, 0x2000);
712      }
713      else
714      {
715         // we first attempt to load the first 'CHIPs' with address 0x8000-0xb000 and 0xe000-0xf000, otherwise we load the first (or first two) 'CHIPs' of the image
716         for (ii = 0; ii < state->m_cart.n_banks; ii++)
717         {
718            if (state->m_cart.bank[ii].addr == 0x8000 && !_80_loaded)
719            {
720               memcpy(state->m_roml, cart_cpy + state->m_cart.bank[ii].start, state->m_cart.bank[ii].size);
721               _80_loaded = 1;
722               if (state->m_cart.bank[ii].size > 0x1000)
723                  _90_loaded = 1;
724               if (state->m_cart.bank[ii].size > 0x2000)
725                  a0_loaded = 1;
726               if (state->m_cart.bank[ii].size > 0x3000)
727                  b0_loaded = 1;
728//                  printf("addr 0x8000: 80 %d, 90 %d, a0 %d, b0 %d\n", _80_loaded, _90_loaded, a0_loaded, b0_loaded);
729            }
730
731            if (state->m_cart.bank[ii].addr == 0x9000 && !_90_loaded)
732            {
733               memcpy(state->m_roml + 0x1000, cart_cpy + state->m_cart.bank[ii].start, state->m_cart.bank[ii].size);
734               _90_loaded = 1;
735               if (state->m_cart.bank[ii].size > 0x1000)
736                  a0_loaded = 1;
737               if (state->m_cart.bank[ii].size > 0x2000)
738                  b0_loaded = 1;
739//                  printf("addr 0x9000: 80 %d, 90 %d, a0 %d, b0 %d\n", _80_loaded, _90_loaded, a0_loaded, b0_loaded);
740            }
741
742            if (state->m_cart.bank[ii].addr == 0xa000 && !a0_loaded)
743            {
744               memcpy(state->m_roml + 0x2000, cart_cpy + state->m_cart.bank[ii].start, state->m_cart.bank[ii].size);
745               a0_loaded = 1;
746               if (state->m_cart.bank[ii].size > 0x1000)
747                  b0_loaded = 1;
748//                  printf("addr 0xa000: 80 %d, 90 %d, a0 %d, b0 %d\n", _80_loaded, _90_loaded, a0_loaded, b0_loaded);
749            }
750
751            if (state->m_cart.bank[ii].addr == 0xb000 && !b0_loaded)
752            {
753               memcpy(state->m_roml + 0x3000, cart_cpy + state->m_cart.bank[ii].start, state->m_cart.bank[ii].size);
754               b0_loaded = 1;
755//                  printf("addr 0xb000: 80 %d, 90 %d, a0 %d, b0 %d\n", _80_loaded, _90_loaded, a0_loaded, b0_loaded);
756            }
757
758            if (state->m_cart.bank[ii].addr == 0xe000 && !e0_loaded)
759            {
760               memcpy(state->m_romh, cart_cpy + state->m_cart.bank[ii].start, state->m_cart.bank[ii].size);
761               e0_loaded = 1;
762               if (state->m_cart.bank[ii].size > 0x1000)
763                  f0_loaded = 1;
764//                  printf("addr 0xe000: e0 %d, f0 %d\n", e0_loaded, f0_loaded);
765            }
766
767            if (state->m_cart.bank[ii].addr == 0xf000 && !f0_loaded)
768            {
769               memcpy(state->m_romh + 0x1000, cart_cpy + state->m_cart.bank[ii].start, state->m_cart.bank[ii].size);
770               f0_loaded = 1;
771//                  printf("addr 0xe000: e0 %d, f0 %d\n", e0_loaded, f0_loaded);
772            }
773         }
774      }
775   }
776
777   return IMAGE_INIT_PASS;
778}
779
780/***************************************************************************
781    SOFTWARE LIST CARTRIDGE HANDLING
782***************************************************************************/
783
784#define install_write_handler(_start, _end, _handler) \
785   image.device().machine().firstcpu->space(AS_PROGRAM).install_legacy_write_handler(_start, _end, FUNC(_handler));
786
787#define install_io1_handler(_handler) \
788   image.device().machine().firstcpu->space(AS_PROGRAM).install_legacy_write_handler(0xde00, 0xde00, 0, 0xff, FUNC(_handler));
789
790#define install_io2_handler(_handler) \
791   image.device().machine().firstcpu->space(AS_PROGRAM).install_legacy_write_handler(0xdf00, 0xdf00, 0, 0xff, FUNC(_handler));
792
793#define allocate_cartridge_timer(_period, _func) \
794   legacy_c64_state *state = image.device().machine().driver_data<legacy_c64_state>(); \
795   state->m_cartridge_timer = image.device().machine().scheduler().timer_alloc(FUNC(_func)); \
796   state->m_cartridge_timer->adjust(_period, 0);
797
798#define set_game_line(_machine, _state) \
799   _machine.driver_data<legacy_c64_state>()->m_game = _state; \
800   c64_bankswitch(_machine, 0);
801
802INLINE void load_cartridge_region(device_image_interface &image, const char *name, offs_t offset, size_t size)
803{
804   UINT8 *cart = image.device().machine().root_device().memregion("user1")->base();
805   UINT8 *rom = image.get_software_region(name);
806   memcpy(cart + offset, rom, size);
807}
808
809INLINE void map_cartridge_roml(running_machine &machine, offs_t offset)
810{
811   legacy_c64_state *state = machine.driver_data<legacy_c64_state>();
812   UINT8 *cart = state->memregion("user1")->base();
813   memcpy(state->m_roml, cart + offset, 0x2000);
814}
815
816INLINE void map_cartridge_romh(running_machine &machine, offs_t offset)
817{
818   legacy_c64_state *state = machine.driver_data<legacy_c64_state>();
819   UINT8 *cart = state->memregion("user1")->base();
820   memcpy(state->m_romh, cart + offset, 0x2000);
821}
822
823static void load_standard_c64_cartridge(device_image_interface &image)
824{
825   legacy_c64_state *state = image.device().machine().driver_data<legacy_c64_state>();
826   UINT32 size;
827
828   // is there anything to load at 0x8000?
829   size = image.get_software_region_length("roml");
830
831   if (size)
832   {
833      memcpy(state->m_roml, image.get_software_region("roml"), MIN(0x2000, size));
834
835      if (size == 0x4000)
836      {
837         // continue loading to ROMH region
838         memcpy(state->m_romh, image.get_software_region("roml") + 0x2000, 0x2000);
839      }
840   }
841
842   // is there anything to load at 0xa000?
843   size = image.get_software_region_length("romh");
844   if (size)
845      memcpy(state->m_romh, image.get_software_region("romh"), size);
846}
847
848static TIMER_CALLBACK( vizawrite_timer )
849{
850   map_cartridge_roml(machine, 0x2000);
851   set_game_line(machine, 1);
852}
853
854static void load_vizawrite_cartridge(device_image_interface &image)
855{
856   #define VW64_DECRYPT_ADDRESS(_offset) \
857      BITSWAP16(_offset,15,14,13,12,7,8,6,9,5,11,4,3,2,10,1,0)
858
859   #define VW64_DECRYPT_DATA(_data) \
860      BITSWAP8(_data,7,6,0,5,1,4,2,3)
861
862   UINT8 *roml = image.get_software_region("roml");
863   UINT8 *romh = image.get_software_region("romh");
864   UINT8 *decrypted = image.device().machine().root_device().memregion("user1")->base();
865
866   // decrypt ROMs
867   for (offs_t offset = 0; offset < 0x2000; offset++)
868   {
869      offs_t address = VW64_DECRYPT_ADDRESS(offset);
870      decrypted[address] = VW64_DECRYPT_DATA(roml[offset]);
871      decrypted[address + 0x2000] = VW64_DECRYPT_DATA(roml[offset + 0x2000]);
872      decrypted[address + 0x4000] = VW64_DECRYPT_DATA(romh[offset]);
873   }
874
875   // map cartridge ROMs
876   map_cartridge_roml(image.device().machine(), 0x0000);
877   map_cartridge_romh(image.device().machine(), 0x4000);
878
879   // allocate GAME changing timer
880   allocate_cartridge_timer(attotime::from_msec(1184), vizawrite_timer);
881}
882
883static WRITE8_HANDLER( hugo_bank_w )
884{
885   /*
886
887       bit     description
888
889       0
890       1
891       2
892       3
893       4       A14
894       5       A15
895       6       A16
896       7       A13
897
898   */
899
900   int bank = ((data >> 3) & 0x0e) | BIT(data, 7);
901
902   map_cartridge_roml(space.machine(), bank * 0x2000);
903}
904
905static void load_hugo_cartridge(device_image_interface &image)
906{
907   #define HUGO_DECRYPT_ADDRESS(_offset) \
908      BITSWAP16(_offset,15,14,13,12,7,6,5,4,3,2,1,0,8,9,11,10)
909
910   #define HUGO_DECRYPT_DATA(_data) \
911      BITSWAP8(_data,7,6,5,4,0,1,2,3)
912
913   UINT8 *roml = image.get_software_region("roml");
914   UINT8 *decrypted = image.device().machine().root_device().memregion("user1")->base();
915
916   // decrypt ROMs
917   for (offs_t offset = 0; offset < 0x20000; offset++)
918   {
919      offs_t address = (offset & 0x10000) | HUGO_DECRYPT_ADDRESS(offset);
920      decrypted[address] = HUGO_DECRYPT_DATA(roml[offset]);
921   }
922
923   // map cartridge ROMs
924   map_cartridge_roml(image.device().machine(), 0x0000);
925
926   // install bankswitch handler
927   install_io1_handler(hugo_bank_w);
928}
929
930static WRITE8_HANDLER( easy_calc_result_bank_w )
931{
932   map_cartridge_romh(space.machine(), 0x2000 + (!offset * 0x2000));
933}
934
935static void load_easy_calc_result_cartridge(device_image_interface &image)
936{
937   load_cartridge_region(image, "roml", 0x0000, 0x2000);
938   load_cartridge_region(image, "romh", 0x2000, 0x4000);
939
940   map_cartridge_roml(image.device().machine(), 0x0000);
941   map_cartridge_romh(image.device().machine(), 0x2000);
942
943   install_write_handler(0xde00, 0xde01, easy_calc_result_bank_w);
944}
945
946static WRITE8_HANDLER( pagefox_bank_w )
947{
948   /*
949
950       Die 96KB des Moduls belegen in 6 16K-Banken den Modulbereich von $8000- $c000.
951       Die Umschaltung erfolgt mit einem Register in $DE80 (-$DEFF, nicht voll decodiert),
952       welches nur beschrieben und nicht gelesen werden kann. Durch Schreiben der Werte
953       $08 oder $0A selektiert man eine der beiden RAM-Banke, $FF deselektiert das Modul.
954
955       Zusatzlich muss Adresse 1 entsprechend belegt werden :$37 fur Lesezugriffe auf das
956       Modul, $35 oder $34 fur Lesezugriffe auf das Ram des C64. Schreibzugriffe lenkt
957       der C64 grundsatzlich ins eigene RAM, weshalb zum Beschreiben des Modulrams ein
958       Trick notwendig ist: Man schaltet das Ram-Modul parallel zum C64-Ram, rettet vor
959       dem Schreiben den C64-Ram-Inhalt und stellt ihn nachher wieder her...
960
961       Ldy#0
962       Lda#$35
963       Sta 1
964       Loop Lda (Ptr),y
965       Pha
966       Lda#$08
967       Sta $DE80
968       Lda (Quell),y
969       Sta (Ptr),y
970       Lda#$FF
971       Sta $DE80
972       Pla
973       Sta (Ptr),y
974       Iny
975       Bne Loop
976
977   */
978
979   legacy_c64_state *state = space.machine().driver_data<legacy_c64_state>();
980   UINT8 *cart = state->memregion("user1")->base();
981
982   if (data == 0xff)
983   {
984      // hide cartridge
985      state->m_game = 1;
986      state->m_exrom = 1;
987   }
988   else
989   {
990      if (state->m_game)
991      {
992         // enable cartridge
993         state->m_game = 0;
994         state->m_exrom = 0;
995      }
996
997      int bank = (data >> 1) & 0x07;
998      int ram = BIT(data, 3);
999      offs_t address = bank * 0x4000;
1000
1001      state->m_roml_writable = ram;
1002
1003      if (ram)
1004      {
1005         state->m_roml = cart + address;
1006      }
1007      else
1008      {
1009         state->m_roml = state->m_c64_roml;
1010
1011         map_cartridge_roml(space.machine(), address);
1012         map_cartridge_romh(space.machine(), address + 0x2000);
1013      }
1014   }
1015
1016   c64_bankswitch(space.machine(), 0);
1017}
1018
1019static void load_pagefox_cartridge(device_image_interface &image)
1020{
1021   load_cartridge_region(image, "rom", 0x0000, 0x10000);
1022
1023   map_cartridge_roml(image.device().machine(), 0x0000);
1024   map_cartridge_romh(image.device().machine(), 0x2000);
1025
1026   install_write_handler(0xde80, 0xdeff, pagefox_bank_w);
1027}
1028
1029static WRITE8_HANDLER( multiscreen_bank_w )
1030{
1031   legacy_c64_state *state = space.machine().driver_data<legacy_c64_state>();
1032   UINT8 *cart = state->memregion("user1")->base();
1033   int bank = data & 0x0f;
1034   offs_t address = bank * 0x4000;
1035
1036   if (bank == 0x0d)
1037   {
1038      // RAM
1039      state->m_roml = cart + address;
1040      state->m_roml_writable = 1;
1041
1042      map_cartridge_romh(space.machine(), 0x2000);
1043   }
1044   else
1045   {
1046      // ROM
1047      state->m_roml = state->m_c64_roml;
1048      state->m_roml_writable = 0;
1049
1050      map_cartridge_roml(space.machine(), address);
1051      map_cartridge_romh(space.machine(), address + 0x2000);
1052   }
1053
1054   c64_bankswitch(space.machine(), 0);
1055}
1056
1057static void load_multiscreen_cartridge(device_image_interface &image)
1058{
1059   load_cartridge_region(image, "roml", 0x0000, 0x4000);
1060   load_cartridge_region(image, "rom", 0x4000, 0x30000);
1061
1062   map_cartridge_roml(image.device().machine(), 0x0000);
1063   map_cartridge_romh(image.device().machine(), 0x2000);
1064
1065   install_write_handler(0xdfff, 0xdfff, multiscreen_bank_w);
1066}
1067
1068static WRITE8_HANDLER( simons_basic_bank_w )
1069{
1070   set_game_line(space.machine(), !BIT(data, 0));
1071}
1072
1073static void load_simons_basic_cartridge(device_image_interface &image)
1074{
1075   load_cartridge_region(image, "roml", 0x0000, 0x2000);
1076   load_cartridge_region(image, "romh", 0x2000, 0x2000);
1077
1078   map_cartridge_roml(image.device().machine(), 0x0000);
1079   map_cartridge_romh(image.device().machine(), 0x2000);
1080
1081   install_io1_handler(simons_basic_bank_w);
1082}
1083
1084static READ8_HANDLER( super_explode_r )
1085{
1086   legacy_c64_state *state = space.machine().driver_data<legacy_c64_state>();
1087
1088   return state->m_roml[0x1f00 | offset];
1089}
1090
1091static WRITE8_HANDLER( super_explode_bank_w )
1092{
1093   map_cartridge_roml(space.machine(), BIT(data, 7) * 0x2000);
1094}
1095
1096static void load_super_explode_cartridge(device_image_interface &image)
1097{
1098   load_cartridge_region(image, "roml", 0x0000, 0x4000);
1099
1100   map_cartridge_roml(image.device().machine(), 0x0000);
1101
1102   address_space &space = image.device().machine().firstcpu->space(AS_PROGRAM);
1103   space.install_legacy_read_handler(0xdf00, 0xdfff, FUNC(super_explode_r));
1104
1105   install_io2_handler(super_explode_bank_w);
1106}
1107
1108static void c64_software_list_cartridge_load(device_image_interface &image)
1109{
1110   legacy_c64_state *state = image.device().machine().driver_data<legacy_c64_state>();
1111
1112   // initialize ROML and ROMH pointers
1113   state->m_roml = state->m_c64_roml;
1114   state->m_romh = state->m_c64_romh;
1115
1116   // clear ROML and ROMH areas
1117   memset(state->m_roml, 0, 0x2000);
1118   memset(state->m_romh, 0, 0x2000);
1119
1120   // set GAME and EXROM
1121   state->m_game = atol(image.get_feature("game"));
1122   state->m_exrom = atol(image.get_feature("exrom"));
1123
1124   // determine cartridge type
1125   const char *cart_type = image.get_feature("cart_type");
1126
1127   if (cart_type == NULL)
1128   {
1129      load_standard_c64_cartridge(image);
1130   }
1131   else
1132   {
1133      if (!strcmp(cart_type, "vizawrite"))
1134         load_vizawrite_cartridge(image);
1135
1136      else if (!strcmp(cart_type, "hugo"))
1137         load_hugo_cartridge(image);
1138
1139      else if (!strcmp(cart_type, "easy_calc_result"))
1140         load_easy_calc_result_cartridge(image);
1141
1142      else if (!strcmp(cart_type, "pagefox"))
1143         load_pagefox_cartridge(image);
1144
1145      else if (!strcmp(cart_type, "multiscreen"))
1146         /*
1147
1148             TODO: crashes on protection check after cartridge RAM test
1149
1150             805A: lda  $01
1151             805C: and  #$FE
1152             805E: sta  $01
1153             8060: m6502_brk#$00 <-- BOOM!
1154
1155         */
1156         load_multiscreen_cartridge(image);
1157
1158      else if (!strcmp(cart_type, "simons_basic"))
1159         load_simons_basic_cartridge(image);
1160
1161      else if (!strcmp(cart_type, "super_explode"))
1162         load_super_explode_cartridge(image);
1163
1164      else
1165         load_standard_c64_cartridge(image);
1166   }
1167}
1168
1169static DEVICE_IMAGE_LOAD( c64_cart )
1170{
1171   int result = IMAGE_INIT_PASS;
1172
1173   if (image.software_entry() != NULL)
1174   {
1175      c64_software_list_cartridge_load(image);
1176   }
1177   else
1178      result = c64_crt_load(image);
1179
1180   return result;
1181}
1182MACHINE_CONFIG_FRAGMENT( c64_cartslot )
1183   MCFG_CARTSLOT_ADD("cart1")
1184   MCFG_CARTSLOT_EXTENSION_LIST("crt,80")
1185   MCFG_CARTSLOT_NOT_MANDATORY
1186   MCFG_CARTSLOT_INTERFACE("c64_cart")
1187   MCFG_CARTSLOT_START(c64_cart)
1188   MCFG_CARTSLOT_LOAD(c64_cart)
1189   MCFG_CARTSLOT_UNLOAD(c64_cart)
1190
1191   MCFG_CARTSLOT_ADD("cart2")
1192   MCFG_CARTSLOT_EXTENSION_LIST("crt,80")
1193   MCFG_CARTSLOT_NOT_MANDATORY
1194   MCFG_CARTSLOT_START(c64_cart)
1195   MCFG_CARTSLOT_LOAD(c64_cart)
1196   MCFG_CARTSLOT_UNLOAD(c64_cart)
1197
1198   MCFG_SOFTWARE_LIST_ADD("cart_list_c64", "c64_cart")
1199MACHINE_CONFIG_END
Property changes on: trunk/src/mess/machine/c64_legacy.c
Added: svn:mime-type
   + text/plain
Added: svn:eol-style
   + native

Previous 199869 Revisions Next


© 1997-2024 The MAME Team