Merge branch 'RfidResearchGroup:master' into master

This commit is contained in:
Davi Mikael 2023-05-24 09:33:20 -03:00 committed by GitHub
commit 440c5ac1fa
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
16 changed files with 333 additions and 72 deletions

View file

@ -3,6 +3,11 @@ All notable changes to this project will be documented in this file.
This project uses the changelog in accordance with [keepchangelog](http://keepachangelog.com/). Please use this to write notable changes, which is not the same as git commit log... This project uses the changelog in accordance with [keepchangelog](http://keepachangelog.com/). Please use this to write notable changes, which is not the same as git commit log...
## [unreleased][unreleased] ## [unreleased][unreleased]
- Changed `hf mf sim` - reduce 6ms threshold to 4ms for reset to idle #1974 (@net147)
- Rebuilt the Spartan-2 `fpga_*.bit` files to include the `hi_iso14443a.v` update (@d18c7db)
- Added minor orphaned change from `hi_iso14443a.v` in `fpga-xc3s100e` to `hi_iso14443a.v` in `fpga-xc2s30` (@d18c7db)
- Added python3 script to convert amiibo nfc Flipper Zero files to eml files to be used with Proxmark3 (@OscarAkaElvis)
- Changed `hf mf restore` - Auth both key A and key B with default password (@wh201906)
- Changed `nfc decode -f` - now can detect and convert MFC dumpfiles to NDEF byte arrays (@iceman1001) - Changed `nfc decode -f` - now can detect and convert MFC dumpfiles to NDEF byte arrays (@iceman1001)
- Changed `nfc decode` - now handles EXTERNAL RECORDS better (@iceman1001) - Changed `nfc decode` - now handles EXTERNAL RECORDS better (@iceman1001)
- Fixed `nfc decode` - now handles NDEF Signature version1 records better (@iceman1001) - Fixed `nfc decode` - now handles NDEF Signature version1 records better (@iceman1001)
@ -61,6 +66,7 @@ This project uses the changelog in accordance with [keepchangelog](http://keepac
- Update documentation for installation on macOS with MacPorts (@linuxgemini) - Update documentation for installation on macOS with MacPorts (@linuxgemini)
- Added possible Paxton id to hitag2 tag info output - Added possible Paxton id to hitag2 tag info output
- Changed `hf mf sim` - reduce 50ms threshold to 6ms for reset to idle #1974 (@net147) - Changed `hf mf sim` - reduce 50ms threshold to 6ms for reset to idle #1974 (@net147)
- Update `amiibo_tools.lua` with new identifiers and create a python script `update_amiibo_tools_lua.py` to automate the process in the future. (@CorySolovewicz)
## [Nitride.4.16191][2023-01-29] ## [Nitride.4.16191][2023-01-29]
- Changed `build_all_firmwares.sh` to fit GENERIC 256kb firmware images (@doegox) - Changed `build_all_firmwares.sh` to fit GENERIC 256kb firmware images (@doegox)

View file

@ -655,6 +655,7 @@ static bool hitag2_password(uint8_t *rx, const size_t rxlen, uint8_t *tx, size_t
*txlen = 0; *txlen = 0;
if (bPwd && (bAuthenticating == false) && write) { if (bPwd && (bAuthenticating == false) && write) {
SpinDelay(2);
if (hitag2_write_page(rx, rxlen, tx, txlen) == false) { if (hitag2_write_page(rx, rxlen, tx, txlen) == false) {
return false; return false;
} }

View file

@ -2097,8 +2097,8 @@ int EmGetCmd(uint8_t *received, uint16_t *len, uint8_t *par) {
if (timer == 0) { if (timer == 0) {
timer = GetTickCount(); timer = GetTickCount();
} else { } else {
// 6ms no field --> card to idle state // 4ms no field --> card to idle state
if (GetTickCountDelta(timer) > 6) { if (GetTickCountDelta(timer) > 4) {
return 2; return 2;
} }
} }

View file

@ -2150,3 +2150,7 @@ D201DBB6AB6E
# Data from Discord, French pool # Data from Discord, French pool
9B7C25052FC3 9B7C25052FC3
494446555455 494446555455
#
# Data from Discord, seems to be related to ASSA
427553754D47

View file

@ -55,6 +55,9 @@ amiibo_tools.db =
["0x00000003039bff02"] = { ["0x00000003039bff02"] = {
name = "Mario - Power Up Band" name = "Mario - Power Up Band"
}, },
["0x000000030430ff02"] = {
name = "Golden - Power Up Band"
},
["0x0000010000190002"] = { ["0x0000010000190002"] = {
name = "Dr. Mario" name = "Dr. Mario"
}, },
@ -214,6 +217,9 @@ amiibo_tools.db =
["0x0100000003990902"] = { ["0x0100000003990902"] = {
name = "Link - Link's Awakening" name = "Link - Link's Awakening"
}, },
["0x0100000004180902"] = {
name = "Link - Tears of the Kingdom"
},
["0x0100010000160002"] = { ["0x0100010000160002"] = {
name = "Toon Link" name = "Toon Link"
}, },
@ -1834,6 +1840,9 @@ amiibo_tools.db =
["0x0800010003820002"] = { ["0x0800010003820002"] = {
name = "Inkling" name = "Inkling"
}, },
["0x0800010004150402"] = {
name = "Inkling - Yellow"
},
["0x08000200003f0402"] = { ["0x08000200003f0402"] = {
name = "Inkling Boy" name = "Inkling Boy"
}, },
@ -1870,9 +1879,15 @@ amiibo_tools.db =
["0x08050200038f0402"] = { ["0x08050200038f0402"] = {
name = "Octoling Boy" name = "Octoling Boy"
}, },
["0x08050200041b0402"] = {
name = "Octoling - Blue"
},
["0x0805030003900402"] = { ["0x0805030003900402"] = {
name = "Octoling Octopus" name = "Octoling Octopus"
}, },
["0x08060100041c0402"] = {
name = "Smallfry"
},
["0x09c0010102690e02"] = { ["0x09c0010102690e02"] = {
name = "Mario - Soccer" name = "Mario - Soccer"
}, },
@ -2374,6 +2389,9 @@ amiibo_tools.db =
["0x3380000003781402"] = { ["0x3380000003781402"] = {
name = "Solaire of Astora" name = "Solaire of Astora"
}, },
["0x33c0000004200002"] = {
name = "Kazuya"
},
["0x3480000000310002"] = { ["0x3480000000310002"] = {
name = "Mega Man" name = "Mega Man"
}, },
@ -2455,6 +2473,9 @@ amiibo_tools.db =
["0x3600010003620002"] = { ["0x3600010003620002"] = {
name = "Cloud - Player 2" name = "Cloud - Player 2"
}, },
["0x3601000004210002"] = {
name = "Sephiroth"
},
["0x3640000003a20002"] = { ["0x3640000003a20002"] = {
name = "Hero" name = "Hero"
}, },
@ -2520,6 +2541,12 @@ amiibo_tools.db =
}, },
["0x3c80000003a40002"] = { ["0x3c80000003a40002"] = {
name = "Terry" name = "Terry"
},
["0x3dc0000004220002"] = {
name = "Steve"
},
["0x3dc1000004230002"] = {
name = "Alex"
} }
}, },
game_series = { game_series = {
@ -2621,6 +2648,7 @@ amiibo_tools.db =
["0x324"] = "Bayonetta", ["0x324"] = "Bayonetta",
["0x334"] = "Pac-man", ["0x334"] = "Pac-man",
["0x338"] = "Dark Souls", ["0x338"] = "Dark Souls",
["0x33c"] = "Tekken",
["0x348"] = "Megaman", ["0x348"] = "Megaman",
["0x34c"] = "Street fighter", ["0x34c"] = "Street fighter",
["0x350"] = "Monster Hunter", ["0x350"] = "Monster Hunter",
@ -2635,7 +2663,8 @@ amiibo_tools.db =
["0x38c"] = "Diablo", ["0x38c"] = "Diablo",
["0x3a0"] = "Persona", ["0x3a0"] = "Persona",
["0x3b4"] = "Banjo Kazooie", ["0x3b4"] = "Banjo Kazooie",
["0x3c8"] = "Fatal Fury" ["0x3c8"] = "Fatal Fury",
["0x3dc"] = "Minecraft"
}, },
types = { types = {
["0x00"] = "Figure", ["0x00"] = "Figure",

112
client/pyscripts/pm3_nfc2eml.py Executable file
View file

@ -0,0 +1,112 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Script to convert amiibo nfc Flipper Zero files to eml files to be used with Proxmark3
Date: 18/05/2023
Script Author: OscarAkaElvis
Tested on: Linux and Windows
OscarAkaElvis - https://twitter.com/OscarAkaElvis
"""
import re
import argparse
import os
from os import path
from sys import argv
# Vars
script_name = path.basename(argv[0])
script_version = "1.0"
# Function to print script's version
def print_version():
print()
return 'v{}'.format(script_version)
# Check if the input file is a text file based on its content
def is_text_file(file_path):
with open(file_path, 'rb') as file:
try:
file_content = file.read().decode('utf-8')
return all(ord(char) < 128 for char in file_content)
except UnicodeDecodeError:
return False
# Main script code
def main():
# Text help data
description_text = "Script to convert amiibo nfc Flipper Zero files to eml files to be used with Proxmark3."
epilog_text = 'Example:\n python3 ' + script_name + ' -i file.nfc -o output.eml'
# Create an argument parser
parser = argparse.ArgumentParser(exit_on_error=False, description=description_text, formatter_class=argparse.RawDescriptionHelpFormatter, epilog=epilog_text)
# Add the input file argument
parser.add_argument("-i", "--input", required=True, help="Path to the input nfc file.")
# Add the output file argument
parser.add_argument("-o", "--output", required=True, help="Name of the output eml file.")
# Add the version argument
parser.add_argument('-v', '--version', action='version', version=print_version(), help="Show script's version number and exit")
# Parse the command-line arguments
args = parser.parse_args()
# Extract the file paths from the command-line arguments
file_path = args.input
output_file = args.output
# Check if the target file exists
if not os.path.isfile(file_path):
print(f"[!] The input file '{file_path}' does not exist.")
exit(0)
# Validation to check if the input file is a text file based on its content
if not is_text_file(file_path):
print("[!] The input file does not appear to be a nfc text file.")
# Check if the input file name has the .nfc extension
if not file_path.lower().endswith('.nfc'):
print("[+] Warning. The input file should have the '.nfc' extension.")
# Get the absolute path of the output file
output_file_path = os.path.abspath(output_file)
# Check if the directory of the output file is writable
output_dir = os.path.dirname(output_file_path)
if not os.access(output_dir, os.W_OK):
print(f"[!] The output directory '{output_dir}' is not writable or doesn't exist.")
# Check if the output file name has the .eml extension
if not output_file.lower().endswith('.eml'):
print("[+] Warning. The output file should have the '.eml' extension.")
# Read the target file
with open(file_path, 'r') as file:
file_content = file.read()
# Extract the data from each "Page X" line
matches = re.findall(r'Page \d+:(.*?)$', file_content, re.MULTILINE | re.DOTALL)
if matches:
# Remove spaces and convert to lowercase for each match
extracted_data = [re.sub(r'\s', '', match).lower() for match in matches]
# Join the extracted data with line feeds
result = '\n'.join(extracted_data)
# Write the extracted data to the output file
with open(output_file_path, 'w', newline='\n') as output_file:
output_file.write(result)
print(f"[*] File converted successfully. Output eml file written as '{os.path.basename(output_file.name)}'.")
else:
# If the needed data is not there
print("[!] Provided input file seems to not be a valid nfc file to work with.")
# Application entrypoint
if __name__ == '__main__':
try:
main()
except:
pass

View file

@ -137,15 +137,14 @@ static char *GenerateFilename(const char *prefix, const char *suffix) {
static int initSectorTable(sector_t **src, size_t items) { static int initSectorTable(sector_t **src, size_t items) {
(*src) = calloc(items, sizeof(sector_t)); (*src) = calloc(items, sizeof(sector_t));
if (*src == NULL) if (*src == NULL)
return PM3_EMALLOC; return PM3_EMALLOC;
// empty e_sector // empty e_sector
for (int i = 0; i < items; ++i) { for (int i = 0; i < items; i++) {
for (int j = 0; j < 2; ++j) { for (int j = 0; j < 2; j++) {
(*src)[i].Key[j] = 0xffffffffffff; (*src)[i].Key[j] = 0xffffffffffff;
(*src)[i].foundKey[j] = false; (*src)[i].foundKey[j] = 0;
} }
} }
return PM3_SUCCESS; return PM3_SUCCESS;
@ -1109,7 +1108,7 @@ static int CmdHF14AMfRestore(const char *Cmd) {
"Restore MIFARE Classic dump file to tag.\n" "Restore MIFARE Classic dump file to tag.\n"
"\n" "\n"
"The key file and dump file will program the card sector trailers.\n" "The key file and dump file will program the card sector trailers.\n"
"By default we authenticate to card with key B 0xFFFFFFFFFFFF.\n" "By default we authenticate to card with key 0xFFFFFFFFFFFF.\n"
"If access rights in dump file is all zeros, it will be replaced with default values\n" "If access rights in dump file is all zeros, it will be replaced with default values\n"
"\n" "\n"
"`--uid` param is used for filename templates `hf-mf-<uid>-dump.bin` and `hf-mf-<uid>-key.bin.\n" "`--uid` param is used for filename templates `hf-mf-<uid>-dump.bin` and `hf-mf-<uid>-key.bin.\n"
@ -1321,56 +1320,37 @@ static int CmdHF14AMfRestore(const char *Cmd) {
uint8_t wdata[26]; uint8_t wdata[26];
memcpy(wdata + 10, bldata, sizeof(bldata)); memcpy(wdata + 10, bldata, sizeof(bldata));
if (use_keyfile_for_auth) { for (int8_t kt = MF_KEY_B; kt > -1; kt--) {
for (int8_t kt = MF_KEY_B; kt > -1; kt--) { if (use_keyfile_for_auth) {
if (kt == MF_KEY_A) if (kt == MF_KEY_A)
memcpy(wdata, keyA[s], 6); memcpy(wdata, keyA[s], 6);
else else
memcpy(wdata, keyB[s], 6); memcpy(wdata, keyB[s], 6);
} else {
PrintAndLogEx(INFO, "block %3d: %s", mfFirstBlockOfSector(s) + b, sprint_hex(bldata, sizeof(bldata))); // use default key to authenticate for the write command
memcpy(wdata, default_key, 6);
clearCommandBuffer();
SendCommandMIX(CMD_HF_MIFARE_WRITEBL, mfFirstBlockOfSector(s) + b, kt, 0, wdata, sizeof(wdata));
PacketResponseNG resp;
if (WaitForResponseTimeout(CMD_ACK, &resp, 1500)) {
uint8_t isOK = resp.oldarg[0] & 0xff;
if (isOK == 0) {
if (b == 0) {
PrintAndLogEx(INFO, "Writing to manufacture block w key %c ( " _RED_("fail") " )", (kt == MF_KEY_A) ? 'A' : 'B');
} else {
PrintAndLogEx(FAILED, "Write to block %u w key %c ( " _RED_("fail") " ) ", b, (kt == MF_KEY_A) ? 'A' : 'B');
}
} else {
// if success, skip to next block
break;
}
} else {
PrintAndLogEx(WARNING, "Command execute timeout");
}
} }
} else {
// use default key to authenticate for the write command
memcpy(wdata, default_key, 6);
PrintAndLogEx(INFO, "block %3d: %s", mfFirstBlockOfSector(s) + b, sprint_hex(bldata, sizeof(bldata))); PrintAndLogEx(INFO, "block %3d: %s", mfFirstBlockOfSector(s) + b, sprint_hex(bldata, sizeof(bldata)));
clearCommandBuffer(); clearCommandBuffer();
SendCommandMIX(CMD_HF_MIFARE_WRITEBL, mfFirstBlockOfSector(s) + b, MF_KEY_B, 0, wdata, sizeof(wdata)); SendCommandMIX(CMD_HF_MIFARE_WRITEBL, mfFirstBlockOfSector(s) + b, kt, 0, wdata, sizeof(wdata));
PacketResponseNG resp; PacketResponseNG resp;
if (WaitForResponseTimeout(CMD_ACK, &resp, 1500)) { if (WaitForResponseTimeout(CMD_ACK, &resp, 1500)) {
uint8_t isOK = resp.oldarg[0] & 0xff; uint8_t isOK = resp.oldarg[0] & 0xff;
if (isOK == 0) { if (isOK == 0) {
if (b == 0) { if (b == 0) {
PrintAndLogEx(INFO, "Writing to manufacture block w key B ( " _RED_("fail") " )"); PrintAndLogEx(INFO, "Writing to manufacture block w key %c ( " _RED_("fail") " )", (kt == MF_KEY_A) ? 'A' : 'B');
} else { } else {
PrintAndLogEx(FAILED, "Write to block %u w key B ( " _RED_("fail") " )", b); PrintAndLogEx(FAILED, "Write to block %u w key %c ( " _RED_("fail") " ) ", b, (kt == MF_KEY_A) ? 'A' : 'B');
} }
} else {
// if success, skip to next block
break;
} }
} else { } else {
PrintAndLogEx(WARNING, "Command execute timeout"); PrintAndLogEx(WARNING, "Command execute timeout");
} }
} // end use_keyfile_for_auth }
} // end loop B } // end loop B
} // end loop S } // end loop S

View file

@ -2690,7 +2690,7 @@ static void wait4response(uint8_t b) {
int CmdHF14MfUTamper(const char *Cmd) { int CmdHF14MfUTamper(const char *Cmd) {
CLIParserContext *ctx; CLIParserContext *ctx;
CLIParserInit(&ctx, "hf mfu tamper", CLIParserInit(&ctx, "hf mfu tamper",
"Set the congiguration of the NTAG 213TT tamper feature\n" "Set the configuration of the NTAG 213TT tamper feature\n"
"Supports:\n" "Supports:\n"
"NTAG 213TT\n", "NTAG 213TT\n",
"hf mfu tamper -e -> enable tamper feature\n" "hf mfu tamper -e -> enable tamper feature\n"
@ -4697,7 +4697,7 @@ static command_t CommandTable[] = {
{"restore", CmdHF14AMfURestore, IfPm3Iso14443a, "Restore a dump onto a MFU MAGIC tag"}, {"restore", CmdHF14AMfURestore, IfPm3Iso14443a, "Restore a dump onto a MFU MAGIC tag"},
{"view", CmdHF14AMfuView, AlwaysAvailable, "Display content from tag dump file"}, {"view", CmdHF14AMfuView, AlwaysAvailable, "Display content from tag dump file"},
{"wrbl", CmdHF14AMfUWrBl, IfPm3Iso14443a, "Write block"}, {"wrbl", CmdHF14AMfUWrBl, IfPm3Iso14443a, "Write block"},
{"tamper", CmdHF14MfUTamper, IfPm3Iso14443a, "Cofigure the tamper feature on an NTAG 213TT"}, {"tamper", CmdHF14MfUTamper, IfPm3Iso14443a, "Configure the tamper feature on an NTAG 213TT"},
{"---------", CmdHelp, IfPm3Iso14443a, "----------------------- " _CYAN_("simulation") " -----------------------"}, {"---------", CmdHelp, IfPm3Iso14443a, "----------------------- " _CYAN_("simulation") " -----------------------"},
{"eload", CmdHF14AMfUeLoad, IfPm3Iso14443a, "Load Ultralight dump file into emulator memory"}, {"eload", CmdHF14AMfUeLoad, IfPm3Iso14443a, "Load Ultralight dump file into emulator memory"},
{"esave", CmdHF14AMfuESave, IfPm3Iso14443a, "Save Ultralight dump file from emulator memory"}, {"esave", CmdHF14AMfuESave, IfPm3Iso14443a, "Save Ultralight dump file from emulator memory"},

View file

@ -43,10 +43,36 @@
static const uint64_t g_mifare_default_keys[] = { static const uint64_t g_mifare_default_keys[] = {
0xffffffffffff, // Default key (first key used by program if no user defined key) 0xffffffffffff, // Default key (first key used by program if no user defined key)
0x000000000000, // Blank key
0xa0a1a2a3a4a5, // NFCForum MAD key 0xa0a1a2a3a4a5, // NFCForum MAD key
0xd3f7d3f7d3f7, // NDEF public key 0xd3f7d3f7d3f7, // NDEF public key
0x4b791bea7bcc, // MFC EV1 Signature B 0x4b791bea7bcc, // MFC EV1 Signature B
0xfc00018778f7, // Public Transport
0x6471a5ef2d1a, // SimonsVoss
0x4E3552426B32, // ID06
0x6A1987C40A21, // Salto
0xef1232ab18a0, // Schlage
0x3B7E4FD575AD, //
0xb7bf0c13066e, // Gallagher
0x135b88a94b8b, // Saflok
0x2A2C13CC242A, // Dorma Kaba
0x5a7a52d5e20d, // Bosch
0x314B49474956, // VIGIK1 A
0x564c505f4d41, // VIGIK1 B
0x021209197591, // BTCINO
0x484558414354, // Intratone
0xEC0A9B1A9E06, // Vingcard
0x66b31e64ca4b, // Vingcard
0x97F5DA640B18, // Bangkok metro key
0xA8844B0BCA06, // Metro Valencia key
0xE4410EF8ED2D, // Armenian metro
0x857464D3AAD1, // HTC Eindhoven key
0x08B386463229, // troika
0xe00000000000, // icopy
0x199404281970, // NSP A
0x199404281998, // NSP B
0x6A1987C40A21, // SALTO
0x7F33625BC129, // SALTO
0x000000000000, // Blank key
0xb0b1b2b3b4b5, 0xb0b1b2b3b4b5,
0xaabbccddeeff, 0xaabbccddeeff,
0x1a2b3c4d5e6f, 0x1a2b3c4d5e6f,
@ -64,29 +90,6 @@ static const uint64_t g_mifare_default_keys[] = {
0x0000014b5c31, 0x0000014b5c31,
0xb578f38a5c61, 0xb578f38a5c61,
0x96a301bce267, 0x96a301bce267,
0xfc00018778f7, // Public Transport
0x6471a5ef2d1a, // SimonsVoss
0x4E3552426B32, // ID06
0x6A1987C40A21, // Salto
0xef1232ab18a0, // Schlage
0x3B7E4FD575AD, //
0xb7bf0c13066e, // Gallagher
0x135b88a94b8b, // Saflock
0x5a7a52d5e20d, // Bosch
0x314B49474956, // VIGIK1 A
0x564c505f4d41, // VIGIK1 B
0x021209197591, // BTCINO
0x484558414354, // Intratone
0xEC0A9B1A9E06, // Vingcard
0x66b31e64ca4b, // Vingcard
0x97F5DA640B18, // Bangkok metro key
0xA8844B0BCA06, // Metro Valencia key
0xE4410EF8ED2D, // Armenian metro
0x857464D3AAD1, // HTC Eindhoven key
0x08B386463229, // troika
0xe00000000000, // icopy
0x199404281970, // NSP A
0x199404281998, // NSP B
}; };
static const uint8_t g_mifare_default_key[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; static const uint8_t g_mifare_default_key[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};

View file

@ -923,7 +923,7 @@ static int ndefDecodeExternal_record(NDEFHeader_t *ndef) {
); );
PrintAndLogEx(NORMAL, ""); PrintAndLogEx(NORMAL, "");
PrintAndLogEx(INFO, "Payload [%u]...", ndef->PayloadLen); PrintAndLogEx(INFO, "Payload [%zu]...", ndef->PayloadLen);
print_hex_noascii_break(ndef->Payload, ndef->PayloadLen, 32); print_hex_noascii_break(ndef->Payload, ndef->PayloadLen, 32);
// do a character check? // do a character check?

View file

@ -0,0 +1,114 @@
#!/usr/bin/env python3
"""
-----------------------------------------------------------------------------
Name: update_amiibo_tools_lua.py
Author: Cory Solovewicz
Description:
This is a python script to automate what the updating of the amiibo_tools.lua
file which holds a lua table of all known amiibos. Previously updating the
amiibo_tools.lua was a very manual process.
This script automates the following original command:
curl https://raw.githubusercontent.com/N3evin/AmiiboAPI/master/database/amiibo.json | jq 'del(.amiibos[].release)' | jq 'del(.characters)' | pbcopy --> transform to table
And outputs the formatted file as amiibo_tools.lua
If everything goes well, this should be an updated copy of amiibo_tools.lua
which can then be placed in the /lualibs/ directory.
The temporary amiibo.json file is then deleted
Dependencies:
python3 -m pip install jq
How to run:
python update_amiibo_tools_lua.py
The script will create the file amiibo_tools.lua
After running, manually backup the original /lualibs/amiibo_tools.lua and move the
updated amiibo_tools.lua to the /lualibs/ directory.
-----------------------------------------------------------------------------
"""
import os
import re
import subprocess
import json
from jq import jq
def fetch_data():
print("Fetching amiibo.json")
# Perform the curl command
curl_command = "curl https://raw.githubusercontent.com/N3evin/AmiiboAPI/master/database/amiibo.json"
curl_process = subprocess.Popen(curl_command.split(), stdout=subprocess.PIPE, stderr=subprocess.PIPE)
output, error = curl_process.communicate()
if curl_process.returncode != 0:
print("Error fetching data: ", error.decode())
return None
return output
def filter_data(data):
print("Filtering downloaded data")
# Convert the output to JSON and use jq to filter data
data_json = json.loads(data)
filtered_data_json = jq('del(.amiibos[].release) | del(.characters)').transform(data_json)
# Convert the filtered JSON data back to a string, preserving Unicode characters
filtered_data = json.dumps(filtered_data_json, indent=2, ensure_ascii=False)
return filtered_data
def save_data(filtered_data, filename):
# Save filtered data to file
with open(filename, 'w', encoding='utf-8') as file:
file.write(filtered_data)
print(f"Data saved to {filename}")
def process_file(filename):
# Open the file
with open(filename, 'r', encoding='utf-8') as file:
data = file.read()
# Perform the replacements
data = data.replace('"name"', 'name')
data = data.replace('"amiibo_series"', 'amiibo_series')
data = data.replace('"amiibos"', 'amiibos')
data = data.replace('"game_series"', 'game_series')
data = data.replace('"types"', 'types')
data = data.replace(':', ' =')
data = re.sub('"0x', '["0x', data)
data = re.sub('" =', '"] =', data)
# Prepend the text
prepend_text = 'local amiibo_tools = {}\n\n-- curl https://raw.githubusercontent.com/N3evin/AmiiboAPI/master/database/amiibo.json | jq \'del(.amiibos[].release)\' | jq \'del(.characters)\' | pbcopy --> transform to table\namiibo_tools.db =\n'
data = prepend_text + data
# Append the text
append_text = '\n\nreturn amiibo_tools\n'
data = data + append_text
return data
def write_to_file(data, filename):
# Write the output
with open(filename, 'w', encoding='utf-8') as file:
file.write(data)
print(f"Output written to {filename}")
def delete_file(filename):
try:
os.remove(filename)
print(f"Temporary file {filename} deleted")
except OSError as e:
print(f"Error deleting file {filename}: ", e)
def main():
data = fetch_data()
if data:
filtered_data = filter_data(data)
save_data(filtered_data, 'amiibo.json')
processed_data = process_file('amiibo.json')
write_to_file(processed_data, 'amiibo_tools.lua')
delete_file('amiibo.json')
if __name__ == "__main__":
main()

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View file

@ -222,17 +222,29 @@ reg signed [10:0] rx_mod_falling_edge_max;
reg signed [10:0] rx_mod_rising_edge_max; reg signed [10:0] rx_mod_rising_edge_max;
reg curbit; reg curbit;
`define EDGE_DETECT_THRESHOLD 5 `define EDGE_DETECT_THRESHOLD 3
`define EDGE_DETECT_THRESHOLDHIGH 20
always @(negedge adc_clk) always @(negedge adc_clk)
begin begin
if(negedge_cnt[3:0] == mod_detect_reset_time) if(negedge_cnt[3:0] == mod_detect_reset_time)
begin begin
// detect modulation signal: if modulating, there must have been a falling AND a rising edge if (mod_type == `FPGA_HF_ISO14443A_SNIFFER)
if ((rx_mod_falling_edge_max > `EDGE_DETECT_THRESHOLD) && (rx_mod_rising_edge_max < -`EDGE_DETECT_THRESHOLD)) begin
curbit <= 1'b1; // modulation // detect modulation signal: if modulating, there must have been a falling AND a rising edge
else if ((rx_mod_falling_edge_max > `EDGE_DETECT_THRESHOLDHIGH) && (rx_mod_rising_edge_max < -`EDGE_DETECT_THRESHOLDHIGH))
curbit <= 1'b0; // no modulation curbit <= 1'b1; // modulation
else
curbit <= 1'b0; // no modulation
end
else
begin
// detect modulation signal: if modulating, there must have been a falling AND a rising edge
if ((rx_mod_falling_edge_max > `EDGE_DETECT_THRESHOLD) && (rx_mod_rising_edge_max < -`EDGE_DETECT_THRESHOLD))
curbit <= 1'b1; // modulation
else
curbit <= 1'b0; // no modulation
end
// reset modulation detector // reset modulation detector
rx_mod_rising_edge_max <= 0; rx_mod_rising_edge_max <= 0;
rx_mod_falling_edge_max <= 0; rx_mod_falling_edge_max <= 0;