Deunan
XOR ROX 
5th-Feb-2011 02:32 am
This is what M1-type NAOMI cart looks like:


And that is what it took to figure out how the FPGA handles the protected data:


Cracking this nut took plenty of time and hard work. Originally I planned on explaining this in great detail, with photos and screenshots, but in the end decided not to. Sadly, most people couldn't care less (as long as they get to play "free" games) and/or consider this black magic that is best left to nerds and otherwise smelly people. So, I'm going to post the source code. Those of you that can parse C should find it somewhat interesting, those that can't are probably reading wrong blog.

/*

This is a concept version of M1 decoder. It's fully functional, except for
clarity it doesn't handle cases where the data stream ends and you want to
keep reading - to add that functionality just move input buffer cursor to next
4-byte boundary and restart decoding (by re-reading dictionary again).

The source includes a brute-force exhaustive cracker (takes about an hour
for a decent CPU). Pattern compare with just 4 bytes might return some very
close but not correct XOR masks so I decided on 6. Due to the simplification
I explained above it's theoreticaly possible for the cracker to fail (if there
is EOS symbol in the first 6 decoded bytes), but that is highly unlikely.

D.

*/

#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <time.h>

#define CRACKER

uint8_t ReadByte ();
void StoreByte (uint8_t b);
void ShiftIn ();
void Decode (uint32_t mask);

  //-------------------------------------------------------------------------
int s_in_len, s_in_pos;
uint8_t* s_input;
uint8_t s_xor [4];

uint8_t s_dict [111];
int s_subst;

int s_out_len, s_out_cnt;
uint8_t* s_output;

int s_shift, s_bits;

  //-------------------------------------------------------------------------
uint8_t ReadByte ()
  {
  uint8_t v;

  switch (s_in_pos & 3)
    {
    case 0:
      v = s_input [s_in_pos + 3];
      v ^= s_input [s_in_pos + 1];
      break;
    case 1:
      v = s_input [s_in_pos + 1];
      v ^= s_input [s_in_pos - 1];
      break;
    case 2:
      v = s_input [s_in_pos - 1];
      break;
    case 3:
      v = s_input [s_in_pos - 3];
      break;
    }
  v ^= s_xor [s_in_pos & 3];
  s_in_pos++;
  return v;
  }

  //-------------------------------------------------------------------------
void StoreByte (uint8_t b)
  {
  if (s_subst && s_out_cnt >= 2)
    b = s_output [s_out_cnt - 2] - b;
  s_output [s_out_cnt] = b;
  s_out_cnt++;
  }

  //-------------------------------------------------------------------------
void ShiftIn ()
  {
  s_shift <<= 8;
  s_shift |= ReadByte ();
  s_bits += 8;
  }

  //-------------------------------------------------------------------------
void Decode (uint32_t mask)
  {
  int i, eos;

  s_xor [0] = (uint8_t)mask;
  s_xor [1] = (uint8_t)(mask >> 8);
  s_xor [2] = (uint8_t)(mask >> 16);
  s_xor [3] = (uint8_t)(mask >> 24);

  // byte dictionary
  s_in_pos = 0;
  for (i = 0; i < 111; i++)
    s_dict [i] = ReadByte ();

  // control bits
  s_subst = (s_dict [0] & 64) ? 1 : 0;

  // command stream
  s_out_cnt = 0, eos = 0;
  s_shift = 0, s_bits = 0;    
  while (!eos && s_in_pos < s_in_len)
    {
    int code, addr, t;

    if (s_bits < 2)
      ShiftIn ();
    code = (s_shift >> (s_bits - 2)) & 3;
    switch (code)
      {
      case 0:
        // 00-aa
        if (s_bits < 4)
          ShiftIn ();
        addr = (s_shift >> (s_bits - 4)) & 3;
        s_bits -= 4;
        if (addr == 0)
          {
          // quotation
          if (s_bits < 8)
            ShiftIn ();
          t = (s_shift >> (s_bits - 8)) & 255;
          s_bits -= 8;
          StoreByte (t);
          break;
          }
        StoreByte (s_dict [addr]);
        break;

      case 1:
        if (s_bits < 5)
          ShiftIn ();
        t = (s_shift >> (s_bits - 3)) & 1;
        if (t == 0)
          {
          // 010-aa
          addr = (s_shift >> (s_bits - 5)) & 3;
          addr += 4;
          s_bits -= 5;
          }
        else
          {
          // 011-aaa
          if (s_bits < 6)
            ShiftIn ();
          addr = (s_shift >> (s_bits - 6)) & 7;
          addr += 8;
          s_bits -= 6;
          }
        StoreByte (s_dict [addr]);
        break;

      case 2:
        if (s_bits < 7)
          ShiftIn ();
        // 10-aaaaa
        addr = (s_shift >> (s_bits - 7)) & 31;
        addr += 16;
        s_bits -= 7;
        StoreByte (s_dict [addr]);
        break;

      case 3:
        if (s_bits < 8)
          ShiftIn ();
        // 11-aaaaaa
        addr = (s_shift >> (s_bits - 8)) & 63;
        addr += 48;
        s_bits -= 8;
        if (addr == 111)
          // end of stream
          eos = 1;
        else
          StoreByte (s_dict [addr]);
        break;
      }
    }
  }
 
  //-------------------------------------------------------------------------
