diff --git a/.gitignore b/.gitignore
index 28d6b50e6..4672f1b6d 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,12 +1,28 @@
+# Built application files
+build/
+app/.externalNativeBuild/
+
+# Crashlytics configuations
+com_crashlytics_export_strings.xml
+
+# Local configuration file (sdk path, etc)
+local.properties
+
+# Gradle generated files
+.gradle/
+
+# Signing files
+.signing/
+
+# User-specific configurations
+.idea/
*.iml
-.gradle
-/local.properties
-/.idea/*
+
+# OS-specific files
.DS_Store
-/build
-/captures
-/ndk/libs
-/ndk/obj
-/app/build
-/app/libs
-/app/app.iml
+.DS_Store?
+._*
+.Spotlight-V100
+.Trashes
+ehthumbs.db
+Thumbs.db
diff --git a/.idea/compiler.xml b/.idea/compiler.xml
deleted file mode 100644
index 96cc43efa..000000000
--- a/.idea/compiler.xml
+++ /dev/null
@@ -1,22 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/.idea/copyright/profiles_settings.xml b/.idea/copyright/profiles_settings.xml
deleted file mode 100644
index c7d1c5a83..000000000
--- a/.idea/copyright/profiles_settings.xml
+++ /dev/null
@@ -1,3 +0,0 @@
-
-
-
\ No newline at end of file
diff --git a/.idea/encodings.xml b/.idea/encodings.xml
deleted file mode 100644
index 97626ba45..000000000
--- a/.idea/encodings.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-
-
-
-
-
-
\ No newline at end of file
diff --git a/.idea/gradle.xml b/.idea/gradle.xml
deleted file mode 100644
index 681d7d03a..000000000
--- a/.idea/gradle.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-
-
-
-
-
-
\ No newline at end of file
diff --git a/.idea/misc.xml b/.idea/misc.xml
deleted file mode 100644
index 5d1998103..000000000
--- a/.idea/misc.xml
+++ /dev/null
@@ -1,46 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/.idea/modules.xml b/.idea/modules.xml
deleted file mode 100644
index a50469e4d..000000000
--- a/.idea/modules.xml
+++ /dev/null
@@ -1,11 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/.idea/runConfigurations.xml b/.idea/runConfigurations.xml
deleted file mode 100644
index 7f68460d8..000000000
--- a/.idea/runConfigurations.xml
+++ /dev/null
@@ -1,12 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/.idea/vcs.xml b/.idea/vcs.xml
deleted file mode 100644
index 94a25f7f4..000000000
--- a/.idea/vcs.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-
-
-
-
-
-
\ No newline at end of file
diff --git a/app/build.gradle b/app/build.gradle
index 949ac880c..f9e66c7d4 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -59,6 +59,11 @@ android {
sourceSets.main {
jniLibs.srcDir '../ndk/libs'
}
+ externalNativeBuild {
+ ndkBuild {
+ path '../ndk/jni/Android.mk'
+ }
+ }
}
dependencies {
diff --git a/app/src/main/java/com/hiddenramblings/tagmo/AmiiboDictionary.java b/app/src/main/java/com/hiddenramblings/tagmo/AmiiboDictionary.java
index 8bb6aa42f..20efa8a4b 100644
--- a/app/src/main/java/com/hiddenramblings/tagmo/AmiiboDictionary.java
+++ b/app/src/main/java/com/hiddenramblings/tagmo/AmiiboDictionary.java
@@ -4,9 +4,12 @@
/**
Data from https://docs.google.com/spreadsheets/d/1WJ4HxS9hkLquq-ATt1Rq9mioH6RDgP3qQrtYVaOdimM by /u/MacGuffen
+ or from : https://docs.google.com/spreadsheets/d/19E7pMhKN6x583uB6bWVBeaTMyBPtEAC-Bk59Y6cfgxA/ by N3evin & CheatFreak
*/
public class AmiiboDictionary {
+ // Last 4 bits of the 2nd byte are the game series identifier
+ // -------- ----XXXX
static final HashMap seriesNames = new HashMap();
static {
@@ -23,8 +26,12 @@ public class AmiiboDictionary {
seriesNames.put(0x0C02, "Kirby");
seriesNames.put(0x0D02, "Pokkén Tournament");
seriesNames.put(0x0F02, "Monster Hunter Stories");
+ seriesNames.put(0x0E02, "Mario Sports Superstars");
+
}
+ // Same as above but with short names
+ // TODO: Useless IMO
static final HashMap seriesShortNames = new HashMap();
static {
@@ -41,8 +48,12 @@ public class AmiiboDictionary {
seriesShortNames.put(0x0C02, "KIR");
seriesShortNames.put(0x0D02, "POK");
seriesShortNames.put(0x0F02, "MON");
+ seriesShortNames.put(0x0E02, "MSS");
+
}
+ // First 4 bits of the 2nd byte are the variant of the character
+ // -------- XXXX----
static final HashMap idList = new HashMap();
static {
@@ -626,11 +637,111 @@ public class AmiiboDictionary {
idList.put(0x031D, "Chelsea (ACCS)");
idList.put(0x031E, "Toby (ACCS)");
idList.put(0x034B, "Link (Ocarina of Time) (LOZ)");
+ idList.put(0x034C, "Link (Majora's Mask) (LOZ)");
+ idList.put(0x034D, "Link (Twilight Princess) (LOZ)");
+ idList.put(0x034E, "Link (Skyward Sword) (LOZ)");
idList.put(0x034F, "8-bit Link (The Legend of Zelda) (LOZ)");
idList.put(0x0350, "Toon Link (The Wind Waker) (LOZ)");
idList.put(0x0352, "Toon Zelda (The Wind Waker) (LOZ)");
+ idList.put(0x0353, "Link (Archer) (BOTW)");
+ idList.put(0x0354, "Link (Rider) (BOTW)");
+ idList.put(0x0355, "Guardian (BOTW)");
+ idList.put(0x0356, "Zelda (BOTW)");
+ idList.put(0x035C, "Bokoblin (BOTW)");
+ idList.put(0x0269,"Mario - Soccer (MSS)");
+ idList.put(0x026A,"Mario - Baseball (MSS)");
+ idList.put(0x026B,"Mario - Tennis (MSS)");
+ idList.put(0x026C,"Mario - Golf (MSS)");
+ idList.put(0x026D,"Mario - Horse Racing (MSS)");
+ idList.put(0x026E,"Luigi - Soccer (MSS)");
+ idList.put(0x026F,"Luigi - Baseball (MSS)");
+ idList.put(0x0270,"Luigi - Tennis (MSS)");
+ idList.put(0x0271,"Luigi - Golf (MSS)");
+ idList.put(0x0272,"Luigi - Horse Racing (MSS)");
+ idList.put(0x0273,"Peach - Soccer (MSS)");
+ idList.put(0x0274,"Peach - Baseball (MSS)");
+ idList.put(0x0275,"Peach - Tennis (MSS)");
+ idList.put(0x0276,"Peach - Golf (MSS)");
+ idList.put(0x0277,"Peach - Horse Racing (MSS)");
+ idList.put(0x0278,"Daisy - Soccer (MSS)");
+ idList.put(0x0279,"Daisy - Baseball (MSS)");
+ idList.put(0x027A,"Daisy - Tennis (MSS)");
+ idList.put(0x027B,"Daisy - Golf (MSS)");
+ idList.put(0x027C,"Daisy - Horse Racing (MSS)");
+ idList.put(0x027D,"Yoshi - Soccer (MSS)");
+ idList.put(0x027E,"Yoshi - Baseball (MSS)");
+ idList.put(0x027F,"Yoshi - Tennis (MSS)");
+ idList.put(0x0280,"Yoshi - Golf (MSS)");
+ idList.put(0x0281,"Yoshi - Horse Racing (MSS)");
+ idList.put(0x0282,"Wario - Soccer (MSS)");
+ idList.put(0x0283,"Wario - Baseball (MSS)");
+ idList.put(0x0284,"Wario - Tennis (MSS)");
+ idList.put(0x0285,"Wario - Golf (MSS)");
+ idList.put(0x0286,"Wario - Horse Racing (MSS)");
+ idList.put(0x0287,"Waluigi - Soccer (MSS)");
+ idList.put(0x0288,"Waluigi - Baseball (MSS)");
+ idList.put(0x0289,"Waluigi - Tennis (MSS)");
+ idList.put(0x028A,"Waluigi - Golf (MSS)");
+ idList.put(0x028B,"Waluigi - Horse Racing (MSS)");
+ idList.put(0x028C,"Donkey Kong - Soccer (MSS)");
+ idList.put(0x028D,"Donkey Kong - Baseball (MSS)");
+ idList.put(0x028E,"Donkey Kong - Tennis (MSS)");
+ idList.put(0x028F,"Donkey Kong - Golf (MSS)");
+ idList.put(0x0290,"Donkey Kong - Horse Racing (MSS)");
+ idList.put(0x0291,"Diddy Kong - Soccer (MSS)");
+ idList.put(0x0292,"Diddy Kong - Baseball (MSS)");
+ idList.put(0x0293,"Diddy Kong - Tennis (MSS)");
+ idList.put(0x0294,"Diddy Kong - Golf (MSS)");
+ idList.put(0x0295,"Diddy Kong - Horse Racing (MSS)");
+ idList.put(0x0296,"Bowser - Soccer (MSS)");
+ idList.put(0x0297,"Bowser - Baseball (MSS)");
+ idList.put(0x0298,"Bowser - Tennis (MSS)");
+ idList.put(0x0299,"Bowser - Golf (MSS)");
+ idList.put(0x029A,"Bowser - Horse Racing (MSS)");
+ idList.put(0x029B,"Bowser Jr. - Soccer (MSS)");
+ idList.put(0x029C,"Bowser Jr. - Baseball (MSS)");
+ idList.put(0x029D,"Bowser Jr. - Tennis (MSS)");
+ idList.put(0x029E,"Bowser Jr. - Golf (MSS)");
+ idList.put(0x029F,"Bowser Jr. - Horse Racing (MSS)");
+ idList.put(0x02A0,"Boo - Soccer (MSS)");
+ idList.put(0x02A1,"Boo - Baseball (MSS)");
+ idList.put(0x02A2,"Boo - Tennis (MSS)");
+ idList.put(0x02A3,"Boo - Golf (MSS)");
+ idList.put(0x02A4,"Boo - Horse Racing (MSS)");
+ idList.put(0x02A5,"Baby Mario - Soccer (MSS)");
+ idList.put(0x02A6,"Baby Mario - Baseball (MSS)");
+ idList.put(0x02A7,"Baby Mario - Tennis (MSS)");
+ idList.put(0x02A8,"Baby Mario - Golf (MSS)");
+ idList.put(0x02A9,"Baby Mario - Horse Racing (MSS)");
+ idList.put(0x02AA,"Baby Luigi - Soccer (MSS)");
+ idList.put(0x02AB,"Baby Luigi - Baseball (MSS)");
+ idList.put(0x02AC,"Baby Luigi - Tennis (MSS)");
+ idList.put(0x02AD,"Baby Luigi - Golf (MSS)");
+ idList.put(0x02AE,"Baby Luigi - Horse Racing (MSS)");
+ idList.put(0x02AF,"Birdo - Soccer (MSS)");
+ idList.put(0x02B0,"Birdo - Baseball (MSS)");
+ idList.put(0x02B1,"Birdo - Tennis (MSS)");
+ idList.put(0x02B2,"Birdo - Golf (MSS)");
+ idList.put(0x02B3,"Birdo - Horse Racing (MSS)");
+ idList.put(0x02B4,"Rosalina - Soccer (MSS)");
+ idList.put(0x02B5,"Rosalina - Baseball (MSS)");
+ idList.put(0x02B6,"Rosalina - Tennis (MSS)");
+ idList.put(0x02B7,"Rosalina - Golf (MSS)");
+ idList.put(0x02B8,"Rosalina - Horse Racing (MSS)");
+ idList.put(0x02B9,"Metal Mario - Soccer (MSS)");
+ idList.put(0x02BA,"Metal Mario - Baseball (MSS)");
+ idList.put(0x02BB,"Metal Mario - Tennis (MSS)");
+ idList.put(0x02BC,"Metal Mario - Golf (MSS)");
+ idList.put(0x02BD,"Metal Mario - Horse Racing (MSS)");
+ idList.put(0x02BE,"Pink Gold Peach - Soccer (MSS)");
+ idList.put(0x02BF,"Pink Gold Peach - Baseball (MSS)");
+ idList.put(0x02C0,"Pink Gold Peach - Tennis (MSS)");
+ idList.put(0x02C1,"Pink Gold Peach - Golf (MSS)");
+ idList.put(0x02C2,"Pink Gold Peach - Horse Racing (MSS)");
}
+ // 1st byte is the character identifier
+ // XXXXXXXX --------
static final HashMap charList = new HashMap();
static {
@@ -653,7 +764,7 @@ public class AmiiboDictionary {
charList.put(0x00130000, "Daisy");
charList.put(0x00140000, "Waluigi");
charList.put(0x00170000, "Boo");
- charList.put(0x01000000, "Link (Ocarina of Time)");
+ charList.put(0x01000000, "Link");
charList.put(0x01000100, "Toon Link (The Wind Waker)");
charList.put(0x01010000, "Toon Zelda (The Wind Waker)");
charList.put(0x01010100, "Sheik");
@@ -1188,6 +1299,101 @@ public class AmiiboDictionary {
charList.put(0x35C00000, "Shovel Knight");
charList.put(0x38400000, "Cloud Strife"); // TODO last two digits for this and next
charList.put(0x39800000, "Bayonetta");
+ charList.put(0x01000000, "Link (Archer)");
+ charList.put(0x01000000, "Link (Rider)");
+ charList.put(0x01400000, "Guardian");
+ charList.put(0x01010000, "Zelda");
+ charList.put(0x01410000, "Bokoblin");
+ charList.put(0x09C00101, "Mario - Soccer");
+ charList.put(0x09C00201, "Mario - Baseball");
+ charList.put(0x09C00301, "Mario - Tennis");
+ charList.put(0x09C00401, "Mario - Golf");
+ charList.put(0x09C00501, "Mario - Horse Racing");
+ charList.put(0x09C10101, "Luigi - Soccer");
+ charList.put(0x09C10201, "Luigi - Baseball");
+ charList.put(0x09C10301, "Luigi - Tennis");
+ charList.put(0x09C10401, "Luigi - Golf");
+ charList.put(0x09C10501, "Luigi - Horse Racing");
+ charList.put(0x09C20101, "Peach - Soccer");
+ charList.put(0x09C20201, "Peach - Baseball");
+ charList.put(0x09C20301, "Peach - Tennis");
+ charList.put(0x09C20401, "Peach - Golf");
+ charList.put(0x09C20501, "Peach - Horse Racing");
+ charList.put(0x09C30101, "Daisy - Soccer");
+ charList.put(0x09C30201, "Daisy - Baseball");
+ charList.put(0x09C30301, "Daisy - Tennis");
+ charList.put(0x09C30401, "Daisy - Golf");
+ charList.put(0x09C30501, "Daisy - Horse Racing");
+ charList.put(0x09C40101, "Yoshi - Soccer");
+ charList.put(0x09C40201, "Yoshi - Baseball");
+ charList.put(0x09C40301, "Yoshi - Tennis");
+ charList.put(0x09C40401, "Yoshi - Golf");
+ charList.put(0x09C40501, "Yoshi - Horse Racing");
+ charList.put(0x09C50101, "Wario - Soccer");
+ charList.put(0x09C50201, "Wario - Baseball");
+ charList.put(0x09C50301, "Wario - Tennis");
+ charList.put(0x09C50401, "Wario - Golf");
+ charList.put(0x09C50501, "Wario - Horse Racing");
+ charList.put(0x09C60101, "Waluigi - Soccer");
+ charList.put(0x09C60201, "Waluigi - Baseball");
+ charList.put(0x09C60301, "Waluigi - Tennis");
+ charList.put(0x09C60401, "Waluigi - Golf");
+ charList.put(0x09C60501, "Waluigi - Horse Racing");
+ charList.put(0x09C70101, "Donkey Kong - Soccer");
+ charList.put(0x09C70201, "Donkey Kong - Baseball");
+ charList.put(0x09C70301, "Donkey Kong - Tennis");
+ charList.put(0x09C70401, "Donkey Kong - Golf");
+ charList.put(0x09C70501, "Donkey Kong - Horse Racing");
+ charList.put(0x09C80101, "Diddy Kong - Soccer");
+ charList.put(0x09C80201, "Diddy Kong - Baseball");
+ charList.put(0x09C80301, "Diddy Kong - Tennis");
+ charList.put(0x09C80401, "Diddy Kong - Golf");
+ charList.put(0x09C80501, "Diddy Kong - Horse Racing");
+ charList.put(0x09C90101, "Bowser - Soccer");
+ charList.put(0x09C90201, "Bowser - Baseball");
+ charList.put(0x09C90301, "Bowser - Tennis");
+ charList.put(0x09C90401, "Bowser - Golf");
+ charList.put(0x09C90501, "Bowser - Horse Racing");
+ charList.put(0x09CA0101, "Bowser Jr. - Soccer");
+ charList.put(0x09CA0201, "Bowser Jr. - Baseball");
+ charList.put(0x09CA0301, "Bowser Jr. - Tennis");
+ charList.put(0x09CA0401, "Bowser Jr. - Golf");
+ charList.put(0x09CA0501, "Bowser Jr. - Horse Racing");
+ charList.put(0x09CB0101, "Boo - Soccer");
+ charList.put(0x09CB0201, "Boo - Baseball");
+ charList.put(0x09CB0301, "Boo - Tennis");
+ charList.put(0x09CB0401, "Boo - Golf");
+ charList.put(0x09CB0501, "Boo - Horse Racing");
+ charList.put(0x09CC0101, "Baby Mario - Soccer");
+ charList.put(0x09CC0201, "Baby Mario - Baseball");
+ charList.put(0x09CC0301, "Baby Mario - Tennis");
+ charList.put(0x09CC0401, "Baby Mario - Golf");
+ charList.put(0x09CC0501, "Baby Mario - Horse Racing");
+ charList.put(0x09CD0101, "Baby Luigi - Soccer");
+ charList.put(0x09CD0201, "Baby Luigi - Baseball");
+ charList.put(0x09CD0301, "Baby Luigi - Tennis");
+ charList.put(0x09CD0401, "Baby Luigi - Golf");
+ charList.put(0x09CD0501, "Baby Luigi - Horse Racing");
+ charList.put(0x09CE0101, "Birdo - Soccer");
+ charList.put(0x09CE0201, "Birdo - Baseball");
+ charList.put(0x09CE0301, "Birdo - Tennis");
+ charList.put(0x09CE0401, "Birdo - Golf");
+ charList.put(0x09CE0501, "Birdo - Horse Racing");
+ charList.put(0x09CF0101, "Rosalina - Soccer");
+ charList.put(0x09CF0201, "Rosalina - Baseball");
+ charList.put(0x09CF0301, "Rosalina - Tennis");
+ charList.put(0x09CF0401, "Rosalina - Golf");
+ charList.put(0x09CF0501, "Rosalina - Horse Racing");
+ charList.put(0x09D00101, "Metal Mario - Soccer");
+ charList.put(0x09D00201, "Metal Mario - Baseball");
+ charList.put(0x09D00301, "Metal Mario - Tennis");
+ charList.put(0x09D00401, "Metal Mario - Golf");
+ charList.put(0x09D00501, "Metal Mario - Horse Racing");
+ charList.put(0x09D10101, "Pink Gold Peach - Soccer");
+ charList.put(0x09D10201, "Pink Gold Peach - Baseball");
+ charList.put(0x09D10301, "Pink Gold Peach - Tennis");
+ charList.put(0x09D10401, "Pink Gold Peach - Golf");
+ charList.put(0x09D10501, "Pink Gold Peach - Horse Racing");
}
diff --git a/app/src/main/java/com/hiddenramblings/tagmo/EditorSSB.java b/app/src/main/java/com/hiddenramblings/tagmo/EditorSSB.java
index 633156545..dfa5b9c9b 100644
--- a/app/src/main/java/com/hiddenramblings/tagmo/EditorSSB.java
+++ b/app/src/main/java/com/hiddenramblings/tagmo/EditorSSB.java
@@ -3,13 +3,8 @@
import android.app.Activity;
import android.content.Intent;
import android.support.v7.app.AppCompatActivity;
-import android.os.Bundle;
import android.util.Log;
-import android.view.View;
-import android.widget.AdapterView;
import android.widget.ArrayAdapter;
-import android.widget.NumberPicker;
-import android.widget.SeekBar;
import android.widget.Spinner;
import android.widget.TextView;
@@ -82,7 +77,7 @@ void afterViews() {
tagData = TagUtil.decrypt(keyManager, tagData);
this.loadData(tagData);
} catch (Exception e) {
- Log.d(TAG, "Error decyrpting data", e);
+ Log.d(TAG, "Error decrypting data", e);
finish();
}
}
@@ -176,9 +171,9 @@ int readLevel(byte[] data) {
}
void writeLevel(byte[] data, int level) {
- int oldlevel = readLevel(data);
- if (oldlevel == level)
- return; //level is a granular value as such we dont want to overwrite it in case its halfway through a level
+ int oldLevel = readLevel(data);
+ if (oldLevel == level)
+ return; //level is a granular value as such we don't want to overwrite it in case its halfway through a level
int value = LEVEL_THRESHOLDS[level - 1];
diff --git a/app/src/main/java/com/hiddenramblings/tagmo/HexViewerActivity.java b/app/src/main/java/com/hiddenramblings/tagmo/HexViewerActivity.java
index b7388c80b..87f565dcb 100644
--- a/app/src/main/java/com/hiddenramblings/tagmo/HexViewerActivity.java
+++ b/app/src/main/java/com/hiddenramblings/tagmo/HexViewerActivity.java
@@ -1,25 +1,20 @@
package com.hiddenramblings.tagmo;
import android.content.Context;
-import android.content.res.Resources;
import android.graphics.Color;
import android.support.v7.app.AppCompatActivity;
-import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.ListView;
-import android.widget.Spinner;
import android.widget.TextView;
import org.androidannotations.annotations.AfterViews;
import org.androidannotations.annotations.EActivity;
import org.androidannotations.annotations.ViewById;
-import java.util.List;
-
@EActivity(R.layout.activity_hex_viewer)
public class HexViewerActivity extends AppCompatActivity {
private static final String TAG = "HexViewerActivity";
@@ -43,7 +38,6 @@ void afterViews() {
void loadData(byte[] tagData) {
int rows = (int)Math.ceil((float)tagData.length / 0x10);
-
String[] data = new String[rows];
for(int i=0; i< rows; i++) {
@@ -80,7 +74,6 @@ public HexDumpAdapter(Context context, String[] data) {
@Override
public View getView(int position, View convertView, ViewGroup parent) {
if (convertView == null) {
- final Context context = getContext();
convertView = LayoutInflater.from(getContext()).inflate(R.layout.hexdump_line, parent, false);
convertView.setTag(convertView.findViewById(R.id.textView2));
}
diff --git a/app/src/main/java/com/hiddenramblings/tagmo/KeyManager.java b/app/src/main/java/com/hiddenramblings/tagmo/KeyManager.java
index eadc71d16..e4f40f3c3 100644
--- a/app/src/main/java/com/hiddenramblings/tagmo/KeyManager.java
+++ b/app/src/main/java/com/hiddenramblings/tagmo/KeyManager.java
@@ -4,13 +4,10 @@
import android.net.Uri;
import android.util.Log;
-import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
-import java.net.URL;
-import java.security.Key;
/**
* Created by MAS on 31/01/2016.
diff --git a/app/src/main/java/com/hiddenramblings/tagmo/MainActivity.java b/app/src/main/java/com/hiddenramblings/tagmo/MainActivity.java
index d4f556af5..23ad37baf 100644
--- a/app/src/main/java/com/hiddenramblings/tagmo/MainActivity.java
+++ b/app/src/main/java/com/hiddenramblings/tagmo/MainActivity.java
@@ -1,6 +1,5 @@
package com.hiddenramblings.tagmo;
-import android.app.Activity;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.DialogInterface;
@@ -37,7 +36,6 @@
import java.io.InputStream;
import java.util.Arrays;
import java.util.Calendar;
-import java.util.jar.Manifest;
@EActivity(R.layout.activity_main)
@@ -189,9 +187,9 @@ void updateStatus() {
try {
if (this.currentTagData != null) {
byte[] charIdData = TagUtil.charIdDataFromTag(this.currentTagData);
- String charid = AmiiboDictionary.getDisplayName(charIdData);
+ String charId = AmiiboDictionary.getDisplayName(charIdData);
String uid = Util.bytesToHex(TagUtil.uidFromPages(this.currentTagData));
- txtTagId.setText("TagId: " + charid + " / " + uid);
+ txtTagId.setText("TagId: " + charId + " / " + uid);
} else {
txtTagId.setText("TagId: ");
}
@@ -296,7 +294,7 @@ protected void onActivityResult(int requestCode, int resultCode, Intent data) {
Log.d(TAG, "onActivityResult");
- String action = null;
+ String action;
switch (requestCode)
{
case EDIT_TAG:
@@ -335,7 +333,7 @@ protected void onActivityResult(int requestCode, int resultCode, Intent data) {
private void showFileChooser(String title, String mimeType, int resultCode) {
Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
- intent.setType("*/*"); //all files
+ intent.setType(mimeType);
intent.addCategory(Intent.CATEGORY_OPENABLE);
try {
@@ -404,17 +402,17 @@ protected void writeTagToFile(byte[] tagdata) {
try {
byte[] charIdData = TagUtil.charIdDataFromTag(this.currentTagData);
- String charid = AmiiboDictionary.getDisplayName(charIdData).replace("/", "-"); //prevent invalid filenames
+ String charId = AmiiboDictionary.getDisplayName(charIdData).replace("/", "-"); //prevent invalid filenames
- byte[] uid = Arrays.copyOfRange(tagdata, 0, 9);
- String uids = Util.bytesToHex(uid);
- String fname = String.format("%1$s [%2$s] %3$ty%3$tm%3$te_%3$tH%3$tM%3$tS%4$s.bin", charid, uids, Calendar.getInstance(), (valid ? "" : "_corrupted_"));
+ byte[] uId = Arrays.copyOfRange(tagdata, 0, 9);
+ String uIds = Util.bytesToHex(uId);
+ String fName = String.format("%1$s [%2$s] %3$ty%3$tm%3$te_%3$tH%3$tM%3$tS%4$s.bin", charId, uIds, Calendar.getInstance(), (valid ? "" : "_corrupted_"));
File dir = new File(Environment.getExternalStorageDirectory(), DATA_DIR);
if (!dir.isDirectory())
dir.mkdir();
- File file = new File(dir.getAbsolutePath(), fname);
+ File file = new File(dir.getAbsolutePath(), fName);
Log.d(TAG, file.toString());
FileOutputStream fos = new FileOutputStream(file);
@@ -428,7 +426,7 @@ protected void writeTagToFile(byte[] tagdata) {
} catch (Exception e) {
Log.e(TAG, "Failed to refresh media scanner", e);
}
- LogMessage("Wrote to file " + fname + " in tagmo directory.");
+ LogMessage("Wrote to file " + fName + " in tagmo directory.");
} catch (Exception e) {
LogError("Error writing to file: " + e.getMessage());
}
diff --git a/app/src/main/java/com/hiddenramblings/tagmo/NfcActivity.java b/app/src/main/java/com/hiddenramblings/tagmo/NfcActivity.java
index 80a86cc41..d42d86a97 100644
--- a/app/src/main/java/com/hiddenramblings/tagmo/NfcActivity.java
+++ b/app/src/main/java/com/hiddenramblings/tagmo/NfcActivity.java
@@ -1,7 +1,6 @@
package com.hiddenramblings.tagmo;
import android.app.Activity;
-import android.app.Notification;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.Context;
@@ -11,23 +10,19 @@
import android.nfc.Tag;
import android.nfc.tech.MifareUltralight;
import android.support.v7.app.AppCompatActivity;
-import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import android.widget.ImageView;
-import android.widget.ProgressBar;
import android.widget.TextView;
import android.widget.Toast;
import org.androidannotations.annotations.AfterViews;
import org.androidannotations.annotations.Background;
import org.androidannotations.annotations.EActivity;
-import org.androidannotations.annotations.OptionsMenu;
import org.androidannotations.annotations.UiThread;
import org.androidannotations.annotations.ViewById;
-import org.androidannotations.annotations.res.AnimationRes;
@EActivity(R.layout.activity_nfc)
public class NfcActivity extends AppCompatActivity {
@@ -149,8 +144,6 @@ void onTagDiscovered(Intent intent) {
try {
Tag tag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
Log.d(TAG, tag.toString());
- if (tag == null)
- showError("Error getting tag data");
MifareUltralight mifare = MifareUltralight.get(tag);
if (mifare == null)
throw new Exception("Error getting tag data. Possibly not a NTAG215");
@@ -159,7 +152,7 @@ void onTagDiscovered(Intent intent) {
int resultCode = Activity.RESULT_CANCELED;
try {
Log.d(TAG, mode);
- byte[] data = null;
+ byte[] data;
switch (mode) {
case ACTION_WRITE_TAG_RAW:
data = commandIntent.getByteArrayExtra(EXTRA_TAG_DATA);
diff --git a/app/src/main/java/com/hiddenramblings/tagmo/TagCreateDialog.java b/app/src/main/java/com/hiddenramblings/tagmo/TagCreateDialog.java
index 56d1f6170..479a89c3c 100644
--- a/app/src/main/java/com/hiddenramblings/tagmo/TagCreateDialog.java
+++ b/app/src/main/java/com/hiddenramblings/tagmo/TagCreateDialog.java
@@ -9,7 +9,6 @@
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
-import android.webkit.WebView;
import android.widget.ArrayAdapter;
import android.widget.Spinner;
diff --git a/app/src/main/java/com/hiddenramblings/tagmo/TagUtil.java b/app/src/main/java/com/hiddenramblings/tagmo/TagUtil.java
index e9961f70a..78b9fe5e0 100644
--- a/app/src/main/java/com/hiddenramblings/tagmo/TagUtil.java
+++ b/app/src/main/java/com/hiddenramblings/tagmo/TagUtil.java
@@ -1,7 +1,5 @@
package com.hiddenramblings.tagmo;
-import android.util.Log;
-
import java.util.Arrays;
public class TagUtil {
diff --git a/app/src/main/java/com/hiddenramblings/tagmo/TagWriter.java b/app/src/main/java/com/hiddenramblings/tagmo/TagWriter.java
index 0c031dded..2fc9a5363 100644
--- a/app/src/main/java/com/hiddenramblings/tagmo/TagWriter.java
+++ b/app/src/main/java/com/hiddenramblings/tagmo/TagWriter.java
@@ -4,7 +4,6 @@
import android.util.Log;
import java.io.IOException;
-import java.util.Arrays;
/**
* Created by MAS on 01/02/2016.
@@ -107,32 +106,29 @@ static boolean compareRange(byte[] data, byte[] data2, int data2offset, int len)
public static final int BULK_READ_PAGE_COUNT = 4;
public static byte[] readFromTag(MifareUltralight tag) throws Exception
{
- byte[] tagdata = new byte[TagUtil.TAG_FILE_SIZE];
+ byte[] tagData = new byte[TagUtil.TAG_FILE_SIZE];
+ int pageCount = TagUtil.TAG_FILE_SIZE / TagUtil.PAGE_SIZE;
- int pagecount = TagUtil.TAG_FILE_SIZE / TagUtil.PAGE_SIZE;
- int readcount = (int)Math.ceil((double)TagUtil.TAG_FILE_SIZE / (pagecount * BULK_READ_PAGE_COUNT));
-
- for(int i=0; i
#include
#define HMAC_POS_DATA 0x008
#define HMAC_POS_TAG 0x1B4
-void bzero(void *s, size_t n);;
-
void nfc3d_amiibo_calc_seed(const uint8_t * dump, uint8_t * key) {
memcpy(key + 0x00, dump + 0x029, 0x02);
- bzero(key + 0x02, 0x0E);
+ memset(key + 0x02, 0x00, 0x0E);
memcpy(key + 0x10, dump + 0x1D4, 0x08);
memcpy(key + 0x18, dump + 0x1D4, 0x08);
memcpy(key + 0x20, dump + 0x1E8, 0x20);
@@ -89,9 +88,22 @@ bool nfc3d_amiibo_unpack(const nfc3d_amiibo_keys * amiiboKeys, const uint8_t * t
// Decrypt
nfc3d_amiibo_cipher(&dataKeys, internal, plain);
- // Check integrity. Note: order matters, data HMAC depends on tag HMAC!
- sha256hmac(tagKeys.hmacKey, sizeof(tagKeys.hmacKey), plain + 0x1D4, 0x34, plain + HMAC_POS_TAG);
- sha256hmac(dataKeys.hmacKey, sizeof(dataKeys.hmacKey), plain + 0x029, 0x1DF, plain + HMAC_POS_DATA);
+ // Init OpenSSL HMAC context
+ HMAC_CTX hmacCtx;
+ HMAC_CTX_init(&hmacCtx);
+
+ // Regenerate tag HMAC. Note: order matters, data HMAC depends on tag HMAC!
+ HMAC_Init_ex(&hmacCtx, tagKeys.hmacKey, sizeof(tagKeys.hmacKey), EVP_sha256(), NULL);
+ HMAC_Update(&hmacCtx, plain + 0x1D4, 0x34);
+ HMAC_Final(&hmacCtx, plain + HMAC_POS_TAG, NULL);
+
+ // Regenerate data HMAC
+ HMAC_Init_ex(&hmacCtx, dataKeys.hmacKey, sizeof(dataKeys.hmacKey), EVP_sha256(), NULL);
+ HMAC_Update(&hmacCtx, plain + 0x029, 0x1DF);
+ HMAC_Final(&hmacCtx, plain + HMAC_POS_DATA, NULL);
+
+ // HMAC cleanup
+ HMAC_CTX_cleanup(&hmacCtx);
return
memcmp(plain + HMAC_POS_DATA, internal + HMAC_POS_DATA, 32) == 0 &&
@@ -107,16 +119,27 @@ void nfc3d_amiibo_pack(const nfc3d_amiibo_keys * amiiboKeys, const uint8_t * pla
nfc3d_amiibo_keygen(&amiiboKeys->tag, plain, &tagKeys);
nfc3d_amiibo_keygen(&amiiboKeys->data, plain, &dataKeys);
- uint8_t plain2[NFC3D_AMIIBO_SIZE];
- memcpy(plain2, plain, NFC3D_AMIIBO_SIZE);
+ // Init OpenSSL HMAC context
+ HMAC_CTX hmacCtx;
+ HMAC_CTX_init(&hmacCtx);
+
+ // Generate tag HMAC
+ HMAC_Init_ex(&hmacCtx, tagKeys.hmacKey, sizeof(tagKeys.hmacKey), EVP_sha256(), NULL);
+ HMAC_Update(&hmacCtx, plain + 0x1D4, 0x34);
+ HMAC_Final(&hmacCtx, cipher + HMAC_POS_TAG, NULL);
+
+ // Generate data HMAC
+ HMAC_Init_ex(&hmacCtx, dataKeys.hmacKey, sizeof(dataKeys.hmacKey), EVP_sha256(), NULL);
+ HMAC_Update(&hmacCtx, plain + 0x029, 0x18B); // Data
+ HMAC_Update(&hmacCtx, cipher + HMAC_POS_TAG, 0x20); // Tag HMAC
+ HMAC_Update(&hmacCtx, plain + 0x1D4, 0x34); // Here be dragons
+ HMAC_Final(&hmacCtx, cipher + HMAC_POS_DATA, NULL);
- // Generate HMAC //tag hmac is used by data hmac
- sha256hmac(tagKeys.hmacKey, sizeof(tagKeys.hmacKey), plain2 + 0x1D4, 0x34, plain2 + HMAC_POS_TAG);
- sha256hmac(tagKeys.hmacKey, sizeof(tagKeys.hmacKey), plain2 + 0x1D4, 0x34, cipher + HMAC_POS_TAG);
- sha256hmac(dataKeys.hmacKey, sizeof(dataKeys.hmacKey), plain2 + 0x029, 0x1DF, cipher + HMAC_POS_DATA);
+ // HMAC cleanup
+ HMAC_CTX_cleanup(&hmacCtx);
// Encrypt
- nfc3d_amiibo_cipher(&dataKeys, plain2, cipher);
+ nfc3d_amiibo_cipher(&dataKeys, plain, cipher);
// Convert back to hardware
nfc3d_amiibo_internal_to_tag(cipher, tag);
diff --git a/ndk/jni/include/nfc3d/amiibo.h b/ndk/jni/include/nfc3d/amiibo.h
index 1dd5c3017..8433fffaa 100644
--- a/ndk/jni/include/nfc3d/amiibo.h
+++ b/ndk/jni/include/nfc3d/amiibo.h
@@ -38,4 +38,6 @@ typedef struct {
bool nfc3d_amiibo_unpack(const nfc3d_amiibo_keys * amiiboKeys, const uint8_t * tag, uint8_t * plain);
void nfc3d_amiibo_pack(const nfc3d_amiibo_keys * amiiboKeys, const uint8_t * plain, uint8_t * tag);
+bool nfc3d_amiibo_load_keys(nfc3d_amiibo_keys * amiiboKeys, const char * path);
+
#endif
diff --git a/ndk/jni/keygen.c b/ndk/jni/keygen.c
index ceb757ccf..16fb43e39 100644
--- a/ndk/jni/keygen.c
+++ b/ndk/jni/keygen.c
@@ -22,17 +22,11 @@
#include "nfc3d/drbg.h"
#include "nfc3d/keygen.h"
+#include "util.h"
#include
#include
#include
-char * stpncpy (char *dst, const char *src, size_t len) {
- size_t n = strlen (src);
- if (n > len)
- n = len;
- return strncpy (dst, src, len) + n;
-}
-
void nfc3d_keygen_prepare_seed(const nfc3d_keygen_masterkeys * baseKeys, const uint8_t * baseSeed, uint8_t * output, size_t * outputSize) {
assert(baseKeys != NULL);
assert(baseSeed != NULL);
@@ -42,7 +36,7 @@ void nfc3d_keygen_prepare_seed(const nfc3d_keygen_masterkeys * baseKeys, const u
uint8_t * start = output;
// 1: Copy whole type string
- output = (uint8_t *) stpncpy((char *) output, baseKeys->typeString, sizeof(baseKeys->typeString)) + 1;
+ output = memccpy(output, baseKeys->typeString, '\0', sizeof(baseKeys->typeString));
// 2: Append (16 - magicBytesSize) from the input seed
size_t leadingSeedBytes = 16 - baseKeys->magicBytesSize;