ShendoXT / memcardrex

Advanced PlayStation 1 Memory Card editor
GNU General Public License v3.0
432 stars 53 forks source link

The curious case of Crash Anywhere, on PocketStation #48

Open NKO55 opened 9 months ago

NKO55 commented 9 months ago

(This might not even be related to MemcardRex, but in the rare case that it is, I leave it here for posterity sake)

Background info: I have been using latest MemcardRex on my Win 11 PC to transfer savedata and PocketStation apps to my PocketStation via PS3 Memorycard Adapter, and everything has been working great. No problems whatsoever.

Prologue: The japanese version of Crash Bandicoot 3 has a PocketStation companion app called Crash Anywhere. You can "install" the app to your PocketStation via a settings menu within the Crash 3 game. Crash Anywhere app has 3 different minigames, and a feature, which allows the player to take "snapshots" of funny in-game moments, that are then saved as little 32 x 32 pixelart images to your in-game gallery. Pretty advanced, huh. When for example the player finishes a dance minigame, they earn a picture to their gallery.

Issue TL;DR: a PocketStation application transferred through MemcardRex is missing an in-game "photo" feature; possibly because a triggered anti-piracy method? When same application is transferred through an actual PS1, the said feature is present.

The issue in-depth: If the user has a real PS1 console and a copy of japanese Crash 3 (burned copy or a real one), and plugs in the PocketStation to their PS1, player is able to succesfully install the companion app to the PocketStation via in-game menus. When the user takes PocketStation out and plays the Crash Anywhere app, it works as expected and user is able to gather in-game "pixel photos" through gameplay. However, if the user instead uses emulator on their PC to emulate the japanese Crash 3 game, with DuckStation as an example, and creates a virtual .mcb-file that has the Crash Anywhere app inside, the user can then transfer the .mcb file to their PocketStation by using latest MemcardRex. The transfer finishes succesfully, and the user is able to play the Crash Anywhere app on their PocketStation, but there is a curious issue now: the events that are supposed to be triggered in game that allows user to take "photos" of said events, does no longer work. Everything else is in place. Only the "photo-feature", that appears after completing minigames etc is gone, and user can't complete the game via collecting these "digital pixel photos". Even if the user uses the same Crash 3 BIN/CUE-imagefile for emulation (the same that has been burned to disc and tried on an actual PS1), doesn't make the PocketStation app work properly.

So my hypothesis is, that there is something missing when transferring the crash 3 .mcb file to PocketStation with MemcardRex. Maybe it's a weird software glitch on MCR's part, or maybe it's some sort of rudimentary copy protection mechanism made by the game studio. Maybe there's a function written inside that can detect the way the files are written on the device, and if something is a miss, the game functions become limited. There were some copy protection methods created by PS1 devs for certain games, so it is not completely out of the question to think that there might be something similar going on here.

Has anyone else ran into similar weird issues with any other PocketStation app?

ShendoXT commented 9 months ago

Hm, strange... What version of MemcardRex are you using?

Edit: I got the save/app and will try this for myself on PocketStation emulator. I never played this Japanese version as I don't know japanese so it may take a while.

What I am curious though, on real PS1 you put the game on the PocketStation directly but on an emulator you made a save and then transferred it to the real PocketStation.

Have you tried making the save on the normal Memory Card first and then transferring it to PocketStation on the real PS1 using save manager?

crash save
ShendoXT commented 9 months ago

I think I know what is happening. The header XOR calc function ends 1 byte prematurely. It should go through 127 bytes and store the value but it goes through 126 bytes.

For 99.9999999% of games that doesn't matter as most of the header is padded with zeros, including that next to last byte. But for some reason Crash Anywhere uses that byte in the header (with value of 1) and the XOR calc skips it messing up the checksum.

https://github.com/ShendoXT/memcardrex/blob/ccaab70151465aab06c525b306547c275135cbb0/MemcardRex/ps1card.cs#L972

If you copy pasted the save via temp buffer it will recalc the XOR value and corrupt the header with wrong checksum.

What probably ends up happening is that he game needs to save the image data to itself basically and it can't because it thinks that the save is invalid/nonexistant so it just skips that part.

What a weird edge case...

In order to burn the image properly don't use the copy/paste but write the complete .mcd file directly to the pocketstation, then it surely must work. I need to fix this XOR calc issue.

