{
- const idmBytes = Uint8Array.from(Buffer.from(idm, 'hex'));
- const readCommand = [
- 0x06, // read
- ...idmBytes,
- 0x01, // service count (fixed)
- 0x0B, 0x00, // service code (000b, le)
- 0x02, // block count
- 0x80, 0x00, // S_PAD0 block
- 0x80, 0x82 // ID block
- ];
-
- let response = await NfcManager.sendFelicaCommandIOS(readCommand);
- const offset = response.indexOf(0x07); // look for 0x07 as for some reason the response may not start at response[0]
-
- // response must have 44 bytes
- if (offset === -1 || response.length - offset !== 44) {
- return null;
- } else if (offset !== 0) {
- response = response.slice(offset);
- }
-
- // response format:
- // 0 - read response (0x07)
- // 1-8 - IDm
- // 9 - status flag 1
- // 10 - status flag 2
- // 11 - number of blocks (0x02)
- // 12-27 - S_PAD0 block
- // 28-43 - ID block (DFC is 35-36)
-
- if (response[9] !== 0x00 || response[11] !== 0x02) {
- return null;
- }
-
- const dfcValue = response[37] | (response[36] << 8);
-
- if (dfcValue in AmusementICVendor && dfcValue !== AmusementICVendor.Unknown) {
- const accessCode = performDecrypt(new Uint8Array(response.slice(12, 28)));
- return {
- type: ICType.Amusement,
- accessCode: [...accessCode.accessCodeBytes].map(x => x.toString(16).padStart(2, '0')).join(''),
- vendor: dfcValue,
- idm
- };
- }
-
- return {
- type: ICType.Amusement,
- accessCode: icCard0008Number(idm),
- vendor: AmusementICVendor.Unknown,
- idm
- };
-}
diff --git a/amnet-native/package-lock.json b/amnet-native/package-lock.json
index b41741f..7ae0bac 100644
--- a/amnet-native/package-lock.json
+++ b/amnet-native/package-lock.json
@@ -1,12 +1,12 @@
{
"name": "amnet-native",
- "version": "1.3.2",
+ "version": "1.3.9",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "amnet-native",
- "version": "1.3.2",
+ "version": "1.3.9",
"dependencies": {
"@babel/runtime": "^7.28.4",
"@expo-google-fonts/jetbrains-mono": "^0.4.1",
@@ -32,7 +32,6 @@
"react-native-context-menu-view": "^1.21.0",
"react-native-gesture-handler": "^2.30.0",
"react-native-get-random-values": "^2.0.0",
- "react-native-nfc-manager": "^3.17.2",
"react-native-paper": "^5.14.5",
"react-native-reanimated": "~4.2.1",
"react-native-safe-area-context": "5.6.2",
@@ -1626,7 +1625,6 @@
"resolved": "https://registry.npmjs.org/@expo/config-plugins/-/config-plugins-54.0.4.tgz",
"integrity": "sha512-g2yXGICdoOw5i3LkQSDxl2Q5AlQCrG7oniu0pCPPO+UxGb7He4AFqSvPSy8HpRUj55io17hT62FTjYRD+d6j3Q==",
"license": "MIT",
- "peer": true,
"dependencies": {
"@expo/config-types": "^54.0.10",
"@expo/json-file": "~10.0.8",
@@ -7344,20 +7342,6 @@
"react-native": "*"
}
},
- "node_modules/react-native-nfc-manager": {
- "version": "3.17.2",
- "resolved": "https://registry.npmjs.org/react-native-nfc-manager/-/react-native-nfc-manager-3.17.2.tgz",
- "integrity": "sha512-0NryP/Iw2hzw4MVH5KCngoRerNUrnRok6VfLrlFcFZRKyTQ7KTgpsdDxCB6cR33qYNyEDrWGBayfAI+ym5gt8Q==",
- "license": "MIT",
- "peerDependencies": {
- "@expo/config-plugins": "*"
- },
- "peerDependenciesMeta": {
- "@expo/config-plugins": {
- "optional": true
- }
- }
- },
"node_modules/react-native-paper": {
"version": "5.14.5",
"resolved": "https://registry.npmjs.org/react-native-paper/-/react-native-paper-5.14.5.tgz",
@@ -8519,9 +8503,9 @@
}
},
"node_modules/tar": {
- "version": "7.5.2",
- "resolved": "https://registry.npmjs.org/tar/-/tar-7.5.2.tgz",
- "integrity": "sha512-7NyxrTE4Anh8km8iEy7o0QYPs+0JKBTj5ZaqHg6B39erLg0qYXN3BijtShwbsNSvQ+LN75+KV+C4QR/f6Gwnpg==",
+ "version": "7.5.7",
+ "resolved": "https://registry.npmjs.org/tar/-/tar-7.5.7.tgz",
+ "integrity": "sha512-fov56fJiRuThVFXD6o6/Q354S7pnWMJIVlDBYijsTNx6jKSE4pvrDTs6lUnmGvNyfJwFQQwWy3owKz1ucIhveQ==",
"license": "BlueOak-1.0.0",
"dependencies": {
"@isaacs/fs-minipass": "^4.0.0",
@@ -8810,9 +8794,9 @@
}
},
"node_modules/undici": {
- "version": "6.22.0",
- "resolved": "https://registry.npmjs.org/undici/-/undici-6.22.0.tgz",
- "integrity": "sha512-hU/10obOIu62MGYjdskASR3CUAiYaFTtC9Pa6vHyf//mAipSvSQg6od2CnJswq7fvzNS3zJhxoRkgNVaHurWKw==",
+ "version": "6.23.0",
+ "resolved": "https://registry.npmjs.org/undici/-/undici-6.23.0.tgz",
+ "integrity": "sha512-VfQPToRA5FZs/qJxLIinmU59u0r7LXqoJkCzinq3ckNJp3vKEh7jTWN589YQ5+aoAC/TGRLyJLCPKcLQbM8r9g==",
"license": "MIT",
"engines": {
"node": ">=18.17"
diff --git a/amnet-native/package.json b/amnet-native/package.json
index bbfd3da..392d9cf 100644
--- a/amnet-native/package.json
+++ b/amnet-native/package.json
@@ -1,6 +1,6 @@
{
"name": "amnet-native",
- "version": "1.3.2",
+ "version": "1.3.9",
"private": true,
"scripts": {
"android": "expo run:android",
@@ -33,7 +33,6 @@
"react-native-context-menu-view": "^1.21.0",
"react-native-gesture-handler": "^2.30.0",
"react-native-get-random-values": "^2.0.0",
- "react-native-nfc-manager": "^3.17.2",
"react-native-paper": "^5.14.5",
"react-native-reanimated": "~4.2.1",
"react-native-safe-area-context": "5.6.2",
diff --git a/amnet-shared/package-lock.json b/amnet-shared/package-lock.json
index ebda06e..9221e3f 100644
--- a/amnet-shared/package-lock.json
+++ b/amnet-shared/package-lock.json
@@ -1253,9 +1253,9 @@
}
},
"node_modules/lodash": {
- "version": "4.17.21",
- "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
- "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==",
+ "version": "4.17.23",
+ "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.23.tgz",
+ "integrity": "sha512-LgVTMpQtIopCi79SJeDiP0TfWi5CNEc/L/aRdTh3yIvmZXTnheWpKjSZhnvMl8iXbC1tFg9gdHHDMLoV7CnG+w==",
"license": "MIT"
},
"node_modules/lru-cache": {
diff --git a/readme.md b/readme.md
index 4080b10..fa1a59c 100644
--- a/readme.md
+++ b/readme.md
@@ -1,7 +1,7 @@
# AMNet
-[TestFlight](https://testflight.apple.com/join/kHbeJTsQ) • [Firebase](https://appdistribution.firebase.dev/i/6acc3151357deaa8) • [Website](http://card.ppc.moe) • [Server DLLs](https://gitea.tendokyu.moe/ppc/amnet/releases)
+[Firebase](https://appdistribution.firebase.dev/i/6acc3151357deaa8) • [Website](http://card.ppc.moe) • [Server DLLs](https://gitea.tendokyu.moe/ppc/amnet/releases)
An Amusement IC Card Switcher for segatools-based games.
@@ -11,6 +11,9 @@ An Amusement IC Card Switcher for segatools-based games.
AMNet is designed to acts as dynamic version of the `DEVICE/aime.txt` file, allowing multiple users to log into a game using their own mobile devices.
This was originally intended for use with maimai and CHUNITHM, but should be compatible with any segatools-based game with that uses Amusement IC for account management.
+> [!WARNING]
+> TestFlight is no longer available and must be sideloaded using AltStore or similar tooling for the forseeable future.
+
## Setup
1. Download the latest `amnet.dll` from the releases page
2. Move `amnet.dll` to the game directory
@@ -26,7 +29,7 @@ This was originally intended for use with maimai and CHUNITHM, but should be com
; serverName - the name of the server to show to users (defaults to the computer name if not set)
; serverAddress - the address to listen on, including the protocol (don't set/change unless you know what you're doing)
; enableKeyboardMode - whether to enable hold-enter-to-login mode. Reads the file set at aimePath for card number (or DEVICE/aime.txt if not set).
- ; useAimeDBForPhysicalCards - Whether physical cards should use AiMeDB to retrieve access codes. If the game is using a hosted network, set this to 1 to load the same account data/profile as you would get on a physical cab.
+ ; useAimeDBForPhysicalCards - Whether codes from real cards should use AiMeDB to retrieve access codes. If the game is using a hosted network, set this to 1 to load the same account data/profile as you would get on a physical cab.
gameId=SDEZ
;serverName=CHUNI-PENGUIN
;serverAddress=http://0.0.0.0:6070
@@ -40,13 +43,13 @@ This was originally intended for use with maimai and CHUNITHM, but should be com
AMNet 1.3 adds support for scanning physical cards on iOS devices. If you own a physical Aime/Banapass/NESiCA/e-Amusement card, you can scan it using the app and use it in-game.
By changing the `useAimeDBForPhysicalCards` in segatools.ini, you can choose how the card is read on a per-game basis:
-- `0` will only use the 20-digit access code (as shown in the app) to load the user profile directly (default option).
-- `1` will present the card's hardware identifier (IDm) to the game and the AiMeDB server configures will be used to retrieve the 20-digit code assigned to the card.
+- `0` will send the 20-digit access code on the back of the card to the game and load the save data directly (default option).
+- `1` - Send the card's IDm to the game and use AiMeDB to retrieve the 20-digit code assigned to the card.
Mode `1` makes the app function in the same way to a real card reader and should be used if you want the same access code to show when scanning the card on a cab.
You should also use this option if you're connecting to a hosted server (AquaNet/rinnet/etc).
-Note: if `useAimeDBForPhysicalCards` is set to `1` and the game is failing to read the card, make sure an up-to-date version of segatools is being used.
+Additionally, if `useAimeDBForPhysicalCards` is set to `1` and the game is failing to read the card, make sure an up-to-date version of segatools is being used.
## Interfaces
AMNet can be used on most platforms, see below for options available for each platform: