1use crate::{
2 exports::raw::{
3 Export0, Export3, Export5, Export6, Export7, Export8, Export9, Export10,
4 ExportAddExtension, ExportFreeExtension, ExportListExtension,
5 },
6 util::{exported_proc, str_from_cstr},
7};
8use std::{ffi::c_char, mem::transmute, sync::OnceLock};
9use windows::Win32::Foundation::HMODULE;
10
11#[inline]
13pub unsafe fn init_arc(arc_handle: HMODULE, version: *const c_char) {
14 unsafe { ArcGlobals::init(arc_handle, str_from_cstr(version)) };
15}
16
17static ARC_GLOBALS: OnceLock<ArcGlobals> = OnceLock::new();
19
20#[derive(Debug)]
23pub struct ArcGlobals {
24 pub handle: HMODULE,
26
27 pub version: Option<&'static str>,
29
30 pub e0: Option<Export0>,
32
33 pub e3: Option<Export3>,
35
36 pub e5: Option<Export5>,
38
39 pub e6: Option<Export6>,
41
42 pub e7: Option<Export7>,
44
45 pub e8: Option<Export8>,
47
48 pub e9: Option<Export9>,
50
51 pub e10: Option<Export10>,
53
54 pub add_extension: Option<ExportAddExtension>,
56
57 pub free_extension: Option<ExportFreeExtension>,
59
60 pub list_extension: Option<ExportListExtension>,
62}
63
64impl ArcGlobals {
65 pub unsafe fn new(handle: HMODULE, version: Option<&'static str>) -> Self {
67 #![allow(clippy::missing_transmute_annotations)]
68 unsafe {
69 Self {
70 handle,
71 version,
72 e0: transmute(exported_proc(handle, "e0\0")),
73 e3: transmute(exported_proc(handle, "e3\0")),
74 e5: transmute(exported_proc(handle, "e5\0")),
75 e6: transmute(exported_proc(handle, "e6\0")),
76 e7: transmute(exported_proc(handle, "e7\0")),
77 e8: transmute(exported_proc(handle, "e8\0")),
78 e9: transmute(exported_proc(handle, "e9\0")),
79 e10: transmute(exported_proc(handle, "e10\0")),
80 add_extension: transmute(exported_proc(handle, "addextension2\0")),
81 free_extension: transmute(exported_proc(handle, "freeextension2\0")),
82 list_extension: transmute(exported_proc(handle, "listextension\0")),
83 }
84 }
85 }
86
87 pub unsafe fn init(handle: HMODULE, version: Option<&'static str>) -> &'static Self {
89 ARC_GLOBALS.get_or_init(|| unsafe { Self::new(handle, version) })
90 }
91
92 #[inline]
94 pub fn get() -> &'static Self {
95 Self::try_get().expect("arcdps globals not initialized")
96 }
97
98 #[inline]
100 pub fn try_get() -> Option<&'static Self> {
101 ARC_GLOBALS.get()
102 }
103}
104
105unsafe impl Send for ArcGlobals {}
106
107unsafe impl Sync for ArcGlobals {}