int main (int ia, char *ta [])
  {
  char* name;
  FILE* f;
  uint32_t m, x;
  time_t t1, t2;
  uint8_t pattern [6];
  int t;

  name = (ia < 2) ? (char*)"input.bin" : ta [1]; 
  f = fopen (name, "rb");
  if (f == NULL)
    {
    printf ("File open error: %s\n", name);
    return 1;
    }

  fseek (f, 0, SEEK_END);
  s_in_len = ftell (f);
  if (s_in_len < 112)
    {
    printf ("File too short: %s\n", name);
    return 1;
    }
  s_input = new uint8_t [s_in_len];
  fseek (f, 0, SEEK_SET);
  fread (s_input, 1, s_in_len, f);
  fclose (f);

  s_out_len = (s_in_len - 111) * 2;
  s_output = new uint8_t [s_out_len];

  name = (ia < 3) ? (char*)"pattern.bin" : ta [2]; 
  f = fopen (name, "rb");
  if (f == NULL)
    {
    printf ("File open error: %s\n", name);
    return 1;
    }
  if (fread (pattern, 1, 6, f) < 6)
    {
    printf ("File too short: %s\n", name);
    return 1;
    }
  fclose (f);

  // 840-0030 / AH! MY GODDESS QUIZ GAME: 0xCD9B4896
  // 840-0039 / Giant Gram 2000: 0x7F805C3F
  // 840-0084 / Virtua Tennis 2: 0x2D2D4743
  // 840-0098 / Shootout Pool: 0xA0F37CA7
  // 840-0106 / Virtua Fighter 4 Evolution: 0x1E5BB0CD
  // 840-0128 / Shootout Pool Prize: 0x9DBDE9CD
  // 840-0136 / Shootout Pool Medal: 0x9DBDE9CD
  // 840-0140 / Kick'4'Cash: 0x820857C9
  // 840-0150 / MKG TKOB 2K3 2ND VER1.003-: 0x3892FB3A
  // 841-0007 / Marvel vs. Capcom 2: 0xC18B6E7C

#ifdef CRACKER
  x = 0, time (&t1);
  t = s_in_len;
  s_in_len = 0x88;
  for (m = ~0; m != 0; m--)
#else
  m = 0xCD9B4896;
#endif
    {
    Decode (m);

#ifdef CRACKER
    if (memcmp (s_output, pattern, 6) == 0)
      {
      printf ("XOR mask: 0x%08X\n", m);
      break;
      }

    if (x - m > 1024)
      {
      x = m;
      time (&t2);
      if (t1 != t2)
        {
        t1 = t2;
        printf ("0x%08X...\n", m);
        fflush (stdout);
        }
      }
#endif
    }

#ifdef CRACKER
  s_in_len = t;
  Decode (m);
#endif

  f = fopen ("output.bin", "wb");
  if (f == NULL)
    return 1;
  fwrite (s_output, 1, s_out_cnt, f);
  fclose (f);
  return 0;
  }