Thanks for the heads up.

snap Screenshot 2024-02-14 at 07 22 11 Screenshot 2024-02-14 at 07 23 02
NKO55 commented 9 months ago

First of all, thanks for a quick answer! I really appreciate it.

I haven't used the copy-paste feature for saves. I always go to "File > Open" and search for the .mcb file that DuckStation has created while playing the japanese Crash 3. I then flash the whole file to my PocketStation. The version I am using is 1.9.1536670.

Copying the contents of one memory card to PocketStation on actual PS1 hardware is a good suggestion, I need to try that later. One thing I have tried is: I create the Crash Anywhere file on a real PS1 hardware and save it directly from the game to my PocketStation. This way the Crash Anywhere app works 100 %. I then take this PocketStation and hook it up to my PC, and use MemcardRex to make a copy of its contents by creating a .mcb file on my computer. I then take another [empty] PocketStation that I have, plug it in to my PC, and transfer previously copied .mcb file to that unit. I take PocketStation out and try it out, and.... Crash Anywhere app again lacks the photo functionality. So even if I copy a confirmed 100 % working file from another PocketStation to my PC, and then transfer the same file back to another PocketStation, the file no longer works as intended. So something weird must happen to it during the transfer progress?

EDIT: Easiest/fastest way to determine if your Crash Anywhere app is working 100 % correctly, is to boot up the app and the first thing it does it goes to a "Crash virtual pet" mode that shows large Crash sprite on the display. If Crash is performing some kind of action (other than standing idle) there should flash a small camera icon in the lower right corner every 3-4 frame (Crash animations usually have only 3-4 frames). Note that if you have already taken a picture of that specific animation, the camera icon wont show anymore (can only take one photo per new animation).

ShendoXT commented 9 months ago

Can you try with this version of MemcardRex? Just replace the one you have in the folder with this one. I fixed the XOR calc function. Xor gets ran through various other functions so it might be executing even if you did not copy/paste the saves.

MemcardRex fixed XOR.zip

NKO55 commented 9 months ago

Thanks for the update! However, the problem still persists... BUT. It was not for vain. I found out something else while testing this, and I think I figured it out.

Say I have PocketStation A and PocketStation B. I use an actual PS1 + Crash 3 to install Crash Anywhere app to both PocketStations. Both work fine. Then, if I use MemcardRex to transfer the app data from PS-A to my PC, then format PS-A completely, then transfer the same data file back to PS-A, it works again. Cool. And if I do similar test for PS-B with its own file, it works the same. So this means that MemcardRex is working perfectly fine.

BUT. If I instead try to transfer the file, which was created for PS-A, to PS-B, it stops working properly. And this error happens same way even if I use PS1's built-in memory manager, so it is definitely not a problem of a MemcardRex, but of the Crash Anywhere software itself.

My non-coder brain tells me that either

  1. there must be some hidden ID or something written to the app while it is being transferred from the PS1 to the PocketStation, and the app checks for it while its running on the device, causing this weird behavior, or

  2. both of my PocketStations have differences in BIOSes, different versions etc, which causes issues when trying to run the same app on different devices. OR

  3. since this app also has a calendar function and real-time clock, it could be that the differences between system times screws up some calculations within the app and thus things start falling apart.

Now that I wrote the last part out, I think it actually makes perfect sense to me... It must be the time differences between the devices. The file created for PS-A has a different time progression, and when I transfer that file to PS-B, the part of the code that checks for time runs into a difference and skips some steps... And the file created by the emulator wouldn't work, because it probably set some arbitrary "default time" for the app during save process, which of course is different to each of my real PocketStations. If the emulator could access the device directly, then I'm sure it'd work too. I guess it's case closed huh?

ShendoXT commented 9 months ago

Hmmm, really curios... Now I'm invested.

Can you do this test? Format both PocketStations and place your Crash 3 save on one plain MemoryCard. Now, put PocketStation A and create a game, swap B and do the same.

Now dump data from each one but don't run the game (just yet). After you have dumped the data you can check if there are any differences in the app that's been placed on the flash.

Open both dumped cards in MemcardRex and copy game "save" from PocketStation A to temp buffer. Now edit->compare it with data from PocketStation B. Any differences?

