What's new
It seems like the same copy protection from back in the day but a variation of it.

And reversing the game and playing the rom somewhere else even if you own the game probably is infringing the terms of service of EPIC.

But... In the other hand as said in this thread it seems part of the MAME code is used and if I'm not mistaken, someone can explain this better, MAME is under GNU, isn't it?
So using it and not providing source code means you are infringing GNU license.

So everyone is wrong but only one side has a legal team to sue.
 
Again, reference the MAME source.

The program rom just needs byte swapped and split in two to be what a normal rom is.
 
Again, reference the MAME source.

The program rom just needs byte swapped and split in two to be what a normal rom is.
Already done that.

Split at 0003FFFF0 with 2x 4096kb parts.
Byteswaped.

Bank error.

Have you got the game to work?
 
I wonder what the legality of this all is. It looks like they set up some fairly decent copy protection to make sure it's not easily pulled into MAME.

If you own the collection are you only legally allowed to play the game via this collection or any emulator or hardware?...
In the United States, Section 117 of the Copyright Act gives the owner of a particular copy of software the explicit right to use the software with a computer, even if use of the software with a computer requires the making of incidental copies or adaptations.

So downloading a copy of the ROM would be copyright infringement, but if someone release a patcher that pulls the ROM out of the copy of the game you own and modifies it to be used on a MVS cart or MAME that would constitute fair use.
 
Definitely looking forward to having this on a MVS, but really, everyone even remotely interested in this should buy this collection to show appreciation for SNK + people involved in tracking this rom down. This is honestly amazing. Buying this right now.

Edit: WTF, was going to buy it, but it's free on epic store?

Uh ok.
 
SNK + people involved still get money when you get it through the Epic Games store - Epic just throws some of that Fortnite $$$ at them.
 
This gets the code running for me in mame.

Code:
$ split -n 16 samsho5_fe.cslot1_maincpu.swap prom.
$ cat prom.aa prom.ab prom.ai prom.ap prom.am prom.ah prom.ao prom.an > 272-p1.p1
$ cat prom.ae prom.ad prom.ac prom.af prom.ak prom.aj prom.ag prom.al > 272-p2.sp2

$ sha1sum 272-p*
96da13050d5b4b3dff47c5ae4e5d55c4f414f528  272-p1.p1
7397b111fd63abb526b6cf52bdfdc897ec474eb3  272-p2.sp2
 
This gets the code running for me in mame.

Code:
$ split -n 16 samsho5_fe.cslot1_maincpu.swap prom.
$ cat prom.aa prom.ab prom.ai prom.ap prom.am prom.ah prom.ao prom.an > 272-p1.p1
$ cat prom.ae prom.ad prom.ac prom.af prom.ak prom.aj prom.ag prom.al > 272-p2.sp2

$ sha1sum 272-p*
96da13050d5b4b3dff47c5ae4e5d55c4f414f528  272-p1.p1
7397b111fd63abb526b6cf52bdfdc897ec474eb3  272-p2.sp2
The graphics are messed up but we are getting close, thanks for this

samsho5p.png
 
The graphics are messed up but we are getting close, thanks for this

samsho5p.png
Yeah I think thats just an artifact of not using the correct C roms.

I believe I have the sprites.swizzled files figured out based on trying to get SamuraiShodown_NGM.sprites.swizzled to match up with the samsho C roms.

If you do a nibble swap of every byte the resulting nibble ordering seems to give you the raw 16 x 16 x 4bpp sprite. However sprites in the C roms need to be in this format https://wiki.neogeodev.org/index.php?title=Sprite_graphics_format
 
Here is some code to convert the swizzled files into the correct sprite formatted C rom data.

C:
// gcc -o ss_unswizzle ss_unswizzle.c
#include <stdio.h>
#include <unistd.h>
#include <stdint.h>