Also, NAOMI Test 12/7. I don't have time to work on T13 lately and I'm not going to rush it, so you get this instead. I experimented a lot on this code - it might be actually less stable than the previous version. On the bright side, Power Stone is playable now. Should be, anyway :)
Comments 
5th-Feb-2011 04:56 am (UTC)
Anonymous
Congratulations!
5th-Feb-2011 11:38 am (UTC) - emulation test
marvel vs capcom 2 not working
5th-Feb-2011 12:18 pm (UTC) - Re: emulation test
Works on my end, but I did say this version might be unstable.
24th-Oct-2011 04:02 pm (UTC) - Re: emulation test
meltyblood act cadenza not run in naomi 12.7
5th-Feb-2011 11:56 am (UTC)
Anonymous
Marvel vs. Capcom 2 hung logfile


2011-02-05 20:53:02 HOLLY/MMAP: NA_n70 <- 0x0007
2011-02-05 20:53:02 HOLLY/MMAP: NA_n70 <- 0x0007
2011-02-05 20:53:02 HOLLY/MMAP: NA_n74 -> 0xffffffff
2011-02-05 20:53:02 MMAP [PC=0xac00206c]: ZB? (0xa301009c, 0x00)
2011-02-05 20:53:02 MMAP [PC=0xac002092]: OB? (0xa301009c)
2011-02-05 20:53:02 SH4/SCI: SCIF set to 38109 baud
2011-02-05 20:53:02 AICA/ARM [PC=0x0c02f2d0]: RESET=0
2011-02-05 20:53:02 AICA/DSP: Code generated: 1
2011-02-05 20:53:11 Z80: Buffers flushed: 39142
2011-02-05 20:53:11 Z80: Code generated: 39142/1526/218
2011-02-05 20:53:17 AICA/ARM [PC=0x0c1f2b70]: RESET=1
2011-02-05 20:53:17 ARM7: Buffers flushed: 66733
2011-02-05 20:53:17 AICA/ARM [PC=0x0c1f2bca]: RESET=0
2011-02-05 20:53:17 AICA/DSP: Code generated: 1
2011-02-05 20:53:17 AICA/DSP: Code generated: 1
2011-02-05 20:53:18 AICA/DSP: Code generated: 9488
2011-02-05 20:53:18 MMAP [PC=0x892bd1ba]: OS? (0x892bd1ba)
2011-02-05 20:53:18 MMAP [PC=0x892bd1ba]: OS? (0x892bd1bc)
2011-02-05 20:53:18 MMAP [PC=0x892bd1ba]: OS? (0x892bd1be)
2011-02-05 20:53:18 MMAP [PC=0x892bd1ba]: OS? (0x892bd1c0)
2011-02-05 20:53:18 MMAP [PC=0x892bd1ba]: OS? (0x892bd1c2)
5th-Feb-2011 01:24 pm (UTC) - Can't load MAME .zip files
Anonymous
If I try to load a MAME .zip file such as dolphin.zip (Dolphin Blue) then NAOMI Test 12/7 doesn't recognise it?

NAOMI: WinMain - NAOMI.GlownaPetla -> NAOMI.Uruchom -> RD.Gra -> RD.MAME: Unknown game "dolphin"
5th-Feb-2011 01:32 pm (UTC) - Re: Can't load MAME .zip files
You do realize this is NAOMI emulator and Dolphin Blue is Atomiswave game, right?
5th-Feb-2011 02:24 pm (UTC) - Re: Can't load MAME .zip files
Anonymous
Sorry, I'm an idiot.

I tried street fighter zero 3 upper 'sfz3ugd' and that doesn't work though.
5th-Feb-2011 04:35 pm (UTC) - Re: Can't load MAME .zip files
Again, works for me. When reporting issues please explain the problem properly and attach the Logfile.txt created by emulator.
That said, you should probably stick to T12/5 if you can't get this version to work at all.
5th-Feb-2011 02:06 pm (UTC) - Some of us like the details!!
Anonymous
I don't play games, but i love emulation and cryptanalysis, please in the future don't take all of us that read your blog as stupid kids....
Anyway congrats, as always you did a great job!!!
PS: how much time lost looking at the dumps of data in/out of the FPGA?