If you want attach both dumps so I can take a look.

Also, Xebra emulator and PK201 can "connect" so you can write a game to the "real" virtual PocketStation. You can also dump your kernel ROM and use it in the PocketStation emulator and see if that one will run the respective dump.

Screenshot 2024-02-14 at 06 44 12

Oh, yeah. Thanks for this, it helped me to fix my flawed xor calc function.

NKO55 commented 9 months ago

So I made a test with two different [formatted] PocketStations as you instructed, and I can definitely see some differences in their data. I couldn't test it with a regular memory card, because the game recognizes it as such and so it refuses to install the PocketStation app to it.

Here's the files I dumped: https://we.tl/t-ETuquZjmxX

There are 4 files in that archive. 2 files per device, one taken before the first launch and one afterwards.

This screenshot shows the difference between the two files (before launch; the one on temp buffer is "PS-A"):

1

And this screenshot shows the difference between the two files (after launch; the one on temp buffer is "PS-A"): 2

ShendoXT commented 9 months ago

OK. That looks like some kind of signature, probably a copy protection measure.

But as I can see, once calculated it stays the same, regardless of the data change within the save file, which is good. It was probably though out as a measure from directly copying using PS1 Memory Card manager.

That must mean that each PocketStation has the unique readable ID somewhere.

I "signed" your launched data from PS-A and ran it on the emulator with my signature. I was able to view the gallery. Even though I left time reset to 1999. I don't think it's time based.

Screenshot 2024-02-15 at 02 57 21

Try to sign the data from launched B and then write it to PS-A: Open dump from launched B, export as .mcs format. Open with hex editor (HxD for example).

Change 4 bytes at 0xA00 to 0x21, 0x1C, 0x5C, 0x57 (PS-A signature) and save.

Screenshot 2024-02-15 at 03 13 08

Create a new card, import that changed save and write it to PocketStation-A.

For quick test I attached your launched B resigned with A signature. If my theory is correct that launched B should work properly on PS-A.

b launched on a resigned.mcr.zip

ShendoXT commented 9 months ago

Well, I couldn't help myself, I had to make a plugin.

CrashReSign.zip

Place it inside plugins directory. You can check if it's properly loaded under options->plugins. After that just right click on the save and select edit with plugin.

If it really is up to that you should be able to read and write signatures for each respective PocketStation.

Screenshot 2024-02-15 at 08 13 47 Screenshot 2024-02-15 at 08 13 30 Screenshot 2024-02-15 at 08 13 06
NKO55 commented 9 months ago

Hmm I don't know if I did this correct or not, as I'm not experienced in hex editing, but anyway. So if I compare the data in MemcardRex, it shows that PS-A has the values "21, 1C, 5C, 57" at 0x0A00, while PS-B has values "8C, 9B, 3D, 47" at the same address. I want to test if I can make PS-B-file work in PS-A, so I open PS-B-file in hex editor and start looking at the values.

Hex editor shows "FF FF FF FF" at the 00000A00 address. Hmm maybe that's not correct? So I try to search for "8C, 9B, 3D, 47" and find them at 00002980. I change the values to those of PS-A, which are: Screenshot 2024-02-15 090206

I save the file, flash it to PS-A and what do you know... It works! The photo feature works now with a file that originated from a different PocketStation. So it is now possible to transfer the Crash Anywhere app from an outside source to your own PocketStation, if you know your PS's signature and know how to edit it in. I wonder if it would be possible to make this a feature in MemcardRex, to determine your PS's signature and inject it to the app that is being transfered? Anyway, big thanks for your help! I wouldn't have figured out any of this without your knowledge!

NKO55 commented 9 months ago

Well, I couldn't help myself, I had to make a plugin.

Haha WHAT. You typed that response the second I sent mine lol. I need to check this out.

NKO55 commented 9 months ago

Hey I got home now I had the time to test your plugin. Sadly I cannot get it to show up in MemcardRex? I tried the XOR-fix edition as well as the usual 1.9.1536670 version by placing the dll in the plugins folder. I closed and reopened the app but it won't show up in plugins menu?

EDIT: Also I can confirm that the PocketStation ID that is given to the Crash Anywhere app during install is the same one each time you write/install the app again [from the Crash 3 game via PS1]. So there is no randomization there.