int main(int argc, char **argv) {
  FILE *input, *output1, *output2;
  uint8_t tile[128];
  uint8_t* offset;
  uint8_t x_offset,y_offset,block, data,row;
  int i;
  uint8_t planes[4];

  if(argc < 4) {
    printf("ss-unsizzle <input file> <output odd> <ouput even>\n");
    return 1;
  }

  input = fopen(argv[1], "r");
  if(!input) {
    printf("Error: unable to open %s for reading.\n", argv[1]);
    return 1;
  }

  output1 = fopen(argv[2], "w");
  if(!output1) {
    printf("Error: unable to open %s for writing.\n", argv[2]);
    return 1;
  }

  output2 = fopen(argv[3], "w");
  if(!output2) {
    printf("Error: unable to open %s for writing.\n", argv[3]);
    return 1;
  }

  while(fread(tile, 1, 128, input) == 128) {
    for(block = 0;block < 4;block++) {

      // x/y_offset get us into the correct block
      switch(block) {
        case 0:
          x_offset = 4;
          y_offset = 0;
          break;
        case 1:
          x_offset = 4;
          y_offset = 8;
          break;
        case 2:
          x_offset = 0;
          y_offset = 0;
          break;
        case 3:
          x_offset = 0;
          y_offset = 8;
          break;
      }

      // traverse each row of the block
      for(row = 0;row < 8;row++) {
        planes[0] = 0;
        planes[1] = 0;
        planes[2] = 0;
        planes[3] = 0;

        offset = &tile[x_offset + (y_offset * 8) + (row * 8)];

        for(i = 3;i >= 0;i--) {
          data = offset[i];

          planes[0] = planes[0] << 1;
          planes[0] = planes[0] | ((data >> 4) & 0x1);
          planes[0] = planes[0] << 1;
          planes[0] = planes[0] | ((data >> 0) & 0x1);

          planes[1] = planes[1] << 1;
          planes[1] = planes[1] | ((data >> 5) & 0x1);
          planes[1] = planes[1] << 1;
          planes[1] = planes[1] | ((data >> 1) & 0x1);

          planes[2] = planes[2] << 1;
          planes[2] = planes[2] | ((data >> 6) & 0x1);
          planes[2] = planes[2] << 1;
          planes[2] = planes[2] | ((data >> 2) & 0x1);

          planes[3] = planes[3] << 1;
          planes[3] = planes[3] | ((data >> 7) & 0x1);
          planes[3] = planes[3] << 1;
          planes[3] = planes[3] | ((data >> 3) & 0x1);

        }
        fwrite(&planes[0],1, 1, output1);
        fwrite(&planes[1],1, 1, output1);
        fwrite(&planes[2],1, 1, output2);
        fwrite(&planes[3],1, 1, output2);
      }
    }
  }

  fclose(input);
  fclose(output1);
  fclose(output2);
}

You would wanna do something like this

Code:
$ ./ss_unswizzle SamuraiShodown5_FE.sprites.swizzled odd even
This will spit out a file called 'odd' which contains all of odd C rom data (ie: c1 + c3 + c5 + etc), and 'even' the even C rom data. You would then need to split those files into the proper sizes based on the required C rom sizes and name those appropriately.

The next issue that someone else will need to figure out. The resulting C rom data from ss_unsizzle'ing of SamuraiShodown5_FE.sprites.swizzled is unencrypted, but mame is expecting encrypted C roms for samsh5sp.
 
it works better if you change the banks at the second chip like this:

cat prom.ak prom.ad prom.ac prom.af prom.ae prom.aj prom.ag prom.al > 272-p2.sp2

Thank you for figuring out how to convert the scramble. Unfortunately you swapped out a single bank pair on wrong positions. Now it works perfectly and only need the correct GFX roms.
This gets the code running for me in mame.

Code:
$ split -n 16 samsho5_fe.cslot1_maincpu.swap prom.
$ cat prom.aa prom.ab prom.ai prom.ap prom.am prom.ah prom.ao prom.an > 272-p1.p1
$ cat prom.ae prom.ad prom.ac prom.af prom.ak prom.aj prom.ag prom.al > 272-p2.sp2

$ sha1sum 272-p*
96da13050d5b4b3dff47c5ae4e5d55c4f414f528  272-p1.p1
7397b111fd63abb526b6cf52bdfdc897ec474eb3  272-p2.sp2
 
