committed by
bunnei
15 changed files with 327 additions and 8 deletions
-
15src/android/app/src/main/AndroidManifest.xml
-
12src/android/app/src/main/java/org/yuzu/yuzu_emu/NativeLibrary.java
-
20src/android/app/src/main/java/org/yuzu/yuzu_emu/activities/EmulationActivity.kt
-
32src/android/app/src/main/java/org/yuzu/yuzu_emu/ui/main/MainActivity.kt
-
7src/android/app/src/main/java/org/yuzu/yuzu_emu/ui/main/MainPresenter.kt
-
165src/android/app/src/main/java/org/yuzu/yuzu_emu/utils/NfcReader.kt
-
9src/android/app/src/main/jni/emu_window/emu_window.cpp
-
3src/android/app/src/main/jni/emu_window/emu_window.h
-
20src/android/app/src/main/jni/native.cpp
-
6src/android/app/src/main/jni/native.h
-
6src/android/app/src/main/res/menu/menu_game_grid.xml
-
2src/android/app/src/main/res/values/strings.xml
-
6src/android/app/src/main/res/xml/nfc_tech_filter.xml
-
26src/input_common/drivers/virtual_amiibo.cpp
-
2src/input_common/drivers/virtual_amiibo.h
@ -0,0 +1,165 @@ |
|||||
|
package org.yuzu.yuzu_emu.utils |
||||
|
|
||||
|
import android.app.Activity |
||||
|
import android.app.PendingIntent |
||||
|
import android.content.Intent |
||||
|
import android.content.IntentFilter |
||||
|
import android.nfc.NfcAdapter |
||||
|
import android.nfc.Tag |
||||
|
import android.nfc.tech.NfcA |
||||
|
import android.os.Build |
||||
|
import android.os.Handler |
||||
|
import android.os.Looper |
||||
|
import org.yuzu.yuzu_emu.NativeLibrary |
||||
|
import java.io.IOException |
||||
|
|
||||
|
class NfcReader(private val activity: Activity) { |
||||
|
private var nfcAdapter: NfcAdapter? = null |
||||
|
private var pendingIntent: PendingIntent? = null |
||||
|
|
||||
|
fun initialize() { |
||||
|
nfcAdapter = NfcAdapter.getDefaultAdapter(activity) ?: return |
||||
|
|
||||
|
pendingIntent = PendingIntent.getActivity( |
||||
|
activity, |
||||
|
0, Intent(activity, activity.javaClass), |
||||
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) |
||||
|
PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_MUTABLE |
||||
|
else PendingIntent.FLAG_UPDATE_CURRENT |
||||
|
) |
||||
|
|
||||
|
val tagDetected = IntentFilter(NfcAdapter.ACTION_TAG_DISCOVERED) |
||||
|
tagDetected.addCategory(Intent.CATEGORY_DEFAULT) |
||||
|
} |
||||
|
|
||||
|
fun startScanning() { |
||||
|
nfcAdapter?.enableForegroundDispatch(activity, pendingIntent, null, null) |
||||
|
} |
||||
|
|
||||
|
fun stopScanning() { |
||||
|
nfcAdapter?.disableForegroundDispatch(activity) |
||||
|
} |
||||
|
|
||||
|
fun onNewIntent(intent: Intent) { |
||||
|
val action = intent.action |
||||
|
if (NfcAdapter.ACTION_TAG_DISCOVERED != action |
||||
|
&& NfcAdapter.ACTION_TECH_DISCOVERED != action |
||||
|
&& NfcAdapter.ACTION_NDEF_DISCOVERED != action |
||||
|
) { |
||||
|
return |
||||
|
} |
||||
|
|
||||
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { |
||||
|
val tag = |
||||
|
intent.getParcelableExtra(NfcAdapter.EXTRA_TAG, Tag::class.java) ?: return |
||||
|
readTagData(tag) |
||||
|
return |
||||
|
} |
||||
|
|
||||
|
val tag = |
||||
|
intent.getParcelableExtra<Tag>(NfcAdapter.EXTRA_TAG) ?: return |
||||
|
readTagData(tag) |
||||
|
} |
||||
|
|
||||
|
private fun readTagData(tag: Tag) { |
||||
|
if (!tag.techList.contains("android.nfc.tech.NfcA")) { |
||||
|
return |
||||
|
} |
||||
|
|
||||
|
val amiibo = NfcA.get(tag) ?: return |
||||
|
amiibo.connect() |
||||
|
|
||||
|
val tagData = ntag215ReadAll(amiibo) ?: return |
||||
|
NativeLibrary.onReadNfcTag(tagData) |
||||
|
|
||||
|
nfcAdapter?.ignore( |
||||
|
tag, |
||||
|
1000, |
||||
|
{ NativeLibrary.onRemoveNfcTag() }, |
||||
|
Handler(Looper.getMainLooper()) |
||||
|
) |
||||
|
} |
||||
|
|
||||
|
private fun ntag215ReadAll(amiibo: NfcA): ByteArray? { |
||||
|
val bufferSize = amiibo.maxTransceiveLength; |
||||
|
val tagSize = 0x21C |
||||
|
val pageSize = 4 |
||||
|
val lastPage = tagSize / pageSize - 1 |
||||
|
val tagData = ByteArray(tagSize) |
||||
|
|
||||
|
// We need to read the ntag in steps otherwise we overflow the buffer |
||||
|
for (i in 0..tagSize step bufferSize - 1) { |
||||
|
val dataStart = i / pageSize |
||||
|
var dataEnd = (i + bufferSize) / pageSize |
||||
|
|
||||
|
if (dataEnd > lastPage) { |
||||
|
dataEnd = lastPage |
||||
|
} |
||||
|
|
||||
|
try { |
||||
|
val data = ntag215FastRead(amiibo, dataStart, dataEnd - 1) |
||||
|
System.arraycopy(data, 0, tagData, i, (dataEnd - dataStart) * pageSize) |
||||
|
} catch (e: IOException) { |
||||
|
return null; |
||||
|
} |
||||
|
} |
||||
|
return tagData |
||||
|
} |
||||
|
|
||||
|
private fun ntag215Read(amiibo: NfcA, page: Int): ByteArray? { |
||||
|
return amiibo.transceive( |
||||
|
byteArrayOf( |
||||
|
0x30.toByte(), |
||||
|
(page and 0xFF).toByte() |
||||
|
) |
||||
|
) |
||||
|
} |
||||
|
|
||||
|
private fun ntag215FastRead(amiibo: NfcA, start: Int, end: Int): ByteArray? { |
||||
|
return amiibo.transceive( |
||||
|
byteArrayOf( |
||||
|
0x3A.toByte(), |
||||
|
(start and 0xFF).toByte(), |
||||
|
(end and 0xFF).toByte() |
||||
|
) |
||||
|
) |
||||
|
} |
||||
|
|
||||
|
private fun ntag215PWrite( |
||||
|
amiibo: NfcA, |
||||
|
page: Int, |
||||
|
data1: Int, |
||||
|
data2: Int, |
||||
|
data3: Int, |
||||
|
data4: Int |
||||
|
): ByteArray? { |
||||
|
return amiibo.transceive( |
||||
|
byteArrayOf( |
||||
|
0xA2.toByte(), |
||||
|
(page and 0xFF).toByte(), |
||||
|
(data1 and 0xFF).toByte(), |
||||
|
(data2 and 0xFF).toByte(), |
||||
|
(data3 and 0xFF).toByte(), |
||||
|
(data4 and 0xFF).toByte() |
||||
|
) |
||||
|
) |
||||
|
} |
||||
|
|
||||
|
private fun ntag215PwdAuth( |
||||
|
amiibo: NfcA, |
||||
|
data1: Int, |
||||
|
data2: Int, |
||||
|
data3: Int, |
||||
|
data4: Int |
||||
|
): ByteArray? { |
||||
|
return amiibo.transceive( |
||||
|
byteArrayOf( |
||||
|
0x1B.toByte(), |
||||
|
(data1 and 0xFF).toByte(), |
||||
|
(data2 and 0xFF).toByte(), |
||||
|
(data3 and 0xFF).toByte(), |
||||
|
(data4 and 0xFF).toByte() |
||||
|
) |
||||
|
) |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,6 @@ |
|||||
|
<?xml version="1.0" encoding="utf-8"?> |
||||
|
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> |
||||
|
<tech-list> |
||||
|
<tech>android.nfc.tech.NfcA</tech> |
||||
|
</tech-list> |
||||
|
</resources> |
||||
Write
Preview
Loading…
Cancel
Save
Reference in new issue