brres_sys/
ffi.rs

1use anyhow::bail;
2use std::ffi::c_void;
3use std::ffi::CString;
4use std::ptr;
5
6#[allow(non_upper_case_globals)]
7#[allow(non_camel_case_types)]
8#[allow(non_snake_case)]
9pub mod bindings {
10    use std::os::raw::c_void;
11
12    #[repr(C)]
13    pub struct CBrres {
14        pub json_metadata: *const u8,
15        pub len_json_metadata: u32,
16        pub buffer_data: *const u8,
17        pub len_buffer_data: u32,
18        pub freeResult: extern "C" fn(*mut CBrres),
19        pub opaque: *mut c_void,
20    }
21
22    extern "C" {
23        pub fn imp_brres_read_from_bytes(result: *mut CBrres, buf: *const u8, len: u32) -> u32;
24        pub fn imp_brres_write_bytes(
25            result: *mut CBrres,
26            json: *const i8,
27            json_len: u32,
28            buffer: *const c_void,
29            buffer_len: u32,
30            write_type: u32,
31        ) -> u32;
32        pub fn imp_brres_free(result: *mut CBrres);
33
34        pub fn imp_brres_read_mdl0mat_preset(
35            result: *mut CBrres,
36            path: *const i8,
37            path_len: u32,
38        ) -> u32;
39    }
40}
41
42pub struct CBrresWrapper<'a> {
43    pub json_metadata: &'a str,
44    pub buffer_data: &'a [u8],
45    result: Box<bindings::CBrres>,
46}
47
48impl<'a> CBrresWrapper<'a> {
49    pub fn default() -> bindings::CBrres {
50        bindings::CBrres {
51            json_metadata: ptr::null(),
52            len_json_metadata: 0,
53            buffer_data: ptr::null(),
54            len_buffer_data: 0,
55            freeResult: dummy_free_result,
56            opaque: ptr::null_mut(),
57        }
58    }
59
60    pub fn from_bytes(buf: &[u8]) -> anyhow::Result<Self> {
61        unsafe {
62            let mut result: Box<bindings::CBrres> = Box::new(Self::default());
63
64            let ok = bindings::imp_brres_read_from_bytes(
65                &mut *result as *mut bindings::CBrres,
66                buf.as_ptr(),
67                buf.len() as u32,
68            );
69
70            let json_metadata = {
71                let slice = std::slice::from_raw_parts(
72                    result.json_metadata,
73                    result.len_json_metadata as usize,
74                );
75                std::str::from_utf8(slice).unwrap()
76            };
77
78            if ok == 0 {
79                bail!("Failed to read BRRES file: {json_metadata}");
80            }
81
82            let buffer_data =
83                std::slice::from_raw_parts(result.buffer_data, result.len_buffer_data as usize);
84
85            Ok(CBrresWrapper {
86                json_metadata,
87                buffer_data,
88                result,
89            })
90        }
91    }
92    pub fn write_bytes(json: &str, buffer: &[u8]) -> anyhow::Result<Self> {
93        let json_cstring = CString::new(json)?;
94        let json_ptr = json_cstring.as_ptr();
95        let json_len = json.len() as u32;
96        let buffer_ptr = buffer.as_ptr() as *const c_void;
97        let buffer_len = buffer.len() as u32;
98
99        unsafe {
100            let mut result: Box<bindings::CBrres> = Box::new(Self::default());
101
102            let ok = bindings::imp_brres_write_bytes(
103                &mut *result as *mut bindings::CBrres,
104                json_ptr,
105                json_len,
106                buffer_ptr,
107                buffer_len,
108                0, // write_type
109            );
110
111            let json_metadata = {
112                let slice = std::slice::from_raw_parts(
113                    result.json_metadata,
114                    result.len_json_metadata as usize,
115                );
116                std::str::from_utf8(slice)?
117            };
118
119            if ok == 0 {
120                anyhow::bail!("Failed to write BRRES file: {json_metadata}");
121            }
122            let buffer_data =
123                std::slice::from_raw_parts(result.buffer_data, result.len_buffer_data as usize);
124
125            Ok(CBrresWrapper {
126                json_metadata,
127                buffer_data,
128                result,
129            })
130        }
131    }
132    pub fn read_preset_folder(json: &str) -> anyhow::Result<Self> {
133        let json_cstring = CString::new(json)?;
134        let json_ptr = json_cstring.as_ptr();
135        let json_len = json.len() as u32;
136
137        unsafe {
138            let mut result: Box<bindings::CBrres> = Box::new(Self::default());
139
140            let ok = bindings::imp_brres_read_mdl0mat_preset(
141                &mut *result as *mut bindings::CBrres,
142                json_ptr,
143                json_len,
144            );
145
146            if ok == 0 {
147                let json_metadata = {
148                    let slice = std::slice::from_raw_parts(
149                        result.json_metadata,
150                        result.len_json_metadata as usize,
151                    );
152                    std::str::from_utf8(slice)?
153                };
154                anyhow::bail!("Failed to write BRRES file: {json_metadata}");
155            }
156            let buffer_data =
157                std::slice::from_raw_parts(result.buffer_data, result.len_buffer_data as usize);
158
159            Ok(CBrresWrapper {
160                json_metadata: "",
161                buffer_data,
162                result,
163            })
164        }
165    }
166}
167
168impl<'a> Drop for CBrresWrapper<'a> {
169    fn drop(&mut self) {
170        // unsafe {
171        (self.result.freeResult)(&mut *self.result as *mut bindings::CBrres);
172        // }
173    }
174}
175
176extern "C" fn dummy_free_result(_: *mut bindings::CBrres) {
177    // This is a dummy function to avoid calling a null function pointer.
178}
179
180// Reentrant Rust (this crate) -> C++ -> Rust (other crate)
181pub mod c_api {
182    use crate::*;
183    use core::ffi::c_char;
184    use gctex;
185    use wiitrig;
186
187    // use simple_logger::SimpleLogger;
188
189    // use log::*;
190
191    #[no_mangle]
192    pub unsafe extern "C" fn rii_compute_image_size2(format: u32, width: u32, height: u32) -> u32 {
193        gctex::c_api::rii_compute_image_size(format, width, height)
194    }
195
196    #[no_mangle]
197    pub unsafe extern "C" fn rsl_log_init2() {
198        // SimpleLogger::new().init().unwrap();
199    }
200
201    #[no_mangle]
202    pub unsafe extern "C" fn rsl_c_debug2(_s: *const c_char, _len: u32) {
203        // // TODO: Use len
204        // let st = String::from_utf8_lossy(CStr::from_ptr(s).to_bytes());
205        // debug!("{}", &st);
206    }
207    #[no_mangle]
208    pub unsafe extern "C" fn rsl_c_error2(_s: *const c_char, _len: u32) {
209        // // TODO: Use len
210        // let st = String::from_utf8_lossy(CStr::from_ptr(s).to_bytes());
211        // error!("{}", &st);
212    }
213    #[no_mangle]
214    pub unsafe extern "C" fn rsl_c_info2(_s: *const c_char, _len: u32) {
215        // // TODO: Use len
216        // let st = String::from_utf8_lossy(CStr::from_ptr(s).to_bytes());
217        // info!("{}", &st);
218    }
219    #[no_mangle]
220    pub unsafe extern "C" fn rsl_c_trace2(_s: *const c_char, _len: u32) {
221        // // TODO: Use len
222        // let st = String::from_utf8_lossy(CStr::from_ptr(s).to_bytes());
223        // trace!("{}", &st);
224    }
225    #[no_mangle]
226    pub unsafe extern "C" fn rsl_c_warn2(_s: *const c_char, _len: u32) {
227        // // TODO: Use len
228        // let st = String::from_utf8_lossy(CStr::from_ptr(s).to_bytes());
229        // warn!("{}", &st);
230    }
231
232    #[no_mangle]
233    pub unsafe extern "C" fn wii_sin2(x: f32) -> f32 {
234        wiitrig::wii_sin(x)
235    }
236
237    #[no_mangle]
238    pub unsafe extern "C" fn wii_cos2(x: f32) -> f32 {
239        wiitrig::wii_cos(x)
240    }
241
242    use core::ffi::c_void;
243
244    #[cfg(feature = "c_api")]
245    #[no_mangle]
246    pub unsafe fn brres_read_from_bytes(
247        result: *mut ffi::bindings::CBrres,
248        buf: *const u8,
249        len: u32,
250    ) -> u32 {
251        ffi::bindings::imp_brres_read_from_bytes(result, buf, len)
252    }
253    #[cfg(feature = "c_api")]
254    #[no_mangle]
255    pub unsafe fn brres_write_bytes(
256        result: *mut ffi::bindings::CBrres,
257        json: *const i8,
258        json_len: u32,
259        buffer: *const c_void,
260        buffer_len: u32,
261        write_type: u32,
262    ) -> u32 {
263        ffi::bindings::imp_brres_write_bytes(result, json, json_len, buffer, buffer_len, write_type)
264    }
265    #[cfg(feature = "c_api")]
266    #[no_mangle]
267    pub unsafe fn brres_free(result: *mut ffi::bindings::CBrres) {
268        ffi::bindings::imp_brres_free(result)
269    }
270    #[cfg(feature = "c_api")]
271    #[no_mangle]
272    pub unsafe fn brres_read_mdl0mat_preset(
273        result: *mut ffi::bindings::CBrres,
274        path: *const i8,
275        path_len: u32,
276    ) {
277        ffi::bindings::imp_brres_read_mdl0mat_preset(result, path, path_len);
278    }
279}