it works better if you change the banks at the second chip like this:

cat prom.ak prom.ad prom.ac prom.af prom.ae prom.aj prom.ag prom.al > 272-p2.sp2

Thank you for figuring out how to convert the scramble. Unfortunately you swapped out a single bank pair on wrong positions. Now it works perfectly and only need the correct GFX roms.
This gets the code running for me in mame.

Code:
$ split -n 16 samsho5_fe.cslot1_maincpu.swap prom.
$ cat prom.aa prom.ab prom.ai prom.ap prom.am prom.ah prom.ao prom.an > 272-p1.p1
$ cat prom.ae prom.ad prom.ac prom.af prom.ak prom.aj prom.ag prom.al > 272-p2.sp2

$ sha1sum 272-p*
96da13050d5b4b3dff47c5ae4e5d55c4f414f528  272-p1.p1
7397b111fd63abb526b6cf52bdfdc897ec474eb3  272-p2.sp2
Thanks for double checking and finding the issue/fix. I wasn't sure it was 100% correct.
 
For the purposes of the darksoft pack:

Please (nicely) tell me where I've missed things.

Darksoft ROM Name
SamSho Collection ROM NameNotes
crom0SamuraiShodown5_FE.sprites.swizzledNeed to be descrambled
m1rom?
promsamsho5_fe.cslot1_maincpuYou need to swap every second byte
sromsamsh5spcslot1_fixed.decI am unsure of this one. cslot1_fixed is srom in SamSho1, this is an educated guess I've made based on this. It can be found in the SamuraiShodown5Special mbundle
vroma0samsh5sp.cslot1_ymsnd.decI am unsure of this one. ymnsd is vroma0 in SamSho1, this is an educated guess I've made based on this. It can be found in the SamuraiShodown5Special mbundle


More notes:
  • SamuraiShodown5_FE.pbin is some sort of patch
  • Not sure what SamuraiShodown5_FE.nv is
 
@ack

for some reason when I put your code to run as a script on my shell it spited a few errors so I compiled it with Code blocks on windows.

Can you check if the result is the same with this?


or just sha1 the odd and even files so I can check here.

Nevermind, just had a problem with GCC here.
It's working now.

So just to clear things up:

split ODD with:
Code:
$ split -n 4 odd


and you will get:
  • 272-c1.c1
  • 272-c3.c3
  • 272-c5.c5
  • 272-c7.c7
and split even with


Code:
$ split -n 4 even
and you will get
  • 272-c2.c2
  • 272-c4.c4
  • 272-c6.c6
  • 272-c8.c8

Correct?
 
Last edited:
Nice, so got it right.

So we need to reverse this:

Code:
static void neogeo_gfx_decrypt(running_machine *machine, int extra_xor)
{
	int rom_size;
	UINT8 *buf;
	UINT8 *rom;
	int rpos;
	int cnt;
	rom_size = memory_region_length(machine, "sprites");

	buf = alloc_array_or_die(UINT8, rom_size);

	rom = memory_region(machine, "sprites");
	gn_init_pbar("Decrypting...", rom_size/2);
	// Data xor
	cnt=0;
	for (rpos = 0;rpos < rom_size/4;rpos++)
	{
		decrypt(buf+4*rpos+0, buf+4*rpos+3, rom[4*rpos+0], rom[4*rpos+3], type0_t03, type0_t12, type1_t03, rpos, (rpos>>8) & 1);
		decrypt(buf+4*rpos+1, buf+4*rpos+2, rom[4*rpos+1], rom[4*rpos+2], type0_t12, type0_t03, type1_t12, rpos, ((rpos>>16) ^ address_16_23_xor2[(rpos>>8) & 0xff]) & 1);
		if (cnt++ > 32768) {
			cnt=0;
			gn_update_pbar(rpos);
		}
	}
	cnt=0;
	// Address xor
	for (rpos = 0;rpos < rom_size/4;rpos++)
	{
		int baser;
		if (cnt++>32768) {
			gn_update_pbar(rpos + (rom_size >> 2));
			cnt++;
		}
		baser = rpos;

		baser ^= extra_xor;

		baser ^= address_8_15_xor1[(baser >> 16) & 0xff] << 8;
		baser ^= address_8_15_xor2[baser & 0xff] << 8;
		baser ^= address_16_23_xor1[baser & 0xff] << 16;
		baser ^= address_16_23_xor2[(baser >> 8) & 0xff] << 16;
		baser ^= address_0_7_xor[(baser >> 8) & 0xff];


		if (rom_size == 0x3000000) /* special handling for preisle2 */
		{
			if (rpos < 0x2000000/4)
				baser &= (0x2000000/4)-1;
			else
				baser = 0x2000000/4 + (baser & ((0x1000000/4)-1));
		}
		else if (rom_size == 0x6000000)	/* special handling for kf2k3pcb */
		{
			if (rpos < 0x4000000/4)
				baser &= (0x4000000/4)-1;
			else
				baser = 0x4000000/4 + (baser & ((0x1000000/4)-1));
		}
		else /* Clamp to the real rom size */
			baser &= (rom_size/4)-1;

		rom[4*rpos+0] = buf[4*baser+0];
		rom[4*rpos+1] = buf[4*baser+1];
		rom[4*rpos+2] = buf[4*baser+2];
		rom[4*rpos+3] = buf[4*baser+3];
	}
	gn_terminate_pbar();
	free(buf);
}
 
