ARCheat.cpp 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176
  1. // Copyright 2021 Dolphin Emulator Project
  2. // SPDX-License-Identifier: GPL-2.0-or-later
  3. #include <string>
  4. #include <vector>
  5. #include <jni.h>
  6. #include "Common/FileUtil.h"
  7. #include "Common/IniFile.h"
  8. #include "Common/StringUtil.h"
  9. #include "Core/ARDecrypt.h"
  10. #include "Core/ActionReplay.h"
  11. #include "Core/ConfigManager.h"
  12. #include "jni/AndroidCommon/AndroidCommon.h"
  13. #include "jni/AndroidCommon/IDCache.h"
  14. #include "jni/Cheats/Cheats.h"
  15. static ActionReplay::ARCode* GetPointer(JNIEnv* env, jobject obj)
  16. {
  17. return reinterpret_cast<ActionReplay::ARCode*>(
  18. env->GetLongField(obj, IDCache::GetARCheatPointer()));
  19. }
  20. jobject ARCheatToJava(JNIEnv* env, const ActionReplay::ARCode& code)
  21. {
  22. return env->NewObject(IDCache::GetARCheatClass(), IDCache::GetARCheatConstructor(),
  23. reinterpret_cast<jlong>(new ActionReplay::ARCode(code)));
  24. }
  25. extern "C" {
  26. JNIEXPORT void JNICALL
  27. Java_org_dolphinemu_dolphinemu_features_cheats_model_ARCheat_finalize(JNIEnv* env, jobject obj)
  28. {
  29. delete GetPointer(env, obj);
  30. }
  31. JNIEXPORT jlong JNICALL
  32. Java_org_dolphinemu_dolphinemu_features_cheats_model_ARCheat_createNew(JNIEnv* env, jobject obj)
  33. {
  34. auto* code = new ActionReplay::ARCode;
  35. code->user_defined = true;
  36. return reinterpret_cast<jlong>(code);
  37. }
  38. JNIEXPORT jstring JNICALL
  39. Java_org_dolphinemu_dolphinemu_features_cheats_model_ARCheat_getName(JNIEnv* env, jobject obj)
  40. {
  41. return ToJString(env, GetPointer(env, obj)->name);
  42. }
  43. JNIEXPORT jstring JNICALL
  44. Java_org_dolphinemu_dolphinemu_features_cheats_model_ARCheat_getCode(JNIEnv* env, jobject obj)
  45. {
  46. ActionReplay::ARCode* code = GetPointer(env, obj);
  47. std::string code_string;
  48. for (size_t i = 0; i < code->ops.size(); ++i)
  49. {
  50. if (i != 0)
  51. code_string += '\n';
  52. code_string += ActionReplay::SerializeLine(code->ops[i]);
  53. }
  54. return ToJString(env, code_string);
  55. }
  56. JNIEXPORT jboolean JNICALL
  57. Java_org_dolphinemu_dolphinemu_features_cheats_model_ARCheat_getUserDefined(JNIEnv* env,
  58. jobject obj)
  59. {
  60. return static_cast<jboolean>(GetPointer(env, obj)->user_defined);
  61. }
  62. JNIEXPORT jboolean JNICALL
  63. Java_org_dolphinemu_dolphinemu_features_cheats_model_ARCheat_getEnabled(JNIEnv* env, jobject obj)
  64. {
  65. return static_cast<jboolean>(GetPointer(env, obj)->enabled);
  66. }
  67. JNIEXPORT jint JNICALL Java_org_dolphinemu_dolphinemu_features_cheats_model_ARCheat_setCheatImpl(
  68. JNIEnv* env, jobject obj, jstring name, jstring creator, jstring notes, jstring code_string)
  69. {
  70. ActionReplay::ARCode* code = GetPointer(env, obj);
  71. std::vector<ActionReplay::AREntry> entries;
  72. std::vector<std::string> encrypted_lines;
  73. std::vector<std::string> lines = SplitString(GetJString(env, code_string), '\n');
  74. for (size_t i = 0; i < lines.size(); i++)
  75. {
  76. const std::string& line = lines[i];
  77. if (line.empty())
  78. continue;
  79. auto parse_result = ActionReplay::DeserializeLine(line);
  80. if (std::holds_alternative<ActionReplay::AREntry>(parse_result))
  81. entries.emplace_back(std::get<ActionReplay::AREntry>(std::move(parse_result)));
  82. else if (std::holds_alternative<ActionReplay::EncryptedLine>(parse_result))
  83. encrypted_lines.emplace_back(std::get<ActionReplay::EncryptedLine>(std::move(parse_result)));
  84. else
  85. return i + 1; // Parse error on line i
  86. }
  87. if (!encrypted_lines.empty())
  88. {
  89. if (!entries.empty())
  90. return Cheats::TRY_SET_FAIL_CODE_MIXED_ENCRYPTION;
  91. ActionReplay::DecryptARCode(encrypted_lines, &entries);
  92. }
  93. if (entries.empty())
  94. return Cheats::TRY_SET_FAIL_NO_CODE_LINES;
  95. code->name = GetJString(env, name);
  96. code->ops = std::move(entries);
  97. return Cheats::TRY_SET_SUCCESS;
  98. }
  99. JNIEXPORT void JNICALL Java_org_dolphinemu_dolphinemu_features_cheats_model_ARCheat_setEnabledImpl(
  100. JNIEnv* env, jobject obj, jboolean enabled)
  101. {
  102. GetPointer(env, obj)->enabled = static_cast<bool>(enabled);
  103. }
  104. JNIEXPORT jobjectArray JNICALL
  105. Java_org_dolphinemu_dolphinemu_features_cheats_model_ARCheat_loadCodes(JNIEnv* env, jclass,
  106. jstring jGameID,
  107. jint revision)
  108. {
  109. const std::string game_id = GetJString(env, jGameID);
  110. Common::IniFile game_ini_local;
  111. // We don't use LoadLocalGameIni() here because user cheat codes that are installed via the UI
  112. // will always be stored in GS/${GAMEID}.ini
  113. game_ini_local.Load(File::GetUserPath(D_GAMESETTINGS_IDX) + game_id + ".ini");
  114. const Common::IniFile game_ini_default = SConfig::LoadDefaultGameIni(game_id, revision);
  115. const std::vector<ActionReplay::ARCode> codes =
  116. ActionReplay::LoadCodes(game_ini_default, game_ini_local);
  117. return VectorToJObjectArray(env, codes, IDCache::GetARCheatClass(), ARCheatToJava);
  118. }
  119. JNIEXPORT void JNICALL Java_org_dolphinemu_dolphinemu_features_cheats_model_ARCheat_saveCodes(
  120. JNIEnv* env, jclass, jstring jGameID, jint revision, jobjectArray jCodes)
  121. {
  122. const jsize size = env->GetArrayLength(jCodes);
  123. std::vector<ActionReplay::ARCode> vector;
  124. vector.reserve(size);
  125. for (jsize i = 0; i < size; ++i)
  126. {
  127. jobject code = reinterpret_cast<jstring>(env->GetObjectArrayElement(jCodes, i));
  128. vector.emplace_back(*GetPointer(env, code));
  129. env->DeleteLocalRef(code);
  130. }
  131. const std::string game_id = GetJString(env, jGameID);
  132. const std::string ini_path = File::GetUserPath(D_GAMESETTINGS_IDX) + game_id + ".ini";
  133. Common::IniFile game_ini_local;
  134. game_ini_local.Load(ini_path);
  135. ActionReplay::SaveCodes(&game_ini_local, vector);
  136. game_ini_local.Save(ini_path);
  137. }
  138. }