fix(sim): load Amiibo PWD/PACK into emulator memory at init, serve from memory

For tagType 7, when the PWD page is unset (0000) the UID-derived Amiibo
password and its PACK (0x8080) are now written into emulator memory at sim
init, and the PWD_AUTH path reads PWD and PACK straight from emulator memory.
Removes the auth-time pwd substitution and the PACK 0x8080 override, so
eset/eview are authoritative (what's in memory is what the sim serves) while
Amiibo sims still work.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
michael
2026-07-02 16:44:27 -07:00
co-authored by Claude Opus 4.8
parent fd5ad55104
commit b30bde22f6
+17 -29
View File
@@ -1644,18 +1644,21 @@ bool SimulateIso14443aInit(uint8_t tagType, uint16_t flags, uint8_t *data,
AddCrc14A(rPPS, sizeof(rPPS) - 2);
// EV1/NTAG, set PWD w AMIIBO algo if all zero.
// EV1/NTAG Amiibo: if no PWD is set, populate emulator memory with the UID-derived
// password and its PACK (0x8080) at the PWD/PACK pages, so the sim serves them from
// emulator memory like any other value. Auth and PACK are then read straight from
// memory, keeping eset/eview authoritative (what you set is what the sim serves).
if (tagType == 7) {
uint8_t pwd[4] = {0, 0, 0, 0};
uint8_t gen_pwd[4] = {0, 0, 0, 0};
emlGet(pwd, (*pages - 1) * 4 + MFU_DUMP_PREFIX_LENGTH, sizeof(pwd));
emlGet(rPACK, (*pages) * 4 + MFU_DUMP_PREFIX_LENGTH, sizeof(rPACK));
Uint4byteToMemBe(gen_pwd, ul_ev1_pwdgenB(data));
if (memcmp(pwd, gen_pwd, sizeof(pwd)) == 0) {
rPACK[0] = 0x80;
rPACK[1] = 0x80;
if (memcmp(pwd, "\x00\x00\x00\x00", 4) == 0) {
uint8_t amiibo_pwd[4] = {0, 0, 0, 0};
Uint4byteToMemLe(amiibo_pwd, ul_ev1_pwdgenB(data));
emlSet(amiibo_pwd, (*pages - 1) * 4 + MFU_DUMP_PREFIX_LENGTH, sizeof(amiibo_pwd));
uint8_t amiibo_pack[4] = {0x80, 0x80, 0x00, 0x00};
emlSet(amiibo_pack, (*pages) * 4 + MFU_DUMP_PREFIX_LENGTH, sizeof(amiibo_pack));
}
emlGet(rPACK, (*pages) * 4 + MFU_DUMP_PREFIX_LENGTH, sizeof(rPACK));
}
AddCrc14A(rPACK, sizeof(rPACK) - 2);
@@ -2347,33 +2350,18 @@ void SimulateIso14443aTagEx(uint8_t tagType, uint16_t flags, uint8_t *useruid, u
Dbhexdump(4, pwd, 0);
}
if (memcmp(pwd, "\x00\x00\x00\x00", 4) == 0) {
Uint4byteToMemLe(pwd, ul_ev1_pwdgenB(useruid));
if (g_dbglevel >= DBG_DEBUG) Dbprintf("Calc pwd... %02X %02X %02X %02X", pwd[0], pwd[1], pwd[2], pwd[3]);
}
// PWD comes straight from emulator memory (read above). For an unset (all-zero)
// PWD, the Amiibo password is populated into memory at sim init, so there's no
// substitution here -- eset/eview stay authoritative.
if (memcmp(receivedCmd + 1, pwd, 4) == 0) {
if (g_dbglevel >= DBG_DEBUG) Dbprintf("Password match, responding with PACK.");
// Serve PACK live from the PACK page (page `pages`) so a running-sim esetblk/eload
// of the PACK page takes effect without restarting the sim (page reads & PWD are
// already served live). Falls back to the same bytes as before for a static sim.
// Serve PACK straight from the PACK page (page `pages`) in emulator memory, so
// eset/eload of the PACK page is honored live. The Amiibo PACK (0x8080) for an
// unset PWD is populated into memory at sim init, so nothing special-cases here.
uint8_t pack_live[4] = {0, 0, 0, 0};
emlGet(pack_live, pages * 4 + MFU_DUMP_PREFIX_LENGTH, 2);
// Preserve init-time Amiibo behavior: if the stored PWD is the Amiibo-generated
// password, PACK is 0x8080. Keep in sync with the sim-init override (~L1650).
// NOTE: Be encoding here intentionally matches init; the pwd substitution above
// (Uint4byteToMemLe) is a separate pre-existing path and must stay Le.
uint8_t stored_pwd[4] = {0, 0, 0, 0};
uint8_t gen_pwd[4] = {0, 0, 0, 0};
emlGet(stored_pwd, (pages - 1) * 4 + MFU_DUMP_PREFIX_LENGTH, sizeof(stored_pwd));
Uint4byteToMemBe(gen_pwd, ul_ev1_pwdgenB(useruid));
if (memcmp(stored_pwd, gen_pwd, sizeof(stored_pwd)) == 0) {
pack_live[0] = 0x80;
pack_live[1] = 0x80;
}
dynamic_response_info.response[0] = pack_live[0];
dynamic_response_info.response[1] = pack_live[1];
AddCrc14A(dynamic_response_info.response, 2);