Last edited:
Nice, so got it right.

So we need to reverse this:

Code:
void neogeo_state::samsh5sp_decrypt_68k()
{
	int i;
	static const int sec[]={0x000000,0x080000,0x500000,0x480000,0x600000,0x580000,0x700000,0x280000,0x100000,0x680000,0x400000,0x780000,0x200000,0x380000,0x300000,0x180000};
	UINT8 *src = memregion("maincpu")->base();
	dynamic_buffer dst(0x800000);
	memcpy( dst, src, 0x800000 );
	for( i=0; i<16; ++i )
	{
		memcpy( src+i*0x80000, dst+sec[i], 0x80000 );
	}
}
That code is related to the program rom only. The junk from above that was splitting the program rom into 512k chunks then cat'ing them back together to get p1/p2.

Code:
void neogeo_samsho5sp_cart_device::decrypt_all(DECRYPT_ALL_PARAMS)
{
	m_kof2k2_prot->samsh5sp_decrypt_68k(cpuregion, cpuregion_size);
	m_cmc_prot->cmc50_m1_decrypt(audiocrypt_region, audiocrypt_region_size, audiocpu_region, audio_region_size);
	m_cmc_prot->cmc50_gfx_decrypt(spr_region, spr_region_size, SAMSHO5SP_GFX_KEY);
	m_cmc_prot->sfix_decrypt(spr_region, spr_region_size, fix_region, fix_region_size);
	m_pcm2_prot->swap(ym_region, ym_region_size, 6);
}
You would need to reverse all of those decrypt functions, some of which are non-trivial. It would be less work to just modify mame and add a new game entry that used all unencrypted roms.
 
Okay, I just made this work on the MVS multi. I was assuming the P ROM from the release was scrambled, which is not the case. You only need it scrambled to make it work with MAME. Because of the C-ROMs not being CMC encrypted it might not even be a good idea run it on MAME with the Samsho5sp slot.

Now the question, am I missing a patch for the C-ROMs, no???

The logo is different than what it is supposed to.

Just making sure I am being clear, putting byteswapped samsho5_fe.cslot1_maincpu as "prom" straight without any changes, making crom0 from ss_unswizzle.exe and odd/even 16bit combined gave me this result. The fpga, srom, vroma0 and m1rom files are from the original Samsho 5 special.

MAYBE, I am having the wrong title screen logo because I don't have the correct srom file? Can anyone check that for me?
 

Attachments

  • TV2020061311125300.jpg
    TV2020061311125300.jpg
    43.5 KB · Views: 211
  • TV2020061311141300.jpg
    TV2020061311141300.jpg
    44 KB · Views: 203
Last edited:
Your bios region should be what is determining the logo screen.
 
Back
Top