diff --git a/Assets/dll/librcheevos.dll b/Assets/dll/librcheevos.dll index 106c20eb85..929e302110 100644 Binary files a/Assets/dll/librcheevos.dll and b/Assets/dll/librcheevos.dll differ diff --git a/Assets/dll/librcheevos.so b/Assets/dll/librcheevos.so index 863434025b..5630e7e983 100644 Binary files a/Assets/dll/librcheevos.so and b/Assets/dll/librcheevos.so differ diff --git a/ExternalProjects/librcheevos/rcheevos b/ExternalProjects/librcheevos/rcheevos index c5304a61bc..b91d539638 160000 --- a/ExternalProjects/librcheevos/rcheevos +++ b/ExternalProjects/librcheevos/rcheevos @@ -1 +1 @@ -Subproject commit c5304a61bcf256ae80fcd1c8f64ad9646aaea757 +Subproject commit b91d539638f08c7810094e9ed8aafffd72a7af26 diff --git a/src/BizHawk.Client.EmuHawk/RetroAchievements/LibRCheevos.cs b/src/BizHawk.Client.EmuHawk/RetroAchievements/LibRCheevos.cs index 2162748881..b0bec8c3a4 100644 --- a/src/BizHawk.Client.EmuHawk/RetroAchievements/LibRCheevos.cs +++ b/src/BizHawk.Client.EmuHawk/RetroAchievements/LibRCheevos.cs @@ -79,22 +79,6 @@ namespace BizHawk.Client.EmuHawk RC_ACHIEVEMENT_CATEGORY_UNOFFICIAL = 5, } - [StructLayout(LayoutKind.Sequential)] - public struct rc_runtime_t - { - public IntPtr triggers; - public int trigger_count; - public int trigger_capacity; - public IntPtr lboards; - public int lboard_count; - public int lboard_capacity; - public IntPtr richpresence; - public IntPtr memrefs; - public IntPtr next_memref; - public IntPtr variables; - public IntPtr next_variable; - } - [StructLayout(LayoutKind.Sequential)] public struct rc_runtime_event_t { @@ -538,65 +522,68 @@ namespace BizHawk.Client.EmuHawk public abstract IntPtr rc_error_str(rc_error_t error_code); [BizImport(cc)] - public abstract void rc_runtime_init(ref rc_runtime_t runtime); + public abstract IntPtr rc_runtime_alloc(); [BizImport(cc)] - public abstract void rc_runtime_destroy(ref rc_runtime_t runtime); + public abstract void rc_runtime_init(IntPtr runtime); [BizImport(cc)] - public abstract void rc_runtime_reset(ref rc_runtime_t runtime); + public abstract void rc_runtime_destroy(IntPtr runtime); [BizImport(cc)] - public abstract void rc_runtime_do_frame(ref rc_runtime_t runtime, rc_runtime_event_handler_t rc_runtime_event_handler_t, rc_peek_t peek, IntPtr ud, IntPtr unused); + public abstract void rc_runtime_reset(IntPtr runtime); [BizImport(cc)] - public abstract rc_error_t rc_runtime_progress_size(ref rc_runtime_t runtime, IntPtr unused); + public abstract void rc_runtime_do_frame(IntPtr runtime, rc_runtime_event_handler_t rc_runtime_event_handler_t, rc_peek_t peek, IntPtr ud, IntPtr unused); [BizImport(cc)] - public abstract void rc_runtime_serialize_progress(byte[] buffer, ref rc_runtime_t runtime, IntPtr unused); + public abstract rc_error_t rc_runtime_progress_size(IntPtr runtime, IntPtr unused); [BizImport(cc)] - public abstract rc_error_t rc_runtime_deserialize_progress(ref rc_runtime_t runtime, byte[] serialized, IntPtr unused); + public abstract void rc_runtime_serialize_progress(byte[] buffer, IntPtr runtime, IntPtr unused); [BizImport(cc)] - public abstract void rc_runtime_invalidate_address(ref rc_runtime_t runtime, int address); + public abstract rc_error_t rc_runtime_deserialize_progress(IntPtr runtime, byte[] serialized, IntPtr unused); [BizImport(cc)] - public abstract void rc_runtime_validate_addresses(ref rc_runtime_t runtime, rc_runtime_event_handler_t event_handler, rc_runtime_validate_address_t validate_handler); + public abstract void rc_runtime_invalidate_address(IntPtr runtime, int address); [BizImport(cc)] - public abstract rc_error_t rc_runtime_activate_achievement(ref rc_runtime_t runtime, int id, string memaddr, IntPtr unused, int unused_idx); + public abstract void rc_runtime_validate_addresses(IntPtr runtime, rc_runtime_event_handler_t event_handler, rc_runtime_validate_address_t validate_handler); [BizImport(cc)] - public abstract rc_error_t rc_runtime_activate_lboard(ref rc_runtime_t runtime, int id, string memaddr, IntPtr unused, int unused_idx); + public abstract rc_error_t rc_runtime_activate_achievement(IntPtr runtime, int id, string memaddr, IntPtr unused, int unused_idx); [BizImport(cc)] - public abstract rc_error_t rc_runtime_activate_richpresence(ref rc_runtime_t runtime, string script, IntPtr unused, int unused_idx); + public abstract rc_error_t rc_runtime_activate_lboard(IntPtr runtime, int id, string memaddr, IntPtr unused, int unused_idx); [BizImport(cc)] - public abstract IntPtr rc_runtime_get_achievement(ref rc_runtime_t runtime, int id); + public abstract rc_error_t rc_runtime_activate_richpresence(IntPtr runtime, string script, IntPtr unused, int unused_idx); [BizImport(cc)] - public abstract IntPtr rc_runtime_get_lboard(ref rc_runtime_t runtime, int id); + public abstract IntPtr rc_runtime_get_achievement(IntPtr runtime, int id); [BizImport(cc)] - public abstract int rc_runtime_get_richpresence(ref rc_runtime_t runtime, byte[] buffer, int buffersize, rc_peek_t peek, IntPtr ud, IntPtr unused); + public abstract IntPtr rc_runtime_get_lboard(IntPtr runtime, int id); + + [BizImport(cc)] + public abstract int rc_runtime_get_richpresence(IntPtr runtime, byte[] buffer, int buffersize, rc_peek_t peek, IntPtr ud, IntPtr unused); [BizImport(cc)] [return: MarshalAs(UnmanagedType.Bool)] - public abstract bool rc_runtime_get_achievement_measured(ref rc_runtime_t runtime, int id, out int measured_value, out int measured_target); + public abstract bool rc_runtime_get_achievement_measured(IntPtr runtime, int id, out int measured_value, out int measured_target); [BizImport(cc)] - public abstract int rc_runtime_format_achievement_measured(ref rc_runtime_t runtime, int id, byte[] buffer, long buffer_size); + public abstract int rc_runtime_format_achievement_measured(IntPtr runtime, int id, byte[] buffer, long buffer_size); [BizImport(cc)] public abstract int rc_runtime_format_lboard_value(byte[] buffer, int size, int value, int format); [BizImport(cc)] - public abstract void rc_runtime_deactivate_achievement(ref rc_runtime_t runtime, int id); + public abstract void rc_runtime_deactivate_achievement(IntPtr runtime, int id); [BizImport(cc)] - public abstract void rc_runtime_deactivate_lboard(ref rc_runtime_t runtime, int id); + public abstract void rc_runtime_deactivate_lboard(IntPtr runtime, int id); [BizImport(cc)] public abstract void rc_hash_init_error_message_callback(rc_hash_message_callback callback); diff --git a/src/BizHawk.Client.EmuHawk/RetroAchievements/RCheevos.Achievements.cs b/src/BizHawk.Client.EmuHawk/RetroAchievements/RCheevos.Achievements.cs index 50943ce4fd..0539e2fdc7 100644 --- a/src/BizHawk.Client.EmuHawk/RetroAchievements/RCheevos.Achievements.cs +++ b/src/BizHawk.Client.EmuHawk/RetroAchievements/RCheevos.Achievements.cs @@ -131,7 +131,7 @@ namespace BizHawk.Client.EmuHawk private string GetCheevoProgress(int id) { - var len = _lib.rc_runtime_format_achievement_measured(ref _runtime, id, _cheevoFormatBuffer, _cheevoFormatBuffer.Length); + var len = _lib.rc_runtime_format_achievement_measured(_runtime, id, _cheevoFormatBuffer, _cheevoFormatBuffer.Length); return Encoding.ASCII.GetString(_cheevoFormatBuffer, 0, len); } @@ -176,7 +176,7 @@ namespace BizHawk.Client.EmuHawk { if (cheevo.IsEnabled && !cheevo.IsUnlocked(hardcore)) { - _lib.rc_runtime_deactivate_achievement(ref _runtime, cheevo.ID); + _lib.rc_runtime_deactivate_achievement(_runtime, cheevo.ID); } } } @@ -189,7 +189,7 @@ namespace BizHawk.Client.EmuHawk { if (cheevo.IsEnabled && !cheevo.IsUnlocked(hardcore)) { - _lib.rc_runtime_activate_achievement(ref _runtime, cheevo.ID, cheevo.Definition, IntPtr.Zero, 0); + _lib.rc_runtime_activate_achievement(_runtime, cheevo.ID, cheevo.Definition, IntPtr.Zero, 0); } } @@ -198,7 +198,7 @@ namespace BizHawk.Client.EmuHawk private void OneShotActivateActiveModeCheevos() { - if (_activeModeCheevosOnceActivated) return; + if (_activeModeCheevosOnceActivated || _gameData.GameID == 0) return; _activeModeUnlocksRequest.Wait(); ActivateCheevos(HardcoreMode); } diff --git a/src/BizHawk.Client.EmuHawk/RetroAchievements/RCheevos.GameInfo.cs b/src/BizHawk.Client.EmuHawk/RetroAchievements/RCheevos.GameInfo.cs index f495d85e00..c2761874d6 100644 --- a/src/BizHawk.Client.EmuHawk/RetroAchievements/RCheevos.GameInfo.cs +++ b/src/BizHawk.Client.EmuHawk/RetroAchievements/RCheevos.GameInfo.cs @@ -307,12 +307,12 @@ namespace BizHawk.Client.EmuHawk foreach (var lboard in _gameData.LBoardEnumerable) { - _lib.rc_runtime_activate_lboard(ref _runtime, lboard.ID, lboard.Definition, IntPtr.Zero, 0); + _lib.rc_runtime_activate_lboard(_runtime, lboard.ID, lboard.Definition, IntPtr.Zero, 0); } if (_gameData.RichPresenseScript is not null) { - _lib.rc_runtime_activate_richpresence(ref _runtime, _gameData.RichPresenseScript, IntPtr.Zero, 0); + _lib.rc_runtime_activate_richpresence(_runtime, _gameData.RichPresenseScript, IntPtr.Zero, 0); } } diff --git a/src/BizHawk.Client.EmuHawk/RetroAchievements/RCheevos.Http.cs b/src/BizHawk.Client.EmuHawk/RetroAchievements/RCheevos.Http.cs index 8093dd60de..c6529d49f9 100644 --- a/src/BizHawk.Client.EmuHawk/RetroAchievements/RCheevos.Http.cs +++ b/src/BizHawk.Client.EmuHawk/RetroAchievements/RCheevos.Http.cs @@ -110,7 +110,6 @@ namespace BizHawk.Client.EmuHawk var apiTask = request.post_data != IntPtr.Zero ? HttpPost(request.URL, request.PostData) : HttpGet(request.URL); - apiTask.ConfigureAwait(false); apiTask.ContinueWith(async t => { @@ -126,7 +125,7 @@ namespace BizHawk.Client.EmuHawk ShouldRetry = false; // this is a bit naive, but if the response callback "fails," retrying will just result in the same thing _completionEvent.Set(); } - }); + }, default, TaskContinuationOptions.ExecuteSynchronously | TaskContinuationOptions.DenyChildAttach, TaskScheduler.Default); _lib.rc_api_destroy_request(ref request); } diff --git a/src/BizHawk.Client.EmuHawk/RetroAchievements/RCheevos.Ping.cs b/src/BizHawk.Client.EmuHawk/RetroAchievements/RCheevos.Ping.cs index 72f0d1e957..0d741b6603 100644 --- a/src/BizHawk.Client.EmuHawk/RetroAchievements/RCheevos.Ping.cs +++ b/src/BizHawk.Client.EmuHawk/RetroAchievements/RCheevos.Ping.cs @@ -79,7 +79,7 @@ namespace BizHawk.Client.EmuHawk { if (RichPresenceActive) { - var len = _lib.rc_runtime_get_richpresence(ref _runtime, _richPresenceBuffer, _richPresenceBuffer.Length, _peekcb, IntPtr.Zero, IntPtr.Zero); + var len = _lib.rc_runtime_get_richpresence(_runtime, _richPresenceBuffer, _richPresenceBuffer.Length, _peekcb, IntPtr.Zero, IntPtr.Zero); CurrentRichPresence = Encoding.UTF8.GetString(_richPresenceBuffer, 0, len); } else diff --git a/src/BizHawk.Client.EmuHawk/RetroAchievements/RCheevos.cs b/src/BizHawk.Client.EmuHawk/RetroAchievements/RCheevos.cs index 5676a3b32d..bd5442ef1e 100644 --- a/src/BizHawk.Client.EmuHawk/RetroAchievements/RCheevos.cs +++ b/src/BizHawk.Client.EmuHawk/RetroAchievements/RCheevos.cs @@ -24,7 +24,7 @@ namespace BizHawk.Client.EmuHawk _lib = BizInvoker.GetInvoker(resolver, CallingConventionAdapters.Native); } - private LibRCheevos.rc_runtime_t _runtime; + private IntPtr _runtime; private readonly LibRCheevos.rc_runtime_event_handler_t _eventcb; private readonly LibRCheevos.rc_peek_t _peekcb; @@ -200,8 +200,11 @@ namespace BizHawk.Client.EmuHawk _httpThread = new(HttpRequestThreadProc) { IsBackground = true, Priority = ThreadPriority.BelowNormal }; _httpThread.Start(); - _runtime = default; - _lib.rc_runtime_init(ref _runtime); + _runtime = _lib.rc_runtime_alloc(); + if (_runtime == IntPtr.Zero) + { + throw new("rc_runtime_alloc returned NULL!"); + } Login(); _eventcb = EventHandlerCallback; @@ -228,7 +231,8 @@ namespace BizHawk.Client.EmuHawk _isActive = false; _httpThread.Join(); - _lib.rc_runtime_destroy(ref _runtime); + _lib.rc_runtime_destroy(_runtime); + _runtime = IntPtr.Zero; Stop(); _gameInfoForm.Dispose(); _cheevoListForm.Dispose(); @@ -247,11 +251,11 @@ namespace BizHawk.Client.EmuHawk OneShotActivateActiveModeCheevos(); - var size = _lib.rc_runtime_progress_size(ref _runtime, IntPtr.Zero); + var size = _lib.rc_runtime_progress_size(_runtime, IntPtr.Zero); if (size > 0) { var buffer = new byte[(int)size]; - _lib.rc_runtime_serialize_progress(buffer, ref _runtime, IntPtr.Zero); + _lib.rc_runtime_serialize_progress(buffer, _runtime, IntPtr.Zero); using var file = File.OpenWrite(path + ".rap"); file.Write(buffer, 0, buffer.Length); } @@ -271,13 +275,13 @@ namespace BizHawk.Client.EmuHawk OneShotActivateActiveModeCheevos(); - _lib.rc_runtime_reset(ref _runtime); + _lib.rc_runtime_reset(_runtime); if (!File.Exists(path + ".rap")) return; using var file = File.OpenRead(path + ".rap"); var buffer = file.ReadAllBytes(); - _lib.rc_runtime_deserialize_progress(ref _runtime, buffer, IntPtr.Zero); + _lib.rc_runtime_deserialize_progress(_runtime, buffer, IntPtr.Zero); } private void QuickLoadCallback(object _, BeforeQuickLoadEventArgs e) @@ -326,9 +330,12 @@ namespace BizHawk.Client.EmuHawk } // reinit the runtime - _lib.rc_runtime_destroy(ref _runtime); - _runtime = default; - _lib.rc_runtime_init(ref _runtime); + _lib.rc_runtime_destroy(_runtime); + _runtime = _lib.rc_runtime_alloc(); + if (_runtime == IntPtr.Zero) + { + throw new("rc_runtime_alloc returned NULL!"); + } // get console id _consoleId = SystemIdToConsoleId(); @@ -399,7 +406,7 @@ namespace BizHawk.Client.EmuHawk // validate addresses now that we have cheevos init // ReSharper disable once ConvertToLocalFunction LibRCheevos.rc_runtime_validate_address_t peekcb = address => _readMap.ContainsKey(address); - _lib.rc_runtime_validate_addresses(ref _runtime, _eventcb, peekcb); + _lib.rc_runtime_validate_addresses(_runtime, _eventcb, peekcb); _gameInfoForm.Restart(_gameData.Title, _gameData.TotalCheevoPoints(HardcoreMode), CurrentRichPresence ?? "N/A"); _cheevoListForm.Restart(_gameData.GameID == 0 ? Array.Empty() : _gameData.CheevoEnumerable, GetCheevoProgress); @@ -443,7 +450,7 @@ namespace BizHawk.Client.EmuHawk var cheevo = _gameData.GetCheevoById(evt->id); if (cheevo.IsEnabled) { - _lib.rc_runtime_deactivate_achievement(ref _runtime, evt->id); + _lib.rc_runtime_deactivate_achievement(_runtime, evt->id); cheevo.SetUnlocked(HardcoreMode, true); var prefix = HardcoreMode ? "[HARDCORE] " : ""; @@ -610,7 +617,7 @@ namespace BizHawk.Client.EmuHawk var input = _inputManager.ControllerOutput; if (input.Definition.BoolButtons.Any(b => (b.Contains("Power") || b.Contains("Reset")) && input.IsPressed(b))) { - _lib.rc_runtime_reset(ref _runtime); + _lib.rc_runtime_reset(_runtime); } if (Emu.HasMemoryDomains()) @@ -618,12 +625,12 @@ namespace BizHawk.Client.EmuHawk // we want to EnterExit to prevent wbx host spam when peeks are spammed using (Domains.MainMemory.EnterExit()) { - _lib.rc_runtime_do_frame(ref _runtime, _eventcb, _peekcb, IntPtr.Zero, IntPtr.Zero); + _lib.rc_runtime_do_frame(_runtime, _eventcb, _peekcb, IntPtr.Zero, IntPtr.Zero); } } else { - _lib.rc_runtime_do_frame(ref _runtime, _eventcb, _peekcb, IntPtr.Zero, IntPtr.Zero); + _lib.rc_runtime_do_frame(_runtime, _eventcb, _peekcb, IntPtr.Zero, IntPtr.Zero); } if (_gameInfoForm.IsShown)