Thanks for the info!

Nuno
5th-Feb-2011 02:35 pm (UTC)
Anonymous
Great work!
Im still exploring the new version, but i was suprised to see F355 running. :)
5th-Feb-2011 04:25 pm (UTC)
Yes, "running" is good description :)

Unfortunately is upsets the emulator by trying to shove data where it doesn't belong (not on NAOMI1 anyway). Upsets NAOMI2 layer, which is disabled but still logs stuff.

Well, it's not like F355 works perfectly on standard NAOMI boxes so...
5th-Feb-2011 03:36 pm (UTC)
Anonymous
The sad thing... i read this type of blog mostly for the technical tidbits, and to a far lesser degree for the games (i test them, but dont' have too much time for playing anything anyway anything arcade-related).

And then in the first comments, 2 are already related that some game xy is not working, either because they don't understand about experimenting, or (and this is hilarious) trying to load games for a different system. No guys, even if there's the same main CPU and also a similar graphics chip, this wouldn't take you far.

So, Deunan if at a later time you could review your decision about giving out more details about your huge efforts, some would be thankful but we would respect fully if not.
5th-Feb-2011 04:25 pm (UTC)
I'll think about it.
5th-Feb-2011 06:46 pm (UTC) - I second that
Anonymous
I read this blog exclusively for the details. In fact, I never used the emu.
6th-Feb-2011 11:02 am (UTC) - Re: I second that
Anonymous
+1
5th-Feb-2011 06:45 pm (UTC)
Anonymous
This the best emulator for NAOMI, thanks Deunan
5th-Feb-2011 09:15 pm (UTC) - log file for mvsc2
Anonymous
It grows fast (212Mb when i crashed out) here is the start of growth (filled with MMAPs from here on in)
2011-02-05 13:11:09 ARM7: Buffers flushed: 66733
2011-02-05 13:11:09 AICA/ARM [PC=0x0c1f2bca]: RESET=0
2011-02-05 13:11:09 AICA/DSP: Code generated: 1
2011-02-05 13:11:10 AICA/DSP: Code generated: 1
2011-02-05 13:11:10 AICA/DSP: Code generated: 9488
2011-02-05 13:11:10 MMAP [PC=0x892bd1ba]: OS? (0x892bd1ba)
2011-02-05 13:11:10 MMAP [PC=0x892bd1ba]: OS? (0x892bd1bc)
2011-02-05 13:11:10 MMAP [PC=0x892bd1ba]: OS? (0x892bd1be)
2011-02-05 13:11:10 MMAP [PC=0x892bd1ba]: OS? (0x892bd1c0)
2011-02-05 13:11:10 MMAP [PC=0x892bd1ba]: OS? (0x892bd1c2)
2011-02-05 13:11:10 MMAP [PC=0x892bd1ba]: OS? (0x892bd1c4)
2011-02-05 13:11:10 MMAP [PC=0x892bd1ba]: OS? (0x892bd1c6)
2011-02-05 13:11:10 MMAP [PC=0x892bd1ba]: OS? (0x892bd1c8)
2011-02-05 13:11:10 MMAP [PC=0x892bd1ba]: OS? (0x892bd1ca)
2011-02-05 13:11:10 MMAP [PC=0x892bd1ba]: OS? (0x892bd1cc)
2011-02-05 13:11:10 MMAP [PC=0x892bd1ba]: OS? (0x892bd1ce)
2011-02-05 13:11:10 MMAP [PC=0x892bd1ba]: OS? (0x892bd1d0)
2011-02-05 13:11:10 MMAP [PC=0x892bd1ba]: OS? (0x892bd1d2)
2011-02-05 13:11:10 MMAP [PC=0x892bd1ba]: OS? (0x892bd1d4)
2011-02-05 13:11:10 MMAP [PC=0x892bd1ba]: OS? (0x892bd1d6)
2011-02-05 13:11:10 MMAP [PC=0x892bd1ba]: OS? (0x892bd1d8)
2011-02-05 13:11:10 MMAP [PC=0x892bd1ba]: OS? (0x892bd1da)
2011-02-05 13:11:10 MMAP [PC=0x892bd1ba]: OS? (0x892bd1dc)
2011-02-05 13:11:10 MMAP [PC=0x892bd1ba]: OS? (0x892bd1de)
2011-02-05 13:11:10 MMAP [PC=0x892bd1ba]: OS? (0x892bd1e0)
2011-02-05 13:11:10 MMAP [PC=0x892bd1ba]: OS? (0x892bd1e2)
2011-02-05 13:11:10 MMAP [PC=0x892bd1ba]: OS? (0x892bd1e4)
2011-02-05 13:11:10 MMAP [PC=0x892bd1ba]: OS? (0x892bd1e6)
2011-02-05 13:11:10 MMAP [PC=0x892bd1ba]: OS? (0x892bd1e8)
2011-02-05 13:11:10 MMAP [PC=0x892bd1ba]: OS? (0x892bd1ea)
2011-02-05 13:11:10 MMAP [PC=0x892bd1ba]: OS? (0x892bd1ec)
2011-02-05 13:11:10 MMAP [PC=0x892bd1ba]: OS? (0x892bd1ee)
2011-02-05 13:11:10 MMAP [PC=0x892bd1ba]: OS? (0x892bd1f0)
2011-02-05 13:11:10 MMAP [PC=0x892bd1ba]: OS? (0x892bd1f2)
2011-02-05 13:11:10 MMAP [PC=0x892bd1ba]: OS? (0x892bd1f4)
2011-02-05 13:11:10 MMAP [PC=0x892bd1ba]: OS? (0x892bd1f6)
2011-02-05 13:11:10 MMAP [PC=0x892bd1ba]: OS? (0x892bd1f8)
2011-02-05 13:11:10 MMAP [PC=0x892bd1ba]: OS? (0x892bd1fa)
2011-02-05 13:11:10 MMAP [PC=0x892bd1ba]: OS? (0x892bd1fc)
2011-02-05 13:11:10 MMAP [PC=0x892bd1ba]: OS? (0x892bd1fe)
2011-02-05 13:11:10 MMAP [PC=0x892bd1ba]: OS? (0x892bd200)
2011-02-05 13:11:10 MMAP [PC=0x892bd1ba]: OS? (0x892bd202)
2011-02-05 13:11:10 MMAP [PC=0x892bd1ba]: OS? (0x892bd204)
2011-02-05 13:11:10 MMAP [PC=0x892bd1ba]: OS? (0x892bd206)
2011-02-05 13:11:10 MMAP [PC=0x892bd1ba]: OS? (0x892bd208)
2011-02-05 13:11:10 MMAP [PC=0x892bd1ba]: OS? (0x892bd20a)
2011-02-05 13:11:10 MMAP [PC=0x892bd1ba]: OS? (0x892bd20c)
2011-02-05 13:11:10 MMAP [PC=0x892bd1ba]: OS? (0x892bd20e)
2011-02-05 13:11:10 MMAP [PC=0x892bd1ba]: OS? (0x892bd210)
2011-02-05 13:11:10 MMAP [PC=0x892bd1ba]: OS? (0x892bd212)
2011-02-05 13:11:10 MMAP [PC=0x892bd1ba]: OS? (0x892bd214)
2011-02-05 13:11:10 MMAP [PC=0x892bd1ba]: OS? (0x892bd216)
2011-02-05 13:11:10 MMAP [PC=0x892bd1ba]: OS? (0x892bd218)
2011-02-05 13:11:10 MMAP [PC=0x892bd1ba]: OS? (0x892bd21a)
2011-02-05 13:11:10 MMAP [PC=0x892bd1ba]: OS? (0x892bd21c)
2011-02-05 13:11:10 MMAP [PC=0x892bd1ba]: OS? (0x892bd21e)
2011-02-05 13:11:10 MMAP [PC=0x892bd1ba]: OS? (0x892bd220)
2011-02-05 13:11:10 MMAP [PC=0x892bd1ba]: OS? (0x892bd222)
5th-Feb-2011 09:09 pm (UTC) - testing
Anonymous
thanks for all your amazing work.

here's my noob report (could just be me):
ggram2 works, vtennis2c works, mvsc2 hangs on loading game text..., vfevoct and vf4cart says "error the game is not acceptable by main board" on the naomi screen.
5th-Feb-2011 09:45 pm (UTC) - nerds
Anonymous
Dear Nerds,
Most of us use emulators to, and you'll be surprised by this, PLAY GAMES !!

Bloody surprising that, don't ya think ?
So keep the technical mumbo jumbo, and get on with the emulation.

Oh, and this emulator sucks ass.
6th-Feb-2011 04:34 am (UTC) - Re: nerds
Anonymous
Oh hi there, creeping sense of entitlement! Didn't here you come in. =P
6th-Feb-2011 02:39 am (UTC) - re
Oh yeah~! And
Expect your Makaron Dreamcast
6th-Feb-2011 03:16 am (UTC)
Anonymous
Hello,Deunan,trizeal not work in Naomi Test 12/7
6th-Feb-2011 08:53 pm (UTC) - Brilliant!
Anonymous
Endless thanks for your work dk.
7th-Feb-2011 05:40 am (UTC)
Anonymous
deunan, this is great, wave runner gp now runs perfectly!!
but im having some issues with the current jvs, and i cant map the buttons
7th-Feb-2011 06:01 am (UTC) - big news!!
Anonymous
with the new redump, of virtua striker 2, the game is perfectlyy playable with makaron test 7!! i cant stop saying thanks to you, cause this is my all time favourite game, i played it as a child endless times, and used a lot of tokens on it
8th-Feb-2011 03:19 am (UTC)
Anonymous
deunan i dont want to bother you, but in wave runner gp you cant press the start button, or the test one, so youre stuck in the attract mode, is there any solution or is like it should work?
8th-Feb-2011 09:49 am (UTC)
Unlike home gaming consoles, arcades often need unique hardware connected to work at all. In NAOMI case it's the I/O boards that handle input (and force feedback, etc).

First, it's difficult without a manual (or proper photo documentation) to figure out what to connect and how. It's usualy down to one of the standard I/Os and button config, in case of fighter games, but the ones that expect analog controls are quite another story.

Second, even though JVS layers in T12/7 is new and improved and can handle a variety of differnt I/O boards, including daisy chains, I didn't add any interface to set it up. So if the game doesn't work with what it being emulated now you're out of luck.
12th-Feb-2011 07:41 am (UTC)
Anonymous
Marvel vs capcom 2 works with the USA bios or EXP Bios

But you can't play with the 2nd player, only with the 1st

The tag P2_START in JVS.ini seems not to work

Sorry, my english is very bad :P
14th-Feb-2011 12:55 am (UTC)
Anonymous
is it possible to configure the analog buttons in naomi?
14th-Feb-2011 03:26 pm (UTC) - danielex5
marvel vs capcom 2

sound anakaris attack is repeated until the end of round
9th-Mar-2011 02:43 am (UTC) - Re: danielex5
Anonymous
Ditto on the Anakaris bug...

Also, would there be any chance that you might include a way for us to program macros for inputs or bind multiple buttons into just one button? Like in other emulators... for example, Kawaks, you could assign all 3 punch or all 3 kick buttons into any other single button you choose. This would be a boon for those of us who have keyboards that don't recognize more than 2 or 3 keys to be pressed at the same time.
9th-Mar-2011 06:58 pm (UTC) - Re: danielex5
Sorry, no. I'd remove keyboard support completly if it wasn't for the fact that some people run Makaron in their cabs, with original wiring/inputs connected to gutted keyboard.
9th-Dec-2011 06:11 pm (UTC) - Error 121
Anonymous
congratulations on your work, it really is very good

I downloaded, this file

but to try I get this error:

[Direct3d error (-121)] in module NAOMI ...

I hope I can help run this emulator correctly

thank you for your help in advance
This page was loaded May 21st 2013, 2:09 pm GMT.