From 9b8817043962f611daed218a8d315d2de2b9c2bf Mon Sep 17 00:00:00 2001 From: TwistedUmbrellaX Date: Tue, 19 Sep 2023 08:36:48 -0400 Subject: [PATCH] Improve random serial duplicator flexibility --- .../hiddenramblings/tagmo/BrowserActivity.kt | 113 ++++++++---------- .../com/hiddenramblings/tagmo/NFCIntent.kt | 2 - .../tagmo/amiibo/AmiiboFile.kt | 51 -------- .../tagmo/amiibo/AmiiboManager.kt | 54 ++++----- .../tagmo/amiibo/PowerTagManager.kt | 1 - .../tagmo/amiibo/tagdata/AppDataMLPaperJam.kt | 2 - .../tagmo/fragment/EliteBankFragment.kt | 33 ++--- .../tagmo/fragment/GattSlotFragment.kt | 4 +- .../tagmo/hexcode/HexCodeViewer.kt | 1 - .../hiddenramblings/tagmo/nfctech/TagArray.kt | 27 ++++- 10 files changed, 117 insertions(+), 171 deletions(-) diff --git a/app/src/main/java/com/hiddenramblings/tagmo/BrowserActivity.kt b/app/src/main/java/com/hiddenramblings/tagmo/BrowserActivity.kt index 320bd83c0..9c9156ae3 100644 --- a/app/src/main/java/com/hiddenramblings/tagmo/BrowserActivity.kt +++ b/app/src/main/java/com/hiddenramblings/tagmo/BrowserActivity.kt @@ -81,6 +81,7 @@ import com.hiddenramblings.tagmo.nfctech.Foomiibo import com.hiddenramblings.tagmo.nfctech.NfcActivity import com.hiddenramblings.tagmo.nfctech.ScanTag import com.hiddenramblings.tagmo.nfctech.TagArray +import com.hiddenramblings.tagmo.nfctech.TagArray.withRandomSerials import com.hiddenramblings.tagmo.nfctech.TagReader import com.hiddenramblings.tagmo.qrcode.QRCodeScanner import com.hiddenramblings.tagmo.update.UpdateManager @@ -973,19 +974,20 @@ class BrowserActivity : AppCompatActivity(), BrowserSettingsListener, private fun exportWithRandomSerial(amiiboFile: AmiiboFile?, tagData: ByteArray?, count: Int) { CoroutineScope(Dispatchers.IO).launch { - val amiiboList = amiiboFile?.withRandomSerials(keyManager, count) + val amiiboList = amiiboFile?.let { + TagArray.getValidatedAmiibo(keyManager, it).withRandomSerials(count, keyManager) + } ?: tagData?.withRandomSerials(count, keyManager) amiiboList?.forEachIndexed { index, amiiboData -> try { val outputData = keyManager.encrypt(amiiboData.array) writeFlipperFile(index, outputData) } catch (ex: Exception) { Debug.warn(ex) - withContext(Dispatchers.Main) { - IconifiedSnackbar(this@BrowserActivity, viewPager).buildSnackbar( - getString(R.string.fail_randomize), Snackbar.LENGTH_SHORT - ).show() - } } + } ?: withContext(Dispatchers.Main) { + IconifiedSnackbar(this@BrowserActivity, viewPager).buildSnackbar( + getString(R.string.fail_randomize), Snackbar.LENGTH_SHORT + ).show() } } } @@ -1010,12 +1012,14 @@ class BrowserActivity : AppCompatActivity(), BrowserSettingsListener, var needsReload = false val fileName = TagArray.decipherFilename(settings?.amiiboManager, tagData, true) - val amiiboList = amiiboFile?.withRandomSerials(keyManager, count) + val amiiboList = amiiboFile?.let { + TagArray.getValidatedAmiibo(keyManager, it).withRandomSerials(count, keyManager) + } ?: tagData?.withRandomSerials(count, keyManager) amiiboList?.forEachIndexed { index, amiiboData -> val name = "${fileName}_$index" try { val outputData = keyManager.encrypt(amiiboData.array) - val outputFile: AmiiboFile? = if (cached) { + if (cached) { val path = TagArray.writeBytesToFile(directory, name, outputData) AmiiboFile(File(path), amiiboData.amiiboID, outputData) } else { @@ -1028,21 +1032,16 @@ class BrowserActivity : AppCompatActivity(), BrowserSettingsListener, AmiiboFile(File(it), amiiboData.amiiboID, amiiboData.array) } } - if (!needsReload) needsReload = null != outputFile } catch (ex: Exception) { Debug.warn(ex) } - } - if (needsReload) { - withContext(Dispatchers.Main) { - onRootFolderChanged(true) - } - } else { - withContext(Dispatchers.Main) { - IconifiedSnackbar(this@BrowserActivity, viewPager).buildSnackbar( + } ?: withContext(Dispatchers.Main) { + IconifiedSnackbar(this@BrowserActivity, viewPager).buildSnackbar( getString(R.string.fail_randomize), Snackbar.LENGTH_SHORT - ).show() - } + ).show() + } + withContext(Dispatchers.Main) { + onRootFolderChanged(true) } } } @@ -2403,22 +2402,18 @@ class BrowserActivity : AppCompatActivity(), BrowserSettingsListener, hideFakeSnackbar() onShowSettingsFragment() } else { - coroutineScope { - uris.map { uri -> - async(Dispatchers.IO) { + coroutineScope { uris.map { uri -> async(Dispatchers.IO) { + try { + contentResolver.openInputStream(uri)?.use { inputStream -> try { - contentResolver.openInputStream(uri)?.use { inputStream -> - try { - keyManager.evaluateKey(inputStream) - } catch (ex: Exception) { - onShowSettingsFragment() - } - hideFakeSnackbar() - } - } catch (e: Exception) { Debug.warn(e) } + keyManager.evaluateKey(inputStream) + } catch (ex: Exception) { + onShowSettingsFragment() + } + hideFakeSnackbar() } - }.awaitAll() - } + } catch (e: Exception) { Debug.warn(e) } + } }.awaitAll() } if (keyManager.isKeyMissing) { onShowSettingsFragment() hideFakeSnackbar() @@ -2442,30 +2437,22 @@ class BrowserActivity : AppCompatActivity(), BrowserSettingsListener, onShowSettingsFragment() } } else { - coroutineScope { - directories.map { - async(Dispatchers.IO) { - if (it.isDirectory) locateKeyFilesRecursive(it, false) - } - }.awaitAll() - } + coroutineScope { directories.map { file -> async(Dispatchers.IO) { + if (file.isDirectory) locateKeyFilesRecursive(file, false) + } }.awaitAll() } } } } else { - coroutineScope { - files.map { file -> - async(Dispatchers.IO) { + coroutineScope { files.map { file -> async(Dispatchers.IO) { + try { + FileInputStream(file).use { inputStream -> try { - FileInputStream(file).use { inputStream -> - try { - keyManager.evaluateKey(inputStream) - } catch (ignored: Exception) { } - } - } catch (e: Exception) { Debug.warn(e) } + keyManager.evaluateKey(inputStream) + } catch (ignored: Exception) { } } - } - }.awaitAll() - } + } catch (e: Exception) { Debug.warn(e) } + } + } }.awaitAll() } if (keyManager.isKeyMissing) { onShowSettingsFragment() hideFakeSnackbar() @@ -2490,21 +2477,17 @@ class BrowserActivity : AppCompatActivity(), BrowserSettingsListener, else locateKeyFilesRecursive(Storage.getFile(prefs.preferEmulated()), true) } else { - coroutineScope { - files.map { file -> - async(Dispatchers.IO) { + coroutineScope { files.map { file -> async(Dispatchers.IO) { + try { + FileInputStream(file).use { inputStream -> try { - FileInputStream(file).use { inputStream -> - try { - keyManager.evaluateKey(inputStream) - } catch (ignored: Exception) { } - } - } catch (e: Exception) { - Debug.warn(e) - } + keyManager.evaluateKey(inputStream) + } catch (ignored: Exception) { } } - }.awaitAll() - } + } catch (e: Exception) { + Debug.warn(e) + } + } }.awaitAll() } if (keyManager.isKeyMissing) { onShowSettingsFragment() hideFakeSnackbar() diff --git a/app/src/main/java/com/hiddenramblings/tagmo/NFCIntent.kt b/app/src/main/java/com/hiddenramblings/tagmo/NFCIntent.kt index 3a78bc2b8..b60f183bb 100644 --- a/app/src/main/java/com/hiddenramblings/tagmo/NFCIntent.kt +++ b/app/src/main/java/com/hiddenramblings/tagmo/NFCIntent.kt @@ -1,8 +1,6 @@ package com.hiddenramblings.tagmo import android.content.ComponentName -import android.content.Intent -import com.hiddenramblings.tagmo.eightbit.os.Version object NFCIntent { @JvmStatic diff --git a/app/src/main/java/com/hiddenramblings/tagmo/amiibo/AmiiboFile.kt b/app/src/main/java/com/hiddenramblings/tagmo/amiibo/AmiiboFile.kt index 0292323bc..e75afb68f 100644 --- a/app/src/main/java/com/hiddenramblings/tagmo/amiibo/AmiiboFile.kt +++ b/app/src/main/java/com/hiddenramblings/tagmo/amiibo/AmiiboFile.kt @@ -3,15 +3,7 @@ package com.hiddenramblings.tagmo.amiibo import android.os.Parcel import android.os.Parcelable import androidx.documentfile.provider.DocumentFile -import com.hiddenramblings.tagmo.amiibo.tagdata.AmiiboData -import com.hiddenramblings.tagmo.eightbit.io.Debug import com.hiddenramblings.tagmo.eightbit.os.Version -import com.hiddenramblings.tagmo.nfctech.Foomiibo -import com.hiddenramblings.tagmo.nfctech.TagArray -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.async -import kotlinx.coroutines.awaitAll -import kotlinx.coroutines.coroutineScope import java.io.File open class AmiiboFile : Parcelable { @@ -55,49 +47,6 @@ open class AmiiboFile : Parcelable { data = ByteArray(parcel.readInt()).also { parcel.readByteArray(it) } } - suspend fun withRandomSerials(keyManager: KeyManager, count: Int) : ArrayList { - val dataList: ArrayList = arrayListOf() - coroutineScope { - val tagData = TagArray.getValidatedAmiibo(keyManager, this@AmiiboFile) - (0 until count).map { - async(Dispatchers.IO) { - try { - AmiiboData(keyManager.decrypt(tagData)).apply { - uID = Foomiibo.generateRandomUID() - }.also { - dataList.add(it) - } - } catch (e: Exception) { - Debug.warn(e) - } - } - }.awaitAll() - } - return dataList - } - - suspend fun withRandomSerials(count: Int) : ArrayList { - val dataList: ArrayList = arrayListOf() - this@AmiiboFile.data?.let { tagData -> - coroutineScope { - (0 until count).map { - async(Dispatchers.IO) { - try { - AmiiboData(tagData).apply { - uID = Foomiibo.generateRandomUID() - }.also { - dataList.add(it) - } - } catch (e: Exception) { - Debug.warn(e) - } - } - }.awaitAll() - } - } - return dataList - } - companion object { @JvmField val CREATOR: Parcelable.Creator = object : Parcelable.Creator { diff --git a/app/src/main/java/com/hiddenramblings/tagmo/amiibo/AmiiboManager.kt b/app/src/main/java/com/hiddenramblings/tagmo/amiibo/AmiiboManager.kt index aedae8b92..3b071f7c2 100644 --- a/app/src/main/java/com/hiddenramblings/tagmo/amiibo/AmiiboManager.kt +++ b/app/src/main/java/com/hiddenramblings/tagmo/amiibo/AmiiboManager.kt @@ -324,22 +324,18 @@ object AmiiboManager { val amiiboFiles = ArrayList() val files = rootFolder?.listFiles { _: File?, name: String -> binFileMatches(name) } if (!files.isNullOrEmpty()) { - coroutineScope { - files.map { file -> - async(Dispatchers.IO) { - try { - TagArray.getValidatedFile(keyManager, file).also { data -> - amiiboFiles.add(AmiiboFile(file, Amiibo.dataToId(data), data)) - } - } catch (e: Exception) { - if (Debug.getExceptionClass(e) == IOException().javaClass.name) - Debug.verbose(e) - else - Debug.info(e) - } + coroutineScope { files.map { file -> async(Dispatchers.IO) { + try { + TagArray.getValidatedFile(keyManager, file).also { data -> + amiiboFiles.add(AmiiboFile(file, Amiibo.dataToId(data), data)) } - }.awaitAll() - } + } catch (e: Exception) { + if (Debug.getExceptionClass(e) == IOException().javaClass.name) + Debug.verbose(e) + else + Debug.info(e) + } + } }.awaitAll() } } else if (recursiveFiles) { val directories = rootFolder?.listFiles() if (directories.isNullOrEmpty()) return amiiboFiles @@ -360,24 +356,20 @@ object AmiiboManager { return arrayListOf().apply { val uris = context?.let { AmiiboDocument(it).listFiles(rootFolder.uri, recursiveFiles) } if (uris.isNullOrEmpty()) return this - coroutineScope { - uris.map { uri -> - async(Dispatchers.IO) { - try { - TagArray.getValidatedDocument(keyManager, uri).also { data -> - DocumentFile.fromSingleUri(context, uri).also { - add(AmiiboFile(it, Amiibo.dataToId(data), data)) - } - } - } catch (e: Exception) { - if (Debug.getExceptionClass(e) == IOException().javaClass.name) - Debug.verbose(e) - else - Debug.info(e) + coroutineScope { uris.map { uri -> async(Dispatchers.IO) { + try { + TagArray.getValidatedDocument(keyManager, uri).also { data -> + DocumentFile.fromSingleUri(context, uri).also { + add(AmiiboFile(it, Amiibo.dataToId(data), data)) } } - }.awaitAll() - } + } catch (e: Exception) { + if (Debug.getExceptionClass(e) == IOException().javaClass.name) + Debug.verbose(e) + else + Debug.info(e) + } + } }.awaitAll() } } } } \ No newline at end of file diff --git a/app/src/main/java/com/hiddenramblings/tagmo/amiibo/PowerTagManager.kt b/app/src/main/java/com/hiddenramblings/tagmo/amiibo/PowerTagManager.kt index a5df68e63..8b9d6ba88 100644 --- a/app/src/main/java/com/hiddenramblings/tagmo/amiibo/PowerTagManager.kt +++ b/app/src/main/java/com/hiddenramblings/tagmo/amiibo/PowerTagManager.kt @@ -3,7 +3,6 @@ package com.hiddenramblings.tagmo.amiibo import android.util.Base64 import com.hiddenramblings.tagmo.R import com.hiddenramblings.tagmo.TagMo -import com.hiddenramblings.tagmo.nfctech.TagArray import com.hiddenramblings.tagmo.nfctech.TagArray.toHex import org.json.JSONException import org.json.JSONObject diff --git a/app/src/main/java/com/hiddenramblings/tagmo/amiibo/tagdata/AppDataMLPaperJam.kt b/app/src/main/java/com/hiddenramblings/tagmo/amiibo/tagdata/AppDataMLPaperJam.kt index 76d9097ed..e3cf9b602 100644 --- a/app/src/main/java/com/hiddenramblings/tagmo/amiibo/tagdata/AppDataMLPaperJam.kt +++ b/app/src/main/java/com/hiddenramblings/tagmo/amiibo/tagdata/AppDataMLPaperJam.kt @@ -7,8 +7,6 @@ */ package com.hiddenramblings.tagmo.amiibo.tagdata -import com.hiddenramblings.tagmo.nfctech.TagArray - class AppDataMLPaperJam(appData: ByteArray?) : AppData(appData!!) { private val sparkleCardHex = "FF FF FF FF FF FF FF" diff --git a/app/src/main/java/com/hiddenramblings/tagmo/fragment/EliteBankFragment.kt b/app/src/main/java/com/hiddenramblings/tagmo/fragment/EliteBankFragment.kt index 38822fa8b..94b8d4347 100644 --- a/app/src/main/java/com/hiddenramblings/tagmo/fragment/EliteBankFragment.kt +++ b/app/src/main/java/com/hiddenramblings/tagmo/fragment/EliteBankFragment.kt @@ -59,6 +59,7 @@ import com.hiddenramblings.tagmo.eightbit.request.ImageTarget import com.hiddenramblings.tagmo.hexcode.HexCodeViewer import com.hiddenramblings.tagmo.nfctech.NfcActivity import com.hiddenramblings.tagmo.nfctech.TagArray +import com.hiddenramblings.tagmo.nfctech.TagArray.withRandomSerials import com.hiddenramblings.tagmo.widget.Toasty import com.shawnlin.numberpicker.NumberPicker import kotlinx.coroutines.CoroutineScope @@ -184,7 +185,7 @@ class EliteBankFragment : Fragment(), EliteBankAdapter.OnAmiiboClickListener { override fun onAmiiboDataClicked(amiiboFile: AmiiboFile?, count: Int) { CoroutineScope(Dispatchers.IO).launch { amiiboFile?.let { - val amiiboData = it.withRandomSerials(count) + val amiiboData = it.data.withRandomSerials(count) withContext(Dispatchers.Main) { if (amiiboData.isEmpty()) { Toasty(requireActivity()).Short( @@ -528,11 +529,11 @@ class EliteBankFragment : Fragment(), EliteBankAdapter.OnAmiiboClickListener { bankAdapter?.notifyItemChanged(clickedPosition) } - private fun scanAmiiboBank(current_bank: Int) { + private fun scanAmiiboBank(currentBank: Int) { onScanTagResult.launch(Intent(requireContext(), NfcActivity::class.java).apply { putExtra(NFCIntent.EXTRA_SIGNATURE, prefs.eliteSignature()) action = NFCIntent.ACTION_SCAN_TAG - putExtra(NFCIntent.EXTRA_CURRENT_BANK, current_bank) + putExtra(NFCIntent.EXTRA_CURRENT_BANK, currentBank) }) } @@ -628,12 +629,12 @@ class EliteBankFragment : Fragment(), EliteBankAdapter.OnAmiiboClickListener { } } - private fun getAmiiboToolbar(tagData: ByteArray?, current_bank: Int) { + private fun getAmiiboToolbar(tagData: ByteArray?, currentBank: Int) { toolbar?.setOnMenuItemClickListener { item: MenuItem -> val notice = Toasty(requireActivity()) val scan = Intent(requireContext(), NfcActivity::class.java) .putExtra(NFCIntent.EXTRA_SIGNATURE, prefs.eliteSignature()) - .putExtra(NFCIntent.EXTRA_CURRENT_BANK, current_bank) + .putExtra(NFCIntent.EXTRA_CURRENT_BANK, currentBank) when (item.itemId) { R.id.mnu_activate -> { scan.action = NFCIntent.ACTION_ACTIVATE_BANK @@ -641,7 +642,7 @@ class EliteBankFragment : Fragment(), EliteBankAdapter.OnAmiiboClickListener { return@setOnMenuItemClickListener true } R.id.mnu_replace -> { - displayWriteDialog(current_bank) + displayWriteDialog(currentBank) return@setOnMenuItemClickListener true } R.id.mnu_write -> { @@ -651,12 +652,12 @@ class EliteBankFragment : Fragment(), EliteBankAdapter.OnAmiiboClickListener { onUpdateTagResult.launch(scan) } else { status = CLICKED.WRITE_DATA - scanAmiiboBank(current_bank) + scanAmiiboBank(currentBank) } return@setOnMenuItemClickListener true } R.id.mnu_erase_bank -> { - if (prefs.eliteActiveBank() == current_bank) { + if (prefs.eliteActiveBank() == currentBank) { notice.Short(R.string.erase_active) } else { scan.action = NFCIntent.ACTION_ERASE_BANK @@ -672,7 +673,7 @@ class EliteBankFragment : Fragment(), EliteBankAdapter.OnAmiiboClickListener { ).putExtra(NFCIntent.EXTRA_TAG_DATA, tagData)) } else { status = CLICKED.EDIT_DATA - scanAmiiboBank(current_bank) + scanAmiiboBank(currentBank) } return@setOnMenuItemClickListener true } @@ -683,7 +684,7 @@ class EliteBankFragment : Fragment(), EliteBankAdapter.OnAmiiboClickListener { ) } else { status = CLICKED.HEX_CODE - scanAmiiboBank(current_bank) + scanAmiiboBank(currentBank) } return@setOnMenuItemClickListener true } @@ -692,7 +693,7 @@ class EliteBankFragment : Fragment(), EliteBankAdapter.OnAmiiboClickListener { displayBackupDialog(tagData) } else { status = CLICKED.BANK_BACKUP - scanAmiiboBank(current_bank) + scanAmiiboBank(currentBank) } return@setOnMenuItemClickListener true } @@ -704,7 +705,7 @@ class EliteBankFragment : Fragment(), EliteBankAdapter.OnAmiiboClickListener { } catch (e: Exception) { notice.Dialog(e.message) } } else { status = CLICKED.VERIFY_TAG - scanAmiiboBank(current_bank) + scanAmiiboBank(currentBank) } return@setOnMenuItemClickListener true } @@ -714,7 +715,7 @@ class EliteBankFragment : Fragment(), EliteBankAdapter.OnAmiiboClickListener { } private fun updateAmiiboView( - amiiboView: View?, tagData: ByteArray?, amiiboId: Long, current_bank: Int + amiiboView: View?, tagData: ByteArray?, amiiboId: Long, currentBank: Int ) { if (null == amiiboView) return val amiiboInfo = requireView().findViewById(R.id.amiiboInfo) @@ -726,7 +727,7 @@ class EliteBankFragment : Fragment(), EliteBankAdapter.OnAmiiboClickListener { val txtAmiiboType = amiiboView.findViewById(R.id.txtAmiiboType) val txtGameSeries = amiiboView.findViewById(R.id.txtGameSeries) val imageAmiibo = amiiboView.findViewById(R.id.imageAmiibo) - if (amiiboView === amiiboCard) getAmiiboToolbar(tagData, current_bank) + if (amiiboView === amiiboCard) getAmiiboToolbar(tagData, currentBank) var tagInfo: String? = null var amiiboHexId: String? = "" var amiiboName = "" @@ -734,7 +735,7 @@ class EliteBankFragment : Fragment(), EliteBankAdapter.OnAmiiboClickListener { var amiiboType = "" var gameSeries = "" var amiiboImageUrl: String? = null - var amiibo = if (amiibos.size > current_bank) amiibos[current_bank] else null + var amiibo = if (amiibos.size > currentBank) amiibos[currentBank] else null val amiiboLongId = when { null != amiibo && amiibo.id > 0L -> { amiibo.id @@ -785,7 +786,7 @@ class EliteBankFragment : Fragment(), EliteBankAdapter.OnAmiiboClickListener { } txtBank?.let { setAmiiboInfoText(it, getString( - R.string.bank_number, eliteBankCount.getValueByPosition(current_bank) + R.string.bank_number, eliteBankCount.getValueByPosition(currentBank) ), hasTagInfo) } setAmiiboInfoText(txtName, amiiboName, hasTagInfo) diff --git a/app/src/main/java/com/hiddenramblings/tagmo/fragment/GattSlotFragment.kt b/app/src/main/java/com/hiddenramblings/tagmo/fragment/GattSlotFragment.kt index 70d75be65..467af13c0 100644 --- a/app/src/main/java/com/hiddenramblings/tagmo/fragment/GattSlotFragment.kt +++ b/app/src/main/java/com/hiddenramblings/tagmo/fragment/GattSlotFragment.kt @@ -55,6 +55,7 @@ import com.hiddenramblings.tagmo.eightbit.widget.ProgressAlert import com.hiddenramblings.tagmo.nfctech.TagArray import com.hiddenramblings.tagmo.nfctech.TagArray.toByteArray import com.hiddenramblings.tagmo.nfctech.TagArray.toHex +import com.hiddenramblings.tagmo.nfctech.TagArray.withRandomSerials import com.hiddenramblings.tagmo.widget.Toasty import com.shawnlin.numberpicker.NumberPicker import kotlinx.coroutines.CoroutineScope @@ -277,7 +278,8 @@ open class GattSlotFragment : Fragment(), GattSlotAdapter.OnAmiiboClickListener, override fun onAmiiboDataClicked(amiiboFile: AmiiboFile?, count: Int) { CoroutineScope(Dispatchers.IO).launch { amiiboFile?.let { - val amiiboData = it.withRandomSerials(keyManager, count) + val amiiboData = TagArray.getValidatedAmiibo(keyManager, it) + .withRandomSerials(count, keyManager) withContext(Dispatchers.Main) { writeAmiiboDataCollection(amiiboData) } diff --git a/app/src/main/java/com/hiddenramblings/tagmo/hexcode/HexCodeViewer.kt b/app/src/main/java/com/hiddenramblings/tagmo/hexcode/HexCodeViewer.kt index 807a34578..f1b79872b 100644 --- a/app/src/main/java/com/hiddenramblings/tagmo/hexcode/HexCodeViewer.kt +++ b/app/src/main/java/com/hiddenramblings/tagmo/hexcode/HexCodeViewer.kt @@ -24,7 +24,6 @@ import com.hiddenramblings.tagmo.R import com.hiddenramblings.tagmo.TagMo import com.hiddenramblings.tagmo.amiibo.Amiibo import com.hiddenramblings.tagmo.amiibo.KeyManager -import com.hiddenramblings.tagmo.amiibo.tagdata.AmiiboData import com.hiddenramblings.tagmo.eightbit.io.Debug import com.hiddenramblings.tagmo.eightbit.os.Storage import com.hiddenramblings.tagmo.eightbit.os.Version diff --git a/app/src/main/java/com/hiddenramblings/tagmo/nfctech/TagArray.kt b/app/src/main/java/com/hiddenramblings/tagmo/nfctech/TagArray.kt index add7e4d48..a92834a83 100644 --- a/app/src/main/java/com/hiddenramblings/tagmo/nfctech/TagArray.kt +++ b/app/src/main/java/com/hiddenramblings/tagmo/nfctech/TagArray.kt @@ -20,9 +20,14 @@ import com.hiddenramblings.tagmo.amiibo.Amiibo import com.hiddenramblings.tagmo.amiibo.AmiiboFile import com.hiddenramblings.tagmo.amiibo.AmiiboManager import com.hiddenramblings.tagmo.amiibo.KeyManager +import com.hiddenramblings.tagmo.amiibo.tagdata.AmiiboData import com.hiddenramblings.tagmo.eightbit.io.Debug import com.hiddenramblings.tagmo.eightbit.os.Storage import com.hiddenramblings.tagmo.eightbit.os.Version +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.async +import kotlinx.coroutines.awaitAll +import kotlinx.coroutines.coroutineScope import java.io.File import java.io.FileOutputStream import java.io.IOException @@ -138,6 +143,24 @@ object TagArray { return pages } + suspend fun ByteArray?.withRandomSerials(count: Int, keyManager: KeyManager? = null) : ArrayList { + val dataList: ArrayList = arrayListOf() + (keyManager?.decrypt(this) ?: this)?.let { tagData -> + coroutineScope { (0 until count).map { async(Dispatchers.IO) { + try { + AmiiboData(tagData).apply { + uID = Foomiibo.generateRandomUID() + }.also { + dataList.add(it) + } + } catch (e: Exception) { + Debug.warn(e) + } + } }.awaitAll() } + } + return dataList + } + fun Long.toByteArray(): ByteArray { return ByteBuffer.allocate( if (Version.isNougat) java.lang.Long.BYTES else 8 @@ -355,8 +378,10 @@ object TagArray { fun writeBytesToDocument( context: Context, directory: DocumentFile, name: String, tagData: ByteArray? ): String? { + // displayName – name of new document, without any file extension appended; the underlying provider may choose to append the extension + // The underlying provider does NOT provide an extension, therefore one IS appended val newFile = directory.createFile( - context.resources.getStringArray(R.array.mimetype_bin)[0], name + context.resources.getStringArray(R.array.mimetype_bin)[0], "$name.bin" ) newFile?.let { file -> context.contentResolver.openOutputStream(file.uri).use { it?.write(tagData) }