ShendoXT commented 9 months ago

Oh, silly me. I compiled it for .net framework 2.0 and MemcardRex uses 4.8. I wonder how it even loaded on my end, usually that mismatch won't work...

Try it now. CrashReSign.dll.zip

NKO55 commented 9 months ago

1

Sorry I must be doing something wrong here because it just wont show up?

ShendoXT commented 9 months ago

Nope, you are doing everything right... I have no idea how that is possible... Both are targeting the same framework now... I'll check on my other laptop if the same happens.

Screenshot 2024-02-15 at 16 27 51

So, first image is from Windows 11, arm. It works fine on another laptop with Windows 10 x64. Heck, I even tried it on x32 Win7 and it shows up. This is all sorts of weird ๐Ÿคจ mcrx win7

Do you have another PC you could try running this on? This is quite a head scratch.

NKO55 commented 9 months ago

Sure I'll have to try it out on my work PC (win 10).

ShendoXT commented 9 months ago

Can you run this special debug version for me? It will open a console and write each loaded plugin and show an error if there is an issue while loading it.

MemcardRex plugin debug.zip

Screenshot 2024-02-15 at 17 08 14
NKO55 commented 9 months ago

Can you run this special debug version for me? It will open a console and write each loaded plugin and show an error if there is an issue while loading it.

Loads everything else OK except one: image

ShendoXT commented 9 months ago

Ah... I get it. Windows is not allowing files from untrusted sources. I found this fix on the internet:

The solution was to unzip the file using 7-Zip instead of the built-in Windows zip extractor (which I presume attached some security attributes to extracted items).

So. delete this dll and use 7zip or any other archiver beside the windows one. It seems it attaches some flags which blocks it from loading.

Also, another solution:

Right Click problematic file Click Properties Click Unblock

Try to see if there is an unblock option in the CrashReSign.dll file properties.

NKO55 commented 9 months ago

Brotherrrrr! Here's Johnny!

image

And it works! Thanks!! I used the plugin to copy-paste ID from one device file to another, and it appears to be running now fully functional as it's supposed to!

Thanks for your help & for the great app!! And thanks for crediting me in the plugin info :D If possible, maybe add some sort of description to let others know (if anyone ever has the same issue lol) what the plugin is for? For example:

"Use this plugin to copy device-ID from one Crash Anywhere file to another. Running the same Crash Anywhere app on multiple devices does not work properly unless the app's ID is changed to match the device's real ID.

This operation is required whenever you try to run a copy of Crash Anywhere app in another PocketStation, that is not the app's original installation device. For example, if you create Crash Anywhere savefile using an emulator and try to transfer the file to your physical PocketStation, you need to change that file's ID to correspond your PocketStation's ID. Otherwise the in-app "photo capture" mode won't work.

Unfortunately, currently the only way to determine your PocketStation's real-ID is to use actual PS1 and a copy of japanese Crash Bandicoot 3 to install Crash Anywhere app to your PocketStation (the correct ID is assigned to your device's Crash Anywhere app during the installation process)."

ShendoXT commented 9 months ago

Hmmm... Maybe this little tool can help us.

PocketStation BIOS Tool v3

Just import .mcs file with edit->import save and flash it to your PocketStation

It can show us serial number of the Pocket Station, aka it's ID. My assumption is that ID must be used by CB3 when making it's signature.

Of course I use an PK201 emulator so it's ID is 00000201. But also my CB3 signature has a lot of zeros, coincidence?

Screenshot 2024-02-15 at 19 31 11

Can you show me your IDs from your Pocket Stations?

Screenshot 2024-02-15 at 19 25 16 Screenshot 2024-02-15 at 19 24 46
ShendoXT commented 9 months ago

So, OpenEmu (Mednafen core) made a save with this signature:

Screenshot 2024-02-15 at 20 45 23

Total zeroes. I would it assume it either implements some form of PocketStation commands or for some other reason CB3 thinks it's a PocketStation but I believe this one probably returns 00000000 as it's ID.

Based on this I would assume it's some byte shifting, swapping, multiplying to get the CB3 style signature from, nothing fancy like hashing.

I wonder if I can force PK201 to use another ID, I would like to try a couple of simple brute force tactics.

NKO55 commented 9 months ago

