diff --git a/.vscode/settings.json b/.vscode/settings.json
index 70322889..4f9e9321 100644
--- a/.vscode/settings.json
+++ b/.vscode/settings.json
@@ -35,6 +35,9 @@
"nrf_log.h": "c",
"string.h": "c",
"math.h": "c",
- "mlib_common.h": "c"
+ "mlib_common.h": "c",
+ "ios": "c",
+ "limits": "c",
+ "algorithm": "c"
}
}
\ No newline at end of file
diff --git a/docs/en/02-Flash-Firmware.md b/docs/en/02-Flash-Firmware.md
index 4968df54..3503f900 100644
--- a/docs/en/02-Flash-Firmware.md
+++ b/docs/en/02-Flash-Firmware.md
@@ -73,8 +73,11 @@ First make sure your device is in off state, then press key sequences bellow to
- Any key to wake up the device
- LEFT
- MIDDLE
-- LEFT X 4
+- LEFT X N
- MIDDLE
+If the firmware version before 2.11.x, press LEFT x 4
+If the firmware version after 2.11.x, press LEFT x 5
+
Now you device is on DFU mode, use any of the [nRF Connect APP](#nRF-Connect-APP) or [Directly to the Firmware Update Page](#directly-to-the-firmware-update-page) methods to upgrade the fimware.
diff --git a/docs/en/04-Using-Firmware.md b/docs/en/04-Using-Firmware.md
index 908d2105..fce02d91 100644
--- a/docs/en/04-Using-Firmware.md
+++ b/docs/en/04-Using-Firmware.md
@@ -47,7 +47,11 @@ You can browse folders and files using the thumbwheel slide dial switch, pushing
Once you select a .BIN file his data is used like the current amiibo, the screen shows current amiibo details like amiibo current UUID, filename and amiibo name.
## Amiibo details screen
-You can use side buttons to change the current amiibo with the next or previous one on the current folder. Pressing the middle button you can change the behavior of the current amiibo, on the sub menu:
+You can use side buttons to change the current amiibo with the next or previous one on the current folder.
+If the amiibo file is marked as read-only, an info icon will be displayed in front of the amiiboe file name line.
+
+## Amiibo detail menu
+Pressing the middle button you can change the behavior of the current amiibo, on the sub menu:
| |
| ------------ |
@@ -58,6 +62,8 @@ You can use side buttons to change the current amiibo with the next or previous
Changes the current UUID presented to game to current amiibo. The new UUID stays in place until you change the current amiibo or select this option again.
### Auto Rand. (Automatic Random)
Turning ON this feature, will generate a new random UUID for the current amiibo each time a game read it. Allowing to use the same amiibo multiple times on games with restrictions.
+### Read-only
+Turning on this feature, any write operation to this tag will be denied.
### Delete Tag
Delete the file associated to current amiibo.
### Back to Tag Details
@@ -90,32 +96,6 @@ Returns to the file list of current folder.
### Back to Main Menu
Exit the amiibo emulator application.
-If you have **highlighted a storage** the properties sub menu is different:
-
-| |
-| ------------ |
-| Storage Status
Total Space
Free Space
Format…
Back List
Back to Main Menu |
-| |
-
-### Storage Status
-Shows the current status and type of the storage, by example:
-```
-=====Not Mounted=====
-===Mounted[LFS]===
-===Mounted[FFS]===
-```
-
-### Total Space
-Shows total space of the mounted storage on KB.
-### Free Space
-Shows the actual free space of the mounted storage on KB.
-### Format…
-Ask confirmation for formatting the current storage, WARNING ALL DATA WILL BE LOST!
-### Back to File List
-Returns to the file list of current folder.
-### Back to Main Menu
-Exit the amiibo emulator application.
-
----
# Amiibo Database
This application allows the emulation of amiibo from the list of well know ones, using legally available information like the model info, then when you select one, a new virtual amiibo is created on memory using a random UUID. In order to use this application you must to provide your «key_retail.bin» file.
@@ -193,6 +173,8 @@ List the configured slots, you can browse the slots using side buttons, select o
If you press and hold middle button a sub menu with the option of reset the slot is shown allowing to empty the slot.
+If you turn on the Read-only feature, the current amiibo slot will denied write operation to this slot. An info icon will be displayed in front of the amiibo name if read-only feature is enabled.
+
## Settings…
The settings menu show you the Keys status and number of slot set up.
@@ -276,9 +258,15 @@ Mifare cards are commonly used for access control cards, and the device can full
NTAG series cards are commonly used for device identification. Supported NTAG card types include:
+* NTAG 210
+* NTAG 212
* NTAG 213
* NTAG 215
* NTAG 216
+* Mifire Ultralight C
+* Mifire Ultralight C
+* Mifire Ultralight EV1(640 bits)
+* Mifire Ultralight EV1(1312 bits)
Currently, a total of 8 cards are supported, with the option for customizing the number of cards in the future.
@@ -317,9 +305,17 @@ Abbreviations for card types:
| MF 1k | Mifare 1K | 1024 |
| MF 2k | Mifare 2K | 2048 |
| MF 4k | Mifare 4K | 4096 |
+| N210 | NTAG 210 | 80 |
+| N212 | NTAG 212 | 164 |
| N213 | NTAG 213 | 180 |
| N215 | NTAG 215 | 540 |
| N216 | NTAG 216 | 924 |
+| MFUL | Mifare Ultralight | 64 |
+| MFULC | Mifare Ultralight C | 144 |
+| MFEV11 | Mifare Ultralight EV1(640 bits) | 80 |
+| MFEV21 | Mifare Ultralight EV1(1312 bits) | 164 |
+
+* It will display a fav icon if the card is default card. The default card is the card that is automatically activated when the device is wakeup by NFC field presents.
# Main Menu
@@ -342,6 +338,7 @@ Pressing the middle button allows you to enter the main menu. As follows:
* Nick: The current name of the card. Pressing the middle button can enter the card name setting interface.
* ID: Displays the current card ID.
* Type: Displays the current card type.
+* Default Card: if enabled, the card will be automatically activated when the device is wakeup by NFC field presents.
* Data: Pressing the middle button can manage card data.
* Advanced: Pressing the middle button can enter advanced card settings.
* Slot Settings: Pressing the middle button enters the slot management interface, where you can enable or disable card slots.
@@ -350,6 +347,7 @@ Pressing the middle button allows you to enter the main menu. As follows:
> **Special Note:**:
> Some modifications need to be saved to storage when exiting to the tag details. If you have modified some configurations, be sure to enter the tag details page to save them.
+> The default card feature is conflict with Fast Resume. If the default card feature is enabled, the device will active the card emulator of the default card instead of the amiibo Fast Resume feature.
## Nick Update
@@ -510,3 +508,9 @@ This option put the device in the DFU mode, allowing OTA firmware update, you ca
You can go to the URL [https://thegecko.github.io/web-bluetooth-dfu/](https://thegecko.github.io/web-bluetooth-dfu/) to upload the firmware, this page also can be open through the official site [https://pixl.amiibo.xyz/](https://pixl.amiibo.xyz/)
## System Reboot
Allows you to reboot the device and get back to the state after you remove and put the battery.
+
+## Reset Default Settings
+Reset all settings to default values.
+
+## About Device
+Show Pixl.js project information, include source code repository, license.
\ No newline at end of file
diff --git a/docs/zh/02-Flash-Firmware.md b/docs/zh/02-Flash-Firmware.md
index 8af0a778..f7bfef73 100644
--- a/docs/zh/02-Flash-Firmware.md
+++ b/docs/zh/02-Flash-Firmware.md
@@ -73,9 +73,12 @@ openocd -f interface/cmsis-dap.cfg -c "transport select swd" -f target/nrf52.cfg
任意键唤醒设备
左
中
-左 x 4
+左 x N
中
+如果固件版本小于 2.11.x, 按左 x 4。
+如果固件版本大于 2.11.x, 按左 x 5。
+
现在您的设备已经进入了DFU模式,请使用任何 [nRF Connect APP](#nRF-Connect-APP) 或 [直接进入固件页面更新](#directly-to-the-firmware-update-page) 的方法来升级固件。
diff --git a/docs/zh/04-Using-Firmware.md b/docs/zh/04-Using-Firmware.md
index e9036201..b8736591 100644
--- a/docs/zh/04-Using-Firmware.md
+++ b/docs/zh/04-Using-Firmware.md
@@ -156,9 +156,15 @@ Mifare卡片常见用于门禁卡,设备可以支持完整模拟Mifare类型
NTAG系列卡片常用于设备识别。支持的NTAG卡片类型有:
+* NTAG 210
+* NTAG 212
* NTAG 213
* NTAG 215
* NTAG 216
+* Mifire Ultralight C
+* Mifire Ultralight C
+* Mifire Ultralight EV1(640 bits)
+* Mifire Ultralight EV1(1312 bits)
目前总共支持存储8张卡片,后续开放自定义卡片数量。
@@ -186,7 +192,7 @@ NTAG系列的模拟功能还是测试中,功能还不太完善,未完全模
界面说明如下:
* 第一行:`01` 是卡片序号,`de:ad:be:ef`是卡号。
* 第二行:`卡槽 01`是当前卡的名字,可以自由设置
-* 第三行:`MF 1K` 显示了卡类型,类型简写见下表,`08`是卡的SAK,`04 00`是卡的ATQA 最后一个符号是写入模式,如果是存储类型标记,则允许写入,否则不允许写入
+* 第三行:`MF 1K` 显示了卡类型,类型简写见下表,`08`是卡的SAK,`04 00`是卡的ATQA 最后一个符号是写入模式,如果是存储类型标记,则允许写入,否则不允许写入。如果当前卡片设置了默认卡片,设备会展示一个收藏图标作为提示。
| 显示 | 类型 | 数据文件大小 |
| ---- | --- | --- |
@@ -194,9 +200,15 @@ NTAG系列的模拟功能还是测试中,功能还不太完善,未完全模
| MF 1k | Mifare 1K | 1024 |
| MF 2k | Mifare 2K | 2048 |
| MF 4k | Mifare 4K | 4096 |
+| N210 | NTAG 210 | 80 |
+| N212 | NTAG 212 | 164 |
| N213 | NTAG 213 | 180 |
| N215 | NTAG 215 | 540 |
| N216 | NTAG 216 | 924 |
+| MFUL | Mifare Ultralight | 64 |
+| MFULC | Mifare Ultralight C | 144 |
+| MFEV11 | Mifare Ultralight EV1(640 bits) | 80 |
+| MFEV21 | Mifare Ultralight EV1(1312 bits) | 164 |
# 主菜单
@@ -207,6 +219,7 @@ NTAG系列的模拟功能还是测试中,功能还不太完善,未完全模
| 卡名 [卡槽 01]|
| ID [de:ad:be:ef]|
| 卡类型 [MiFare 1K] |
+| 默认卡片 [开] |
| 卡数据.. |
| 卡高级设置.. |
| 卡槽管理.. |
@@ -218,6 +231,7 @@ NTAG系列的模拟功能还是测试中,功能还不太完善,未完全模
* 卡名:卡当前的名字,按中键可以进入设置卡名界面
* ID:显示了当前卡ID
* 卡类型:显示了当前卡类型
+* 默认卡片:如果开启默认卡片,当设备从NFC场唤醒时,默认模拟这张卡。
* 卡数据:按中键可以进行卡数据管理
* 卡高级设置:按中键可以进入卡高级设置
* 卡槽管理:按中键进入卡槽管理界面,可以开启关闭卡槽
@@ -226,6 +240,7 @@ NTAG系列的模拟功能还是测试中,功能还不太完善,未完全模
> **特别注意**:
> 部分的修改需要在退出到标签详情才会保存到存储,如果修改了部分配置,请务必进入到标签详情页面保存下。
+> 如果开启的默认卡片功能,当设备从NFC场唤醒时,会调用卡模拟器应用,默认模拟这张卡。此功能和快速唤醒功能冲突,如果设置了默认卡,快速唤醒功能不再生效。
## 卡名修改
diff --git a/fw/application/Makefile b/fw/application/Makefile
index 7792905e..bec2b9cb 100644
--- a/fw/application/Makefile
+++ b/fw/application/Makefile
@@ -329,6 +329,7 @@ SRC_FILES += \
$(PROJ_DIR)/app/settings/scene/settings_scene_oled_contrast.c \
$(PROJ_DIR)/app/settings/scene/settings_scene_language.c \
$(PROJ_DIR)/app/settings/scene/settings_scene_storage.c \
+ $(PROJ_DIR)/app/settings/scene/settings_scene_about.c \
$(PROJ_DIR)/i18n/en_US.c \
$(PROJ_DIR)/i18n/zh_Hans.c \
$(PROJ_DIR)/i18n/zh_TW.c \
@@ -367,7 +368,7 @@ SRC_FILES += \
$(CHAMELEON_ROOT)/application/src/rfid/nfctag/hf/crypto1_helper.c \
$(CHAMELEON_ROOT)/application/src/rfid/nfctag/hf/nfc_14a.c \
$(CHAMELEON_ROOT)/application/src/rfid/nfctag/hf/nfc_mf1.c \
- $(CHAMELEON_ROOT)/application/src/rfid/nfctag/hf/nfc_ntag.c \
+ $(CHAMELEON_ROOT)/application/src/rfid/nfctag/hf/nfc_mf0_ntag.c \
$(CHAMELEON_ROOT)/application/src/rfid/crc_utils.c \
$(CHAMELEON_ROOT)/application/src/rfid/hex_utils.c \
$(CHAMELEON_ROOT)/application/src/rfid/mf1_crapto1.c \
@@ -855,6 +856,7 @@ full: settingsgen
gen:
python3 ../scripts/amiibo_db_gen.py
python3 ../scripts/i18n_gen.py
+ python3 ../scripts/font_data_gen.py
python3 ../scripts/resource_gen.py
flash_ocd: default
diff --git a/fw/application/src/app/amiibo/scene/amiibo_scene_amiibo_detail.c b/fw/application/src/app/amiibo/scene/amiibo_scene_amiibo_detail.c
index 53912364..5b470d5c 100644
--- a/fw/application/src/app/amiibo/scene/amiibo_scene_amiibo_detail.c
+++ b/fw/application/src/app/amiibo/scene/amiibo_scene_amiibo_detail.c
@@ -1,17 +1,17 @@
+#include "amiibo_helper.h"
#include "amiibo_scene.h"
#include "app_amiibo.h"
#include "app_timer.h"
#include "cwalk2.h"
+#include "db_header.h"
+#include "i18n/language.h"
#include "mui_list_view.h"
#include "nrf_log.h"
#include "ntag_emu.h"
-#include "vfs.h"
-#include "vfs_meta.h"
-#include "amiibo_helper.h"
#include "ntag_store.h"
#include "settings.h"
-#include "i18n/language.h"
-#include "db_header.h"
+#include "vfs.h"
+#include "vfs_meta.h"
#define NRF_ERR_NOT_AMIIBO -1000
#define NRF_ERR_READ_ERROR -1001
@@ -70,10 +70,15 @@ static int32_t ntag_read(vfs_driver_t *p_vfs_driver, const char *path, ntag_t *n
vfs_meta_t meta;
memset(&meta, 0, sizeof(vfs_meta_t));
vfs_meta_decode(obj.meta, sizeof(obj.meta), &meta);
- if(meta.has_notes){
+ if (meta.has_notes) {
memcpy(ntag->notes, meta.notes, strlen(meta.notes));
}
+ NRF_LOG_INFO("has_flag:%d flag:%d", meta.has_flags, meta.flags);
+ if (meta.has_flags && (meta.flags & VFS_OBJ_FLAG_READONLY)) {
+ ntag->read_only = true;
+ }
+
res = p_vfs_driver->read_file_data(path, ntag->data, 540);
if (res != 540 && res != 532) {
return NRF_ERR_READ_ERROR;
@@ -83,7 +88,7 @@ static int32_t ntag_read(vfs_driver_t *p_vfs_driver, const char *path, ntag_t *n
static void ntag_gen(void *p_context) {
ret_code_t err_code;
- app_amiibo_t * app = p_context;
+ app_amiibo_t *app = p_context;
ntag_t *ntag_current = &app->ntag;
err_code = amiibo_helper_rand_amiibo_uuid(ntag_current);
@@ -136,7 +141,7 @@ static void ntag_update_cb(ntag_event_type_t type, void *context, ntag_t *p_ntag
if (type == NTAG_EVENT_TYPE_WRITTEN) {
ntag_update(app, p_ntag);
} else if (type == NTAG_EVENT_TYPE_READ) {
- settings_data_t* p_settings = settings_get_data();
+ settings_data_t *p_settings = settings_get_data();
if (p_settings->auto_gen_amiibo) {
app_timer_stop(m_amiibo_gen_delay_timer);
app_timer_start(m_amiibo_gen_delay_timer, APP_TIMER_TICKS(1000), app);
@@ -187,7 +192,9 @@ static void amiibo_scene_amiibo_detail_reload_files(app_amiibo_t *app) {
vfs_meta_t meta;
memset(&meta, 0, sizeof(vfs_meta_t));
vfs_meta_decode(obj.meta, sizeof(obj.meta), &meta);
- if (obj.type == VFS_TYPE_REG && (obj.size == NTAG_DATA_SIZE || obj.size == NTAG_TAGMO_DATA_SIZE || obj.size == NTAG_THENAYA_DATA_SIZE) &&
+ if (obj.type == VFS_TYPE_REG &&
+ (obj.size == NTAG_DATA_SIZE || obj.size == NTAG_TAGMO_DATA_SIZE ||
+ obj.size == NTAG_THENAYA_DATA_SIZE) &&
(!meta.has_flags || !(meta.flags & VFS_OBJ_FLAG_HIDDEN))) {
string_set_str(file_name, obj.name);
string_array_push_back(app->amiibo_files, file_name);
diff --git a/fw/application/src/app/amiibo/scene/amiibo_scene_amiibo_detail_menu.c b/fw/application/src/app/amiibo/scene/amiibo_scene_amiibo_detail_menu.c
index 09c5218d..a491febb 100644
--- a/fw/application/src/app/amiibo/scene/amiibo_scene_amiibo_detail_menu.c
+++ b/fw/application/src/app/amiibo/scene/amiibo_scene_amiibo_detail_menu.c
@@ -7,6 +7,7 @@
#include "nrf_log.h"
#include "settings.h"
#include "vfs.h"
+#include "vfs_meta.h"
#include "ntag_emu.h"
#include "ntag_store.h"
@@ -19,12 +20,46 @@
enum amiibo_detail_menu_t {
AMIIBO_DETAIL_MENU_RAND_UID,
AMIIBO_DETAIL_MENU_AUTO_RAND_UID,
+ AMIIBO_DETAIL_MENU_READ_ONLY,
AMIIBO_DETAIL_MENU_REMOVE_AMIIBO,
AMIIBO_DETAIL_MENU_BACK_AMIIBO_DETAIL,
AMIIBO_DETAIL_MENU_BACK_FILE_BROWSER,
AMIIBO_DETAIL_MENU_BACK_MAIN_MENU,
};
+static ret_code_t amiibo_scene_amiibo_detail_set_readonly(app_amiibo_t *app, bool readonly) {
+ char path[VFS_MAX_PATH_LEN];
+ vfs_meta_t meta;
+ vfs_obj_t obj;
+ uint8_t meta_buf[VFS_MAX_META_LEN];
+
+
+ cwalk_append_segment(path, string_get_cstr(app->current_folder), string_get_cstr(app->current_file));
+
+ vfs_driver_t *p_vfs_driver = vfs_get_driver(VFS_DRIVE_EXT);
+ int32_t res = p_vfs_driver->stat_file(path, &obj);
+ if (res < 0) {
+ return -1;
+ }
+
+ memset(&meta, 0, sizeof(vfs_meta_t));
+ vfs_meta_decode(obj.meta, sizeof(obj.meta), &meta);
+
+ meta.has_flags = true;
+ if (readonly) {
+ meta.flags |= VFS_OBJ_FLAG_READONLY;
+ } else {
+ meta.flags &= ~VFS_OBJ_FLAG_READONLY;
+ }
+
+ vfs_meta_encode(meta_buf, sizeof(meta_buf), &meta);
+ if (p_vfs_driver->update_file_meta(path, meta_buf, sizeof(meta_buf)) == VFS_OK) {
+ return NRF_SUCCESS;
+ } else {
+ return -1;
+ }
+}
+
static void amiibo_scene_amiibo_detail_menu_msg_box_no_key_cb(mui_msg_box_event_t event, mui_msg_box_t *p_msg_box) {
app_amiibo_t *app = p_msg_box->user_data;
if (event == MUI_MSG_BOX_EVENT_SELECT_CENTER) {
@@ -129,7 +164,18 @@ static void amiibo_scene_amiibo_detail_menu_on_selected(mui_list_view_event_t ev
p_settings->auto_gen_amiibo = !p_settings->auto_gen_amiibo;
settings_save();
- mui_list_view_item_set_sub_text(p_item, (p_settings->auto_gen_amiibo ? getLangString(_L_ON_F) : getLangString(_L_OFF_F)));
+ mui_list_view_item_set_sub_text(
+ p_item, (p_settings->auto_gen_amiibo ? getLangString(_L_ON_F) : getLangString(_L_OFF_F)));
+ } break;
+
+ case AMIIBO_DETAIL_MENU_READ_ONLY: {
+ ret_code_t err_code = amiibo_scene_amiibo_detail_set_readonly(app, !app->ntag.read_only);
+ if (err_code == NRF_SUCCESS) {
+ app->ntag.read_only = !app->ntag.read_only;
+ ntag_emu_set_tag(&app->ntag);
+ mui_list_view_item_set_sub_text(p_item,
+ app->ntag.read_only ? getLangString(_L_ON_F) : getLangString(_L_OFF_F));
+ }
} break;
case AMIIBO_DETAIL_MENU_REMOVE_AMIIBO: {
@@ -157,9 +203,14 @@ void amiibo_scene_amiibo_detail_menu_on_enter(void *user_data) {
(void *)AMIIBO_DETAIL_MENU_RAND_UID);
settings_data_t *p_settings = settings_get_data();
- mui_list_view_add_item_ext(app->p_list_view, 0xe1c6, getLangString(_L_AUTO_RANDOM_GENERATION),
- (p_settings->auto_gen_amiibo ? getLangString(_L_ON_F) : getLangString(_L_OFF_F)),
- (void *)AMIIBO_DETAIL_MENU_AUTO_RAND_UID);
+ mui_list_view_add_item_ext(app->p_list_view, 0xe1c6, getLangString(_L_AUTO_RANDOM_GENERATION),
+ (p_settings->auto_gen_amiibo ? getLangString(_L_ON_F) : getLangString(_L_OFF_F)),
+ (void *)AMIIBO_DETAIL_MENU_AUTO_RAND_UID);
+
+ mui_list_view_add_item_ext(app->p_list_view, 0xe007, getLangString(_L_READ_ONLY),
+ app->ntag.read_only ? getLangString(_L_ON_F) : getLangString(_L_OFF_F),
+ (void *)AMIIBO_DETAIL_MENU_READ_ONLY);
+
mui_list_view_add_item(app->p_list_view, 0xe1c7, getLangString(_L_DELETE_TAG),
(void *)AMIIBO_DETAIL_MENU_REMOVE_AMIIBO);
mui_list_view_add_item(app->p_list_view, 0xe068, getLangString(_L_BACK_TO_DETAILS),
diff --git a/fw/application/src/app/amiibo/scene/amiibo_scene_file_browser.c b/fw/application/src/app/amiibo/scene/amiibo_scene_file_browser.c
index 1db3982f..a8ba0d1a 100644
--- a/fw/application/src/app/amiibo/scene/amiibo_scene_file_browser.c
+++ b/fw/application/src/app/amiibo/scene/amiibo_scene_file_browser.c
@@ -54,7 +54,7 @@ static void amiibo_scene_file_browser_reload_folders(app_amiibo_t *app) {
vfs_meta_t meta;
memset(&meta, 0, sizeof(vfs_meta_t));
vfs_meta_decode(obj.meta, sizeof(obj.meta), &meta);
- if (meta.has_flags && (meta.flags && VFS_OBJ_FLAG_HIDDEN)) {
+ if (meta.has_flags && (meta.flags & VFS_OBJ_FLAG_HIDDEN)) {
continue;
}
uint16_t icon = obj.type == VFS_TYPE_DIR ? ICON_FOLDER : ICON_FILE;
diff --git a/fw/application/src/app/amiibo/view/amiibo_detail_view.c b/fw/application/src/app/amiibo/view/amiibo_detail_view.c
index c6b0eae7..dbd26638 100644
--- a/fw/application/src/app/amiibo/view/amiibo_detail_view.c
+++ b/fw/application/src/app/amiibo/view/amiibo_detail_view.c
@@ -1,11 +1,12 @@
#include "amiibo_detail_view.h"
-#include "mui_element.h"
-#include "i18n/language.h"
-#include "db_header.h"
#include "amiibo_helper.h"
+#include "db_header.h"
+#include "i18n/language.h"
+#include "mui_element.h"
#define ICON_LEFT 0xe1ac
#define ICON_RIGHT 0xe1aa
+#define ICON_INFO 0xe0ae
static void amiibo_detail_view_on_draw(mui_view_t *p_view, mui_canvas_t *p_canvas) {
char buff[64];
@@ -36,14 +37,22 @@ static void amiibo_detail_view_on_draw(mui_view_t *p_view, mui_canvas_t *p_canva
y += 12;
- mui_canvas_draw_utf8(p_canvas, 0, y += 12, string_get_cstr(p_amiibo_detail_view->file_name));
+ if (ntag->read_only) {
+ mui_canvas_set_font(p_canvas, u8g2_font_siji_t_6x10);
+ mui_canvas_draw_glyph(p_canvas, 0, y += 12, ICON_INFO);
+ mui_canvas_set_font(p_canvas, u8g2_font_wqy12_t_gb2312a);
+ mui_canvas_draw_utf8(p_canvas, 12, y, string_get_cstr(p_amiibo_detail_view->file_name));
+ } else {
+ mui_canvas_draw_utf8(p_canvas, 0, y += 12, string_get_cstr(p_amiibo_detail_view->file_name));
+ }
uint32_t head = to_little_endian_int32(&ntag->data[84]);
uint32_t tail = to_little_endian_int32(&ntag->data[88]);
const db_amiibo_t *amd = get_amiibo_by_id(head, tail);
if (amd != NULL) {
- const char *name =(getLanguage() == LANGUAGE_ZH_TW || getLanguage() == LANGUAGE_ZH_HANS) ? amd->name_cn : amd->name_en;
+ const char *name =
+ (getLanguage() == LANGUAGE_ZH_TW || getLanguage() == LANGUAGE_ZH_HANS) ? amd->name_cn : amd->name_en;
mui_element_autowrap_text(p_canvas, 0, y += 15, mui_canvas_get_width(p_canvas), 24, name);
if (strlen(ntag->notes) > 0) {
mui_element_autowrap_text(p_canvas, 0, y += 13, mui_canvas_get_width(p_canvas), 24, ntag->notes);
diff --git a/fw/application/src/app/amiidb/api/amiidb_api_slot.c b/fw/application/src/app/amiidb/api/amiidb_api_slot.c
index 07812205..cb799c6e 100644
--- a/fw/application/src/app/amiidb/api/amiidb_api_slot.c
+++ b/fw/application/src/app/amiidb/api/amiidb_api_slot.c
@@ -30,6 +30,10 @@ int32_t amiidb_api_slot_read(uint8_t slot, ntag_t *p_ntag) {
strcpy(p_ntag->notes, meta.notes);
}
+ if (meta.has_flags && (meta.flags & VFS_OBJ_FLAG_READONLY)) {
+ p_ntag->read_only = true;
+ }
+
return 0;
}
@@ -51,6 +55,14 @@ int32_t amiidb_api_slot_write(uint8_t slot, ntag_t *p_ntag) {
meta.amiibo_head = to_little_endian_int32(&p_ntag->data[84]);
meta.amiibo_tail = to_little_endian_int32(&p_ntag->data[88]);
+ // TODO write only flag???
+ meta.has_flags = true;
+ if (p_ntag->read_only) {
+ meta.flags |= VFS_OBJ_FLAG_READONLY;
+ } else {
+ meta.flags &= ~VFS_OBJ_FLAG_READONLY;
+ }
+
vfs_meta_encode(meta_encoded, sizeof(meta_encoded), &meta);
res = p_vfs_driver->update_file_meta(path, meta_encoded, sizeof(meta_encoded));
if (res < 0) {
@@ -90,13 +102,13 @@ int32_t amiidb_api_slot_info(uint8_t slot, amiidb_slot_info_t *p_info) {
p_info->slot = slot;
p_info->is_empty = false;
+ p_info->is_readonly = meta.has_flags && meta.flags & VFS_OBJ_FLAG_READONLY;
p_info->amiibo_head = meta.amiibo_head;
p_info->amiibo_tail = meta.amiibo_tail;
return 0;
}
-
int32_t amiidb_api_slot_list(amiibo_slot_info_cb_t cb, void *ctx) {
vfs_dir_t dir;
vfs_obj_t obj;
@@ -108,6 +120,7 @@ int32_t amiidb_api_slot_list(amiibo_slot_info_cb_t cb, void *ctx) {
for (uint8_t i = 0; i < MAX_SLOT_COUNT; i++) {
slots[i].slot = i;
slots[i].is_empty = true;
+ slots[i].is_readonly = false;
slots[i].amiibo_head = 0;
slots[i].amiibo_tail = 0;
}
@@ -123,20 +136,53 @@ int32_t amiidb_api_slot_list(amiibo_slot_info_cb_t cb, void *ctx) {
if (sscanf(obj.name, "%02d.bin", &index) == 1 && index >= 0 && index < max_slot_num) {
memset(&meta, 0, sizeof(vfs_meta_t));
vfs_meta_decode(obj.meta, sizeof(obj.meta), &meta);
- if(meta.has_amiibo_id) {
+ if (meta.has_amiibo_id) {
slots[index].is_empty = false;
slots[index].amiibo_head = meta.amiibo_head;
slots[index].amiibo_tail = meta.amiibo_tail;
}
+ if (meta.has_flags && (meta.flags & VFS_OBJ_FLAG_READONLY)) {
+ slots[index].is_readonly = true;
+ }
}
}
}
p_vfs_driver->close_dir(&dir);
-
for (uint8_t i = 0; i < max_slot_num; i++) {
cb(&slots[i], ctx);
}
return 0;
+}
+
+int32_t amiidb_api_slot_set_readonly(uint8_t slot, bool readonly) {
+ char path[VFS_MAX_PATH_LEN];
+ vfs_meta_t meta;
+ vfs_obj_t obj;
+ uint8_t meta_buf[VFS_MAX_META_LEN];
+
+ sprintf(path, "/amiibo/data/%02d.bin", slot);
+ vfs_driver_t *p_vfs_driver = vfs_get_driver(VFS_DRIVE_EXT);
+ int32_t res = p_vfs_driver->stat_file(path, &obj);
+ if (res < 0) {
+ return -1;
+ }
+
+ memset(&meta, 0, sizeof(vfs_meta_t));
+ vfs_meta_decode(obj.meta, sizeof(obj.meta), &meta);
+
+ meta.has_flags = true;
+ if (readonly) {
+ meta.flags |= VFS_OBJ_FLAG_READONLY;
+ } else {
+ meta.flags &= ~VFS_OBJ_FLAG_READONLY;
+ }
+
+ vfs_meta_encode(meta_buf, sizeof(meta_buf), &meta);
+ if (p_vfs_driver->update_file_meta(path, meta_buf, sizeof(meta_buf)) == VFS_OK) {
+ return NRF_SUCCESS;
+ } else {
+ return -1;
+ }
}
\ No newline at end of file
diff --git a/fw/application/src/app/amiidb/api/amiidb_api_slot.h b/fw/application/src/app/amiidb/api/amiidb_api_slot.h
index 4481439e..50210967 100644
--- a/fw/application/src/app/amiidb/api/amiidb_api_slot.h
+++ b/fw/application/src/app/amiidb/api/amiidb_api_slot.h
@@ -14,6 +14,7 @@
typedef struct {
uint8_t slot;
uint8_t is_empty;
+ uint8_t is_readonly;
uint32_t amiibo_head;
uint32_t amiibo_tail;
} amiidb_slot_info_t;
@@ -28,4 +29,6 @@ int32_t amiidb_api_slot_remove(uint8_t slot);
int32_t amiidb_api_slot_info(uint8_t slot, amiidb_slot_info_t * p_info);
int32_t amiidb_api_slot_list(amiibo_slot_info_cb_t cb, void* ctx);
+int32_t amiidb_api_slot_set_readonly(uint8_t slot, bool readonly);
+
#endif // FW_AMIIDB_API_SLOT_H
diff --git a/fw/application/src/app/amiidb/scene/amiidb_scene_amiibo_detail.c b/fw/application/src/app/amiidb/scene/amiidb_scene_amiibo_detail.c
index 440c066f..bd1faa5c 100644
--- a/fw/application/src/app/amiidb/scene/amiidb_scene_amiibo_detail.c
+++ b/fw/application/src/app/amiidb/scene/amiidb_scene_amiibo_detail.c
@@ -182,6 +182,7 @@ static void ntag_generate_timer_handler(void *p_context) {
static void amiidb_scene_amiibo_view_on_event(amiibo_view_event_t event, amiibo_view_t *p_view) {
app_amiidb_t *app = p_view->user_data;
if (event == AMIIBO_VIEW_EVENT_MENU) {
+ app->cur_slot_index = amiibo_view_get_focus(app->p_amiibo_view);
mui_scene_dispatcher_next_scene(app->p_scene_dispatcher, AMIIDB_SCENE_AMIIBO_DETAIL_MENU);
} else if (event == AMIIBO_VIEW_EVENT_UPDATE) {
if (app->prev_scene_id == AMIIDB_SCENE_GAME_LIST) {
diff --git a/fw/application/src/app/amiidb/scene/amiidb_scene_amiibo_detail_menu.c b/fw/application/src/app/amiidb/scene/amiidb_scene_amiibo_detail_menu.c
index 60c4254e..2d4ebc41 100644
--- a/fw/application/src/app/amiidb/scene/amiidb_scene_amiibo_detail_menu.c
+++ b/fw/application/src/app/amiidb/scene/amiidb_scene_amiibo_detail_menu.c
@@ -17,9 +17,12 @@
#include "mini_app_launcher.h"
#include "mini_app_registry.h"
+#include "amiidb_api_slot.h"
+
static enum amiidb_detail_menu_t {
AMIIDB_DETAIL_MENU_RAND_UID,
AMIIDB_DETAIL_MENU_AUTO_RAND_UID,
+ AMIIDB_DETAIL_MENU_READ_ONLY,
AMIIDB_DETAIL_MENU_SHOW_QRCODE,
AMIIDB_DETAIL_MENU_FAVORITE,
AMIIDB_DETAIL_MENU_SAVE_AS,
@@ -82,6 +85,15 @@ static void amiidb_scene_amiibo_detail_menu_on_selected(mui_list_view_event_t ev
break;
}
+ case AMIIDB_DETAIL_MENU_READ_ONLY: {
+ ret_code_t err_code = amiidb_api_slot_set_readonly(app->cur_slot_index, !app->ntag.read_only);
+ if (err_code == NRF_SUCCESS) {
+ app->ntag.read_only = !app->ntag.read_only;
+ mui_list_view_item_set_sub_text(p_item,
+ app->ntag.read_only ? getLangString(_L_ON_F) : getLangString(_L_OFF_F));
+ }
+ } break;
+
case AMIIDB_DETAIL_MENU_BACK_AMIIBO_DETAIL: {
mui_scene_dispatcher_previous_scene(app->p_scene_dispatcher);
break;
@@ -146,6 +158,13 @@ void amiidb_scene_amiibo_detail_menu_on_enter(void *user_data) {
snprintf(txt, sizeof(txt), "%s", p_settings->qrcode_enabled ? getLangString(_L_ON_F) : getLangString(_L_OFF_F));
mui_list_view_add_item_ext(app->p_list_view, 0xe006, getLangString(_L_SHOW_QRCODE), txt,
(void *)AMIIDB_DETAIL_MENU_SHOW_QRCODE);
+
+ if (app->prev_scene_id == AMIIDB_SCENE_DATA_LIST){
+ mui_list_view_add_item_ext(app->p_list_view, 0xe007, getLangString(_L_READ_ONLY),
+ app->ntag.read_only ? getLangString(_L_ON_F) : getLangString(_L_OFF_F),
+ (void *)AMIIDB_DETAIL_MENU_READ_ONLY);
+ }
+
mui_list_view_add_item(app->p_list_view, ICON_FAVORITE, getLangString(_L_APP_AMIIDB_DETAIL_FAVORITE),
(void *)AMIIDB_DETAIL_MENU_FAVORITE);
mui_list_view_add_item(app->p_list_view, ICON_DATA, getLangString(_L_APP_AMIIDB_DETAIL_SAVE_AS),
diff --git a/fw/application/src/app/amiidb/view/amiibo_view.c b/fw/application/src/app/amiidb/view/amiibo_view.c
index 9ad258b0..de163a00 100644
--- a/fw/application/src/app/amiidb/view/amiibo_view.c
+++ b/fw/application/src/app/amiidb/view/amiibo_view.c
@@ -7,6 +7,7 @@
#define ICON_LEFT 0xe1ac
#define ICON_RIGHT 0xe1aa
+#define ICON_INFO 0xe0ae
static void amiibo_view_on_draw(mui_view_t *p_view, mui_canvas_t *p_canvas) {
char buff[64];
@@ -42,9 +43,17 @@ static void amiibo_view_on_draw(mui_view_t *p_view, mui_canvas_t *p_canvas) {
const db_amiibo_t *amd = get_amiibo_by_id(head, tail);
if (amd != NULL) {
- const char *name =(getLanguage() == LANGUAGE_ZH_TW || getLanguage() == LANGUAGE_ZH_HANS) ? amd->name_cn : amd->name_en;
- mui_canvas_draw_utf8(p_canvas, 0, y += 13, name);
-
+ const char *name =
+ (getLanguage() == LANGUAGE_ZH_TW || getLanguage() == LANGUAGE_ZH_HANS) ? amd->name_cn : amd->name_en;
+
+ if (ntag->read_only) {
+ mui_canvas_set_font(p_canvas, u8g2_font_siji_t_6x10);
+ mui_canvas_draw_glyph(p_canvas, 0, y += 12, ICON_INFO);
+ mui_canvas_set_font(p_canvas, u8g2_font_wqy12_t_gb2312a);
+ mui_canvas_draw_utf8(p_canvas, 12, y, name);
+ } else {
+ mui_canvas_draw_utf8(p_canvas, 0, y += 12, name);
+ }
mui_rect_t clip_win_prev;
mui_rect_t clip_win_cur;
mui_canvas_get_clip_window(p_canvas, &clip_win_prev);
@@ -67,17 +76,21 @@ static void amiibo_view_on_draw(mui_view_t *p_view, mui_canvas_t *p_canvas) {
p_amiibo_view->desc_page_size = clip_win_cur.h;
const db_link_t *link = get_link_by_id(p_amiibo_view->game_id, head, tail);
if (strlen(ntag->notes) > 0) {
- p_amiibo_view->desc_total = mui_element_autowrap_text_box(p_canvas, clip_win_cur.x, clip_win_cur.y, clip_win_cur.w, clip_win_cur.h, p_amiibo_view->desc_offset, square_r, ntag->notes);
+ p_amiibo_view->desc_total =
+ mui_element_autowrap_text_box(p_canvas, clip_win_cur.x, clip_win_cur.y, clip_win_cur.w, clip_win_cur.h,
+ p_amiibo_view->desc_offset, square_r, ntag->notes);
} else if (link != NULL) {
const char *notes;
- if (getLanguage() == LANGUAGE_ZH_HANS) {
+ if (getLanguage() == LANGUAGE_ZH_HANS) {
notes = link->note_cn;
- } else if(getLanguage() == LANGUAGE_IT_IT) {
+ } else if (getLanguage() == LANGUAGE_IT_IT) {
notes = link->note_it;
} else {
notes = link->note_en;
}
- p_amiibo_view->desc_total = mui_element_autowrap_text_box(p_canvas, clip_win_cur.x, clip_win_cur.y, clip_win_cur.w, clip_win_cur.h, p_amiibo_view->desc_offset, square_r, notes);
+ p_amiibo_view->desc_total =
+ mui_element_autowrap_text_box(p_canvas, clip_win_cur.x, clip_win_cur.y, clip_win_cur.w, clip_win_cur.h,
+ p_amiibo_view->desc_offset, square_r, notes);
}
mui_canvas_set_clip_window(p_canvas, &clip_win_prev);
} else if (head > 0 && tail > 0) {
@@ -107,7 +120,11 @@ static void amiibo_view_on_input(mui_view_t *p_view, mui_input_event_t *event) {
}
break;
case INPUT_KEY_RIGHT:
- if (p_amiibo_view->desc_total > 0 && p_amiibo_view->desc_offset < p_amiibo_view->desc_page_size * ((p_amiibo_view->desc_total + p_amiibo_view->desc_page_size - 1) / p_amiibo_view->desc_page_size - 1)) {
+ if (p_amiibo_view->desc_total > 0 &&
+ p_amiibo_view->desc_offset <
+ p_amiibo_view->desc_page_size * ((p_amiibo_view->desc_total + p_amiibo_view->desc_page_size - 1) /
+ p_amiibo_view->desc_page_size -
+ 1)) {
p_amiibo_view->desc_offset += p_amiibo_view->desc_step;
}
diff --git a/fw/application/src/app/chameleon/app_chameleon.c b/fw/application/src/app/chameleon/app_chameleon.c
index fdb1fb53..f1d93708 100644
--- a/fw/application/src/app/chameleon/app_chameleon.c
+++ b/fw/application/src/app/chameleon/app_chameleon.c
@@ -6,6 +6,8 @@
#include "chameleon_scene.h"
#include "fds_utils.h"
#include "i18n/language.h"
+#include "settings.h"
+#include "tag_helper.h"
static void app_chameleon_on_run(mini_app_inst_t *p_app_inst);
static void app_chameleon_on_kill(mini_app_inst_t *p_app_inst);
@@ -76,7 +78,16 @@ void app_chameleon_on_kill(mini_app_inst_t *p_app_inst) {
p_retain->cycle_mode_index = chameleon_view_get_index(p_app_handle->p_chameleon_view);
+ settings_data_t *settings = settings_get_data();
+ if (tag_helper_valid_default_slot() &&
+ tag_emulation_slot_is_enabled(settings->chameleon_default_slot_index, TAG_SENSE_HF)) {
+ tag_emulation_change_slot(settings->chameleon_default_slot_index, false);
+ } else {
+ settings->chameleon_default_slot_index = INVALID_SLOT_INDEX;
+ }
+
tag_emulation_save();
+ settings_save();
mui_scene_dispatcher_exit(p_app_handle->p_scene_dispatcher);
mui_scene_dispatcher_free(p_app_handle->p_scene_dispatcher);
diff --git a/fw/application/src/app/chameleon/port/tag_helper.c b/fw/application/src/app/chameleon/port/tag_helper.c
index 61504d0a..52c51631 100644
--- a/fw/application/src/app/chameleon/port/tag_helper.c
+++ b/fw/application/src/app/chameleon/port/tag_helper.c
@@ -3,9 +3,12 @@
#include "fds_utils.h"
#include "i18n/language.h"
#include "nrf_log.h"
+#include "settings.h"
#include "utils2.h"
#include
+#define NFC_TAG_NTAG_DATA_SIZE 4
+
const static tag_specific_type_name_t tag_type_names[] = {
{TAG_TYPE_UNDEFINED, "-", "-", 0},
// MiFare series
@@ -14,10 +17,19 @@ const static tag_specific_type_name_t tag_type_names[] = {
{TAG_TYPE_MIFARE_2048, "MF 2K", "MiFare 2K", 128 * NFC_TAG_MF1_DATA_SIZE},
{TAG_TYPE_MIFARE_4096, "MF 4K", "MiFare 4K", 256 * NFC_TAG_MF1_DATA_SIZE},
// NTAG series
- {TAG_TYPE_NTAG_213, "N213", "NTAG 213", 45 * NFC_TAG_NTAG_DATA_SIZE},
- {TAG_TYPE_NTAG_215, "N215", "NTAG 215", 135 * NFC_TAG_NTAG_DATA_SIZE},
- {TAG_TYPE_NTAG_216, "N216", "NTAG 216", 231 * NFC_TAG_NTAG_DATA_SIZE},
+ {TAG_TYPE_NTAG_210, "N210", "NTAG 210", NTAG210_PAGES *NFC_TAG_NTAG_DATA_SIZE},
+ {TAG_TYPE_NTAG_212, "N212", "NTAG 212", NTAG212_PAGES *NFC_TAG_NTAG_DATA_SIZE},
+ {TAG_TYPE_NTAG_213, "N213", "NTAG 213", NTAG213_PAGES *NFC_TAG_NTAG_DATA_SIZE},
+ {TAG_TYPE_NTAG_215, "N215", "NTAG 215", NTAG215_PAGES *NFC_TAG_NTAG_DATA_SIZE},
+ {TAG_TYPE_NTAG_216, "N216", "NTAG 216", NTAG216_PAGES *NFC_TAG_NTAG_DATA_SIZE},
+
+ {TAG_TYPE_MF0ICU1, "MFUL", "Mifare Ultralight", MF0ICU1_PAGES *NFC_TAG_NTAG_DATA_SIZE},
+ {TAG_TYPE_MF0ICU2, "MFULC", "Mifare Ultralight C", MF0ICU2_PAGES *NFC_TAG_NTAG_DATA_SIZE},
+ {TAG_TYPE_MF0UL11, "MFEV11", "Mifare Ultralight EV1 (640 bit)", MF0UL11_PAGES *NFC_TAG_NTAG_DATA_SIZE},
+ {TAG_TYPE_MF0UL21, "MFEV21", "Mifare Ultralight EV1 (1312 bit)", MF0UL21_PAGES *NFC_TAG_NTAG_DATA_SIZE},
+
};
+
// typedef enum {
// NFC_TAG_MF1_WRITE_NORMAL = 0u,
// NFC_TAG_MF1_WRITE_DENIED = 1u,
@@ -36,15 +48,11 @@ const tag_specific_type_t hf_tag_specific_types[] = {
// Specific and necessary signs do not exist
TAG_TYPE_UNDEFINED,
// MiFare series
- TAG_TYPE_MIFARE_Mini,
- TAG_TYPE_MIFARE_1024,
- TAG_TYPE_MIFARE_2048,
- TAG_TYPE_MIFARE_4096,
+ TAG_TYPE_MIFARE_Mini, TAG_TYPE_MIFARE_1024, TAG_TYPE_MIFARE_2048, TAG_TYPE_MIFARE_4096,
// NTAG series
- TAG_TYPE_NTAG_213,
- TAG_TYPE_NTAG_215,
- TAG_TYPE_NTAG_216,
-};
+ TAG_TYPE_NTAG_210, TAG_TYPE_NTAG_212, TAG_TYPE_NTAG_213, TAG_TYPE_NTAG_215, TAG_TYPE_NTAG_216,
+
+ TAG_TYPE_MF0ICU1, TAG_TYPE_MF0ICU2, TAG_TYPE_MF0UL11, TAG_TYPE_MF0UL21};
tag_group_type_t tag_helper_get_tag_group_type(tag_specific_type_t tag_type) {
if (tag_type == TAG_TYPE_MIFARE_Mini || tag_type == TAG_TYPE_MIFARE_1024 || tag_type == TAG_TYPE_MIFARE_2048 ||
@@ -75,9 +83,9 @@ const nfc_tag_14a_coll_res_reference_t *tag_helper_get_active_coll_res_ref() {
// nfc_tag_mf1_information_t *m_tag_information = (nfc_tag_mf1_information_t *)tag_buffer->buffer;
// return &m_tag_information->res_coll;
} else {
- // nfc_tag_ntag_information_t *m_tag_information = (nfc_tag_ntag_information_t *)tag_buffer->buffer;
+ // nfc_tag_mf0_ntag_information_t *m_tag_information = (nfc_tag_mf0_ntag_information_t *)tag_buffer->buffer;
// return &m_tag_information->res_coll;
- return get_ntag_coll_res();
+ return nfc_tag_mf0_ntag_get_coll_res();
}
}
@@ -150,7 +158,7 @@ uint8_t *tag_helper_get_active_tag_memory_data() {
nfc_tag_mf1_information_t *m_tag_information = (nfc_tag_mf1_information_t *)tag_buffer->buffer;
return &m_tag_information->memory;
} else {
- nfc_tag_ntag_information_t *m_tag_information = (nfc_tag_ntag_information_t *)tag_buffer->buffer;
+ nfc_tag_mf0_ntag_information_t *m_tag_information = (nfc_tag_mf0_ntag_information_t *)tag_buffer->buffer;
return &m_tag_information->memory;
}
}
@@ -160,12 +168,12 @@ void tag_helper_generate_uid() {
tag_group_type_t tag_group_type = tag_helper_get_tag_group_type(tag_type);
tag_data_buffer_t *tag_buffer = get_buffer_by_tag_type(tag_type);
if (tag_group_type == TAG_GROUP_NTAG) {
- nfc_tag_ntag_information_t *m_tag_information = (nfc_tag_ntag_information_t *)tag_buffer->buffer;
+ nfc_tag_mf0_ntag_information_t *m_tag_information = (nfc_tag_mf0_ntag_information_t *)tag_buffer->buffer;
uint8_t uuid[7];
ret_code_t err_code = utils_rand_bytes(uuid, sizeof(uuid));
if (err_code == NRF_SUCCESS) {
uuid[0] = 04; // fixed
- m_tag_information->memory[0][0] = uuid[0];
+ m_tag_information->memory[0][0] = uuid[0];
m_tag_information->memory[0][1] = uuid[1];
m_tag_information->memory[0][2] = uuid[2];
// BCC 0 is always equal to UID0 ⊕ UID 1 ⊕ UID 2 ⊕ 0x88
@@ -184,4 +192,14 @@ void tag_helper_generate_uid() {
memcpy(m_tag_information->res_coll.uid, uuid, sizeof(uuid));
}
}
+}
+
+bool tag_helper_is_defult_slot() {
+ settings_data_t *settings = settings_get_data();
+ return settings->chameleon_default_slot_index == tag_emulation_get_slot();
+}
+
+bool tag_helper_valid_default_slot(){
+ settings_data_t *settings = settings_get_data();
+ return settings->chameleon_default_slot_index != INVALID_SLOT_INDEX;
}
\ No newline at end of file
diff --git a/fw/application/src/app/chameleon/port/tag_helper.h b/fw/application/src/app/chameleon/port/tag_helper.h
index 19669c8d..31048870 100644
--- a/fw/application/src/app/chameleon/port/tag_helper.h
+++ b/fw/application/src/app/chameleon/port/tag_helper.h
@@ -1,13 +1,12 @@
#ifndef TAG_HELPER_H
#define TAG_HELPER_H
-#include "tag_base_type.h"
#include "nfc_14a.h"
+#include "nfc_mf0_ntag.h"
#include "nfc_mf1.h"
-#include "nfc_ntag.h"
+#include "tag_base_type.h"
-#define TAG_TYPE_MAX 9
-#define TAG_TYPE_HF_MAX 8
+#define TAG_TYPE_HF_MAX 13
#define SLOT_MAX 8
typedef struct {
@@ -25,7 +24,7 @@ typedef enum {
extern const tag_specific_type_t hf_tag_specific_types[];
-const tag_specific_type_name_t* tag_helper_get_tag_type_name(tag_specific_type_t tag_type);
+const tag_specific_type_name_t *tag_helper_get_tag_type_name(tag_specific_type_t tag_type);
const nfc_tag_14a_coll_res_reference_t *tag_helper_get_active_coll_res_ref();
tag_specific_type_t tag_helper_get_active_tag_type();
void tag_helper_format_uid(char *buff, uint8_t *uid, uint8_t uid_len);
@@ -39,5 +38,8 @@ uint8_t *tag_helper_get_active_tag_memory_data();
void tag_helper_generate_uid();
+bool tag_helper_is_defult_slot();
+
+bool tag_helper_valid_default_slot();
#endif
\ No newline at end of file
diff --git a/fw/application/src/app/chameleon/scene/chameleon_scene_menu.c b/fw/application/src/app/chameleon/scene/chameleon_scene_menu.c
index cf752419..61aa1a61 100644
--- a/fw/application/src/app/chameleon/scene/chameleon_scene_menu.c
+++ b/fw/application/src/app/chameleon/scene/chameleon_scene_menu.c
@@ -14,12 +14,15 @@
#include "tag_helper.h"
+#include "settings.h"
+
typedef enum {
CHAMELEON_MENU_HOME,
CHAMELEON_MENU_BACK,
CHAMELEON_MENU_SLOT,
CHAMELEON_MENU_CARD_NAME,
CHAMELEON_MENU_SLOT_SELECT,
+ CHAMELEON_MENU_DEFAULT_CARD,
CHAMELEON_MENU_CARD_DATA,
CHAMELEON_MENU_CARD_TYPE,
CHAMELEON_MENU_CARD_ADVANCED,
@@ -41,6 +44,18 @@ void chameleon_scene_menu_on_event(mui_list_view_event_t event, mui_list_view_t
mui_scene_dispatcher_next_scene(app->p_scene_dispatcher, CHAMELEON_SCENE_MENU_CARD_SLOT);
break;
+ case CHAMELEON_MENU_DEFAULT_CARD: {
+ settings_data_t *settings = settings_get_data();
+ uint8_t slot = tag_emulation_get_slot();
+ if (settings->chameleon_default_slot_index == slot) {
+ settings->chameleon_default_slot_index = INVALID_SLOT_INDEX;
+ } else {
+ settings->chameleon_default_slot_index = slot;
+ }
+
+ mui_list_view_item_set_sub_text(p_item, slot == settings->chameleon_default_slot_index ? _T(ON_F) : _T(OFF_F));
+ } break;
+
case CHAMELEON_MENU_SLOT_SELECT:
mui_scene_dispatcher_next_scene(app->p_scene_dispatcher, CHAMELEON_SCENE_MENU_CARD_SLOT_SELECT);
break;
@@ -65,7 +80,6 @@ void chameleon_scene_menu_on_event(mui_list_view_event_t event, mui_list_view_t
void chameleon_scene_menu_on_enter(void *user_data) {
app_chameleon_t *app = user_data;
-
char buff[64];
uint8_t slot = tag_emulation_get_slot();
tag_specific_type_t tag_type = tag_helper_get_active_tag_type();
@@ -73,11 +87,13 @@ void chameleon_scene_menu_on_enter(void *user_data) {
const nfc_tag_14a_coll_res_reference_t *coll_res = tag_helper_get_active_coll_res_ref();
sprintf(buff, "[%02d]", slot + 1);
- mui_list_view_add_item_ext(app->p_list_view, ICON_VIEW, _T(APP_CHAMELEON_CARD_SLOT), buff, (void *)CHAMELEON_MENU_SLOT_SELECT);
+ mui_list_view_add_item_ext(app->p_list_view, ICON_VIEW, _T(APP_CHAMELEON_CARD_SLOT), buff,
+ (void *)CHAMELEON_MENU_SLOT_SELECT);
strcpy(buff, "[");
tag_helper_get_nickname(buff + 1, sizeof(buff) - 3);
strcat(buff, "]");
- mui_list_view_add_item_ext(app->p_list_view, ICON_KEY, _T(APP_CHAMELEON_CARD_NICK), buff, (void *)CHAMELEON_MENU_CARD_NAME);
+ mui_list_view_add_item_ext(app->p_list_view, ICON_KEY, _T(APP_CHAMELEON_CARD_NICK), buff,
+ (void *)CHAMELEON_MENU_CARD_NAME);
strcpy(buff, "[");
tag_helper_format_uid(buff + 1, coll_res->uid, *(coll_res->size));
@@ -85,12 +101,19 @@ void chameleon_scene_menu_on_enter(void *user_data) {
mui_list_view_add_item_ext(app->p_list_view, ICON_DATA, _T(APP_CHAMELEON_CARD_ID), buff, (void *)-1);
sprintf(buff, "[%s]", tag_name->long_name);
- mui_list_view_add_item_ext(app->p_list_view, ICON_FAVORITE, _T(APP_CHAMELEON_CARD_TYPE), buff, (void *)CHAMELEON_MENU_CARD_TYPE);
+ mui_list_view_add_item_ext(app->p_list_view, ICON_FAVORITE, _T(APP_CHAMELEON_CARD_TYPE), buff,
+ (void *)CHAMELEON_MENU_CARD_TYPE);
+
+ settings_data_t *settings = settings_get_data();
+ mui_list_view_add_item_ext(app->p_list_view, ICON_SLOT, _T(APP_CHAMELEON_CARD_DEFAULT_CARD),
+ settings->chameleon_default_slot_index == slot ? _T(ON_F) : _T(OFF_F),
+ (void *)CHAMELEON_MENU_DEFAULT_CARD);
mui_list_view_add_item(app->p_list_view, ICON_FILE, _T(APP_CHAMELEON_CARD_DATA), (void *)CHAMELEON_MENU_CARD_DATA);
- mui_list_view_add_item(app->p_list_view, ICON_PAGE, _T(APP_CHAMELEON_CARD_ADVANCED), (void *)CHAMELEON_MENU_CARD_ADVANCED);
- mui_list_view_add_item(app->p_list_view, ICON_SLOT, _T(APP_CHAMELEON_CARD_SLOT_SETTINGS), (void *)CHAMELEON_MENU_SLOT);
- // mui_list_view_add_item(app->p_list_view, ICON_SETTINGS, "全局设置..", (void *)-1);
+ mui_list_view_add_item(app->p_list_view, ICON_PAGE, _T(APP_CHAMELEON_CARD_ADVANCED),
+ (void *)CHAMELEON_MENU_CARD_ADVANCED);
+ mui_list_view_add_item(app->p_list_view, ICON_SLOT, _T(APP_CHAMELEON_CARD_SLOT_SETTINGS),
+ (void *)CHAMELEON_MENU_SLOT);
mui_list_view_add_item(app->p_list_view, ICON_BACK, _T(TAG_DETAILS), (void *)CHAMELEON_MENU_BACK);
mui_list_view_add_item(app->p_list_view, ICON_HOME, _T(MAIN_MENU), (void *)CHAMELEON_MENU_HOME);
diff --git a/fw/application/src/app/chameleon/scene/chameleon_scene_menu_card_type.c b/fw/application/src/app/chameleon/scene/chameleon_scene_menu_card_type.c
index 0593f934..a90a3510 100644
--- a/fw/application/src/app/chameleon/scene/chameleon_scene_menu_card_type.c
+++ b/fw/application/src/app/chameleon/scene/chameleon_scene_menu_card_type.c
@@ -66,7 +66,7 @@ void chameleon_scene_menu_card_type_on_enter(void *user_data) {
app_chameleon_t *app = user_data;
// 0 is unkown...
- for (uint32_t i = 1; i < TAG_TYPE_HF_MAX; i++) {
+ for (uint32_t i = 1; i < TAG_TYPE_HF_MAX + 1; i++) {
const tag_specific_type_name_t *tag_name = tag_helper_get_tag_type_name(hf_tag_specific_types[i]);
mui_list_view_add_item(app->p_list_view, ICON_FILE, tag_name->long_name, (void *)CHAMELEON_MENU_CARD_TYPE);
}
diff --git a/fw/application/src/app/chameleon/view/chameleon_view.c b/fw/application/src/app/chameleon/view/chameleon_view.c
index 13fbbec8..5e524364 100644
--- a/fw/application/src/app/chameleon/view/chameleon_view.c
+++ b/fw/application/src/app/chameleon/view/chameleon_view.c
@@ -80,6 +80,12 @@ static void chameleon_view_on_draw(mui_view_t *p_view, mui_canvas_t *p_canvas) {
icon_glyph);
}
+ if(tag_helper_is_defult_slot()){
+ mui_canvas_set_font(p_canvas, MUI_FONT_ICON);
+ mui_canvas_draw_glyph(p_canvas, mui_canvas_get_width(p_canvas) - 20, mui_canvas_get_height(p_canvas),
+ ICON_FAVORITE);
+ }
+
mui_canvas_set_font(p_canvas, MUI_FONT_NORMAL);
}
diff --git a/fw/application/src/app/settings/scene/settings_scene_about.c b/fw/application/src/app/settings/scene/settings_scene_about.c
new file mode 100644
index 00000000..42f865f0
--- /dev/null
+++ b/fw/application/src/app/settings/scene/settings_scene_about.c
@@ -0,0 +1,37 @@
+#include "app_settings.h"
+#include "i18n/language.h"
+#include "mini_app_launcher.h"
+#include "nrf_pwr_mgmt.h"
+#include "settings.h"
+#include "settings_scene.h"
+#include "utils2.h"
+#include "version2.h"
+#include "mui_icons.h"
+
+
+static void settings_scene_about_list_view_on_selected(mui_list_view_event_t event, mui_list_view_t *p_list_view,
+ mui_list_item_t *p_item) {
+ app_settings_t *app = p_list_view->user_data;
+ if(p_item->icon == ICON_BACK){
+ mui_scene_dispatcher_previous_scene(app->p_scene_dispatcher);
+ }
+}
+
+void settings_scene_about_on_enter(void *user_data) {
+
+ app_settings_t *app = user_data;
+
+ mui_list_view_add_item(app->p_list_view, ICON_FILE, _T(APP_SET_ABOUT_OPEN_SOURCE_PROJECT), NULL_USER_DATA);
+ mui_list_view_add_item(app->p_list_view, ICON_FILE, _T(APP_SET_ABOUT_LGPL_LICENSE), NULL_USER_DATA);
+ mui_list_view_add_item(app->p_list_view, ICON_FILE, "github.com/solosky/pixl.js", NULL_USER_DATA);
+ mui_list_view_add_item(app->p_list_view, ICON_BACK, getLangString(_L_BACK), NULL_USER_DATA);
+
+ mui_list_view_set_selected_cb(app->p_list_view, settings_scene_about_list_view_on_selected);
+ mui_view_dispatcher_switch_to_view(app->p_view_dispatcher, SETTINGS_VIEW_ID_MAIN);
+}
+
+void settings_scene_about_on_exit(void *user_data) {
+ app_settings_t *app = user_data;
+ mui_list_view_clear_items(app->p_list_view);
+ mui_list_view_set_selected_cb(app->p_list_view, NULL);
+}
diff --git a/fw/application/src/app/settings/scene/settings_scene_config.h b/fw/application/src/app/settings/scene/settings_scene_config.h
index f740b9ec..54c5295b 100644
--- a/fw/application/src/app/settings/scene/settings_scene_config.h
+++ b/fw/application/src/app/settings/scene/settings_scene_config.h
@@ -8,4 +8,5 @@ ADD_SCENE(settings, lcd_backlight, LCD_BACKLIGHT)
ADD_SCENE(settings, oled_contrast, OLED_CONTRAST)
#endif
ADD_SCENE(settings, language, LANGUAGE)
-ADD_SCENE(settings, storage, STORAGE)
\ No newline at end of file
+ADD_SCENE(settings, storage, STORAGE)
+ADD_SCENE(settings, about, ABOUT)
\ No newline at end of file
diff --git a/fw/application/src/app/settings/scene/settings_scene_main.c b/fw/application/src/app/settings/scene/settings_scene_main.c
index d90c2e68..3ccf26d7 100644
--- a/fw/application/src/app/settings/scene/settings_scene_main.c
+++ b/fw/application/src/app/settings/scene/settings_scene_main.c
@@ -22,6 +22,7 @@ enum settings_main_menu_t {
SETTINGS_MAIN_MENU_DFU,
SETTINGS_MAIN_MENU_REBOOT,
SETTINGS_MAIN_MENU_RESET_DEFAULT,
+ SETTINGS_MAIN_MENU_ABOUT,
SETTINGS_MAIN_MENU_EXIT
};
@@ -128,9 +129,11 @@ static void settings_scene_main_list_view_on_selected(mui_list_view_event_t even
mui_msg_box_set_event_cb(app->p_msg_box, settings_scene_main_msg_box_reset_settings_cb);
mui_view_dispatcher_switch_to_view(app->p_view_dispatcher, SETTINGS_VIEW_ID_MSG_BOX);
- }
+ } break;
- break;
+ case SETTINGS_MAIN_MENU_ABOUT: {
+ mui_scene_dispatcher_next_scene(app->p_scene_dispatcher, SETTINGS_SCENE_ABOUT);
+ } break;
}
}
@@ -207,6 +210,8 @@ static void settings_scene_main_reload(void *user_data) {
mui_list_view_add_item(app->p_list_view, 0xe1ce, _T(APP_SET_RESET_DEFAULT),
(void *)SETTINGS_MAIN_MENU_RESET_DEFAULT);
+ mui_list_view_add_item(app->p_list_view, 0xe1cf, _T(APP_SET_ABOUT), (void *)SETTINGS_MAIN_MENU_ABOUT);
+
mui_list_view_add_item(app->p_list_view, 0xe069, _T(BACK_TO_MAIN_MENU), (void *)SETTINGS_MAIN_MENU_EXIT);
mui_list_view_set_focus(app->p_list_view, foucs_index);
diff --git a/fw/application/src/core/mini_app_launcher.c b/fw/application/src/core/mini_app_launcher.c
index c6f5cc4d..5dc15da0 100644
--- a/fw/application/src/core/mini_app_launcher.c
+++ b/fw/application/src/core/mini_app_launcher.c
@@ -4,6 +4,8 @@
#include "nrf_log.h"
#include "nrf_log_ctrl.h"
#include "settings.h"
+#include "nrf_power.h"
+#include "tag_helper.h"
mini_app_launcher_t *mini_app_launcher() {
static mini_app_launcher_t launcher;
@@ -71,7 +73,7 @@ void mini_app_launcher_exit(mini_app_launcher_t* p_launcher){
mini_app_launcher_kill(p_launcher, p_launcher->p_main_app_inst->p_app->id);
}
-void mini_app_launcher_init(mini_app_launcher_t *p_launcher) {
+void mini_app_launcher_init(mini_app_launcher_t *p_launcher, uint32_t wakeup_reason) {
mui_app_inst_dict_init(p_launcher->app_inst_dict);
p_launcher->p_main_app_inst = NULL;
@@ -80,7 +82,12 @@ void mini_app_launcher_init(mini_app_launcher_t *p_launcher) {
cache_data_t *p_cache = cache_get_data();
settings_data_t *p_settings = settings_get_data();
- if (p_cache->enabled == 1 && p_settings->hibernate_enabled == 1) {
+
+ NRF_LOG_INFO("wakeup reason: %d", wakeup_reason);
+
+ if( (wakeup_reason & NRF_POWER_RESETREAS_NFC_MASK) && tag_helper_valid_default_slot()){
+ mini_app_launcher_run_with_retain_data(p_launcher, MINI_APP_ID_CHAMELEON, NULL);
+ }else if (p_cache->enabled == 1 && p_settings->hibernate_enabled == 1) {
mini_app_launcher_run_with_retain_data(p_launcher, p_cache->id, p_cache->retain_data);
} else {
mini_app_launcher_run_with_retain_data(p_launcher, MINI_APP_ID_DESKTOP, NULL);
diff --git a/fw/application/src/core/mini_app_launcher.h b/fw/application/src/core/mini_app_launcher.h
index 0305dc18..30bd4113 100644
--- a/fw/application/src/core/mini_app_launcher.h
+++ b/fw/application/src/core/mini_app_launcher.h
@@ -19,7 +19,7 @@ mini_app_launcher_t* mini_app_launcher();
void mini_app_launcher_run(mini_app_launcher_t* p_launcher, uint32_t id);
void mini_app_launcher_kill(mini_app_launcher_t* p_launcher, uint32_t id);
void mini_app_launcher_exit(mini_app_launcher_t* p_launcher);
-void mini_app_launcher_init(mini_app_launcher_t* p_launcher);
+void mini_app_launcher_init(mini_app_launcher_t* p_launcher, uint32_t wakeup_reason);
void mini_app_launcher_sleep(mini_app_launcher_t* p_launcher);
void mini_app_launcher_post_event(mini_app_launcher_t* p_launcher, uint32_t id, mini_app_event_t* p_event);
void* mini_app_launcher_get_app_handle(mini_app_launcher_t* p_launcher, uint32_t id);
diff --git a/fw/application/src/i18n/de_DE.c b/fw/application/src/i18n/de_DE.c
index b0968e08..315dd7e7 100644
--- a/fw/application/src/i18n/de_DE.c
+++ b/fw/application/src/i18n/de_DE.c
@@ -31,6 +31,9 @@ const char * const lang_de_DE[_L_COUNT] = {
[_L_APP_SET_RESET_DEFAULT] = "Standardeinstellungen",
[_L_APP_SET_RESET_DEFAULT_SUCCESS] = "Einstellungen zurückgesetzt!",
[_L_APP_SET_RESET_DEFAULT_CONFIRM] = "Auf Standardeinstellungen zurücksetzen?",
+ [_L_APP_SET_ABOUT] = "",
+ [_L_APP_SET_ABOUT_OPEN_SOURCE_PROJECT] = "",
+ [_L_APP_SET_ABOUT_LGPL_LICENSE] = "",
[_L_15S] = "15 Sekunden",
[_L_30S] = "30 Sekunden",
[_L_45S] = "45 Sekunden",
@@ -43,6 +46,7 @@ const char * const lang_de_DE[_L_COUNT] = {
[_L_RANDOM_GENERATION] = "Zufällige UUID",
[_L_AUTO_RANDOM_GENERATION] = "Zufällige UUID (Automatisch)",
[_L_SHOW_QRCODE] = "QR Code",
+ [_L_READ_ONLY] = "",
[_L_DELETE_TAG] = "Tag löschen",
[_L_DELETE_TAG_CONFIRM] = "Löschen von %s bestätigen?",
[_L_BACK_TO_DETAILS] = "Zurück zu Tag Details",
diff --git a/fw/application/src/i18n/en_US.c b/fw/application/src/i18n/en_US.c
index 61c31833..502de2c0 100644
--- a/fw/application/src/i18n/en_US.c
+++ b/fw/application/src/i18n/en_US.c
@@ -31,6 +31,9 @@ const char * const lang_en_US[_L_COUNT] = {
[_L_APP_SET_RESET_DEFAULT] = "Reset Default Setting",
[_L_APP_SET_RESET_DEFAULT_SUCCESS] = "Reset Success!",
[_L_APP_SET_RESET_DEFAULT_CONFIRM] = "Confirm Reset Settings?",
+ [_L_APP_SET_ABOUT] = "About Device",
+ [_L_APP_SET_ABOUT_OPEN_SOURCE_PROJECT] = "Open Source Project",
+ [_L_APP_SET_ABOUT_LGPL_LICENSE] = "GPL 2.0 License",
[_L_15S] = "15 Seconds",
[_L_30S] = "30 Seconds",
[_L_45S] = "45 Seconds",
@@ -43,6 +46,7 @@ const char * const lang_en_US[_L_COUNT] = {
[_L_RANDOM_GENERATION] = "Rand. Tag",
[_L_AUTO_RANDOM_GENERATION] = "Auto Rand.",
[_L_SHOW_QRCODE] = "Display QR Code",
+ [_L_READ_ONLY] = "Read-only",
[_L_DELETE_TAG] = "Delete Tag",
[_L_DELETE_TAG_CONFIRM] = "Confirm Delete %s ?",
[_L_BACK_TO_DETAILS] = "Back to Tag Details",
diff --git a/fw/application/src/i18n/es_ES.c b/fw/application/src/i18n/es_ES.c
index 372f0485..f83bf95f 100644
--- a/fw/application/src/i18n/es_ES.c
+++ b/fw/application/src/i18n/es_ES.c
@@ -22,7 +22,7 @@ const char * const lang_es_ES[_L_COUNT] = {
[_L_APP_SET_LCD_BACKLIGHT_TITLE] = "Brillo de fondo",
[_L_APP_SET_ANIM] = "Animar menú",
[_L_APP_SET_LIPO_BAT] = "Batería LiPO",
- [_L_APP_SET_SHOW_MEM_USAGE] = "Mem. usada",
+ [_L_APP_SET_SHOW_MEM_USAGE] = "Estad. Mem.",
[_L_APP_SET_HIBERNATE] = "Hibernar",
[_L_APP_SET_SLEEP_TIMEOUT] = "Dormir en:",
[_L_APP_SET_LANGUAGE] = "Idioma",
@@ -30,7 +30,10 @@ const char * const lang_es_ES[_L_COUNT] = {
[_L_APP_SET_REBOOT] = "Reiniciar",
[_L_APP_SET_RESET_DEFAULT] = "Restablecer config.",
[_L_APP_SET_RESET_DEFAULT_SUCCESS] = "¡Configuración Restablecida!",
- [_L_APP_SET_RESET_DEFAULT_CONFIRM] = "",
+ [_L_APP_SET_RESET_DEFAULT_CONFIRM] = "¿Confirma Restablecer\nConfig.?",
+ [_L_APP_SET_ABOUT] = "Acerca del dispositivo",
+ [_L_APP_SET_ABOUT_OPEN_SOURCE_PROJECT] = "Poyecto de código abierto",
+ [_L_APP_SET_ABOUT_LGPL_LICENSE] = "Licencia GPL 2.0",
[_L_15S] = "15 segundos",
[_L_30S] = "30 segundos",
[_L_45S] = "45 segundos",
@@ -43,8 +46,9 @@ const char * const lang_es_ES[_L_COUNT] = {
[_L_RANDOM_GENERATION] = "Nuevo serial aleat.",
[_L_AUTO_RANDOM_GENERATION] = "Serial alea. aut",
[_L_SHOW_QRCODE] = "Mostrar QR",
+ [_L_READ_ONLY] = "",
[_L_DELETE_TAG] = "Borrar amiibo...",
- [_L_DELETE_TAG_CONFIRM] = "¿\nBorrar %s\n?",
+ [_L_DELETE_TAG_CONFIRM] = "¿Borrar %s?",
[_L_BACK_TO_DETAILS] = "[Detalles amiibo]",
[_L_BACK_TO_FILE_LIST] = "[Lista Archivos]",
[_L_BACK_TO_MAIN_MENU] = "[Menú Principal]",
@@ -65,7 +69,7 @@ const char * const lang_es_ES[_L_COUNT] = {
[_L_READ_FILE_FAILED] = "Error al leer archivo",
[_L_INPUT_FOLDER_NAME] = "Nombre carpeta:",
[_L_INPUT_AMIIBO_NAME] = "Nombre amiibo:",
- [_L_DELETE_FILE] = "¿Borrar el %s ?",
+ [_L_DELETE_FILE] = "¿Borrar %s?",
[_L_DELETE] = "Borrar...",
[_L_TIPS] = "Confirmar",
[_L_INPUT_NEW_NAME] = "Nuevo nombre:",
@@ -75,7 +79,7 @@ const char * const lang_es_ES[_L_COUNT] = {
[_L_CREATE_NEW_TAG_BATCH] = "Crear amiibo en lote...",
[_L_INPUT_TAG_NUM] = "¿Cuántos?",
[_L_CREATE_TOO_MANY_NUM] = "Sólo se puede crear %d en lote",
- [_L_CREATING_TAG_BATCH] = "Creando",
+ [_L_CREATING_TAG_BATCH] = "Creando...",
[_L_CREATING_TAG_FAILED] = "¡Error al crear %s!",
[_L_RENAME] = "Renombrar...",
[_L_OPEN_FOLDER_FAILED] = "Fallo al abrir carpeta",
@@ -85,8 +89,8 @@ const char * const lang_es_ES[_L_COUNT] = {
[_L_RANDOM_MODE_AUTO] = "Aleatorio (Auto.)",
[_L_SEQUENCE_MODE] = "Modo Secuencial",
[_L_READ_WRITE_MODE] = "Modo Lectura/Escrit.",
- [_L_AMIIBOLINK_V1] = "V1",
- [_L_AMIIBOLINK_V2] = "V2",
+ [_L_AMIIBOLINK_V1] = "AmiiboLink V1",
+ [_L_AMIIBOLINK_V2] = "AmiiboLink V2",
[_L_AMILOOP] = "AmiLoop",
[_L_MODE] = "Modo",
[_L_AUTO_RANDOM] = "Aleat. autom.",
@@ -129,8 +133,8 @@ const char * const lang_es_ES[_L_COUNT] = {
[_L_APP_AMIIDB_FAV_EMPTY_MSG] = "¿Vaciar Carp. Favoritos?",
[_L_APP_AMIIDB_FAV_DELETE_MSG] = "¿Confirma borrado?",
[_L_APP_AMIIDB_FAV_SELECT_FOLDER] = "Selec. carp. favoritos...",
- [_L_APP_AMIIDB_FAV_SUCCESS] = "¡Favorito correcto!",
- [_L_APP_AMIIDB_FAV_FAILED] = "¡Favorito fallido!",
+ [_L_APP_AMIIDB_FAV_SUCCESS] = "¡Adicionado a Favoritos!",
+ [_L_APP_AMIIDB_FAV_FAILED] = "¡Fallo al adicionar\na Favoritos!",
[_L_APP_AMIIDB_SLOT_SAVE_SUCCESS] = "Asignación correcta",
[_L_APP_AMIIDB_SLOT_SAVE_FAILED] = "¡Asignación fallida!",
[_L_APP_CHAMELEON] = "Emular Etiqueta RFID",
@@ -156,14 +160,14 @@ const char * const lang_es_ES[_L_COUNT] = {
[_L_APP_CHAMELEON_CARD_DATA_FACTORY_SUCCESS] = "¡Datos inicializados!",
[_L_APP_CHAMELEON_CARD_DATA_LOAD_NOT_FOUND] = "Archivo no encontrado",
[_L_APP_CHAMELEON_CARD_DATA_LOAD_SIZE_NOT_MATCH] = "Tamaño archivo incorrecto",
- [_L_APP_CHAMELEON_CARD_DATA_LOAD_FAILED] = "Falla carga archivo",
+ [_L_APP_CHAMELEON_CARD_DATA_LOAD_FAILED] = "Falla al cargar archivo",
[_L_APP_CHAMELEON_CARD_DATA_LOAD_SUCCESS] = "Carga archivo correcta",
[_L_APP_CHAMELEON_CARD_DATA_SAVE_INPUT_FILE_NAME] = "Nombre archivo:",
[_L_APP_CHAMELEON_CARD_DATA_SAVE_FAILED] = "¡Error al guardar!",
[_L_APP_CHAMELEON_CARD_DATA_SAVE_SUCCESS] = "Guardado correcto",
[_L_APP_CHAMELEON_CARD_ADV_CUSTOM_MODE] = "Modo personali.",
[_L_APP_CHAMELEON_CARD_GEN1A_MODE] = "Gen1A habilitada",
- [_L_APP_CHAMELEON_CARD_GENERATE_UID] = "Generar nuevo UID",
+ [_L_APP_CHAMELEON_CARD_GENERATE_UID] = "Generar UID aleat.",
[_L_APP_CHAMELEON_CARD_GENERATE_UID_SUCCESS] = "UID generado",
[_L_APP_CHAMELEON_CARD_GEN2_MODE] = "Gen2 habilitada",
[_L_APP_CHAMELEON_CARD_WRITE_MODE] = "Modo escrit.",
diff --git a/fw/application/src/i18n/fr_FR.c b/fw/application/src/i18n/fr_FR.c
index d3773122..63c44be5 100644
--- a/fw/application/src/i18n/fr_FR.c
+++ b/fw/application/src/i18n/fr_FR.c
@@ -31,6 +31,9 @@ const char * const lang_fr_FR[_L_COUNT] = {
[_L_APP_SET_RESET_DEFAULT] = "Rétablir les Paramètres par Défaut",
[_L_APP_SET_RESET_DEFAULT_SUCCESS] = "Réinitialiser les Paramètres Par Défaut",
[_L_APP_SET_RESET_DEFAULT_CONFIRM] = "",
+ [_L_APP_SET_ABOUT] = "",
+ [_L_APP_SET_ABOUT_OPEN_SOURCE_PROJECT] = "",
+ [_L_APP_SET_ABOUT_LGPL_LICENSE] = "",
[_L_15S] = "15 sec.",
[_L_30S] = "30 sec.",
[_L_45S] = "45 sec.",
@@ -43,6 +46,7 @@ const char * const lang_fr_FR[_L_COUNT] = {
[_L_RANDOM_GENERATION] = "Randomiser la Balise",
[_L_AUTO_RANDOM_GENERATION] = "Randomisation Automatique",
[_L_SHOW_QRCODE] = "Afficher le Code QR",
+ [_L_READ_ONLY] = "",
[_L_DELETE_TAG] = "Supprimer la Balise",
[_L_DELETE_TAG_CONFIRM] = "Confirmer la Suppression de %s ?",
[_L_BACK_TO_DETAILS] = "Retour Aux Détails de L'étiquette",
diff --git a/fw/application/src/i18n/hu_HU.c b/fw/application/src/i18n/hu_HU.c
index 36402679..7960c521 100644
--- a/fw/application/src/i18n/hu_HU.c
+++ b/fw/application/src/i18n/hu_HU.c
@@ -31,6 +31,9 @@ const char * const lang_hu_HU[_L_COUNT] = {
[_L_APP_SET_RESET_DEFAULT] = "Alapért. Beállítás Visszaállítása",
[_L_APP_SET_RESET_DEFAULT_SUCCESS] = "Alapért. Beállítások Visszaállítása",
[_L_APP_SET_RESET_DEFAULT_CONFIRM] = "",
+ [_L_APP_SET_ABOUT] = "",
+ [_L_APP_SET_ABOUT_OPEN_SOURCE_PROJECT] = "",
+ [_L_APP_SET_ABOUT_LGPL_LICENSE] = "",
[_L_15S] = "15 sec.",
[_L_30S] = "30 sec.",
[_L_45S] = "45 sec.",
@@ -43,6 +46,7 @@ const char * const lang_hu_HU[_L_COUNT] = {
[_L_RANDOM_GENERATION] = "Véletlengenerátor",
[_L_AUTO_RANDOM_GENERATION] = "Automat. Véletlengenerátor",
[_L_SHOW_QRCODE] = "QR-kód Megjelenítése",
+ [_L_READ_ONLY] = "",
[_L_DELETE_TAG] = "Címke Törlése",
[_L_DELETE_TAG_CONFIRM] = "Törlés Megerősítése?",
[_L_BACK_TO_DETAILS] = "Vissza a Címke Részletkhez",
diff --git a/fw/application/src/i18n/it_IT.c b/fw/application/src/i18n/it_IT.c
index 984d529b..289f6320 100644
--- a/fw/application/src/i18n/it_IT.c
+++ b/fw/application/src/i18n/it_IT.c
@@ -31,6 +31,9 @@ const char * const lang_it_IT[_L_COUNT] = {
[_L_APP_SET_RESET_DEFAULT] = "Ripristina impostazioni predefinite",
[_L_APP_SET_RESET_DEFAULT_SUCCESS] = "Ripristino riuscito!",
[_L_APP_SET_RESET_DEFAULT_CONFIRM] = "Conferma il ripristino delle impostazioni?",
+ [_L_APP_SET_ABOUT] = "",
+ [_L_APP_SET_ABOUT_OPEN_SOURCE_PROJECT] = "",
+ [_L_APP_SET_ABOUT_LGPL_LICENSE] = "",
[_L_15S] = "15 secondi",
[_L_30S] = "30 secondi",
[_L_45S] = "45 secondi",
@@ -43,6 +46,7 @@ const char * const lang_it_IT[_L_COUNT] = {
[_L_RANDOM_GENERATION] = "Tag casuale",
[_L_AUTO_RANDOM_GENERATION] = "Casuale automatico",
[_L_SHOW_QRCODE] = "Mostra codice QR",
+ [_L_READ_ONLY] = "",
[_L_DELETE_TAG] = "Elimina tag",
[_L_DELETE_TAG_CONFIRM] = "Conferma eliminazione %s\n?",
[_L_BACK_TO_DETAILS] = "[Torna ai dettagli del tag]",
@@ -169,4 +173,6 @@ const char * const lang_it_IT[_L_COUNT] = {
[_L_APP_CHAMELEON_CARD_WRITE_MODE] = "Modalità scrittura",
[_L_APP_CHAMELEON_CARD_ADV_ID_EDIT_INVALID_INPUT] = "Input non valido!",
[_L_APP_CHAMELEON_CARD_TYPE_FACTORY_DATA_CONFRIM] = "Tipo di carta modificato\nInizializzare carta?",
+ [_L_APP_READER] = "",
+ [_L_APP_READER_SCANNING] = "_L_APP_CHAMELEON_CARD_DEFAULT_CARD",
};
diff --git a/fw/application/src/i18n/ja_JP.c b/fw/application/src/i18n/ja_JP.c
index 030ae4c2..e77b75e3 100644
--- a/fw/application/src/i18n/ja_JP.c
+++ b/fw/application/src/i18n/ja_JP.c
@@ -31,6 +31,9 @@ const char * const lang_ja_JP[_L_COUNT] = {
[_L_APP_SET_RESET_DEFAULT] = "デフォルト設定に戻す",
[_L_APP_SET_RESET_DEFAULT_SUCCESS] = "設定を初期化",
[_L_APP_SET_RESET_DEFAULT_CONFIRM] = "",
+ [_L_APP_SET_ABOUT] = "",
+ [_L_APP_SET_ABOUT_OPEN_SOURCE_PROJECT] = "",
+ [_L_APP_SET_ABOUT_LGPL_LICENSE] = "",
[_L_15S] = "15秒",
[_L_30S] = "30秒",
[_L_45S] = "45秒",
@@ -43,6 +46,7 @@ const char * const lang_ja_JP[_L_COUNT] = {
[_L_RANDOM_GENERATION] = "タグのランダム化",
[_L_AUTO_RANDOM_GENERATION] = "自動ランダム化",
[_L_SHOW_QRCODE] = "QRコード表示",
+ [_L_READ_ONLY] = "",
[_L_DELETE_TAG] = "タグの削除",
[_L_DELETE_TAG_CONFIRM] = "%s を削除しますか?",
[_L_BACK_TO_DETAILS] = "タグの詳細に戻る",
diff --git a/fw/application/src/i18n/nl_NL.c b/fw/application/src/i18n/nl_NL.c
index ab983593..38f2a0ef 100644
--- a/fw/application/src/i18n/nl_NL.c
+++ b/fw/application/src/i18n/nl_NL.c
@@ -31,6 +31,9 @@ const char * const lang_nl_NL[_L_COUNT] = {
[_L_APP_SET_RESET_DEFAULT] = "Terugzetten Naar Standaardwaarden",
[_L_APP_SET_RESET_DEFAULT_SUCCESS] = "Standaardinstellingen Herstellen",
[_L_APP_SET_RESET_DEFAULT_CONFIRM] = "",
+ [_L_APP_SET_ABOUT] = "",
+ [_L_APP_SET_ABOUT_OPEN_SOURCE_PROJECT] = "",
+ [_L_APP_SET_ABOUT_LGPL_LICENSE] = "",
[_L_15S] = "15 sec.",
[_L_30S] = "30 sec.",
[_L_45S] = "45 sec.",
@@ -43,6 +46,7 @@ const char * const lang_nl_NL[_L_COUNT] = {
[_L_RANDOM_GENERATION] = "Willekeurige Tag",
[_L_AUTO_RANDOM_GENERATION] = "Automatische Randomisatie",
[_L_SHOW_QRCODE] = "QR-Code Weergeven",
+ [_L_READ_ONLY] = "",
[_L_DELETE_TAG] = "Tag Verwijderen",
[_L_DELETE_TAG_CONFIRM] = "Bevestig Verwijderen %s ?",
[_L_BACK_TO_DETAILS] = "Terug naar Tag Details",
diff --git a/fw/application/src/i18n/pt_BR.c b/fw/application/src/i18n/pt_BR.c
index 270a1805..a2dccde4 100644
--- a/fw/application/src/i18n/pt_BR.c
+++ b/fw/application/src/i18n/pt_BR.c
@@ -31,6 +31,9 @@ const char * const lang_pt_BR[_L_COUNT] = {
[_L_APP_SET_RESET_DEFAULT] = "Restaurar Configurações Padrão",
[_L_APP_SET_RESET_DEFAULT_SUCCESS] = "Redefinir a Configuração Padrão",
[_L_APP_SET_RESET_DEFAULT_CONFIRM] = "",
+ [_L_APP_SET_ABOUT] = "",
+ [_L_APP_SET_ABOUT_OPEN_SOURCE_PROJECT] = "",
+ [_L_APP_SET_ABOUT_LGPL_LICENSE] = "",
[_L_15S] = "15 seg.",
[_L_30S] = "30 seg.",
[_L_45S] = "45 seg.",
@@ -43,6 +46,7 @@ const char * const lang_pt_BR[_L_COUNT] = {
[_L_RANDOM_GENERATION] = "Randomizar Etiqueta",
[_L_AUTO_RANDOM_GENERATION] = "Randomização Automática",
[_L_SHOW_QRCODE] = "Exibir QR Code",
+ [_L_READ_ONLY] = "",
[_L_DELETE_TAG] = "Excluir Etiqueta",
[_L_DELETE_TAG_CONFIRM] = "Confirmar Exclusão de %s ?",
[_L_BACK_TO_DETAILS] = "Voltar Aos Detalhes da Tag",
diff --git a/fw/application/src/i18n/ru_RU.c b/fw/application/src/i18n/ru_RU.c
index b4cbb811..e8e73812 100644
--- a/fw/application/src/i18n/ru_RU.c
+++ b/fw/application/src/i18n/ru_RU.c
@@ -31,6 +31,9 @@ const char * const lang_ru_RU[_L_COUNT] = {
[_L_APP_SET_RESET_DEFAULT] = "Сброс настроек",
[_L_APP_SET_RESET_DEFAULT_SUCCESS] = "Сброс выполнен",
[_L_APP_SET_RESET_DEFAULT_CONFIRM] = "Выполнить?",
+ [_L_APP_SET_ABOUT] = "Об устройстве",
+ [_L_APP_SET_ABOUT_OPEN_SOURCE_PROJECT] = "Проект с открытым кодом",
+ [_L_APP_SET_ABOUT_LGPL_LICENSE] = "Лицензия GPL 2.0",
[_L_15S] = "15 секунд",
[_L_30S] = "30 секунд",
[_L_45S] = "45 секунд",
@@ -43,6 +46,7 @@ const char * const lang_ru_RU[_L_COUNT] = {
[_L_RANDOM_GENERATION] = "Сгенерировать UUID",
[_L_AUTO_RANDOM_GENERATION] = "Автогенерация",
[_L_SHOW_QRCODE] = "QR-код",
+ [_L_READ_ONLY] = "Только чтение",
[_L_DELETE_TAG] = "Удалить тег",
[_L_DELETE_TAG_CONFIRM] = "Удалить %s?",
[_L_BACK_TO_DETAILS] = "[Назад к деталям]",
@@ -169,4 +173,3 @@ const char * const lang_ru_RU[_L_COUNT] = {
[_L_APP_CHAMELEON_CARD_WRITE_MODE] = "Запись",
[_L_APP_CHAMELEON_CARD_ADV_ID_EDIT_INVALID_INPUT] = "Недопустимый ввод",
[_L_APP_CHAMELEON_CARD_TYPE_FACTORY_DATA_CONFRIM] = "Тип карты изменен.\nСбросить данные карты?",
-};
diff --git a/fw/application/src/i18n/string_id.h b/fw/application/src/i18n/string_id.h
index f675f8a3..c2ebd127 100644
--- a/fw/application/src/i18n/string_id.h
+++ b/fw/application/src/i18n/string_id.h
@@ -32,6 +32,9 @@ typedef enum {
_L_APP_SET_RESET_DEFAULT,
_L_APP_SET_RESET_DEFAULT_SUCCESS,
_L_APP_SET_RESET_DEFAULT_CONFIRM,
+ _L_APP_SET_ABOUT,
+ _L_APP_SET_ABOUT_OPEN_SOURCE_PROJECT,
+ _L_APP_SET_ABOUT_LGPL_LICENSE,
_L_15S,
_L_30S,
_L_45S,
@@ -44,6 +47,7 @@ typedef enum {
_L_RANDOM_GENERATION,
_L_AUTO_RANDOM_GENERATION,
_L_SHOW_QRCODE,
+ _L_READ_ONLY,
_L_DELETE_TAG,
_L_DELETE_TAG_CONFIRM,
_L_BACK_TO_DETAILS,
diff --git a/fw/application/src/i18n/zh_Hans.c b/fw/application/src/i18n/zh_Hans.c
index 82823369..7016742c 100644
--- a/fw/application/src/i18n/zh_Hans.c
+++ b/fw/application/src/i18n/zh_Hans.c
@@ -31,6 +31,9 @@ const char * const lang_zh_Hans[_L_COUNT] = {
[_L_APP_SET_RESET_DEFAULT] = "重置默认配置",
[_L_APP_SET_RESET_DEFAULT_SUCCESS] = "重置成功",
[_L_APP_SET_RESET_DEFAULT_CONFIRM] = "确认重置默认设置?",
+ [_L_APP_SET_ABOUT] = "关于设备",
+ [_L_APP_SET_ABOUT_OPEN_SOURCE_PROJECT] = "开源项目",
+ [_L_APP_SET_ABOUT_LGPL_LICENSE] = "GPL 2.0 授权",
[_L_15S] = "15秒",
[_L_30S] = "30秒",
[_L_45S] = "45秒",
@@ -43,6 +46,7 @@ const char * const lang_zh_Hans[_L_COUNT] = {
[_L_RANDOM_GENERATION] = "随机生成",
[_L_AUTO_RANDOM_GENERATION] = "自动随机生成",
[_L_SHOW_QRCODE] = "显示二维码",
+ [_L_READ_ONLY] = "禁止写入",
[_L_DELETE_TAG] = "删除标签",
[_L_DELETE_TAG_CONFIRM] = "确认删除 %s ?",
[_L_BACK_TO_DETAILS] = "返回详情",
diff --git a/fw/application/src/i18n/zh_TW.c b/fw/application/src/i18n/zh_TW.c
index f275109c..3e8eb72f 100644
--- a/fw/application/src/i18n/zh_TW.c
+++ b/fw/application/src/i18n/zh_TW.c
@@ -31,6 +31,9 @@ const char * const lang_zh_TW[_L_COUNT] = {
[_L_APP_SET_RESET_DEFAULT] = "重置默認配置",
[_L_APP_SET_RESET_DEFAULT_SUCCESS] = "重置成功",
[_L_APP_SET_RESET_DEFAULT_CONFIRM] = "确认重置默认设置?",
+ [_L_APP_SET_ABOUT] = "關於設俻",
+ [_L_APP_SET_ABOUT_OPEN_SOURCE_PROJECT] = "開源項目",
+ [_L_APP_SET_ABOUT_LGPL_LICENSE] = "GPL 2.0 授權",
[_L_15S] = "15秒",
[_L_30S] = "30秒",
[_L_45S] = "45秒",
@@ -43,6 +46,7 @@ const char * const lang_zh_TW[_L_COUNT] = {
[_L_RANDOM_GENERATION] = "隨機產生",
[_L_AUTO_RANDOM_GENERATION] = "自動隨機產生",
[_L_SHOW_QRCODE] = "顯示二維碼",
+ [_L_READ_ONLY] = "禁止寫入",
[_L_DELETE_TAG] = "刪除標籤",
[_L_DELETE_TAG_CONFIRM] = "確認刪除 %s ?",
[_L_BACK_TO_DETAILS] = "返回詳情",
diff --git a/fw/application/src/main.c b/fw/application/src/main.c
index 4624ce09..f6015c05 100644
--- a/fw/application/src/main.c
+++ b/fw/application/src/main.c
@@ -92,6 +92,8 @@
#include "hal_spi_bus.h"
#include "hal_spi_flash.h"
+#include "tag_helper.h"
+
#include "cache.h"
#include "i18n/language.h"
#include "settings.h"
@@ -99,10 +101,10 @@
#include "nfc_reader.h"
#include "tusb.h"
-//#include "usbd.h"
+// #include "usbd.h"
#define APP_SCHED_MAX_EVENT_SIZE 255 /**< Maximum size of scheduler events. */
-#define APP_SCHED_QUEUE_SIZE 16 /**< Maximum number of events in the scheduler queue. */
+#define APP_SCHED_QUEUE_SIZE 16 /**< Maximum number of events in the scheduler queue. */
#define BTN_ID_SLEEP 1 /**< ID of button used to put the application into sleep mode. */
#define BTN_ACTION_KEY1_LONGPUSH BSP_EVENT_KEY_LAST + 9
@@ -196,16 +198,28 @@ NRF_PWR_MGMT_HANDLER_REGISTER(shutdown_handler, APP_SHUTDOWN_HANDLER_PRIORITY);
/**
*@brief :检测唤醒源
*/
-static void check_wakeup_src(void) {
+static uint32_t check_wakeup_src(void) {
uint32_t rr;
sd_power_reset_reason_get(&rr);
NRF_LOG_INFO("nrf_power_resetreas_get: 0x%04x", rr);
- if (cache_valid()) {
- cache_data_t *p_cache = cache_get_data();
- ntag_emu_set_tag(&(p_cache->ntag));
+ // 如果卡模拟器设置了默认卡,这里就不开启模拟NTAG
+ if (tag_helper_valid_default_slot() && (rr & NRF_POWER_RESETREAS_NFC_MASK)) {
+ tag_emulation_init();
+ hal_nfc_set_nrfx_irq_enable(true);
+ tag_emulation_sense_run();
} else {
- cache_clean();
+
+ extern const ntag_t default_ntag215;
+ ret_code_t err_code = ntag_emu_init(&default_ntag215);
+ APP_ERROR_CHECK(err_code);
+
+ if (cache_valid()) {
+ cache_data_t *p_cache = cache_get_data();
+ ntag_emu_set_tag(&(p_cache->ntag));
+ } else {
+ cache_clean();
+ }
}
if (rr == 0) {
@@ -217,6 +231,7 @@ static void check_wakeup_src(void) {
NRF_LOG_INFO("First power system");
}
sd_power_reset_reason_clr(rr);
+ return rr;
}
/**
@@ -256,23 +271,20 @@ int main(void) {
hal_spi_bus_init();
// enable sd to enable pwr mgmt
- err_code = nrf_sdh_enable_request();
- APP_ERROR_CHECK(err_code);
-
- extern const ntag_t default_ntag215;
- err_code = ntag_emu_init(&default_ntag215);
+ err_code = nrf_sdh_enable_request();
APP_ERROR_CHECK(err_code);
// cache_clean(); //FOR TESTING
- check_wakeup_src();
err_code = settings_init();
// we ignore error here, cause flash may not be presented or settings.bin did not exist
NRF_LOG_INFO("settings init: %d", err_code);
// APP_ERROR_CHECK(err_code);
+ uint32_t wakeup_reason = check_wakeup_src();
+
#ifdef RC522
- //nfc initialized as emulator mode
+ // nfc initialized as emulator mode
nfc_reader_init();
#endif
@@ -284,7 +296,7 @@ int main(void) {
amiibo_helper_try_load_amiibo_keys_from_vfs();
#ifdef NRF52840_XXAA
- //usb_init();
+ // usb_init();
board_init();
tud_init(BOARD_TUD_RHPORT);
#endif
@@ -297,7 +309,7 @@ int main(void) {
mui_init(p_mui);
mini_app_launcher_t *p_launcher = mini_app_launcher();
- mini_app_launcher_init(p_launcher);
+ mini_app_launcher_init(p_launcher, wakeup_reason);
NRF_LOG_FLUSH();
@@ -307,8 +319,8 @@ int main(void) {
mui_tick(p_mui);
#ifdef NRF52840_XXAA
- //usb_tick();
-
+ // usb_tick();
+
tud_task(); // device task
#endif
NRF_LOG_FLUSH();
diff --git a/fw/application/src/mod/settings.c b/fw/application/src/mod/settings.c
index d074a6a7..b7477034 100644
--- a/fw/application/src/mod/settings.c
+++ b/fw/application/src/mod/settings.c
@@ -4,14 +4,16 @@
#include "vfs.h"
#include "vfs_meta.h"
+#include "tag_helper.h"
+
#define SETTINGS_FILE_NAME "/settings.bin"
#ifdef OLED_SCREEN
// Though OLED doesn't necessarily imply rechargeable battery, it's usually the case.
#define DEFAULT_BAT_MODE 1
-#else // !OLED_SCREEN
+#else // !OLED_SCREEN
#define DEFAULT_BAT_MODE 0
-#endif // OLED_SCREEN
+#endif // OLED_SCREEN
const settings_data_t def_settings_data = {.backlight = 0,
.oled_contrast = 40,
@@ -27,7 +29,8 @@ const settings_data_t def_settings_data = {.backlight = 0,
.show_mem_usage = false,
.anim_enabled = false,
.amiidb_data_slot_num = 20,
- .qrcode_enabled = true};
+ .qrcode_enabled = true,
+ .chameleon_default_slot_index = INVALID_SLOT_INDEX};
settings_data_t m_settings_data = {0};
@@ -64,6 +67,7 @@ static void validate_settings() {
BOOL_VALIDATE(m_settings_data.qrcode_enabled, 0);
INT8_VALIDATE(m_settings_data.language, 0, LANGUAGE_COUNT - 1, LANGUAGE_EN_US);
INT8_VALIDATE(m_settings_data.amiidb_data_slot_num, 1, 100, 20);
+ INT8_VALIDATE(m_settings_data.chameleon_default_slot_index, 0, TAG_MAX_SLOT_NUM, INVALID_SLOT_INDEX);
}
int32_t settings_init() {
diff --git a/fw/application/src/mod/settings.h b/fw/application/src/mod/settings.h
index d53b7ad0..45c85319 100644
--- a/fw/application/src/mod/settings.h
+++ b/fw/application/src/mod/settings.h
@@ -7,12 +7,14 @@
#include "app_amiibolink.h"
#include "i18n/language.h"
+#define INVALID_SLOT_INDEX 0xFF
+
typedef struct {
- bool backlight; //deprecated, keep for capability issue
+ bool backlight; // deprecated, keep for capability issue
uint8_t sleep_timeout_sec;
bool dirty;
bool auto_gen_amiibo;
- bool auto_gen_amiibolink; //deprecated, keep for capability issue
+ bool auto_gen_amiibolink; // deprecated, keep for capability issue
bool skip_driver_select;
bool bat_mode;
ble_amiibolink_ver_t amiibo_link_ver;
@@ -24,6 +26,7 @@ typedef struct {
bool qrcode_enabled;
Language language;
uint8_t amiidb_data_slot_num;
+ uint8_t chameleon_default_slot_index;
} settings_data_t;
int32_t settings_init();
diff --git a/fw/application/src/mod/vfs/vfs_meta.h b/fw/application/src/mod/vfs/vfs_meta.h
index 9c59bb7d..df7c91b8 100644
--- a/fw/application/src/mod/vfs/vfs_meta.h
+++ b/fw/application/src/mod/vfs/vfs_meta.h
@@ -11,6 +11,7 @@
typedef enum {
VFS_OBJ_FLAG_HIDDEN = 1 << 0,
VFS_OBJ_FLAG_SYSTEM = 1 << 1,
+ VFS_OBJ_FLAG_READONLY = 1 << 2,
} vfs_obj_flags_t;
typedef enum {
diff --git a/fw/application/src/mui/u8g2_font_wqy12_t_gb2312a.c b/fw/application/src/mui/u8g2_font_wqy12_t_gb2312a.c
index 90fa8c12..af03189e 100644
--- a/fw/application/src/mui/u8g2_font_wqy12_t_gb2312a.c
+++ b/fw/application/src/mui/u8g2_font_wqy12_t_gb2312a.c
@@ -6,12 +6,12 @@
/*
Fontname: -wenquanyi-wenquanyi bitmap song-medium-r-normal--12-120-75-75-P-119-ISO10646-1
Copyright: (null)
- Glyphs: 1615/30503
+ Glyphs: 1622/30503
BBX Build Mode: 0
*/
#ifdef U8G2_USE_LARGE_FONTS
-const uint8_t u8g2_font_wqy12_t_gb2312a[40531] U8G2_FONT_SECTION("u8g2_font_wqy12_t_gb2312a") =
- "O\0\3\2\4\4\4\4\5\14\15\0\376\10\376\12\377\1d\2\332\5y \5\0\230\26!\7\221\212"
+const uint8_t u8g2_font_wqy12_t_gb2312a[40718] U8G2_FONT_SECTION("u8g2_font_wqy12_t_gb2312a") =
+ "V\0\3\2\4\4\4\4\5\14\15\0\376\10\376\12\377\1d\2\332\5y \5\0\230\26!\7\221\212"
"\26\247\0\42\7\64\371\26\221)#\16\226\210\67Q\313\260D\275\14K\324\2$\17\245xV\331RQ"
"\62QK\224\312\26\1%\20\226x\66Q\322EK\302\64\211\222.Z\2&\16\205\210VY\22%Y"
"eJ\242H\11'\6\61\372\25\3(\13\263yVI\224D\335\242,)\14\263y\26Y\224E]\242"
@@ -55,1227 +55,1233 @@ const uint8_t u8g2_font_wqy12_t_gb2312a[40531] U8G2_FONT_SECTION("u8g2_font_wqy1
"Y\222\3K\66\14a:\4\353\15\205\210\66u`\311\206!L\207\0\355\11\222\210\63Z\322\13\0\361"
"\13\225\210\66\246xH\62o\1\363\13\225\210vud\311\334\222\5\365\16\246\210\66\222\35\31\222\320c"
"\62$\0\366\13\205\210\66u`\311\334\222\5\371\13\225\210\66i\16d\336\222!\372\13\225\210vu "
- "\363\226\14\1\374\12\205\210\66\345\314[\62\4\0\0\0\70\60\247\6\71N\272\10\241Q\267\12\220T\15"
- "\12\77Y\231\12z^\253\12bb\354\13\21go\13\25on\12\350x\64\12\300\177\23\13\21\211\177"
- "\12\270\217\203\13\22\377\377\1M\14\205\210\66;\260dn\311\2\1Q\15\225\210VI;\260dn\311"
+ "\363\226\14\1\374\12\205\210\66\345\314[\62\4\0\0\0\70\60\246\6\77N\262\10\224Q\263\12\217T\11"
+ "\12DY}\12p^\234\12ib\345\13\14gQ\13 n\220\12\331w\355\12\310~\342\13\20\210h"
+ "\12\277\217l\13\15\377\377\1M\14\205\210\66;\260dn\311\2\1Q\15\225\210VI;\260dn\311"
"\2\4\1\15\245\210\66\345a\14\207\261\70\10\4\20\16\205\210VK\224D\232\66\14\231\26\4\21\15\205"
"\210\26\307pH\62\333\240\0\4\22\16\205\210\26C\222i\203\222\331\6\5\4\23\11\205\210\26\307>\2"
"\4\24\23\227xXC\26eQ\26eQ-\312\222aP\3\4\27\16\205\210\66K\26Fj\250%\13"
- "\0\4\30\15\205\210\26\231\323\222(\311\244\5\4\32\17\205\210\26\231\224\224\246J\224dZ\0\4\34\21"
- "\207\210\30\351\66dKE\251H\221\24\251\1\4\35\14\205\210\26\231m\30\62\267\0\4\36\13\205\210\66"
- "K\346[\262\0\4\37\11\205\210\26\67\277\5\4 \15\205\210\26C\222i\203\22\66\2\4!\14\205\210"
- "\66K&vK\26\0\4\42\12\205\210\26\203\24\366\11\4#\14\205\210\26\231\267d\10\7\5\4$\21"
- "\207\210x\341\240D\221\24I\221T\31\304\14\4'\13\205\210\26\231[\62\204\15\4-\16\205\210\66K"
- "\26&C\30j\311\2\4/\17\205\210\66\203\246%C\22%\221\246\5\4\60\13d\210\65b\62DR"
- "\62\4\61\15\224\210u\211\222-\221S\242\0\4\62\15d\210\25K\64$\221\64$\0\4\63\11d\210"
- "\25\203\326\15\4\64\17vxW[\222%Y\22U\206!\14\4\65\14d\210\65J\64lQ\242\0\4"
- "\66\16g\210\30Q\245mK\232\42\251\0\4\67\13d\210\65JT\224\22\5\4\70\15e\210\26\231\264"
- "$J\62i\1\4\71\17\225\210\66\265\34\310\244%Q\222I\13\4:\14d\210\25\221\222HII\12"
- "\4;\12d\210\65K\277H\1\4<\14f\210\27\341\64D\213\307\0\4=\13d\210\25\221\64L\246"
- "\0\4>\13d\210\65J\344\224(\0\4\77\11d\210\25\203\344)\4@\16\205h\26\211I\323&E"
- "\11C\0\4A\13d\210\65J\244\225\22\5\4B\12e\210\26\203\24v\2\4C\14\204h\25\221\245"
- "I\312\242\14\4D\23\247hxq\70(Q$ER$U\6\61\316\0\4E\14e\210\26YR\253"
- "\324\264\0\4F\20ux\26Q\22%Q\22%Q\62\210\1\4G\12d\210\25\221)\331\12\4H\20"
- "g\210\30Q$ER$ER\64\14\2\4I\22xx\31Q%\252D\225\250\22U\206A\7\2\4"
- "K\16f\210\27\241\70DR\42%C\24\4L\14d\210\25Y\266D\322\220\0\4M\14d\210\65J"
- "\24iR\242\0\4N\17f\210\27\221R\32\42%R\42\13\0\4O\14d\210\65C$%K\42\5"
- "\4Q\16\204\210\25Q\252D\303\26%\12\0 \23\10\33\311\34\17\2 \34\13E\376<\221\224(C"
- "\42 \35\14E\371\34\312\220(\221\224\0\60\1\10\63\210\34\231\24\60\2\13D\213\30\273x\34\273x\134\311\260\225\262R\62(\305,\231\262R"
- "\61RZ\244,\315\222,\322\2W@\35\273x\134a\32\246a\66,i\224\14Q%\215\222\64J\322"
- "!\311\264$\36\6\1WG\33\273x\134Y\234\305\321p\210\243b\224\225\222,\211\264h\323r,G"
- "\24\0WO\32\273x\134\71\226\14C\224F\203\26VC\61S\62\245\64\265\3\71\226\1WP\27\273"
- "x\274\71\20\25\243bTKz\333\322x\70\347X:\34\4WW\35\273x\134a\32\246\321\240\14R"
- "\222\205I\26&Y\62\14\221\226\211I\16d\241\32W[\32\273x\134\71\26\15Z\216\14\71\224\14C"
- "\24\246Y,\205Zq\30\304\64W\203\32\273x\134Y\34\246\321p\320\221(+eM\331\22%b\222"
- "c\361\60\4W\213\37\273x<\303\224%Q\222%Q\222\14\203\222%Q\222%a\24\231s\340\220\3"
- "\351p\20W\316\33\273x<\261\24'\245\341\255\264\64%]\224DR\232\224D\251U\244\254\0W\337"
- "\33\273x\134\251\226&Q\62\34\304\312RJ:%\213&F\232R\223\22\71\13W\372\30\273x|\305"
- "\341\230\305K\234\314Y\66\34\244&eP\324t\70\10X\2\32\273x\134\255Imx\207\224aH\242"
- "\64\34\206\34\310\201\203\234\16\7\1XT\35\273x\134\265\312\60D\225\312\240\24\243\254\222,Q\216\15"
- "\203\62e\361 g\11\0X^\31\273x\274\351\360\224E\311p\314\262\341\240U\243Z\62(q:\34"
- "\4X\203\36\273x\134a\232\14C\224%\321p\220j\245A\213\262L\31\24\61\311\201(\311D\1X"
- "\223\32\273x\34\17b\224\16C\230\206\303\20\246\321p\220\232\224AQ\343\341\2X\231\37\273x\32\273x\274\351pPs *F\265\244\267-Lr K"
- "\323A\7\22\0YG\33\273x\274\361pMr \313\206\203\216\204\203\22fI\70(\71\226C\22\0"
- "YH\27\273x\274\351p\320\252%ePtt\70\347@Tk\311\304\0YO\31\273x\274\361p\215"
- "\207\203V\35\206H\313\244a\210\223\34\310BU\1YV\33\273x\34Q\26&\321\240%RfR\262"
- "\70\321\241t\70\210I\254I: YW\32\273x\234\361p\320\302pX\22%\316\6\71\7\36\304\34"
- "\12\303aP\0Ye\31\273x\234\71\360\224t\212\246h\70ES\245\313p\20\223\34\310\262uYs"
- "\30\273x\234\71\226c\361p\320\312Y\32\246K\16\351H\244\255\11\0Yy\36\273x\134a\32%\331"
- "\220$S\222,Q\262\224\222NIe\213\222T\11\223Fu\20Y}\33\273x\134\71\226\15\207\60K"
- "\262\60\311J\303\220\24C\261\222\225\262(\235\0Y\202 \273x\134\71\226#\203\62HI-JjI"
- "\224dI\224d\221\224E\322\240DI\246c\0Y\231\34\273x\134a\32f\203\242d\211\22U\242J"
- "T\325\242,\315\222\254\232\205\42\0Y\256\35\273x<\331\260d\341\60\204IeX\232\223&)i\222"
- "\22Q)%QI\12\7Y\306 \273x<\331 eR\62$MI-J\206S\42%Q\322$e"
- "\231\62H\305$\7\24\0Y\313 \273x\134a\32f\203\22eI-J\206!\211r \211\6I\312"
- "\242\244\226D\311\260f\1Y\354\34\273x\134\321\60\65\15S\226T\246\244S\322)\351\26%\233\22e"
- "\221T\34\6Z\1 \273x\374@\222#Q\62\34\222\64L\226(\211Z\206!\211\222N\221\224H\221"
- "\262Da\0Z\3\34\273x\134a\32fC\62HI\26&\303)\13\223,\215\6M\13\243Z\70\14"
- "Z\5 \273x<\71\26\15\7)\311\222(\311\22\245\27KT\311\264$\314\222,\211\222(\33\206\0"
- "Z\34\42\273x<\311\220,QR\31\226\212\222,\211\322\242$\203\222(}JZ\224\312RJ\242J"
- "\24\1ZZ\37\273x\134\321\240E\245\341\240\64eI\42)\345\244\62hQ\226)\203\24iI\70("
- "\0[P\30\273x\134\303\220C\71\224C\71\226\16\7\65\307r,G\352P\14[W\31\273x\274\361"
- "pHrD\32\224\34\310\241t\70\250\71\226c\71\262\2[X\31\273x\234\361p\320r(\31\266\64"
- "\23\263d\70\205i\230\206i\264\1[f\31\272y\33\273x\134\303\240\305\331\60h\241\70\310\331\220\15r\66d\203\226\204\231:\10\134@\36\273x"
- "\134\303\240\305\331\60h\71\66\234r J\206\250\22U\242!J\242\222\16(\0\134B\33\273x\134\303"
- "\240\305\331\60h\71\226\14[\216\15\247,\216jQ\230d\303\20\134E\34\273x\134\303\240\305\331\60h"
- "\345\341\224\305\311\260%a\226\204Q\64,Y\230\0\134O\31\273x\134\303)\7\242\341\224\204YT\34"
- "N\215\303\251-\312\242b\4\134U\31\273x<\303)\7\242\341\324\70\234\32\207CRj\311\244JT"
- "\22\5\134^\37\273x<\303)\7\242\341\224\3Q\62la\232\14C\224D\225d\70$Y\246$C"
- "\42\134q\27\271y\234\71\22f\231\226i\231\226i\231\226i\331p\320\201\0\134\201\30\272x \273x\134a\234e\303\62DY\224EImJ\262$J"
- "\262$+EZ\224DI\224\204\1e\77\37\273x\374@\66,q\66d\221\22%K)\311\222(\311"
- "\222(\11\263d\212\306$\326\2eE\33\273x|\345,\33\226!\253\204QiPJ-Q\255\224e"
- "C\224D\321\26eH\35\273x\134a\234e\303\62DI\242DY\322\26%Y\22%aKVM\212"
- "Z\0eL\34\273x|R\66\246\341p\211\262(\251\205I\62HI\255\224\225\6)\251m\1eO"
- "\37\273x\34\273x\134\303\20\246\341\60\204i\70\14q\222FI\224%\245,"
- "iN\302\341 fB\35\273x\374@\66$\203\22e\245,\33\236\302(\32NI\24\15Q\222c\71"
- "\62\1fZ\36\273x\274\351\64DI)K\206AYJI\247\244\62,\65mJ\242\60\252eC\0"
- "fh\36\273x\134\303\20\246\341\60\204i\66\34\222\34K\206!\312\261\341\220\224\222(\222\26\0fn"
- "\32\273x|\305\341T\211\262\244i\70\350\360\60\204i\70\14a\32\16C\4fz\37\272y<\71\64"
- "$\203\222E\303 E\322\220DI\244\14C\226f\303\220\245\331\60$\0f\202\37\273x\134q\62("
- "[\22\205\203\62hQ\22\15I\24\16C\230\206\303\20\246\341\60D\0f\227\36\273x\374@\66<%"
- "Y\22U\242\341)\7\242dP\206$K\242d\220\263xP\0f\362\27\272y|Q\34e\303A*"
- "I%\251\64<\225\244\322\360\216\4f\364\31\273x<\303!\216\207A+e\303\240\225\262aP\223\34"
- "\312\21\333:f\370\33\273x\134\303\220\3Q\64\34\324(\33\316\351p\220\322p\30\302\64\34\206\10f"
- "\374\32\272y\134\303\230Da\224D\303A*\15\7\35\35\326(\7\304!\32\2f\376\31\271y\134\265"
- "\341 EK\313p\310\261a\210\322h\30\242\64\32\206\4g\0\33\273x\134\303\20\246\341\60\204i\64"
- "\34\224(\7\236*Q\64D\246H\236\4g\10\32\271y\134\303\20\245Q\32\15C\224Fi\64\14Q"
- "\32\245I\230\310\11\0g\11\30\273x\234\361p\320rl\30\305,\31\246b:\254a\32\246\231\4g"
- "\13\36\273x\33\273x|\265a\211\263!\31\222"
- ",G*C\226c\321\60eIOMK\30kL\37\273x\34\227\34\210\262%\32\224\266aP\342,"
- "Z\262()%\311\22%i\222ec\0kb\27\272y\274\71\224Cq\24GC\26\305Q\34\305Q"
- "\34\205\303!kc\32\253x\34\17j\216\345@\224\3\321\240E\71\20\345@\224\3Q:\34\4kd"
- "\36\273x|\345,\316\242\244\226D\311\242%Y\230da\222\205I\26%\311\22\15\351\0ke\31\273"
- "x\274\71\20\15Z\224\3Q:\34\324\34\251\225ji\216\210\203\14kw\34\273x<\303!\311J\211"
- "\244EY\66\34\222(\253\234\224>\15ITL\206\3k{\30\273x\34\17Z\216\225\227\250\245$%"
- "R\245\16Dq\26\25\243yk\265\34\273x|\312\246%Y\230dK\264\344\330\62HY)L\242!"
- "\13+Y\244\11k\301\33\273x\34\213\262\204IEY\32\223d\270cC\62,\305,\11\253Ke+"
- "k\315\34\273x\134\303\20&Y\30\25\323h\70HI\26F\305\64\33\16\71\222#\32\0k\317\33\273"
- "x\134\71\66\134r(\32\326$\212\206\203\324\230%\331p\310\221\34\321\0k\322\30\273x\274\351pP"
- "\343\341\234\16\7\251i\70(Y\224\15\207X\3k\324\25\272y\34aOI\230DC\242\205}Q\262"
- "-S\207\0k\333\27\273x\334\333\240c\71\66d\203\216\345\330\360\216\205i\30\17\2l\21\31\272y"
- "\34/\71\220\344@\62\134\262\64K\207\203XJ\62%\213\326\1l\24\32\273x|\71\66\14Y\16%"
- "\303\224\243\303\216\345X\224\3Q\216\324!\1l\27\33\273x|\71\66\14R\16%\303\220\344\340\60\350"
- "H\61\252jI\24Y\302,l\64\30\273x\274\71\226c\225!Q\322\244\234T\243bTk\211\222\260"
- "\14l\70\31\273x\274\71\30\17Y\34ECRN\344(I\243ZmJr(\6lB\32\273x\274"
- "Q\16d\311pPs \252&u`\7\222jT\322\62Q\5lI\33\273x<\71\220%\303 f"
- "QR\13\223\254%\314\222H\15+YS\242\6l_\32\273x<\71\30\15J\34&Y\234\245a\32"
- "fj\230\206\311\60(\71\4l`\37\273x\35\273x<\261\226\14\71\20n\311\226(\305\244SR\61%"
- "\265(\211Z\242J$\5mA\32\273x\34ie\30\324Z\313\60dq\226\64II-J:%="
- "E\2mN\34\273x\32\273x\245\331pG\207\203\324d\23y\217\37\273x"
- "<\321\60D\71<(C\222\205\311\240\345\330pQ\242HI\206!J\242\226a\10y\273\33\273x\274"
- "\351p\220\222\306\250\230\64\16C\16\304\303\251%J\6%\212\25\0y\301\32\273x|\362\230\206\331 "
- "\245Y:\245J\61\211\262\312\60D\305(G\0y\315\33\273x|R\66\246\321\360\22\265D\221RJ"
- "\224aP\302\64L\303\64\314\0y\321\34\273x|b\262EY\230$\203\230\225\62-\211\224p\11\267"
- "H\312\342,N\0y\322\33\273x|\265\61\215\222\312\220\224Z\242d)*Q\244\304Y\32fj\242"
- "\2y\360\31\273x|J\270\305\321p\220\32\303\245IJz*iQ\61\315\64\0y\373\33\273x|"
- "\265\203T\34\226(\13-J\230DC\242eJ\224\324\322\60\332\0z\13\36\273x|\311\240LY)"
- "K\206d\320rL\31$%\12\245A)\246a\232\14C\0z\15\36\273x|R\64DI-\314\206"
- "C\26e\321\62H\212\226\224\6-\312JY)R\0z.\34\273x|\311\240\214i\64\274\324\242A"
- "S\332\222a\22\263$\32\264\60M\206!z\61\35\273x|\241\62M\225(\32\224\266h\320\224\266d"
- "\230\244\244\313\60D\265R\244\0z\77\36\273x|R\66\15S\26%\203\62d\71\66\234\222\64Q\222"
- "E\351)I\226(\11\5zv\30\273x\274\351\360\224E\325,\12\323\34\31v \212\263\250\30\315\3"
- "zz\30\273x\274\361pHrD\213\342\60\223\303a\7r,\307\342\341\20z\177\32\273x\274\351\360"
- "\224EJ\232$\303 f\351pMr \212\263P\32\1z\201\31\273x\274\361pH\242\222\24\226\222"
- "r\224\15\207\64\207\222X\223t@z\227\36\272y\274\341pP\302\244\224%\303!\211\262(\31\246)"
- "\211\42\251\22%\321\60(\0z\313\30\273x\274\71\230\16\207\234\20\246a\34\345@\224\3I\216\205\303"
- "Az\326\36\273x|\311 %\265(\211\222,\311\302$J\322$\223\323\341\230\345@\22\16\7\1z"
- "\331\34\273x\65&\215Z\0\226b\35"
- "\273x\34C\24FY%\31N\251\22\15J\224\3\321pHJ\225\250\242U\244T\226d\36\273x\34"
- "CV\252DI\224%R\262(a\26\15\247,\233\222\266(\222\262H\325\0\226\206 \273x\34C\222"
- "F\311\240T\264D\234\222D\233\222Z\224\14\7)K\242A\211\263h\30\4\226\217 \273x\34c\226"
- "(\303\220\64j\203R\213\222\344\220tJ\244dH\262$J\62\65\212\6\1\226\220\42\273x\34C\62"
- "D\225\250\222\14\213\222&\245A\211\322$J\6E\211\302$Q\232\222(\21\207\10\226\250!\273x\34"
- "CVR\206%*i\303\220\204IiY\242\244eH\222\245\224\264%Q\22eC\0\226\274\30\273x"
- "\134Y<\134\264\60\31\6\255<\14Zy\70\207\303A\16\1\226\276\35\273x\334I\64DI\232\14C"
- "\64eI)\214\206\251-I\206\245\251\30\345\300\1\226\304\37\273x|\345(\211\206\203\224%a\244d"
- "I\64(\245$*\15K\226\204I\333\220\14\2\226\306\34\273x|I\16d\351pP\242\34\70hQ"
- "\16\34\264(\35\16ZR\233\242\1\226\314\37\273x\134I\224&\215I\62,\203\22%\225a\351\224T"
- "\206\245S\62(\221\224\14r\10\226\350\30\273x\34\17j\216\305\303)+%\235\42O\225NY)\213"
- "\24\0\226\352\31\273x<\303\71\35\36CEI\224\34\35\356X\66\14:\26\15\27\0\226\366\31\273x"
- "<\303\71\35\236\222R\70k\222\226I\303\220C\71\260c\32\0\226\367\30\273x<\303\71\35\36CE"
- "I\224\64\36NYi\70e\245\341\2\226\373\30\273x<\303\71\35^\242J\62\234\262\322p\312J\303"
- "\71L\207\1\227\0\31\273x<\303\71\35^\224DI\323\341 \346\300S%j\211Z\22\5\227\6\34"
- "\273x<\303\71\35^\242\312\240\14Z\30.\203\230\205\311\60H\71\242\14\203\0\227\23\34\273x<\303"
- "\71\35^\242J\62\15Q\16DC\62D\71\20\15\307(\33\262A\227\36\32\273x<\303\71\35\236\222"
- "\322\260\14Q\61\32Na\24\15IT\325\242I\227\62\36\273x<\303\71\35\236\222\322 \15I\224H"
- "\311\220\211\221\264\34\222Z\224\14\321\220\0\227\70\34\273x<\303\71\35\236\222\322p\220*Q\62(C"
- "\322)\31\16Y)\213\42\5\227R\30\273x\274\361p\316\201C\16\244\303A\13\323a\15\323a\15#"
- "\0\227Y\37\273x\134a\66,[%\33\222!\13\223d\70(Q%R\222!J\244\60*&\66\0"
- "\227^\34\273x\234I\216\24\7e\20\223\34\251\16\311\220&\71R\34\224ALr\244\10\227`\34\273"
- "x\134u\340 e\351p\220\322p\30\342$\34\224AL\302A\31\304$\4\227b\30\272y\34\17a"
- "\216\304\303A*IC$\225\244!\222J\303;\22\227i\31\273x|\265\341\240\225\7\35\311\201C\30"
- "\25\207!\7\322\341\240\246\0\227\215\35\273x<\265l\70(\215\311\226\206\331\360RJ\222A\211\262P"
- "\32\244$\213\264\0\227\363\32\273x\274\361p\314r \11\207\203\16\17C\230\206\303\20\246\341\60D\0"
- "\227\365\35\273x\134Y\70(a\226\14J\343\260d\71\20\15\253\26)\303\240i\351\260)\0\230\30\36"
- "\273x|\311\60\211Y\224\14K\244\225\206C\222\205\311\240\224\262(\33\264\250\230\204\1\230^\36\273x"
- "\34IeP\306\332pH\262d\32\226\266(\33\16I\26e\203RKj[\0\230o\42\273x<\203"
- "\62$Y\224\15\312\220dI\224\14\312\220D\211\24)\311\220tJ\224aH\372\267\0\230u\31\273x"
- "\34\17j\16\34\302\64\214\212Q\61*FJ\34\305\241$'\0\230\177\35\273x\134\331 \245\321\240\14"
- "R\226)]\224.\303\322\224%\245$\13\265$\326\2\230\206\33\273x|\321\240\205\225(\224\206!\252"
- "\305IeH\32\223\266\260%\214\262\0\230\221\37\273x|\321\240\24\263d\30\224R\66\14J-J\272"
- "(-JE\252\224\302$\321\264\0\230\230!\273x\13d\210\65J\344\224(\0\4\77\11"
+ "d\210\25\203\344)\4@\16\205h\26\211I\323&E\11C\0\4A\13d\210\65J\244\225\22\5\4"
+ "B\12e\210\26\203\24v\2\4C\14\204h\25\221\245I\312\242\14\4D\23\247hxq\70(Q$"
+ "ER$U\6\61\316\0\4E\14e\210\26YR\253\324\264\0\4F\20ux\26Q\22%Q\22%"
+ "Q\62\210\1\4G\12d\210\25\221)\331\12\4H\20g\210\30Q$ER$ER\64\14\2\4I"
+ "\22xx\31Q%\252D\225\250\22U\206A\7\2\4K\16f\210\27\241\70DR\42%C\24\4L"
+ "\14d\210\25Y\266D\322\220\0\4M\14d\210\65J\24iR\242\0\4N\17f\210\27\221R\32\42"
+ "%R\42\13\0\4O\14d\210\65C$%K\42\5\4Q\16\204\210\25Q\252D\303\26%\12\0 "
+ "\23\10\33\311\34\17\2 \34\13E\376<\221\224(C\42 \35\14E\371\34\312\220(\221\224\0\60\1"
+ "\10\63\210\34\231\24\60\2\13D\213\30\273x\34"
+ "\273x\134\311\260\225\262R\62(\305,\231\262R\61RZ\244,\315\222,\322\2W@\35\273x\134a"
+ "\32\246a\66,i\224\14Q%\215\222\64J\322!\311\264$\36\6\1WG\33\273x\134Y\234\305\321"
+ "p\210\243b\224\225\222,\211\264h\323r,G\24\0WO\32\273x\134\71\226\14C\224F\203\26V"
+ "C\61S\62\245\64\265\3\71\226\1WP\27\273x\274\71\20\25\243bTKz\333\322x\70\347X:"
+ "\34\4WW\35\273x\134a\32\246\321\240\14R\222\205I\26&Y\62\14\221\226\211I\16d\241\32W"
+ "[\32\273x\134\71\26\15Z\216\14\71\224\14C\24\246Y,\205Zq\30\304\64W\203\32\273x\134Y"
+ "\34\246\321p\320\221(+eM\331\22%b\222c\361\60\4W\213\37\273x<\303\224%Q\222%Q"
+ "\222\14\203\222%Q\222%a\24\231s\340\220\3\351p\20W\316\33\273x<\261\24'\245\341\255\264\64"
+ "%]\224DR\232\224D\251U\244\254\0W\337\33\273x\134\251\226&Q\62\34\304\312RJ:%\213"
+ "&F\232R\223\22\71\13W\372\30\273x|\305\341\230\305K\234\314Y\66\34\244&eP\324t\70\10"
+ "X\2\32\273x\134\255Imx\207\224aH\242\64\34\206\34\310\201\203\234\16\7\1XT\35\273x\134"
+ "\265\312\60D\225\312\240\24\243\254\222,Q\216\15\203\62e\361 g\11\0X^\31\273x\274\351\360\224"
+ "E\311p\314\262\341\240U\243Z\62(q:\34\4X\203\36\273x\134a\232\14C\224%\321p\220j"
+ "\245A\213\262L\31\24\61\311\201(\311D\1X\223\32\273x\34\17b\224\16C\230\206\303\20\246\321p"
+ "\220\232\224AQ\343\341\2X\231\37\273x\32\273x\274"
+ "\351pPs *F\265\244\267-Lr K\323A\7\22\0YG\33\273x\274\361pMr \313"
+ "\206\203\216\204\203\22fI\70(\71\226C\22\0YH\27\273x\274\351p\320\252%ePtt\70\347"
+ "@Tk\311\304\0YO\31\273x\274\361p\215\207\203V\35\206H\313\244a\210\223\34\310BU\1Y"
+ "V\33\273x\34Q\26&\321\240%RfR\262\70\321\241t\70\210I\254I: YW\32\273x\234"
+ "\361p\320\302pX\22%\316\6\71\7\36\304\34\12\303aP\0Ye\31\273x\234\71\360\224t\212\246"
+ "h\70ES\245\313p\20\223\34\310\262uYs\30\273x\234\71\226c\361p\320\312Y\32\246K\16\351"
+ "H\244\255\11\0Yy\36\273x\134a\32%\331\220$S\222,Q\262\224\222NIe\213\222T\11\223"
+ "Fu\20Y}\33\273x\134\71\226\15\207\60K\262\60\311J\303\220\24C\261\222\225\262(\235\0Y\202"
+ " \273x\134\71\226#\203\62HI-JjI\224dI\224d\221\224E\322\240DI\246c\0Y\231"
+ "\34\273x\134a\32f\203\242d\211\22U\242JT\325\242,\315\222\254\232\205\42\0Y\256\35\273x<"
+ "\331\260d\341\60\204IeX\232\223&)i\222\22Q)%QI\12\7Y\306 \273x<\331 e"
+ "R\62$MI-J\206S\42%Q\322$e\231\62H\305$\7\24\0Y\313 \273x\134a\32f"
+ "\203\22eI-J\206!\211r \211\6I\312\242\244\226D\311\260f\1Y\354\34\273x\134\321\60\65"
+ "\15S\226T\246\244S\322)\351\26%\233\22e\221T\34\6Z\1 \273x\374@\222#Q\62\34\222"
+ "\64L\226(\211Z\206!\211\222N\221\224H\221\262Da\0Z\3\34\273x\134a\32fC\62HI"
+ "\26&\303)\13\223,\215\6M\13\243Z\70\14Z\5 \273x<\71\26\15\7)\311\222(\311\22\245"
+ "\27KT\311\264$\314\222,\211\222(\33\206\0Z\34\42\273x<\311\220,QR\31\226\212\222,\211"
+ "\322\242$\203\222(}JZ\224\312RJ\242J\24\1ZZ\37\273x\134\321\240E\245\341\240\64eI"
+ "\42)\345\244\62hQ\226)\203\24iI\70(\0[P\30\273x\134\303\220C\71\224C\71\226\16\7"
+ "\65\307r,G\352P\14[W\31\273x\274\361pHrD\32\224\34\310\241t\70\250\71\226c\71\262"
+ "\2[X\31\273x\234\361p\320r(\31\266\64\23\263d\70\205i\230\206i\264\1[f\31\272y<"
+ "QVJ\242\341\240#\321\260#\71\22\16\207\64\207r`\4[i\33\273x\34\203\24'\303\24\246Y"
+ "\224)C\64F\265(\213\212\225\266J$\6[\203\30\273x\274\361pHrDJ\303\34\213\326\35\311"
+ "\261\70\213\303a\10[\210\31\273x\274\71\230\16\207$\7\222\64\35\356@\234\345@\224c\71\62\2["
+ "\211\30\273x\274\361pHrD\13\323x\70hU-\7v$\322V\1[\214\33\273x\274\361pH"
+ "rD\32\224\34\36\16a\222\3Q\16DY\224U\322![\230\32\273x\274\361pHrD\32\206\260"
+ ":\254\71\66\14a\32\16C\230&\0[\232\33\273x\274\361pHrDG\262a\220s \312\201h"
+ "\10\243\70\251f\303\20[\235\32\273x\234\71\230\16\357P\64\14\71\220c\71p\310\201$G\242h\70"
+ "\10[\236\31\273x\334\351pH\312Z\22eu J\207C\234CI\16d\331*[\242\30\272y\234"
+ "\351p\220\322h\330\222(\313dI\32\16Q\330\70L\0[\243\31\273x\274\351\360\16E\303\220S\206"
+ "!L\303a\10\323p\30\242\341 [\244\32\273x\274\351\360\16)\303\220\204\71\224\245\203\222\3\71p"
+ "\310\201t\70\10[\253\30\272y\234\351p\320\221h\30\213\303\16\17\203\24G\303 \305\11\0[\263\32"
+ "\273x\274\351\360\30*\303\220\244\71p\310\201t\70Hi\230\206\303\20\1[\264\31\272y\234\351pP"
+ "\302D\31\226(\14\207\71\35\16Q\26\17\331\220\15[\266\31\273x\274\351\360\16)\303\220dIVi"
+ "\215DeI\243\222VT\1[\271\30\273x\274\351\360\224E\335\242$\12\263\264\244\14\212V\316\342A"
+ "\3[\275\32\273x\274\351\360\224E\311p\314\322a\10\243bTL\272E\331\20\16\1[\304\32\273x"
+ "\274\351\360\30*\303\220d\265\341\240#\341\20\205Qq\210rd\2[\306\32\273x\274\351\360V\351-"
+ "jL\242dH\6%\315\201\250\30\25\207!\2[\314\30\273x\274\351\360\16E\303\220\16r\26\16\247"
+ "\254\64\234\262\322p\1[\337\35\273x\274\351\360\222e\312\220\14\211\22%Q\22V\206$\321\221d\270"
+ "E%\233\0[\353\31\273x\274\351\360\226*\322\22\245\341\62\246\341pP\232*=%\211\2[\371\33"
+ "\273x\374H\64\204\351p\12\263$,\25\263$K\302,\11\243\64\311\241\14[\373\33\273x<\303\240"
+ "c\341\60\344X\66\14:\224\15\7)\214\263\34\251C!\0[\374\35\273x\134\303\20\246\341\60$Q"
+ "\16d\303\240\3\331p\320\352@\224\3Q\16i\0\134\4\34\273x\134q\64hQV\32\16IV\32"
+ "\246ZR\31\266R\26e\225LR\0\134\6\34\273x\134Y\34\15J\251\246$j\226\204QM\31\6"
+ "%*fI\230\206\241\4\134\7\37\273x|\305$\32\224\236\222(\211\206,\11\243\312pPJ-Y"
+ "\22%i\22e\13\0\134\15\35\273x\134I\230t\212\24-\31\16R\22F\203R\14\245A\13\323p"
+ "\251\254\21\0\134\16\35\273x\34a\224%\303 V\244!\211*CTL\222\341\216D\303A\13\343H"
+ "\2\134\17\30\273x\274\71\226c\71\20\25\243,\312JY(Vs\244\16\305\0\134\21\32\273x\274\71"
+ "\226#\245\64\311Ja\222E\71\220\344P\16\345\210\274#\0\134\24\30\272y\134\71\64\14J\16\210Q"
+ "\134J\302\250-\252eb\226\215\0\134\35\30\273x\33\273x\134\303\240\305\331\60h\241\70\310\331\220"
+ "\15r\66d\203\226\204\231:\10\134@\36\273x\134\303\240\305\331\60h\71\66\234r J\206\250\22U"
+ "\242!J\242\222\16(\0\134B\33\273x\134\303\240\305\331\60h\71\226\14[\216\15\247,\216jQ\230"
+ "d\303\20\134E\34\273x\134\303\240\305\331\60h\345\341\224\305\311\260%a\226\204Q\64,Y\230\0\134"
+ "O\31\273x\134\303)\7\242\341\224\204YT\34N\215\303\251-\312\242b\4\134U\31\273x<\303)"
+ "\7\242\341\324\70\234\32\207CRj\311\244JT\22\5\134^\37\273x<\303)\7\242\341\224\3Q\62"
+ "la\232\14C\224D\225d\70$Y\246$C\42\134q\27\271y\234\71\22f\231\226i\231\226i\231"
+ "\226i\331p\320\201\0\134\201\30\272x \273x\134a\234e"
+ "\303\62DY\224EImJ\262$J\262$+EZ\224DI\224\204\1e\77\37\273x\374@\66,"
+ "q\66d\221\22%K)\311\222(\311\222(\11\263d\212\306$\326\2eE\33\273x|\345,\33\226"
+ "!\253\204QiPJ-Q\255\224eC\224D\321\26eH\35\273x\134a\234e\303\62DI\242D"
+ "Y\322\26%Y\22%aKVM\212Z\0eL\34\273x|R\66\246\341p\211\262(\251\205I\62"
+ "HI\255\224\225\6)\251m\1eO\37\273x\34\273x\134\303\20\246\341\60\204i\70\14"
+ "q\222FI\224%\245,iN\302\341 fB\35\273x\374@\66$\203\22e\245,\33\236\302(\32"
+ "NI\24\15Q\222c\71\62\1fZ\36\273x\274\351\64DI)K\206AYJI\247\244\62,\65"
+ "mJ\242\60\252eC\0fh\36\273x\134\303\20\246\341\60\204i\66\34\222\34K\206!\312\261\341\220"
+ "\224\222(\222\26\0fn\32\273x|\305\341T\211\262\244i\70\350\360\60\204i\70\14a\32\16C\4"
+ "fz\37\272y<\71\64$\203\222E\303 E\322\220DI\244\14C\226f\303\220\245\331\60$\0f"
+ "\202\37\273x\134q\62([\22\205\203\62hQ\22\15I\24\16C\230\206\303\20\246\341\60D\0f\227"
+ "\36\273x\374@\66<%Y\22U\242\341)\7\242dP\206$K\242d\220\263xP\0f\362\27\272"
+ "y|Q\34e\303A*I%\251\64<\225\244\322\360\216\4f\364\31\273x<\303!\216\207A+e"
+ "\303\240\225\262aP\223\34\312\21\333:f\370\33\273x\134\303\220\3Q\64\34\324(\33\316\351p\220\322"
+ "p\30\302\64\34\206\10f\374\32\272y\134\303\230Da\224D\303A*\15\7\35\35\326(\7\304!\32"
+ "\2f\376\31\271y\134\265\341 EK\313p\310\261a\210\322h\30\242\64\32\206\4g\0\33\273x\134"
+ "\303\20\246\341\60\204i\64\34\224(\7\236*Q\64D\246H\236\4g\10\32\271y\134\303\20\245Q\32"
+ "\15C\224Fi\64\14Q\32\245I\230\310\11\0g\11\30\273x\234\361p\320rl\30\305,\31\246b"
+ ":\254a\32\246\231\4g\13\36\273x\33\273x"
+ "|\265a\211\263!\31\222,G*C\226c\321\60eIOMK\30kL\37\273x\34\227\34\210\262"
+ "%\32\224\266aP\342,Z\262()%\311\22%i\222ec\0kb\27\272y\274\71\224Cq\24"
+ "GC\26\305Q\34\305Q\34\205\303!kc\32\253x\34\17j\216\345@\224\3\321\240E\71\20\345@"
+ "\224\3Q:\34\4kd\36\273x|\345,\316\242\244\226D\311\242%Y\230da\222\205I\26%\311"
+ "\22\15\351\0ke\31\273x\274\71\20\15Z\224\3Q:\34\324\34\251\225ji\216\210\203\14kw\34"
+ "\273x<\303!\311J\211\244EY\66\34\222(\253\234\224>\15ITL\206\3k{\30\273x\34\17"
+ "Z\216\225\227\250\245$%R\245\16Dq\26\25\243yk\265\34\273x|\312\246%Y\230dK\264\344"
+ "\330\62HY)L\242!\13+Y\244\11k\301\33\273x\34\213\262\204IEY\32\223d\270cC\62"
+ ",\305,\11\253Ke+k\315\34\273x\134\303\20&Y\30\25\323h\70HI\26F\305\64\33\16\71"
+ "\222#\32\0k\317\33\273x\134\71\66\134r(\32\326$\212\206\203\324\230%\331p\310\221\34\321\0k"
+ "\322\30\273x\274\351pP\343\341\234\16\7\251i\70(Y\224\15\207X\3k\324\25\272y\34aOI"
+ "\230DC\242\205}Q\262-S\207\0k\333\27\273x\334\333\240c\71\66d\203\216\345\330\360\216\205i"
+ "\30\17\2l\21\31\272y\34/\71\220\344@\62\134\262\64K\207\203XJ\62%\213\326\1l\24\32\273"
+ "x|\71\66\14Y\16%\303\224\243\303\216\345X\224\3Q\216\324!\1l\27\33\273x|\71\66\14R"
+ "\16%\303\220\344\340\60\350H\61\252jI\24Y\302,l\64\30\273x\274\71\226c\225!Q\322\244\234"
+ "T\243bTk\211\222\260\14l\70\31\273x\274\71\30\17Y\34ECRN\344(I\243ZmJr"
+ "(\6lB\32\273x\274Q\16d\311pPs \252&u`\7\222jT\322\62Q\5lI\33\273"
+ "x<\71\220%\303 fQR\13\223\254%\314\222H\15+YS\242\6l_\32\273x<\71\30\15"
+ "J\34&Y\234\245a\32fj\230\206\311\60(\71\4l`\37\273x\35\273x<\261\226\14\71\20n\311"
+ "\226(\305\244SR\61%\265(\211Z\242J$\5mA\32\273x\34ie\30\324Z\313\60dq\226"
+ "\64II-J:%=E\2mN\34\273x\32\273x\245\331pG\207\203"
+ "\324d\23y\217\37\273x<\321\60D\71<(C\222\205\311\240\345\330pQ\242HI\206!J\242\226"
+ "a\10y\273\33\273x\274\351p\220\222\306\250\230\64\16C\16\304\303\251%J\6%\212\25\0y\301\32"
+ "\273x|\362\230\206\331 \245Y:\245J\61\211\262\312\60D\305(G\0y\315\33\273x|R\66\246"
+ "\321\360\22\265D\221RJ\224aP\302\64L\303\64\314\0y\321\34\273x|b\262EY\230$\203\230"
+ "\225\62-\211\224p\11\267H\312\342,N\0y\322\33\273x|\265\61\215\222\312\220\224Z\242d)*"
+ "Q\244\304Y\32fj\242\2y\360\31\273x|J\270\305\321p\220\32\303\245IJz*iQ\61\315"
+ "\64\0y\373\33\273x|\265\203T\34\226(\13-J\230DC\242eJ\224\324\322\60\332\0z\13\36"
+ "\273x|\311\240LY)K\206d\320rL\31$%\12\245A)\246a\232\14C\0z\15\36\273x"
+ "|R\64DI-\314\206C\26e\321\62H\212\226\224\6-\312JY)R\0z.\34\273x|\311"
+ "\240\214i\64\274\324\242AS\332\222a\22\263$\32\264\60M\206!z\61\35\273x|\241\62M\225("
+ "\32\224\266h\320\224\266d\230\244\244\313\60D\265R\244\0z\77\36\273x|R\66\15S\26%\203\62"
+ "d\71\66\234\222\64Q\222E\351)I\226(\11\5zv\30\273x\274\351\360\224E\325,\12\323\34\31"
+ "v \212\263\250\30\315\3zz\30\273x\274\361pHrD\213\342\60\223\303a\7r,\307\342\341\20"
+ "z\177\32\273x\274\351\360\224EJ\232$\303 f\351pMr \212\263P\32\1z\201\31\273x\274"
+ "\361pH\242\222\24\226\222r\224\15\207\64\207\222X\223t@z\227\36\272y\274\341pP\302\244\224%"
+ "\303!\211\262(\31\246)\211\42\251\22%\321\60(\0z\313\30\273x\274\71\230\16\207\234\20\246a\34"
+ "\345@\224\3I\216\205\303Az\326\36\273x|\311 %\265(\211\222,\311\302$J\322$\223\323\341"
+ "\230\345@\22\16\7\1z\331\34\273x"
+ "\65&\215Z\0\226b\35\273x\34C\24FY%\31N\251\22\15J\224\3\321pHJ\225\250\242U"
+ "\244T\226d\36\273x\34CV\252DI\224%R\262(a\26\15\247,\233\222\266(\222\262H\325\0"
+ "\226\206 \273x\34C\222F\311\240T\264D\234\222D\233\222Z\224\14\7)K\242A\211\263h\30\4"
+ "\226\217 \273x\34c\226(\303\220\64j\203R\213\222\344\220tJ\244dH\262$J\62\65\212\6\1"
+ "\226\220\42\273x\34C\62D\225\250\222\14\213\222&\245A\211\322$J\6E\211\302$Q\232\222(\21"
+ "\207\10\226\250!\273x\34CVR\206%*i\303\220\204IiY\242\244eH\222\245\224\264%Q\22"
+ "eC\0\226\274\30\273x\134Y<\134\264\60\31\6\255<\14Zy\70\207\303A\16\1\226\276\35\273x"
+ "\334I\64DI\232\14C\64eI)\214\206\251-I\206\245\251\30\345\300\1\226\304\37\273x|\345("
+ "\211\206\203\224%a\244dI\64(\245$*\15K\226\204I\333\220\14\2\226\306\34\273x|I\16d"
+ "\351pP\242\34\70hQ\16\34\264(\35\16ZR\233\242\1\226\314\37\273x\134I\224&\215I\62,"
+ "\203\22%\225a\351\224T\206\245S\62(\221\224\14r\10\226\350\30\273x\34\17j\216\305\303)+%"
+ "\235\42O\225NY)\213\24\0\226\352\31\273x<\303\71\35\36CEI\224\34\35\356X\66\14:\26"
+ "\15\27\0\226\366\31\273x<\303\71\35\236\222R\70k\222\226I\303\220C\71\260c\32\0\226\367\30\273"
+ "x<\303\71\35\36CEI\224\64\36NYi\70e\245\341\2\226\373\30\273x<\303\71\35^\242J"
+ "\62\234\262\322p\312J\303\71L\207\1\227\0\31\273x<\303\71\35^\224DI\323\341 \346\300S%"
+ "j\211Z\22\5\227\6\34\273x<\303\71\35^\242\312\240\14Z\30.\203\230\205\311\60H\71\242\14\203"
+ "\0\227\23\34\273x<\303\71\35^\242J\62\15Q\16DC\62D\71\20\15\307(\33\262A\227\36\32"
+ "\273x<\303\71\35\236\222\322\260\14Q\61\32Na\24\15IT\325\242I\227\62\36\273x<\303\71\35"
+ "\236\222\322 \15I\224H\311\220\211\221\264\34\222Z\224\14\321\220\0\227\70\34\273x<\303\71\35\236\222"
+ "\322p\220*Q\62(C\322)\31\16Y)\213\42\5\227R\30\273x\274\361p\316\201C\16\244\303A"
+ "\13\323a\15\323a\15#\0\227Y\37\273x\134a\66,[%\33\222!\13\223d\70(Q%R\222"
+ "!J\244\60*&\66\0\227^\34\273x\234I\216\24\7e\20\223\34\251\16\311\220&\71R\34\224A"
+ "Lr\244\10\227`\34\273x\134u\340 e\351p\220\322p\30\342$\34\224AL\302A\31\304$\4"
+ "\227b\30\272y\34\17a\216\304\303A*IC$\225\244!\222J\303;\22\227i\31\273x|\265\341"
+ "\240\225\7\35\311\201C\30\25\207!\7\322\341\240\246\0\227\215\35\273x<\265l\70(\215\311\226\206\331"
+ "\360RJ\222A\211\262P\32\244$\213\264\0\227\363\32\273x\274\361p\314r \11\207\203\16\17C\230"
+ "\206\303\20\246\341\60D\0\227\365\35\273x\134Y\70(a\226\14J\343\260d\71\20\15\253\26)\303\240"
+ "i\351\260)\0\230\5\31\273x\274\303AJ\243a*F\321\60\25\243\341\240\205\351\60G\251\30\230\30"
+ "\36\273x|\311\60\211Y\224\14K\244\225\206C\222\205\311\240\224\262(\33\264\250\230\204\1\230^\36\273"
+ "x\34IeP\306\332pH\262d\32\226\266(\33\16I\26e\203RKj[\0\230o\42\273x<"
+ "\203\62$Y\224\15\312\220dI\224\14\312\220D\211\24)\311\220tJ\224aH\372\267\0\230u\31\273"
+ "x\34\17j\16\34\302\64\214\212Q\61*FJ\34\305\241$'\0\230y\32\273x\274\303AJ\243a"
+ "*F\225\250%j\211\242!\211V\35\211R\61\230\177\35\273x\134\331 \245\321\240\14R\226)]\224"
+ ".\303\322\224%\245$\13\265$\326\2\230\206\33\273x|\321\240\205\225(\224\206!\252\305IeH\32"
+ "\223\266\260%\214\262\0\230\221\37\273x|\321\240\24\263d\30\224R\66\14J-J\272(-JE\252"
+ "\224\302$\321\264\0\230\230!\273x
#include
+#include
#define NTAG_DATA_SIZE 540
#define NTAG_TAGMO_DATA_SIZE 532
#define NTAG_THENAYA_DATA_SIZE 572
-typedef enum
-{
- NTAG_213,
- NTAG_215,
- NTAG_216
-} ntag_type_t;
+typedef enum { NTAG_213, NTAG_215, NTAG_216 } ntag_type_t;
-typedef struct {
- uint8_t data[NTAG_DATA_SIZE];
- uint8_t notes[128];
+typedef struct {
+ uint8_t data[NTAG_DATA_SIZE];
+ uint8_t notes[128];
+ bool read_only;
} ntag_t;
-
#endif /* NTAG_DEF_H_ */
diff --git a/fw/application/src/ntag/ntag_emu_v2.c b/fw/application/src/ntag/ntag_emu_v2.c
index 258c91cc..b40226aa 100644
--- a/fw/application/src/ntag/ntag_emu_v2.c
+++ b/fw/application/src/ntag/ntag_emu_v2.c
@@ -106,6 +106,11 @@ static void nfc_received_process(const uint8_t *p_data, size_t data_length, uint
p_data = p_data + 1;
case NFC_CMD_WRITE:
NRF_LOG_INFO("NFC Write Block %d", block_num);
+ if (ntag_emu.ntag.read_only) {
+ NRF_LOG_INFO("NFC Read Only");
+ hal_send_ack_nack(0x0);
+ return;
+ }
if (data_length == 6) {
ntag_emu.dirty = true;
if (block_num == 133 || block_num == 134) {
diff --git a/fw/components/chameleon-ultra b/fw/components/chameleon-ultra
index a7461bd4..3217bbc0 160000
--- a/fw/components/chameleon-ultra
+++ b/fw/components/chameleon-ultra
@@ -1 +1 @@
-Subproject commit a7461bd4c17f1717a7510934a8ef94a1f54cc7fc
+Subproject commit 3217bbc0ba3f6fc46dcafe8576b9087f09e71365
diff --git a/fw/data/i18n.csv b/fw/data/i18n.csv
index bcf47dbf..9ce03119 100644
--- a/fw/data/i18n.csv
+++ b/fw/data/i18n.csv
@@ -21,7 +21,7 @@ _L_APP_SET_LCD_BACKLIGHT,Backlight,背光亮度,背光亮度,Brillo,Háttérvil
_L_APP_SET_LCD_BACKLIGHT_TITLE,Backlight Brightness,背光亮度,背光亮度,Brillo de fondo,Háttérvilágítás Fényerő,Helligkeit,Luminosité du Rétroéclairage,Helderheid Achtergrondverlichting,Brilho da Luz de Fundo,バックライトの明るさ,Luminosità schermo,Яркость подсветки
_L_APP_SET_ANIM,Menu Animation,动画效果,動畫效果,Animar menú,Menü Animáció,Menü Animation,Animation du Menu,Menu-Animatie,Animação do Menu,メニュー アニメーション,Animazione menu,Анимация меню
_L_APP_SET_LIPO_BAT,LiPO Battery,LiPO电池,LiPO電池,Batería LiPO,LiPO Akkumulátor,LiPO Batterie,Batterie LiPO,LiPO-Batterij,Bateria LiPO,LiPOバッテリー,Batteria LiPO,Батарея LiPO
-_L_APP_SET_SHOW_MEM_USAGE,Memory Used,内存使用率,記憶體使用率,Mem. usada,Használt Memória,Speicheranzeige,Mémoire Utilisée,Gebruikt Geheugen,Memória Usada,使用メモリ,Memoria usata,Статус памяти
+_L_APP_SET_SHOW_MEM_USAGE,Memory Used,内存使用率,記憶體使用率,Estad. Mem.,Használt Memória,Speicheranzeige,Mémoire Utilisée,Gebruikt Geheugen,Memória Usada,使用メモリ,Memoria usata,Статус памяти
_L_APP_SET_HIBERNATE,Fast Wakeup,快速唤醒,快速喚醒,Hibernar,Gyors Ébresztés,Schnelles Aufwachen,Réveil Rapide,Snel Ontwaken,Despertar Rápido,高速起動,Risveglio rapido,Гибернация
_L_APP_SET_SLEEP_TIMEOUT,Sleep Timeout,休眠时间,休眠時間,Dormir en:,Alvási Időkorlát,Standby nach,Délai de mise en veille,Time-out Slaapstand,Tempo Limite de Suspensão,スリープタイムアウト,Timeout di sospensione,Таймаут сна
_L_APP_SET_LANGUAGE,Language,系统语言,系統語言,Idioma,Nyelv,Sprache,Langue,Taal,Idioma,言語,Lingua,Язык
@@ -29,7 +29,10 @@ _L_APP_SET_DFU,Firmware Update,固件更新,軟體升級,Actualizar firmware,Fir
_L_APP_SET_REBOOT,System Reboot,重启设备,重啟設備,Reiniciar,Rendszer Újraindítása,System Neustart,Redémarrage du Système,Systeem Herstarten,Reinicialização do Sistema,システム再起動,Riavvio del sistema,Перезагрузка
_L_APP_SET_RESET_DEFAULT,Reset Default Setting,重置默认配置,重置默認配置,Restablecer config.,Alapért. Beállítás Visszaállítása,Standardeinstellungen,Rétablir les Paramètres par Défaut,Terugzetten Naar Standaardwaarden,Restaurar Configurações Padrão,デフォルト設定に戻す,Ripristina impostazioni predefinite,Сброс настроек
_L_APP_SET_RESET_DEFAULT_SUCCESS,Reset Success!,重置成功,重置成功,¡Configuración Restablecida!,Alapért. Beállítások Visszaállítása,Einstellungen zurückgesetzt!,Réinitialiser les Paramètres Par Défaut,Standaardinstellingen Herstellen,Redefinir a Configuração Padrão,設定を初期化,Ripristino riuscito!,Сброс выполнен
-_L_APP_SET_RESET_DEFAULT_CONFIRM,Confirm Reset Settings?,确认重置默认设置?,确认重置默认设置?,,,Auf Standardeinstellungen zurücksetzen?,,,,,Conferma il ripristino delle impostazioni?,Выполнить?
+_L_APP_SET_RESET_DEFAULT_CONFIRM,Confirm Reset Settings?,确认重置默认设置?,确认重置默认设置?,¿Confirma Restablecer\nConfig.?,,Auf Standardeinstellungen zurücksetzen?,,,,,Conferma il ripristino delle impostazioni?,Выполнить?
+_L_APP_SET_ABOUT,About Device,关于设备,關於設俻,Acerca del dispositivo,,,,,,,,Об устройстве
+_L_APP_SET_ABOUT_OPEN_SOURCE_PROJECT,Open Source Project,开源项目,開源項目,Poyecto de código abierto,,,,,,,,Проект с открытым кодом
+_L_APP_SET_ABOUT_LGPL_LICENSE,GPL 2.0 License,GPL 2.0 授权,GPL 2.0 授權,Licencia GPL 2.0,,,,,,,,Лицензия GPL 2.0
_L_15S,15 Seconds,15秒,15秒,15 segundos,15 sec.,15 Sekunden,15 sec.,15 sec.,15 seg.,15秒,15 secondi,15 секунд
_L_30S,30 Seconds,30秒,30秒,30 segundos,30 sec.,30 Sekunden,30 sec.,30 sec.,30 seg.,30秒,30 secondi,30 секунд
_L_45S,45 Seconds,45秒,45秒,45 segundos,45 sec.,45 Sekunden,45 sec.,45 sec.,45 seg.,45秒,45 secondi,45 секунд
@@ -42,12 +45,13 @@ _L_KNOW,Got it,知道了,知道了,Entendido,Megvan,Verstanden,Compris,Begrepen,
_L_RANDOM_GENERATION,Rand. Tag,随机生成,隨機產生,Nuevo serial aleat.,Véletlengenerátor,Zufällige UUID,Randomiser la Balise,Willekeurige Tag,Randomizar Etiqueta,タグのランダム化,Tag casuale,Сгенерировать UUID
_L_AUTO_RANDOM_GENERATION,Auto Rand.,自动随机生成,自動隨機產生,Serial alea. aut,Automat. Véletlengenerátor,Zufällige UUID (Automatisch),Randomisation Automatique,Automatische Randomisatie,Randomização Automática,自動ランダム化,Casuale automatico,Автогенерация
_L_SHOW_QRCODE,Display QR Code,显示二维码,顯示二維碼,Mostrar QR,QR-kód Megjelenítése,QR Code,Afficher le Code QR,QR-Code Weergeven,Exibir QR Code,QRコード表示,Mostra codice QR,QR-код
+_L_READ_ONLY,Read-only,禁止写入,禁止寫入,,,,,,,,,Только чтение
_L_DELETE_TAG,Delete Tag,删除标签,刪除標籤,Borrar amiibo...,Címke Törlése,Tag löschen,Supprimer la Balise,Tag Verwijderen,Excluir Etiqueta,タグの削除,Elimina tag,Удалить тег
-_L_DELETE_TAG_CONFIRM,Confirm Delete %s ?,确认删除 %s ?,確認刪除 %s ?,¿\nBorrar %s\n?,Törlés Megerősítése?,Löschen von %s bestätigen?,Confirmer la Suppression de %s ?,Bevestig Verwijderen %s ?,Confirmar Exclusão de %s ?,%s を削除しますか?,Conferma eliminazione %s\n?,Удалить %s?
+_L_DELETE_TAG_CONFIRM,Confirm Delete %s ?,确认删除 %s ?,確認刪除 %s ?,¿Borrar %s?,Törlés Megerősítése?,Löschen von %s bestätigen?,Confirmer la Suppression de %s ?,Bevestig Verwijderen %s ?,Confirmar Exclusão de %s ?,%s を削除しますか?,Conferma eliminazione %s\n?,Удалить %s?
_L_BACK_TO_DETAILS,Back to Tag Details,返回详情,返回詳情,[Detalles amiibo],Vissza a Címke Részletkhez,Zurück zu Tag Details,Retour Aux Détails de L'étiquette,Terug naar Tag Details,Voltar Aos Detalhes da Tag,タグの詳細に戻る,[Torna ai dettagli del tag],[Назад к деталям]
_L_BACK_TO_FILE_LIST,Back to File List,返回文件列表,返回檔案清單,[Lista Archivos],Vissza a Fájl Listához,Zurück zur Liste,Retour à La Liste Des Fichiers,Terug naar Bestandslijst,Voltar Para a Lista de Arquivos,ファイル一覧に戻る,[Torna alla lista dei file],[Назад к списку]
_L_BACK_TO_MAIN_MENU,Back to Main Menu,返回主菜单,返回主選單,[Menú Principal],Vissza a Főmenübe,Hauptmenü,Retour au Menu Principal,Terug naar Hoofdmenu,Voltar ao Menu Principal,メインメニューに戻る,[Torna al menu principale],[В главное меню]
-_L_FORMAT,Format,格式化,格式化,Formatear...,Formátum ,Formatieren,Format,Formatteren,Formatar,フォーマット,Formatta...,Отформатировать
+_L_FORMAT,Format,格式化,格式化,Formatear...,"Formátum ",Formatieren,Format,Formatteren,Formatar,フォーマット,Formatta...,Отформатировать
_L_FORMAT_STORAGE,Format Storage,格式化存储,格式化儲存,Formatear mem. Flash,Formátum Tárolás,Speicher formatieren,Format de Stockage,Opslag Formatteren,Formatar Armazenamento,保存領域フォーマット,Formatta memoria,Форматирование
_L_DELETE_ALL_DATA,This will delete all data. Confirm format?,将删除所有数据。\n确认格式化?,將刪除所有資料。\n確認格式化?,Se borrará todos los\ndatos.,Minden adatot töröl. Formázás megerősítése?,Alle Daten löschen?,Cette opération efface toutes les données. Confirmer le formatage?,Hierdoor worden alle gegevens gewist. Formatteren bevestigen?,Isso excluirá todos os dados. Confirmar a formatação?,これですべてのデータが削除されます。よろしいですか?,Questo cancellerà tutti i dati.\nConferma la formattazione?,Это удалит все данные.\nВыполнить?
_L_DELETING_MESSAGE,Formatting ...,格式化中...,格式化中...,Formateando...,Formázás ...,Formatiere...,Formatage ...,Formatteren ...,Formatando ...,書式設定 ...,Formattazione in corso ...,Форматирование...
@@ -64,7 +68,7 @@ _L_NOT_AMIIBO_FILE,This is not Amiibo file,这不是Amiibo文件,這不是Amiibo
_L_READ_FILE_FAILED,Failed read the file,读取文件失败,讀取檔案失敗,Error al leer archivo,Fájl beolvasása sikerten,Lesen fehlgeschlagen,Échec de la lecture du fichier,Lezen van het bestand is mislukt,Falha na Leitura do Arquivo,ファイルの読み込みに失敗しました,Errore nella lettura del file,Ошибка чтения файла
_L_INPUT_FOLDER_NAME,Input Folder Name:,输入文件夹名:,輸入資料夾名稱:,Nombre carpeta:,Bemeneti Mappa Neve:,Ordnername eingeben:,Nom du Dossier D'entrée:,Naam Invoermap:,Nome da Pasta de Entrada:,入力フォルダ名:,Nome cartella:,Задайте имя папки:
_L_INPUT_AMIIBO_NAME,Input Amiibo Name:,输入amiibo名:,輸入amiibo名稱:,Nombre amiibo:,Amiibo Neve:,Amiibo Namen eingeben:,Nom de l'Amiibo D'entrée:,Naam Amiibo Invoeren:,Nome do Amiibo de Entrada:,入力Amiibo名:,Nome Amiibo:,Задайте имя Amiibo:
-_L_DELETE_FILE,Delete %s ?,删除 %s ?,刪除 %s ?,¿Borrar el %s ?,Törli a %s fájlt?,%s löschen ?,Supprimer le %s ?,%s verwijderen ?,Excluir %s ?,%s を削除しますか ?,Eliminare %s ?,Удалить %s?
+_L_DELETE_FILE,Delete %s ?,删除 %s ?,刪除 %s ?,¿Borrar %s?,Törli a %s fájlt?,%s löschen ?,Supprimer le %s ?,%s verwijderen ?,Excluir %s ?,%s を削除しますか ?,Eliminare %s ?,Удалить %s?
_L_DELETE,Delete...,删除...,刪除...,Borrar...,Töröl...,Löschen...,Supprimer...,Verwijder...,Excluir...,削除...,Elimina...,Удалить...
_L_TIPS,Confirm,提示,提示,Confirmar,Megerősítés,Bestätigen,Confirmer,Bevestigen,Confirmar,確認する,Conferma,Внимание
_L_INPUT_NEW_NAME,Input New Name:,输入新名:,輸入新名稱:,Nuevo nombre:,Új Név Bevitele:,Neuen Namen eingeben:,Nouveau nom D'entrée:,Nieuwe Naam Invoeren:,Novo Nome de Entrada:,新しい名前を入力してください:,Nuovo nome:,Задайте новое имя:
@@ -74,18 +78,18 @@ _L_CREATE_NEW_TAG,Create New Tag...,新建标签...,新建標籤...,Crear amiibo
_L_CREATE_NEW_TAG_BATCH,Batch Create New Tag...,批量创建标签...,批量創建標簽...,Crear amiibo en lote...,Kötegelt Új Címke Létrehozása...,Mehrere Tags erstellen...,Créer de Nouvelles Étiquettes Par Lot...,Nieuwe Tags in een Batch Aanmaken...,Criar Novas Tags em Lote...,新規タグの一括作成...,Crea Amiibo in serie...,Создать группу тегов...
_L_INPUT_TAG_NUM,Input Tag Number:,输入标签数量:,輸入標簽數量:,¿Cuántos?,Beviteli Címke Száma:,Tag Anzahl eingeben:,Saisir le Numéro de l'Étiquette:,Labelnummer Invoeren:,Número da Tag de Entrada:,タグ番号を入力:,Numero di tag:,Задайте число тегов:
_L_CREATE_TOO_MANY_NUM,Only max %d tags created in a batch.,一次最多只能创建%d个标签,一次最多只能創建%d個標簽,Sólo se puede crear %d en lote,Max. létrehozható címke egy kötegben %d,Sie können nur maximal %d Tags auf einmal erstellen.,Seulement %d balises maximum créées dans un lot.,Maximum %d tags aangemaakt in een batch.,Somente no máximo %d tags criadas em um lote.,1つのバッチで作成されるタグの数はは最大 %d までです。,Numero max di %d tag in serie.,За раз можно создать\n не более %d тегов
-_L_CREATING_TAG_BATCH,Creating tag,创建标签,創建標簽,Creando,Címke létrehozása,Tag erstellen,Création d'une balise,Tag aanmaken,Criando tag,タグの作成,Creazione tag,Создание тега
+_L_CREATING_TAG_BATCH,Creating tag,创建标签,創建標簽,Creando...,Címke létrehozása,Tag erstellen,Création d'une balise,Tag aanmaken,Criando tag,タグの作成,Creazione tag,Создание тега
_L_CREATING_TAG_FAILED,Create tag %s failed!,写入 %s 标签失败,寫入 %s 標簽失敗,¡Error al crear %s!,Címke létrehozása %s sikertelen!,Erstellen von Tag %s fehlgeschlagen!,La création de la balise %s a échoué!,Aanmaken tag %s mislukt!,Falha ao criar a tag %s!,タグ %s の作成に失敗しました!,Creazione tag %s fallita!,Ошибка создания тега %s
_L_RENAME,Rename...,重命名...,重新命名...,Renombrar...,Átnevezés...,Umbenennen...,Renommer...,Hernoem...,Renomear...,名前の変更...,Rinomina...,Переименовать...
-_L_OPEN_FOLDER_FAILED,Failed to open folder,打开文件夹失败,開啟資料夾失敗,Fallo al abrir carpeta,Mappa megnyitása sikertelen ,Ordner konnte nicht geöffnet werden,Échec de l'ouverture du dossier,Kan map niet openen,Falha ao abrir a pasta,フォルダを開けませんでした,Errore nell'apertura della cartella,Ошибка открытия папки
+_L_OPEN_FOLDER_FAILED,Failed to open folder,打开文件夹失败,開啟資料夾失敗,Fallo al abrir carpeta,"Mappa megnyitása sikertelen ",Ordner konnte nicht geöffnet werden,Échec de l'ouverture du dossier,Kan map niet openen,Falha ao abrir a pasta,フォルダを開けませんでした,Errore nell'apertura della cartella,Ошибка открытия папки
_L_RENAME_FAILED,Failed to rename\nError code,重命名失败,重新命名失敗,Fallo al renombrar\nCódigo de error,Átnevezés Sikertelen\nHibakód,Umbenennen fehlgeschlagen\nFehlercode,Échec du renommage.\nCode d'Erreur,Hernoemen mislukt.\nFoutcode,Falha ao renomear\nCódigo de erro,名前の変更に失敗しました。\nエラーコード,Errore nella rinomina\nCodice errore,Ошибка переименования
_L_MAIN_RETURN,[RETURN],[返回],[返回],[Volver],[VISSZA],[Zurück],[RETOUR],[TERUG],[RETORNO],[リターン],[Torna indietro],[Назад]
_L_RANDOM_MODE_MANUAL,Randomize (Manual),随机模式(手动),隨機模式(手動),Aleatorio (Manual),Randomizálás (Kézi),Zufällige UUID (Manuell),Randomiser (Manuel),Willekeurig (Handmatig),Randomizar (Manual),ランダム化 (手動),Casuale (Manuale),Ручная генерация UUID
_L_RANDOM_MODE_AUTO,Randomize (Auto),随机模式(自动),隨機模式(自動),Aleatorio (Auto.),Randomizálás (Automat.),Zufällige UUID (Automatisch),Randomiser (Automatique),Willekeurig (Automatisch),Randomizar (Automático),ランダム化(自動),Casuale (Automatico),Автогенерация UUID
_L_SEQUENCE_MODE,Sequential mode,按序模式,按序模式,Modo Secuencial,Szekvenciális Mód,Sequentieller Modus,Mode Séquentiel,Sequentiële Modus,Modo Sequencial,シーケンシャルモード,Modo sequenziale,Последовательный
_L_READ_WRITE_MODE,Read-write mode,读写模式,讀寫模式,Modo Lectura/Escrit.,Olvasás-írás Mód,Lese-Schreibmodus,Mode Lecture-Écriture,Lees-Schrijfmodus,Modo de Leitura e Gravação,読み書きモード,Modo lettura/scrittura,Чтение-запись
-_L_AMIIBOLINK_V1,V1,V1(历史版本),V1(歷史版本),V1,V1,V1,V1,V1,V1,V1,V1,V1
-_L_AMIIBOLINK_V2,V2,V2(最新版本),V2(最新版本),V2,V2,V2,V2,V2,V2,V2,V2,V2
+_L_AMIIBOLINK_V1,V1,V1(历史版本),V1(歷史版本),AmiiboLink V1,V1,V1,V1,V1,V1,V1,V1,V1
+_L_AMIIBOLINK_V2,V2,V2(最新版本),V2(最新版本),AmiiboLink V2,V2,V2,V2,V2,V2,V2,V2,V2
_L_AMILOOP,AmiLoop,AmiLoop,AmiLoop,AmiLoop,AmiLoop,AmiLoop,AmiLoop,AmiLoop,AmiLoop,AmiLoop,AmiLoop,AmiLoop
_L_MODE,Mode,模式,模式,Modo,Mód,Modus,Mode,Modus,Modo,モード,Modalità,Режим
_L_AUTO_RANDOM,Auto Random.,自动随机,自動隨機,Aleat. autom.,Automat. Randomizálás,Zufällige UUID (Automatisch),Randomisation Automatique,Automatische Randomisatie,Randomização Automática,自動ランダム化,Auto. casuale,Автогенерация
@@ -128,8 +132,8 @@ _L_APP_AMIIDB_FAV_NEW_HEAD,New Fav. Folder:,新建收藏夹:,新建收藏夾:,Nu
_L_APP_AMIIDB_FAV_EMPTY_MSG,Empty Fav. Folder?,确认清空收藏夹?,確認清空收藏夾?,¿Vaciar Carp. Favoritos?,Üres Kedvenc Mappa?,Fav.-Ordner leeren?,Vider le Dossier Favori?,Favoriete Map Leegmaken?,Esvaziar Pasta de Favoritos?,お気に入りフォルダを空にしますか?,Svuotare cart. preferiti?,Выполнить удаление\n избранного?
_L_APP_AMIIDB_FAV_DELETE_MSG,Confirm Delete?,确认删除?,確認刪除?,¿Confirma borrado?,Törlés Megerősítése?,Löschen Bestätigen?,Confirmer la Suppression?,Verwijderen Bevestigen?,Confirmar Exclusão?,削除してよろしいですか?,Conferma cancellazione?,Выполнить удаление?
_L_APP_AMIIDB_FAV_SELECT_FOLDER,Select Fav. Folder...,选择收藏夹...,選擇收藏夾...,Selec. carp. favoritos...,Kedvenc Mappa Kiválasztása...,Fav.-Ordner auswählen...,Sélectionner le Dossier Favori...,Selecteer Favoriete Map...,Selecionar Pasta Favorita...,お気に入りフォルダを選択...,Selez. cart. preferiti...,Выбрать папку избранного...
-_L_APP_AMIIDB_FAV_SUCCESS,Favorite Success,收藏成功,收藏成功,¡Favorito correcto!,Kedvenc Sikeres,Favorit erstellt ,Succès du Favori,Favoriet Geslaagd,Favorito Bem-Sucedido,お気に入りに追加されました,Preferito aggiunto!,Добавлено
-_L_APP_AMIIDB_FAV_FAILED,Favorite Failed!,收藏失败,收藏失敗,¡Favorito fallido!,Kedvenc Sikertelen!,Favorisieren fehlgeschlagen!,Échec du Favori!,Favoriet Mislukt!,Favorito Falhou!,お気に入りに追加できませんでした!,Preferito non aggiunto!,Ошибка добавления
+_L_APP_AMIIDB_FAV_SUCCESS,Favorite Success,收藏成功,收藏成功,¡Adicionado a Favoritos!,Kedvenc Sikeres,"Favorit erstellt ",Succès du Favori,Favoriet Geslaagd,Favorito Bem-Sucedido,お気に入りに追加されました,Preferito aggiunto!,Добавлено
+_L_APP_AMIIDB_FAV_FAILED,Favorite Failed!,收藏失败,收藏失敗,¡Fallo al adicionar\na Favoritos!,Kedvenc Sikertelen!,Favorisieren fehlgeschlagen!,Échec du Favori!,Favoriet Mislukt!,Favorito Falhou!,お気に入りに追加できませんでした!,Preferito non aggiunto!,Ошибка добавления
_L_APP_AMIIDB_SLOT_SAVE_SUCCESS,Save Success,保存成功,保存成功,Asignación correcta,Sikeresen Mentve,Speichern erfolgreich,Sauvegarder Succès,Opslaan Succes,Salvar Com Êxito,保存されました,Assegnazione corretta,Сохранено
_L_APP_AMIIDB_SLOT_SAVE_FAILED,Save Failed!,保存失败,保存失敗,¡Asignación fallida!,Mentés Sikertelen!,Speichern fehlgeschlagen!,Sauvegarde Échouée!,Opslaan Mislukt!,Falha ao Salvar!,保存に失敗しました!,Assegnazione fallita!,Ошибка сохранения
_L_APP_CHAMELEON,Card Emulator,卡模拟器,卡模擬器,Emular Etiqueta RFID,Kártya Emulátor,Karten Emulator,Emulateur de Carte,Kaart Emulator,Emulador de Cartão,カードエミュレータ,Emula tag RFID,Эмулятор карт
@@ -155,18 +159,18 @@ _L_APP_CHAMELEON_CARD_DATA_FACTORY,Factory...,重置...,重置...,Inicializar...
_L_APP_CHAMELEON_CARD_DATA_FACTORY_SUCCESS,Data Factory Success,卡片初始化成功,卡片初始化成功,¡Datos inicializados!,Adatok Visszaállítása Sikeres,Daten zurückgesetzt,Réinitialisation des Données Succès,Fabriekgegeven terugzetten Succesvol,Restauração de Dados Bem-Sucedida,初期化成功,Dati inizializzati!,Данные сброшены
_L_APP_CHAMELEON_CARD_DATA_LOAD_NOT_FOUND,File Not Found,文件不存在,文件不存在,Archivo no encontrado,Fájl Nem Található,Datei nicht gefunden,Fichier Non Trouvé,Bestand Niet Gevonden,Arquivo Não Encontrado,ファイルが見つかりません,File non trovato,Файл не обнаружен
_L_APP_CHAMELEON_CARD_DATA_LOAD_SIZE_NOT_MATCH,File Size Not Match,文件大小不匹配,文件大小不匹配,Tamaño archivo incorrecto,Fájl Mérete Nem Egyezik,Dateigröße stimmt nicht überein,La Taille du Fichier ne Correspond Pas,Bestandsgrootte Komt Niet Overeen,Tamanho do Arquivo Não Corresponde,ファイルサイズが一致しません,Dimensione file non corretta,Файл несоразмерен
-_L_APP_CHAMELEON_CARD_DATA_LOAD_FAILED,Load File Failed,读取文件失败,讀取文件失敗,Falla carga archivo,Fájl betöltése Sikertelen,Laden der Datei fehlgeschlagen,Échec du Chargement du Fichier,Bestand Laden Mislukt,Falha no Carregamento do Arquivo,ファイルの読み込み失敗,Caricamento file fallito,Ошибка загрузки файла
+_L_APP_CHAMELEON_CARD_DATA_LOAD_FAILED,Load File Failed,读取文件失败,讀取文件失敗,Falla al cargar archivo,Fájl betöltése Sikertelen,Laden der Datei fehlgeschlagen,Échec du Chargement du Fichier,Bestand Laden Mislukt,Falha no Carregamento do Arquivo,ファイルの読み込み失敗,Caricamento file fallito,Ошибка загрузки файла
_L_APP_CHAMELEON_CARD_DATA_LOAD_SUCCESS,Load File Success,加载卡片数据成功,加載卡片數據成功,Carga archivo correcta,Fájl Betöltése Sikeres,Datei erfolgreich geladen,Chargement du Fichier Réussi,Laad Bestand Succesvol,Sucesso no Carregamento do Arquivo,ファイルの読み込みに成功,Caricamento file riuscito,Данные загружены
_L_APP_CHAMELEON_CARD_DATA_SAVE_INPUT_FILE_NAME,Input File Name:,输入文件名,輸入文件名,Nombre archivo:,Bemeneti Fájl Neve:,Datei Namen eingeben:,Saisir le Nom du Fichier:,Bestandsnaam Invoeren:,Nome do Arquivo de Entrada:,入力ファイル名:,Nome file:,Задайте имя файла:
_L_APP_CHAMELEON_CARD_DATA_SAVE_FAILED,Save File Failed!,写入文件失败,寫入文件失敗,¡Error al guardar!,Fájl Mentése Sikertelen!,Datei speichern fehlgeschlagen!,Échec de l'Enregistrement du Fichier!,Bestand Opslaan Mislukt!,Falha ao Salvar o Arquivo!,ファイルの保存に失敗しました!,Errore nel salvataggio!,Ошибка сохранения файла
_L_APP_CHAMELEON_CARD_DATA_SAVE_SUCCESS,Save File Success,导出卡片数据成功,導出卡片數據成功,Guardado correcto,Fájl Mentése Sikeres,Datei erfolgreich gespeichert,Sauvegarde du Fichier Réussie,Bestand Opslaan Gelukt,Arquivo Salvo com êxito,ファイルが保存されました,Salvataggio riuscito,Данные сохранены
_L_APP_CHAMELEON_CARD_ADV_CUSTOM_MODE,Custom Mode,自定义模式,自定義模式,Modo personali.,Egyéni Mód,Benutzerdefinierter Modus,Mode Personnalisé,Aangepaste Modus,Modo Personalizado,カスタムモード,Modalità personalizzata,Заказной режим
_L_APP_CHAMELEON_CARD_GEN1A_MODE,Gen1A Enabled,Gen1A模式,Gen1A模式,Gen1A habilitada,Gen1A Engedélyezve,Gen1A aktiv,Gen1A Activé,Gen1A Ingeschakeld,Gen1A Ativada,Gen1A 有効,Gen1A abilitata,Gen1A
-_L_APP_CHAMELEON_CARD_GENERATE_UID,Rand. UID,生成UID,生成UID,Generar nuevo UID,Véletlen UID,Zufällige UID,Randomiser l'UID,Willekeurige UID,UID Aleatório,UIDのランダム化,Genera nuovo UID,Сгенерировать UID
+_L_APP_CHAMELEON_CARD_GENERATE_UID,Rand. UID,生成UID,生成UID,Generar UID aleat.,Véletlen UID,Zufällige UID,Randomiser l'UID,Willekeurige UID,UID Aleatório,UIDのランダム化,Genera nuovo UID,Сгенерировать UID
_L_APP_CHAMELEON_CARD_GENERATE_UID_SUCCESS,UID Generated,UID已生成,UID已生成,UID generado,Generált UID,UID generiert,UID Généré,UID Gegenereerd,UID Gerado,UID 生成,UID generato,UID сгенерирован
_L_APP_CHAMELEON_CARD_GEN2_MODE,Gen2 Enabled,Gen2模式,Gen2模式,Gen2 habilitada,Gen2 Engedélyezve,Gen2 aktiv,Gen2 Activé,Gen2 Ingeschakeld,Gen2 Ativado,Gen2 有効,Gen2 abilitata,Gen2
_L_APP_CHAMELEON_CARD_WRITE_MODE,Write Mode,写入模式,寫入模式,Modo escrit.,Írási Mód,Schreibmodus,Mode d'Écriture,Schrijfmodus,Modo de Gravação,書き込みモード,Modalità scrittura,Запись
_L_APP_CHAMELEON_CARD_ADV_ID_EDIT_INVALID_INPUT,Invalid Input!,无效的输入!,無效的輸入!,¡Entrada inválida!,Érvénytelen bemenet!,Ungültige Eingabe!,Entrée Invalide!,Ongeldige Invoer!,Entrada Inválida!,無効な入力,Input non valido!,Недопустимый ввод
_L_APP_CHAMELEON_CARD_TYPE_FACTORY_DATA_CONFRIM,Card type changed. \nFactory card data?,卡类型已修改\n重置卡数据?,卡類型已修改\n重置卡數據?,Tipo tarjeta modificado\n¿Inicializar tarjeta?,A kártya típusa megváltozott.\nGyári kártyaadatok?,Kartentyp geändert. \nKartendaten zurücksetzen?,Le Type de Carte a Été Modifié. \nRéinitialiser les Données de la Carte?,Kaarttype gewijzigd. \nGegevens terugzetten naar standaard?,O tipo de cartão foi alterado. \nRedefinir dados do cartão?,カードの種類が変更されました。\nカードデータを初期化しますか?,Tipo di carta modificato\nInizializzare carta?,Тип карты изменен.\nСбросить данные карты?
_L_APP_READER,NFC Reader,读卡器,读卡器,,,,,,,,
-_L_APP_READER_SCANNING,Dicovering Tag...,请靠近卡片...,,,,,,,,,
\ No newline at end of file
+_L_APP_READER_SCANNING,Dicovering Tag...,请靠近卡片...,,,,,,,,,_L_APP_CHAMELEON_CARD_DEFAULT_CARD,Default Card,默认卡片,默认卡片,,,,,,,,,По умолчанию
diff --git a/fw/scripts/amiibo_db_gen.py b/fw/scripts/amiibo_db_gen.py
index 2901fc81..d12f78eb 100644
--- a/fw/scripts/amiibo_db_gen.py
+++ b/fw/scripts/amiibo_db_gen.py
@@ -5,7 +5,6 @@
import json
import os
import csv
-import certifi
class Amiibo:
def __init__(self):
@@ -36,7 +35,6 @@ def get_prorject_directory():
def fetch_amiibo_from_api():
- os.environ['SSL_CERT_FILE'] = certifi.where()
conn = urlopen("https://www.amiiboapi.com/api/amiibo/")
body = json.loads(conn.read())
amiibos = list()
diff --git a/fw/scripts/font_data_gen.sh b/fw/scripts/font_data_gen.sh
deleted file mode 100644
index b90954d8..00000000
--- a/fw/scripts/font_data_gen.sh
+++ /dev/null
@@ -1,18 +0,0 @@
-#!/bin/bash
-
-cd $(dirname "$0") && cd ..
-echo "Current dir: $(pwd)"
-cat application/src/i18n/*.c application/src/amiidb/*.c |grep -Po '".*?"' | tr -d '[:print:]' |sort|uniq > data/pixjs.txt
-echo '32-128,' > data/gb2312a.map
-cat data/chinese3.txt data/pixjs.txt | iconv -f utf-8 -t c99 | sed 's/\\u\([0-9a-f]\{4\}\)/\$\1,\n/g' | sort | uniq | sed '/^$/d' | tr '/a-f/' '/A-F/' >> data/gb2312a.map
-scripts/bdfconv -b 0 -f 1 -M data/gb2312a.map -n u8g2_font_wqy12_t_gb2312a -o application/src/mui/u8g2_font_wqy12_t_gb2312a_t.c data/wenquanyi_9pt_u8g2.bdf
-echo '''
-#include "mui_u8g2.h"
-
-#include "u8x8.h"
-
-''' > application/src/mui/u8g2_font_wqy12_t_gb2312a.c
-cat application/src/mui/u8g2_font_wqy12_t_gb2312a_t.c >> application/src/mui/u8g2_font_wqy12_t_gb2312a.c
-sed -i 's/U8G2_USE_LARGE_FONTS/U8G2_USE_LARGE_GB2312_FONT/g' application/src/mui/u8g2_font_wqy12_t_gb2312a.c
-rm application/src/mui/u8g2_font_wqy12_t_gb2312a_t.c
-rm data/gb2312a.map data/pixjs.txt
\ No newline at end of file
diff --git a/gh-pages/index.html b/gh-pages/index.html
index 1796976c..7774719b 100644
--- a/gh-pages/index.html
+++ b/gh-pages/index.html
@@ -11,6 +11,6 @@
-