-
Notifications
You must be signed in to change notification settings - Fork 257
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Generate unique mempaks ID when formatting them #919
Conversation
- also better conform to expected factory formatted state according to @bryc research - unique mempak ID is based on xoshiro256++ PRNG seeded with current time. This should prove good enough for our purpose, while still being simple to implement. - added endian aware serialization primitives (loosely modeled after http://www.open-std.org/jtc1/sc22/wg14/www/docs/n2827.htm) - added xoshiro256++ PRNG functions
would have required C99 + some extension... :(
Code looks good to me. :) What mempak ID are actually used for? Why should we emulate it? Thanks in advance! |
What is the reason for using xoshiro256++ instead of rand() for a random number? We already use rand() elsewhere in the code for random numbers ( mupen64plus-core/src/device/r4300/interrupt.c Lines 119 to 123 in 6860d13
|
All mempaks when factory formatted are assigned a unique ID which is written (and backed up in many places) in mempak memory. This ID is useful for software to determine when switching between different paks if the newly plugged mempak is still the same as the last known memory pak. It shouldn't really change anything in practice though, because current m64p logic doesn't allow to change between different mempaks while in game. (You can switch between mempak, rumblepak, transferpak, none, and back to original mempak).
I chose xoshiro256++ because it was fast, recent and easy to implement. It also has other advantages regarding reproducibility:
|
Just giving my two cents 😄
When a user switches between controller paks on real hardware (physically remove and insert a different one), the checksum of the ID is checked to determine if a new pak was inserted. Some input plugins may allow pak swapping during emulation that can trigger this result. Also, the ID would've been used to support bank sizes beyond 32 KiB, but it was never fully realized.
Less hacky. It better models real world conditions. Future-proofing. Creating the .MPK as if it were brand new and unused. Real paks have unique serial numbers preinstalled to them when they flash the chip data, including even third-party ones (InterAct specifically). See: Mempak Serial block list to see real dumps of the preinstalled serial data (ID refers to the whole 32-byte block. The first 24 bytes is the 'serial number' part of the ID struct). When games do a 'repair' to a controller pak, a new serial is intentionally generated using a "random" value (technically the CP0 timer register value).
As mentioned before, actual games don't use random numbers. Even the preinstalled serials in official paks don't seem fully random (InterAct did use random numbers however). The library simply writes the current value of the CP0 timer (32-bit program counter), which isn't great, but is usually enough to make the checksum different. One homebrew utility does pak formatting this way: uint64_t sn = C0_COUNT(); // some form of entropy, time(0) would've worked too
for (i = 0; i < 24; i++) {
// simple 64-bit generator with decent statistics
sn ^= sn >> 27; sn *= 0x9E3779B97F4A7C55; sn ^= sn >> 33;
init_id_block[i] = sn; // set one byte AAT to the random output
} |
Personally, I'm more in favour of just using rand(), it would keep the code more simple, and seems like it would accomplish the same goal, but I'm fine with whatever, mupen64plus doesn't see a lot of development so I don't think we should be too picky about contributions if the author is happy with it. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
looks good to me. the PRNG is small so it's okay to leave in.
according to @bryc research
time. This should prove good enough for our purpose, while still being
simple to implement.