Previous 199869 Revisions Next

r21774 Saturday 9th March, 2013 at 20:06:50 UTC by David Haywood
further stvprot.c reworking + logging
[src/mame/machine]stvprot.c

trunk/src/mame/machine/stvprot.c
r21773r21774
11/* ST-V protection stuff */
22
3/* todo:
4 figure out properly
5 clean up
6 fix remaining games
7 split them on a per-game basis
3/*
84
9 Known Protected ST-V Games
5 Known ST-V Games using this kind of protection
106
117 Astra Superstars (text layer gfx transfer)
128 Elandoree (gfx transfer of textures)
13 Final Fight Revenge (boot vectors etc.?)
14 Radiant Silvergun (game start protection ?)
9 Final Fight Revenge (boot vectors etc.)
10 Radiant Silvergun (game start protection)
1511 Steep Slope Sliders (gfx transfer of character portraits)
16 Decathlete (transfer of all gfx data)
17 Tecmo World Cup '98 (tecmo logo, player movement?)
12 Tecmo World Cup '98 (tecmo logo, player movement)
1813
14 I think this is an encryption device.  Decathlete is also protected, but uses a different device
15 see machine/decathlt.c for details of that one, unlike this that appears to perform decompression
16 operations.
1917
20 Is this just scrambled, or also compressed somehow?  I've not had much luck
21 locating the data some of the games want (for example decathlete)
2218
23 RSGun doesn't appear to make use of the data transfer features..
24
25 The protection addresses are in the A-Bus area, this should map to the cartridge slot,
26 is there something special in these game cartridges?
27
2819 Astra Superstars data were extracted from Saturn version of the game. It is not known if
2920 protection device has data stored inside, or they are read from roms (using decryption/decompression)
3021
r21773r21774
112103static UINT32 internal_counter;
113104static UINT8 char_offset; //helper to jump the decoding of the NULL chars.
114105
106static UINT32 (*prot_readback)(address_space&,int,UINT32);
115107
116
117108/************************
118109*
119110* Tecmo World Cup '98
r21773r21774
136127// TODO: encrypted / compressed data.
137128// Both points to a section that has a string ("TECMO" / "TITLE")
138129
139static UINT32 twcup_prot_data[8] =
140{
141   0x23232323, 0x23232323, 0x4c4c4c4c, 0x4c156301
142};
143130
144static READ32_HANDLER( twcup98_prot_r )
145{
146   UINT32 *ROM = (UINT32 *)space.machine().root_device().memregion("abus")->base();
147
148   if(m_abus_protenable & 0x00010000)
149   {
150      if(offset == 3)
151      {
152         UINT32 res;
153         logerror("A-Bus control protection read at %06x with data = %08x\n",space.device().safe_pc(),m_abus_protkey);
154         #ifdef MAME_DEBUG
155         popmessage("Prot read at %06x with data = %08x",space.device().safe_pc(),m_abus_protkey);
156         #endif
157         switch(m_abus_protkey >> 16)
158         {
159            case 0x1212:
160               if(ctrl_index & 2)
161               {
162                  res = (ROM[ctrl_index / 4] & 0xffff) << 16;
163                  res |= (ROM[(ctrl_index+4) / 4] & 0xffff0000) >> 16;
164               }
165               else
166               {
167                  res = ROM[ctrl_index / 4] & 0xffff0000;
168                  res |= ROM[ctrl_index / 4] & 0xffff;
169               }
170
171               if(ctrl_index >= 0xD215A4+0x100c && ctrl_index < 0xD215A4+0x100c+8*4)
172                  res = twcup_prot_data[(ctrl_index-(0xD215A4+0x100c))/4];
173
174               ctrl_index+=4;
175               return res;
176         }
177
178      }
179      return a_bus[offset];
180   }
181   else
182   {
183      if(a_bus[offset] != 0) return a_bus[offset];
184      else return ROM[(0x02fffff0/4)+offset];
185   }
186}
187
188
189
190/**************************
191*
192* Steep Slope Sliders
193*
194**************************/
195
196static READ32_HANDLER( sss_prot_r )
197{
198   UINT32 *ROM = (UINT32 *)space.machine().root_device().memregion("abus")->base();
199
200   if(m_abus_protenable & 0x00010000)//protection calculation is activated
201   {
202      if(offset == 3)
203      {
204         UINT32 res;
205
206         logerror("A-Bus control protection read at %06x with data = %08x\n",space.device().safe_pc(),m_abus_protkey);
207         #ifdef MAME_DEBUG
208         popmessage("Prot read at %06x with data = %08x",space.device().safe_pc(),m_abus_protkey);
209         #endif
210         int read_offset_hack = 0;
211         
212         /*
213            MAIN : 2c5b0000  DATA : 000000a6 014c0000
214            MAIN : 47f10000  DATA : 0f9800a6 014c1f30
215            MAIN : fcda0000  DATA : 1d4800a6 014c3a90
216            MAIN : b5e60000  DATA : 29e300a6 014c53c6
217            MAIN : 392c0000  DATA : 38e900a6 014c71d2
218            MAIN : 77c30000  DATA : 462500a6 014c8c4a
219            MAIN : 8a620000  DATA : 555c00a6 014caab8
220         */
221
222         // I have a feeling rather than the offsets being scrambled they were lazy
223         // and left unencrypted copies in the ROM... but this still needs verification
224         switch(m_abus_protkey>>16)
225         {
226            case 0x2c5b: read_offset_hack = 0x60054; break;
227            case 0x47f1: read_offset_hack = 0x56498; break;
228            case 0xfcda: read_offset_hack = 0x50b0c; break;
229            case 0xb5e6: read_offset_hack = 0x4af56; break;
230            case 0x392c: read_offset_hack = 0x45876; break;
231            case 0x77c3: read_offset_hack = 0x3fe02; break;
232            case 0x8a62: read_offset_hack = 0x3a784; break;
233         }
234
235         switch(m_abus_protkey>>16)
236         {
237            default:
238               if(ctrl_index & 2)
239               {
240                  res = (ROM[(ctrl_index-read_offset_hack) / 4] & 0xffff) << 16;
241                  res |= (ROM[((ctrl_index-read_offset_hack)+4) / 4] & 0xffff0000) >> 16;
242               }
243               else
244               {
245                  res = ROM[(ctrl_index-read_offset_hack) / 4] & 0xffff0000;
246                  res |= ROM[(ctrl_index-read_offset_hack) / 4] & 0xffff;
247               }
248               ctrl_index+=4;
249               return res;
250         }
251      }
252      return a_bus[offset];
253   }
254   else
255   {
256      if(a_bus[offset] != 0) return a_bus[offset];
257      else return ROM[(0x02fffff0/4)+offset];
258   }
259}
260
261
262
263
264/*************************************
265*
266* Radiant Silvergun
267*
268*************************************/
269
270static READ32_HANDLER( rsgun_prot_r )
271{
272   UINT32 *ROM = (UINT32 *)space.machine().root_device().memregion("abus")->base();
273
274   if(m_abus_protenable & 0x00010000)//protection calculation is activated
275   {
276      if(offset == 3)
277      {
278         logerror("A-Bus control protection read at %06x with data = %08x\n",space.device().safe_pc(),m_abus_protkey);
279         #ifdef MAME_DEBUG
280         popmessage("Prot read at %06x with data = %08x",space.device().safe_pc(),m_abus_protkey);
281         #endif
282         switch(m_abus_protkey)
283         {
284            case 0x77770000: {//rsgun
285               UINT32 val =
286                  ((ctrl_index & 0xff)<<24) |
287                  (((ctrl_index+1) & 0xff)<<16) |
288                  (((ctrl_index+2) & 0xff)<<8) |
289                  ((ctrl_index+3) & 0xff);
290               if(ctrl_index & 0x100)
291                  val &= 0x0f0f0f0f;
292               else
293                  val &= 0xf0f0f0f0;
294
295               ctrl_index += 4;
296               return val;
297            }
298         }
299      }
300      return a_bus[offset];
301   }
302   else
303   {
304      if(a_bus[offset] != 0) return a_bus[offset];
305      else return ROM[(0x02fffff0/4)+offset];
306   }
307}
308
309static WRITE32_HANDLER ( rsgun_prot_w )
310{
311   COMBINE_DATA(&a_bus[offset]);
312   logerror("A-Bus control protection write at %06x: [%02x] <- %08x\n",space.device().safe_pc(),offset,data);
313
314   if (offset == 0)
315   {
316      COMBINE_DATA(&m_abus_protenable);
317   }
318   else if(offset == 2)
319   {
320      COMBINE_DATA(&m_abus_prot_addr);
321   }
322   else if(offset == 3)
323   {
324      COMBINE_DATA(&m_abus_protkey);
325//      int a_bus_vector;
326
327//      a_bus_vector = m_abus_prot_addr >> 16;
328//      a_bus_vector|= (m_abus_prot_addr & 0xffff) << 16;
329//      a_bus_vector<<= 1;
330//      printf("MAIN : %08x  DATA : %08x %08x\n",m_abus_protkey,m_abus_prot_addr,a_bus_vector);
331      switch(m_abus_protkey)
332      {
333         case 0x77770000: ctrl_index = 0; break;
334      }
335   }
336   //popmessage("%04x %04x",data,offset/4);
337}
338
339
340
341
342131/*************************
343132*
344* Elandoree
345*
346*************************/
347
348static READ32_HANDLER( elandore_prot_r )
349{
350   UINT32 *ROM = (UINT32 *)space.machine().root_device().memregion("abus")->base();
351
352   if(m_abus_protenable & 0x00010000)//protection calculation is activated
353   {
354      if(offset == 3)
355      {
356         UINT32 res;
357         logerror("A-Bus control protection read at %06x with data = %08x\n",space.device().safe_pc(),m_abus_protkey);
358         #ifdef MAME_DEBUG
359         popmessage("Prot read at %06x with data = %08x",space.device().safe_pc(),m_abus_protkey);
360         #endif
361         switch(m_abus_protkey >> 16)
362         {
363            default:
364               if(ctrl_index & 2)
365               {
366                  res = (ROM[ctrl_index / 4] & 0xffff) << 16;
367                  res |= (ROM[(ctrl_index+4) / 4] & 0xffff0000) >> 16;
368               }
369               else
370               {
371                  res = ROM[ctrl_index / 4] & 0xffff0000;
372                  res |= ROM[ctrl_index / 4] & 0xffff;
373               }
374               ctrl_index+=4;
375               return res;
376         }
377      }
378      return a_bus[offset];
379   }
380   else
381   {
382      if(a_bus[offset] != 0) return a_bus[offset];
383      else return ROM[(0x02fffff0/4)+offset];
384   }
385}
386
387
388
389/*************************
390*
391133* Final Fight Revenge
392134*
393135*************************/
r21773r21774
65339500002203 00001cf4 _WHSRMAP.BIN;1 1999/11/9
654396*/
655397
656static READ32_HANDLER( ffreveng_prot_r )
398
399
400
401
402
403
404UINT32 rsgun_prot_read_callback( address_space &space, int protaddr, UINT32 key )
657405{
406   int tempctrl = protaddr - 0x0201000; // technically it doesn't seem to care, but...
407         
408   switch(key)
409   {
410      case 0x77770000:
411      {
412         UINT32 val =
413            ((tempctrl & 0xff)<<24) |
414            (((tempctrl+1) & 0xff)<<16) |
415            (((tempctrl+2) & 0xff)<<8) |
416            ((tempctrl+3) & 0xff);
417         if(tempctrl & 0x100)
418            val &= 0x0f0f0f0f;
419         else
420            val &= 0xf0f0f0f0;
421               
422         return val;
423      }
424   }
425
426   return 0;
427}
428
429UINT32 twcup98_prot_read_callback( address_space &space, int protaddr, UINT32 key )
430{
658431   UINT32 *ROM = (UINT32 *)space.machine().root_device().memregion("abus")->base();
432   UINT32 res = 0;
659433
660   if(m_abus_protenable & 0x00010000)//protection calculation is activated
434   UINT32 twcup_prot_data[8] =
661435   {
662      if(offset == 3)
663      {
664         #if 0
665         UINT32 res;
666         #endif
667         logerror("A-Bus control protection read at %06x with data = %08x\n",space.device().safe_pc(),m_abus_protkey);
668         switch(m_abus_protkey >> 16)
436      0x23232323, 0x23232323, 0x4c4c4c4c, 0x4c156301
437   };
438
439   switch(key >> 16)
440   {
441      case 0x1212:
442         if(protaddr & 2)
669443         {
670            case 0x10da://ffreveng, boot vectors at $6080000,test mode
671            case 0x10d7://ffreveng, boot vectors at $6080000,attract mode
672               #if 0
673               if(ctrl_index & 2)
674               {
675                  res = (ROM[ctrl_index / 4] & 0xffff) << 16;
676                  res |= (ROM[(ctrl_index+4) / 4] & 0xffff0000) >> 16;
677               }
678               else
679               {
680                  res = ROM[ctrl_index / 4] & 0xffff0000;
681                  res |= ROM[ctrl_index / 4] & 0xffff;
682               }
683               #endif
684               ctrl_index+=4;
685               return 0;
444            res = (ROM[protaddr / 4] & 0xffff) << 16;
445            res |= (ROM[(protaddr+4) / 4] & 0xffff0000) >> 16;
686446         }
687      }
688      return a_bus[offset];
447         else
448         {
449            res = ROM[protaddr / 4] & 0xffff0000;
450            res |= ROM[protaddr / 4] & 0xffff;
451         }
452
453         if(protaddr >= 0xD215A4+0x100c && protaddr < 0xD215A4+0x100c+8*4)
454            res = twcup_prot_data[(protaddr-(0xD215A4+0x100c))/4];
455
456         return res;
689457   }
690   else
458
459   return 0;
460}
461
462UINT32 sss_prot_read_callback( address_space &space, int protaddr, UINT32 key )
463{
464   UINT32 *ROM = (UINT32 *)space.machine().root_device().memregion("abus")->base();
465   int read_offset_hack = 0;
466   UINT32 res;
467
468   /*
469      MAIN : 2c5b0000  DATA : 000000a6 014c0000
470      MAIN : 47f10000  DATA : 0f9800a6 014c1f30
471      MAIN : fcda0000  DATA : 1d4800a6 014c3a90
472      MAIN : b5e60000  DATA : 29e300a6 014c53c6
473      MAIN : 392c0000  DATA : 38e900a6 014c71d2
474      MAIN : 77c30000  DATA : 462500a6 014c8c4a
475      MAIN : 8a620000  DATA : 555c00a6 014caab8
476   */
477
478   // I have a feeling rather than the offsets being scrambled they were lazy
479   // and left unencrypted copies in the ROM... but this still needs verification
480   switch(key>>16)
691481   {
692      if(a_bus[offset] != 0) return a_bus[offset];
693      else return ROM[(0x02fffff0/4)+offset];
482      case 0x2c5b: read_offset_hack = 0x60054; break;
483      case 0x47f1: read_offset_hack = 0x56498; break;
484      case 0xfcda: read_offset_hack = 0x50b0c; break;
485      case 0xb5e6: read_offset_hack = 0x4af56; break;
486      case 0x392c: read_offset_hack = 0x45876; break;
487      case 0x77c3: read_offset_hack = 0x3fe02; break;
488      case 0x8a62: read_offset_hack = 0x3a784; break;
694489   }
490
491   switch(key>>16)
492   {
493      default:
494         if(protaddr & 2)
495         {
496            res = (ROM[(protaddr-read_offset_hack) / 4] & 0xffff) << 16;
497            res |= (ROM[((protaddr-read_offset_hack)+4) / 4] & 0xffff0000) >> 16;
498         }
499         else
500         {
501            res = ROM[(protaddr-read_offset_hack) / 4] & 0xffff0000;
502            res |= ROM[(protaddr-read_offset_hack) / 4] & 0xffff;
503         }
504         return res;
505   }
506
507   return 0;
695508}
696509
510UINT32 astrass_prot_read_callback( address_space &space, int protaddr, UINT32 key )
511{
512   /* we're reading from a custom region where we've loaded the data from the Saturn version
513      NOT the rom address, so we're based at 0.  The real data likely exists at the given
514      address in encrypted form */
515   int read_offset_hack = 0x4ec260;
516   int useoffset = (protaddr-read_offset_hack);
517   UINT32 data = 0;
518   UINT32 *prot_data = (UINT32 *)space.machine().root_device().memregion("user2")->base();
519   int prot_size = space.machine().root_device().memregion("user2")->bytes();
697520
521   if (useoffset<prot_size)
522   {
523      data = prot_data[useoffset/4];
524      return data;
525   }
526   return 0x00;
527}
698528
699/************************
700*
701* Astra Super Stars
702*
703************************/
704529
705static READ32_HANDLER(astrass_prot_r)
530UINT32 elandore_prot_read_callback( address_space &space, int protaddr, UINT32 key )
706531{
707   if(m_abus_protenable & 0x00010000)
532   UINT32 *ROM = (UINT32 *)space.machine().root_device().memregion("abus")->base();
533   UINT32 res = 0;
534
535   switch(key >> 16)
708536   {
709      if(offset == 3)
710      {
537      default:
538         if(protaddr & 2)
539         {
540            res = (ROM[protaddr / 4] & 0xffff) << 16;
541            res |= (ROM[(protaddr+4) / 4] & 0xffff0000) >> 16;
542         }
543         else
544         {
545            res = ROM[protaddr / 4] & 0xffff0000;
546            res |= ROM[protaddr / 4] & 0xffff;
547         }
548         return res;
549   }
711550
712         /* we're reading from a custom region, NOT the rom address, so we're based at 0, the real data likely exists at this address */
713         int read_offset_hack = 0x4ec260;
551   return 0;
552}
714553
715         UINT32 data = 0;
716         UINT32 *prot_data = (UINT32 *)space.machine().root_device().memregion("user2")->base();
554UINT32 ffreveng_prot_read_callback( address_space &space, int protaddr, UINT32 key )
555{
556   //UINT32 res = 0;
717557
718         data = prot_data[(ctrl_index-read_offset_hack)];
719         ctrl_index++;
720
721         if ( (ctrl_index-read_offset_hack) >= space.machine().root_device().memregion("user2")->bytes()/4 )
558   switch(key >> 16)
559   {
560      case 0x10da://ffreveng, boot vectors at $6080000,test mode
561      case 0x10d7://ffreveng, boot vectors at $6080000,attract mode
562         #if 0
563         if(protaddr & 2)
722564         {
723            ctrl_index = -1;
565            res = (ROM[protaddr / 4] & 0xffff) << 16;
566            res |= (ROM[(protaddr+4) / 4] & 0xffff0000) >> 16;
724567         }
568         else
569         {
570            res = ROM[protaddr / 4] & 0xffff0000;
571            res |= ROM[protaddr / 4] & 0xffff;
572         }
573         #endif
574         return 0;
575   }
725576
726         return data;
577   return 0;
578}
579
580
581/*************************************
582*
583* Common Handlers
584*
585*************************************/
586
587static READ32_HANDLER( common_prot_r )
588{
589   UINT32 *ROM = (UINT32 *)space.machine().root_device().memregion("abus")->base();
590
591   if(m_abus_protenable & 0x00010000)//protection calculation is activated
592   {
593      if(offset == 3)
594      {
595         #ifdef MAME_DEBUG
596         popmessage("Prot read at %06x with data = %08x",space.device().safe_pc(),m_abus_protkey);
597         #endif
598         UINT32 realret = space.read_dword(0x2000000+ctrl_index);
599         UINT32 retdata = prot_readback(space, ctrl_index, m_abus_protkey);
600   
601         logerror("A-Bus control protection read at %06x with data = %08x Returning = %08x Would otherwise return = %08x\n",space.device().safe_pc(),m_abus_protkey, retdata, realret);
602
603         ctrl_index += 4;
604         return retdata;
605
727606      }
728     
607      return a_bus[offset];
729608   }
730   return a_bus[offset];
609   else
610   {
611      if(a_bus[offset] != 0) return a_bus[offset];
612      else return ROM[(0x02fffff0/4)+offset];
613   }
731614}
732615
733616
734617
618
735619static WRITE32_HANDLER ( common_prot_w )
736620{
737621   COMBINE_DATA(&a_bus[offset]);
r21773r21774
768652   }
769653}
770654
655void install_common_protection(running_machine &machine)
656{
657   machine.device("maincpu")->memory().space(AS_PROGRAM).install_legacy_readwrite_handler(0x4fffff0, 0x4ffffff, FUNC(common_prot_r), FUNC(common_prot_w));
658}
771659
772
773
774660void install_sss_protection(running_machine &machine)
775661{
776   machine.device("maincpu")->memory().space(AS_PROGRAM).install_legacy_readwrite_handler(0x4fffff0, 0x4ffffff, FUNC(sss_prot_r), FUNC(common_prot_w));
662   install_common_protection(machine);
663   prot_readback = sss_prot_read_callback;
777664}
778665
779666void install_astrass_protection(running_machine &machine)
780667{
781   ctrl_index = -1;
782   machine.device("maincpu")->memory().space(AS_PROGRAM).install_legacy_readwrite_handler(0x4fffff0, 0x4ffffff, FUNC(astrass_prot_r), FUNC(common_prot_w));
668   install_common_protection(machine);
669   prot_readback = astrass_prot_read_callback;   
783670}
784671
785672void install_ffreveng_protection(running_machine &machine)
786673{
787   machine.device("maincpu")->memory().space(AS_PROGRAM).install_legacy_readwrite_handler(0x4fffff0, 0x4ffffff, FUNC(ffreveng_prot_r), FUNC(common_prot_w));
674   install_common_protection(machine);
675   prot_readback = ffreveng_prot_read_callback;
788676}
789677
790678void install_elandore_protection(running_machine &machine)
791679{
792   machine.device("maincpu")->memory().space(AS_PROGRAM).install_legacy_readwrite_handler(0x4fffff0, 0x4ffffff, FUNC(elandore_prot_r), FUNC(common_prot_w));
680   install_common_protection(machine);
681   prot_readback = elandore_prot_read_callback;
793682}
794683
795684void install_rsgun_protection(running_machine &machine)
796685{
797   machine.device("maincpu")->memory().space(AS_PROGRAM).install_legacy_readwrite_handler(0x4fffff0, 0x4ffffff, FUNC(rsgun_prot_r), FUNC(rsgun_prot_w));
686   install_common_protection(machine);
687   prot_readback = rsgun_prot_read_callback;
798688}
799689
800690void install_twcup98_protection(running_machine &machine)
801691{
802   machine.device("maincpu")->memory().space(AS_PROGRAM).install_legacy_readwrite_handler(0x4fffff0, 0x4ffffff, FUNC(twcup98_prot_r), FUNC(common_prot_w));
692   install_common_protection(machine);
693   prot_readback = twcup98_prot_read_callback;
694
803695}
804696
805697

Previous 199869 Revisions Next


© 1997-2024 The MAME Team