Hmmm... Maybe this little tool can help us.

PocketStation BIOS Tool v3

That tool saves the BIOS file inside a .mcr but I didn't know how to extract them out. You can dl them here if you want to take a look: https://we.tl/t-pEod7QQfjV

The BIOS info reads as:

PS-A:

Serial: W06036513 Date: 1998/10/23 C110 J110

PS-B:

Serial: G04037516 Date: 1998/10/23 C110 J110

ShendoXT commented 9 months ago

It looks like I'm on a good trail. no$gba supports PocketStation and it has a debugger.

Since Crash Anywhere has to verify on the device itself it must contain a complete code for checksum generation.

Notice something similar?

Screenshot 2024-02-15 at 22 30 04

register r0 holds the calculated checksum (from no$gba PS ID) and register r1 holds our checksum in the game data (from your files)

Game will compare r0 and r1 and if they do not match it won't unlock the gallery.

I just have to trace the code from a point of reading the PS ID from memory and to the generated checksum and if I can repeat that in code we should be able to sign images with just the PS ID read from the device itself.

I managed to sign your pocketstation b image on no$gba emulator with that value from r0 before comparison so that's the right signature we are looking for.

Screenshot 2024-02-15 at 22 59 31
NKO55 commented 9 months ago

...

Didn't understand any of it! But it sounds like a very impressive discovery!

And this just dawned on me: Are we possibly witnessing here the birth of a world's first ever PocketStation crack...? The game that took the longest to crack...? :D This might call for a ice cold Pepsi(tm). I'm excited to see what comes from this!

ShendoXT commented 9 months ago

Oh ๐Ÿ˜ฎ I figured it out. The games (both CB3 and CA) do not obfuscate the serial number, they use it as is. What I didn't realise is that the serial is BCD (binary coded decimal) and it turns out it's really easy to convert.

So for your first PocketStation we have W06036513 serial. W in ASCII is - 0x57 and the rest of the serial (06036513) if we convert from decimal to hexadecimal we get 0x575C1C21, combine them together and reverse the order, bam - 211C5C57.

Let's try with other PocketStation: G04037516 G - 0x47 04037516 - 0x3D9B8C, combine and reverse 8C9B3D47.

I just need to implement that conversion in CrashReSign and we are good, we can use serial to sign the game. If you have a label with the serial on your PocketStation you won't even have to run the BIOS tool ๐Ÿคฃ

ShendoXT commented 9 months ago

Alright. I did it. ๐Ÿฅณ CrashReSign is working with proper serials now.

CrashReSign 0.2.zip

Find out your PocketStation serial either by a sticker or BIOS tool and sign the game, no CB3 involved.

Screenshot 2024-02-16 at 02 23 52

Also I added more info to the about dialog as you suggested.

Screenshot 2024-02-16 at 03 02 34

Cracked? I'd say pretty much ๐Ÿ˜œ

NKO55 commented 9 months ago

You crazy sonovabitch, you did it! And it works! I just tested it by taking the file of PS-B, wrote the serial from PS-A and installed it to PS-A... and it runs flawlessly! Thanks for your hard work!!

It is true that PocketStations have the serial written on the actual item under the lid, but not all seem to have it. For example in my collection this PS-A does have the serial under lid but PS-B doesn't, so it's a good thing that Orion's BIOS tool exists so that the serial can be acquired at least by digital means.

Now imagine if there were a function in MemcardRex, "Read PocketStation serial", that when activated would present a "In progress, please wait.." screen to the user, while MemcardRex would write a tiny temporary app similar to BIOS tool to the PS, read devices ID, save it to a savefile, then download it back to PC, read the serial within and present it to the user, while at the same the removing itself from the PS memory so that no junk data would be left behind... ๐Ÿ˜Ž Weeeell maybe that's for future versions haha. But good thing is that this plugin is now pretty much perfect for this use. I have plenty of PocketStation games to go through and who knows if some other game uses similar ID lock.

Thanks again!!

EDIT: And congrats for the world's first PS game crack ๐Ÿ˜๐ŸŽ‰

ShendoXT commented 9 months ago

You crazy sonovabitch, you did it! And it works! EDIT: And congrats for the world's first PS game crack ๐Ÿ˜๐ŸŽ‰

crash adance

Now imagine if there were a function in MemcardRex, "Read PocketStation serial", that when activated would present a "In progress, please wait.." screen to the user, while MemcardRex would write a tiny temporary app similar to BIOS tool to the PS, read devices ID, save it to a savefile, then download it back to PC, read the serial within and present it to the user, while at the same the removing itself from the PS memory so that no junk data would be left behind... ๐Ÿ˜Ž

There is certainly more fun to be had with PocketStation. I'll try to score one for myself so I can add more features to MemcardRex.

The serial read is not a bad idea, I believe PocketStation even has extended commands to easily report it's serial back to PlayStation.

Your idea could work also for a BIOS dumper, apparently you can upload applications to it's ram and execute them, so no need to mess with user apps on flash...

I'll include CrashReSign as standard for every new release from now on. One thing I was thinking it would benefit from is a dropdown menu to autofill serials from the popular emulators (PK201, no$gba, etc) so users don't have to hunt that info by themselves if they want to play the game on the emulator.

NKO55 commented 9 months ago

Hey this is a bit off topic but do you have email or anything that I could send a inquiry about different topic? You can ignore that if you don't have the time, and I totally understand it. I'm messing around with PocketStation coding project for my own fun and I've got a simple test app working, but there's one specific issue I'm having, and that is how reading the system time works. I mean it's basic C stuff for most people, I just have trouble figuring it out as I'm more of a graphics guy than a code guy lol. I could send more detailed description by email.

ShendoXT commented 9 months ago

You can find my email in the ReadMe.txt of MemcardRex. I avoid it posting publicly because of the spam of course.

But, have you heard of the PSX.Dev discord channel? Many enthusiasts, coders, emu authors, hw devs, etc hang there myself included and I'm sure if you ask the question there you will get the best possible solution to the problem. PocketStation devs like _Orion also frequent the channel.

Screenshot 2024-02-17 at 23 38 13
ShendoXT commented 3 months ago

image I know you'll appreciate this. Some cool stuff are coming in version 2.0 ๐Ÿ˜

NKO55 commented 3 months ago

Whaatt ๐Ÿ˜„๐Ÿ˜„ Pocketstation features hypee!!

Lรคhetetty Gmail Mobilesta

ma 5.8.2024 klo 17.09 Shendo @.***> kirjoitti:

image.png (view on web) https://github.com/user-attachments/assets/f27a5ad0-8341-4b1d-88ee-a0798ad699fa I know you'll appreciate this. Some cool stuff are coming in version 2.0 ๐Ÿ˜

โ€” Reply to this email directly, view it on GitHub https://github.com/ShendoXT/memcardrex/issues/48#issuecomment-2269173960, or unsubscribe https://github.com/notifications/unsubscribe-auth/AHWBRQN4C2J7VHXYBAV2RLDZP6BTPAVCNFSM6AAAAABDHA4TD2VHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMZDENRZGE3TGOJWGA . You are receiving this because you authored the thread.Message ID: @.***>

ShendoXT commented 2 months ago

Hey @NKO55 Would you like to beta test the newest build of MemcardRex?

I added support for PocketStation commands for both MemCARDuino and PS3 MC Adaptor.

So you can easily read serial, dump bios and push current date and time with a couple of clicks.

If you are interested I'll send you compiled build via email.

NKO55 commented 2 months ago

Hey!

Sure thing dude I can test it!

Lรคhetetty Gmail Mobilesta

su 8.9.2024 klo 16.11 Shendo @.***> kirjoitti:

Hey @NKO55 https://github.com/NKO55 Would you like to beta test the newest build of MemcardRex?

I added support for PocketStation commands for both MemCARDuino and PS3 MC Adaptor.

So you can easily read serial, dump bios and push current date and time with a couple of clicks.

If you are interested I'll send you compiled build via email.

โ€” Reply to this email directly, view it on GitHub https://github.com/ShendoXT/memcardrex/issues/48#issuecomment-2336681482, or unsubscribe https://github.com/notifications/unsubscribe-auth/AHWBRQK7O6ZRGPZ2SOWH3PDZVREHXAVCNFSM6AAAAABDHA4TD2VHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMZDGMZWGY4DCNBYGI . You are receiving this because you were mentioned.Message ID: @.***>