bethkit 1.0.0__py3-none-win_amd64.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- bethkit/__init__.py +102 -0
- bethkit/_error.py +85 -0
- bethkit/_ffi/__init__.py +44 -0
- bethkit/_ffi/_loader.py +568 -0
- bethkit/_ffi/_types.py +97 -0
- bethkit/archive/__init__.py +16 -0
- bethkit/archive/archive.py +694 -0
- bethkit/enums.py +139 -0
- bethkit/load_order.py +198 -0
- bethkit/plugin/__init__.py +22 -0
- bethkit/plugin/cache.py +251 -0
- bethkit/plugin/plugin.py +823 -0
- bethkit/plugin/writer.py +510 -0
- bethkit/py.typed +0 -0
- bethkit/schema/__init__.py +26 -0
- bethkit/schema/schema.py +472 -0
- bethkit/strings/__init__.py +13 -0
- bethkit/strings/strings.py +522 -0
- bethkit-1.0.0.dist-info/METADATA +155 -0
- bethkit-1.0.0.dist-info/RECORD +22 -0
- bethkit-1.0.0.dist-info/WHEEL +4 -0
- bethkit-1.0.0.dist-info/licenses/LICENSE +203 -0
bethkit/_ffi/_loader.py
ADDED
|
@@ -0,0 +1,568 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Copyright (c) Modding Forge
|
|
3
|
+
"""
|
|
4
|
+
from __future__ import annotations
|
|
5
|
+
|
|
6
|
+
import ctypes
|
|
7
|
+
import os
|
|
8
|
+
import sys
|
|
9
|
+
import threading
|
|
10
|
+
from collections.abc import Callable
|
|
11
|
+
from pathlib import Path
|
|
12
|
+
|
|
13
|
+
from ._types import (
|
|
14
|
+
BethkitFieldValue,
|
|
15
|
+
BethkitGlobalFormId,
|
|
16
|
+
BethkitNamedField,
|
|
17
|
+
BethkitSlice,
|
|
18
|
+
)
|
|
19
|
+
|
|
20
|
+
_lib: ctypes.CDLL | None = None
|
|
21
|
+
_lib_lock: threading.Lock = threading.Lock()
|
|
22
|
+
|
|
23
|
+
_c = ctypes.c_char_p
|
|
24
|
+
_vp = ctypes.c_void_p
|
|
25
|
+
_sz = ctypes.c_size_t
|
|
26
|
+
_i32 = ctypes.c_int32
|
|
27
|
+
_u8 = ctypes.c_uint8
|
|
28
|
+
_u16 = ctypes.c_uint16
|
|
29
|
+
_u32 = ctypes.c_uint32
|
|
30
|
+
_u64 = ctypes.c_uint64
|
|
31
|
+
_i64 = ctypes.c_int64
|
|
32
|
+
_f32 = ctypes.c_float
|
|
33
|
+
_bl = ctypes.c_bool
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
def _find_library() -> Path:
|
|
37
|
+
"""
|
|
38
|
+
Locate the bethkit shared library.
|
|
39
|
+
|
|
40
|
+
Checks the ``BETHKIT_LIB`` environment variable first, then looks
|
|
41
|
+
next to the package directory, then falls back to a bare name for
|
|
42
|
+
the OS loader.
|
|
43
|
+
|
|
44
|
+
Returns:
|
|
45
|
+
Path: Resolved path to the library file.
|
|
46
|
+
"""
|
|
47
|
+
|
|
48
|
+
env = os.environ.get("BETHKIT_LIB")
|
|
49
|
+
if env:
|
|
50
|
+
return Path(env)
|
|
51
|
+
|
|
52
|
+
if sys.platform == "win32":
|
|
53
|
+
candidates = ["bethkit_ffi.dll"]
|
|
54
|
+
elif sys.platform == "darwin":
|
|
55
|
+
candidates = ["libbethkit_ffi.dylib"]
|
|
56
|
+
else:
|
|
57
|
+
candidates = ["libbethkit_ffi.so"]
|
|
58
|
+
|
|
59
|
+
pkg_dir = Path(__file__).parent
|
|
60
|
+
for name in candidates:
|
|
61
|
+
for search_dir in (pkg_dir, pkg_dir.parent):
|
|
62
|
+
path = search_dir / name
|
|
63
|
+
if path.exists():
|
|
64
|
+
return path
|
|
65
|
+
|
|
66
|
+
return Path(candidates[0])
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
def load_lib() -> ctypes.CDLL:
|
|
70
|
+
"""
|
|
71
|
+
Load the bethkit shared library (thread-safe singleton).
|
|
72
|
+
|
|
73
|
+
Returns the already-loaded library on subsequent calls.
|
|
74
|
+
|
|
75
|
+
Returns:
|
|
76
|
+
ctypes.CDLL: The loaded native library handle.
|
|
77
|
+
|
|
78
|
+
Raises:
|
|
79
|
+
BethkitLibraryNotFoundError: If the shared library file cannot
|
|
80
|
+
be found or loaded.
|
|
81
|
+
"""
|
|
82
|
+
|
|
83
|
+
global _lib
|
|
84
|
+
if _lib is not None:
|
|
85
|
+
return _lib
|
|
86
|
+
with _lib_lock:
|
|
87
|
+
if _lib is None:
|
|
88
|
+
from .._error import BethkitLibraryNotFoundError
|
|
89
|
+
|
|
90
|
+
path = _find_library()
|
|
91
|
+
try:
|
|
92
|
+
if sys.platform == "win32" and path.is_absolute():
|
|
93
|
+
with os.add_dll_directory(str(path.parent)):
|
|
94
|
+
loaded = ctypes.CDLL(str(path))
|
|
95
|
+
else:
|
|
96
|
+
loaded = ctypes.CDLL(str(path))
|
|
97
|
+
except OSError as exc:
|
|
98
|
+
raise BethkitLibraryNotFoundError(
|
|
99
|
+
f"Cannot load bethkit native library '{path}': {exc}. "
|
|
100
|
+
"Place bethkit_ffi.dll / libbethkit_ffi.so / "
|
|
101
|
+
"libbethkit_ffi.dylib next to the package or set the "
|
|
102
|
+
"BETHKIT_LIB environment variable."
|
|
103
|
+
) from exc
|
|
104
|
+
_declare(loaded)
|
|
105
|
+
_lib = loaded
|
|
106
|
+
return _lib
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
def last_error(lib: ctypes.CDLL) -> str:
|
|
110
|
+
"""
|
|
111
|
+
Return the last error message for the current thread.
|
|
112
|
+
|
|
113
|
+
Must be called immediately after a failing FFI call because the
|
|
114
|
+
thread-local error buffer is overwritten by the next FFI call.
|
|
115
|
+
|
|
116
|
+
Args:
|
|
117
|
+
lib (ctypes.CDLL): Loaded bethkit native library handle.
|
|
118
|
+
|
|
119
|
+
Returns:
|
|
120
|
+
str: The error text, or ``"unknown error"`` if none is set.
|
|
121
|
+
"""
|
|
122
|
+
|
|
123
|
+
msg: bytes | None = lib.bethkit_last_error()
|
|
124
|
+
if msg:
|
|
125
|
+
return msg.decode("utf-8")
|
|
126
|
+
return "unknown error"
|
|
127
|
+
|
|
128
|
+
|
|
129
|
+
def raise_last_error(lib: ctypes.CDLL) -> None:
|
|
130
|
+
"""
|
|
131
|
+
Raise :class:`~bethkit.BethkitNativeError` with the last FFI error.
|
|
132
|
+
|
|
133
|
+
Args:
|
|
134
|
+
lib (ctypes.CDLL): Loaded bethkit native library handle.
|
|
135
|
+
|
|
136
|
+
Raises:
|
|
137
|
+
BethkitNativeError: Always raised with the current thread-local
|
|
138
|
+
error text.
|
|
139
|
+
"""
|
|
140
|
+
|
|
141
|
+
from .._error import BethkitNativeError
|
|
142
|
+
|
|
143
|
+
raise BethkitNativeError(last_error(lib))
|
|
144
|
+
|
|
145
|
+
|
|
146
|
+
def copy_and_free_str(
|
|
147
|
+
ptr: int,
|
|
148
|
+
free_fn: Callable[[int], None],
|
|
149
|
+
lib: ctypes.CDLL,
|
|
150
|
+
) -> str:
|
|
151
|
+
"""
|
|
152
|
+
Copy the UTF-8 string at *ptr* into Python and free the native buffer.
|
|
153
|
+
|
|
154
|
+
This is the correct pattern for owned ``char*`` values returned by
|
|
155
|
+
the native library: copy first, then free, never hold the raw pointer.
|
|
156
|
+
|
|
157
|
+
Args:
|
|
158
|
+
ptr (int): Non-null ``c_void_p`` value pointing to the string.
|
|
159
|
+
free_fn (Callable[[int], None]): The matching ``*_free`` function
|
|
160
|
+
to call after copying.
|
|
161
|
+
lib (ctypes.CDLL): Loaded native library (unused here but kept
|
|
162
|
+
for uniform call-site signature).
|
|
163
|
+
|
|
164
|
+
Returns:
|
|
165
|
+
str: The decoded UTF-8 string.
|
|
166
|
+
"""
|
|
167
|
+
|
|
168
|
+
try:
|
|
169
|
+
return ctypes.string_at(ptr).decode("utf-8")
|
|
170
|
+
finally:
|
|
171
|
+
free_fn(ptr)
|
|
172
|
+
|
|
173
|
+
|
|
174
|
+
def enc(s: Path) -> bytes:
|
|
175
|
+
"""
|
|
176
|
+
Encode a filesystem path to a NUL-compatible UTF-8 bytes object.
|
|
177
|
+
|
|
178
|
+
Args:
|
|
179
|
+
s (Path): Filesystem path to encode.
|
|
180
|
+
|
|
181
|
+
Returns:
|
|
182
|
+
bytes: UTF-8 encoded path bytes.
|
|
183
|
+
"""
|
|
184
|
+
|
|
185
|
+
return str(s).encode("utf-8")
|
|
186
|
+
|
|
187
|
+
|
|
188
|
+
def senc(s: str) -> bytes:
|
|
189
|
+
"""
|
|
190
|
+
Encode a plain string to a NUL-compatible UTF-8 bytes object.
|
|
191
|
+
|
|
192
|
+
Args:
|
|
193
|
+
s (str): String to encode.
|
|
194
|
+
|
|
195
|
+
Returns:
|
|
196
|
+
bytes: UTF-8 encoded bytes.
|
|
197
|
+
"""
|
|
198
|
+
|
|
199
|
+
return s.encode("utf-8")
|
|
200
|
+
|
|
201
|
+
|
|
202
|
+
def _declare(lib: ctypes.CDLL) -> None:
|
|
203
|
+
"""
|
|
204
|
+
Declare argtypes and restype for every exported bethkit function.
|
|
205
|
+
|
|
206
|
+
Args:
|
|
207
|
+
lib (ctypes.CDLL): The freshly loaded native library handle.
|
|
208
|
+
"""
|
|
209
|
+
|
|
210
|
+
lib.bethkit_last_error.restype = _c
|
|
211
|
+
lib.bethkit_last_error.argtypes = []
|
|
212
|
+
|
|
213
|
+
lib.bethkit_bytes_free.restype = None
|
|
214
|
+
lib.bethkit_bytes_free.argtypes = [ctypes.POINTER(_u8), _sz]
|
|
215
|
+
|
|
216
|
+
lib.bethkit_plugin_open.restype = _vp
|
|
217
|
+
lib.bethkit_plugin_open.argtypes = [_c, _i32]
|
|
218
|
+
|
|
219
|
+
lib.bethkit_plugin_open_from_bytes.restype = _vp
|
|
220
|
+
lib.bethkit_plugin_open_from_bytes.argtypes = [
|
|
221
|
+
ctypes.POINTER(_u8), _sz, _i32
|
|
222
|
+
]
|
|
223
|
+
|
|
224
|
+
lib.bethkit_plugin_free.restype = None
|
|
225
|
+
lib.bethkit_plugin_free.argtypes = [_vp]
|
|
226
|
+
|
|
227
|
+
lib.bethkit_plugin_kind.restype = _i32
|
|
228
|
+
lib.bethkit_plugin_kind.argtypes = [_vp]
|
|
229
|
+
|
|
230
|
+
lib.bethkit_plugin_is_localized.restype = _bl
|
|
231
|
+
lib.bethkit_plugin_is_localized.argtypes = [_vp]
|
|
232
|
+
|
|
233
|
+
lib.bethkit_plugin_master_count.restype = _sz
|
|
234
|
+
lib.bethkit_plugin_master_count.argtypes = [_vp]
|
|
235
|
+
|
|
236
|
+
lib.bethkit_plugin_master_get.restype = _c
|
|
237
|
+
lib.bethkit_plugin_master_get.argtypes = [_vp, _sz]
|
|
238
|
+
|
|
239
|
+
lib.bethkit_plugin_description.restype = _c
|
|
240
|
+
lib.bethkit_plugin_description.argtypes = [_vp]
|
|
241
|
+
|
|
242
|
+
lib.bethkit_plugin_group_count.restype = _sz
|
|
243
|
+
lib.bethkit_plugin_group_count.argtypes = [_vp]
|
|
244
|
+
|
|
245
|
+
lib.bethkit_plugin_group_get.restype = _vp
|
|
246
|
+
lib.bethkit_plugin_group_get.argtypes = [_vp, _sz]
|
|
247
|
+
|
|
248
|
+
lib.bethkit_plugin_find_record.restype = _vp
|
|
249
|
+
lib.bethkit_plugin_find_record.argtypes = [_vp, _u32]
|
|
250
|
+
|
|
251
|
+
lib.bethkit_record_signature.restype = _i32
|
|
252
|
+
lib.bethkit_record_signature.argtypes = [_vp, ctypes.POINTER(_u8)]
|
|
253
|
+
|
|
254
|
+
lib.bethkit_record_form_id.restype = _u32
|
|
255
|
+
lib.bethkit_record_form_id.argtypes = [_vp]
|
|
256
|
+
|
|
257
|
+
lib.bethkit_record_flags.restype = _u32
|
|
258
|
+
lib.bethkit_record_flags.argtypes = [_vp]
|
|
259
|
+
|
|
260
|
+
lib.bethkit_record_form_version.restype = _u16
|
|
261
|
+
lib.bethkit_record_form_version.argtypes = [_vp]
|
|
262
|
+
|
|
263
|
+
lib.bethkit_record_editor_id.restype = _vp
|
|
264
|
+
lib.bethkit_record_editor_id.argtypes = [_vp]
|
|
265
|
+
|
|
266
|
+
lib.bethkit_record_editor_id_free.restype = None
|
|
267
|
+
lib.bethkit_record_editor_id_free.argtypes = [_vp]
|
|
268
|
+
|
|
269
|
+
lib.bethkit_record_subrecord_count.restype = _i64
|
|
270
|
+
lib.bethkit_record_subrecord_count.argtypes = [_vp]
|
|
271
|
+
|
|
272
|
+
lib.bethkit_record_subrecord_get.restype = _vp
|
|
273
|
+
lib.bethkit_record_subrecord_get.argtypes = [_vp, _sz]
|
|
274
|
+
|
|
275
|
+
lib.bethkit_record_subrecord_find.restype = _vp
|
|
276
|
+
lib.bethkit_record_subrecord_find.argtypes = [_vp, ctypes.POINTER(_u8)]
|
|
277
|
+
|
|
278
|
+
lib.bethkit_subrecord_signature.restype = _i32
|
|
279
|
+
lib.bethkit_subrecord_signature.argtypes = [_vp, ctypes.POINTER(_u8)]
|
|
280
|
+
|
|
281
|
+
lib.bethkit_subrecord_bytes.restype = BethkitSlice
|
|
282
|
+
lib.bethkit_subrecord_bytes.argtypes = [_vp]
|
|
283
|
+
|
|
284
|
+
lib.bethkit_subrecord_as_u8.restype = _i32
|
|
285
|
+
lib.bethkit_subrecord_as_u8.argtypes = [_vp, ctypes.POINTER(_u8)]
|
|
286
|
+
|
|
287
|
+
lib.bethkit_subrecord_as_u16.restype = _i32
|
|
288
|
+
lib.bethkit_subrecord_as_u16.argtypes = [_vp, ctypes.POINTER(_u16)]
|
|
289
|
+
|
|
290
|
+
lib.bethkit_subrecord_as_u32.restype = _i32
|
|
291
|
+
lib.bethkit_subrecord_as_u32.argtypes = [_vp, ctypes.POINTER(_u32)]
|
|
292
|
+
|
|
293
|
+
lib.bethkit_subrecord_as_f32.restype = _i32
|
|
294
|
+
lib.bethkit_subrecord_as_f32.argtypes = [_vp, ctypes.POINTER(_f32)]
|
|
295
|
+
|
|
296
|
+
lib.bethkit_subrecord_as_zstring.restype = _vp
|
|
297
|
+
lib.bethkit_subrecord_as_zstring.argtypes = [_vp]
|
|
298
|
+
|
|
299
|
+
lib.bethkit_zstring_free.restype = None
|
|
300
|
+
lib.bethkit_zstring_free.argtypes = [_vp]
|
|
301
|
+
|
|
302
|
+
lib.bethkit_group_type.restype = _i32
|
|
303
|
+
lib.bethkit_group_type.argtypes = [_vp]
|
|
304
|
+
|
|
305
|
+
lib.bethkit_group_child_count.restype = _sz
|
|
306
|
+
lib.bethkit_group_child_count.argtypes = [_vp]
|
|
307
|
+
|
|
308
|
+
lib.bethkit_group_child_is_record.restype = _bl
|
|
309
|
+
lib.bethkit_group_child_is_record.argtypes = [_vp, _sz]
|
|
310
|
+
|
|
311
|
+
lib.bethkit_group_child_as_record.restype = _vp
|
|
312
|
+
lib.bethkit_group_child_as_record.argtypes = [_vp, _sz]
|
|
313
|
+
|
|
314
|
+
lib.bethkit_group_child_as_group.restype = _vp
|
|
315
|
+
lib.bethkit_group_child_as_group.argtypes = [_vp, _sz]
|
|
316
|
+
|
|
317
|
+
lib.bethkit_archive_open.restype = _vp
|
|
318
|
+
lib.bethkit_archive_open.argtypes = [_c]
|
|
319
|
+
|
|
320
|
+
lib.bethkit_archive_free.restype = None
|
|
321
|
+
lib.bethkit_archive_free.argtypes = [_vp]
|
|
322
|
+
|
|
323
|
+
lib.bethkit_archive_format_name.restype = _c
|
|
324
|
+
lib.bethkit_archive_format_name.argtypes = [_vp]
|
|
325
|
+
|
|
326
|
+
lib.bethkit_archive_file_count.restype = _sz
|
|
327
|
+
lib.bethkit_archive_file_count.argtypes = [_vp]
|
|
328
|
+
|
|
329
|
+
lib.bethkit_archive_entry_get.restype = _vp
|
|
330
|
+
lib.bethkit_archive_entry_get.argtypes = [_vp, _sz]
|
|
331
|
+
|
|
332
|
+
lib.bethkit_archive_entry_path.restype = _vp
|
|
333
|
+
lib.bethkit_archive_entry_path.argtypes = [_vp]
|
|
334
|
+
|
|
335
|
+
lib.bethkit_archive_entry_path_free.restype = None
|
|
336
|
+
lib.bethkit_archive_entry_path_free.argtypes = [_vp]
|
|
337
|
+
|
|
338
|
+
lib.bethkit_archive_entry_uncompressed_size.restype = _u32
|
|
339
|
+
lib.bethkit_archive_entry_uncompressed_size.argtypes = [_vp]
|
|
340
|
+
|
|
341
|
+
lib.bethkit_archive_extract.restype = ctypes.POINTER(_u8)
|
|
342
|
+
lib.bethkit_archive_extract.argtypes = [_vp, _c, ctypes.POINTER(_sz)]
|
|
343
|
+
|
|
344
|
+
lib.bethkit_archive_extract_to_file.restype = _i32
|
|
345
|
+
lib.bethkit_archive_extract_to_file.argtypes = [_vp, _c, _c]
|
|
346
|
+
|
|
347
|
+
lib.bethkit_bsa_writer_new.restype = _vp
|
|
348
|
+
lib.bethkit_bsa_writer_new.argtypes = [_i32]
|
|
349
|
+
|
|
350
|
+
lib.bethkit_bsa_writer_free.restype = None
|
|
351
|
+
lib.bethkit_bsa_writer_free.argtypes = [_vp]
|
|
352
|
+
|
|
353
|
+
lib.bethkit_bsa_writer_set_compress.restype = _i32
|
|
354
|
+
lib.bethkit_bsa_writer_set_compress.argtypes = [_vp, _bl]
|
|
355
|
+
|
|
356
|
+
lib.bethkit_bsa_writer_set_embed_names.restype = _i32
|
|
357
|
+
lib.bethkit_bsa_writer_set_embed_names.argtypes = [_vp, _bl]
|
|
358
|
+
|
|
359
|
+
lib.bethkit_bsa_writer_add.restype = _i32
|
|
360
|
+
lib.bethkit_bsa_writer_add.argtypes = [
|
|
361
|
+
_vp, _c, ctypes.POINTER(_u8), _sz
|
|
362
|
+
]
|
|
363
|
+
|
|
364
|
+
lib.bethkit_bsa_writer_write_to.restype = _i32
|
|
365
|
+
lib.bethkit_bsa_writer_write_to.argtypes = [_vp, _c]
|
|
366
|
+
|
|
367
|
+
lib.bethkit_ba2_gnrl_writer_new.restype = _vp
|
|
368
|
+
lib.bethkit_ba2_gnrl_writer_new.argtypes = [_i32]
|
|
369
|
+
|
|
370
|
+
lib.bethkit_ba2_gnrl_writer_free.restype = None
|
|
371
|
+
lib.bethkit_ba2_gnrl_writer_free.argtypes = [_vp]
|
|
372
|
+
|
|
373
|
+
lib.bethkit_ba2_gnrl_writer_add.restype = _i32
|
|
374
|
+
lib.bethkit_ba2_gnrl_writer_add.argtypes = [
|
|
375
|
+
_vp, _c, ctypes.POINTER(_u8), _sz
|
|
376
|
+
]
|
|
377
|
+
|
|
378
|
+
lib.bethkit_ba2_gnrl_writer_write_to.restype = _i32
|
|
379
|
+
lib.bethkit_ba2_gnrl_writer_write_to.argtypes = [_vp, _c]
|
|
380
|
+
|
|
381
|
+
lib.bethkit_ba2_dx10_writer_new.restype = _vp
|
|
382
|
+
lib.bethkit_ba2_dx10_writer_new.argtypes = [_i32]
|
|
383
|
+
|
|
384
|
+
lib.bethkit_ba2_dx10_writer_free.restype = None
|
|
385
|
+
lib.bethkit_ba2_dx10_writer_free.argtypes = [_vp]
|
|
386
|
+
|
|
387
|
+
lib.bethkit_ba2_dx10_writer_add.restype = _i32
|
|
388
|
+
lib.bethkit_ba2_dx10_writer_add.argtypes = [
|
|
389
|
+
_vp, _c, ctypes.POINTER(_u8), _sz
|
|
390
|
+
]
|
|
391
|
+
|
|
392
|
+
lib.bethkit_ba2_dx10_writer_write_to.restype = _i32
|
|
393
|
+
lib.bethkit_ba2_dx10_writer_write_to.argtypes = [_vp, _c]
|
|
394
|
+
|
|
395
|
+
lib.bethkit_load_order_new.restype = _vp
|
|
396
|
+
lib.bethkit_load_order_new.argtypes = []
|
|
397
|
+
|
|
398
|
+
lib.bethkit_load_order_free.restype = None
|
|
399
|
+
lib.bethkit_load_order_free.argtypes = [_vp]
|
|
400
|
+
|
|
401
|
+
lib.bethkit_load_order_push.restype = _i32
|
|
402
|
+
lib.bethkit_load_order_push.argtypes = [_vp, _c, _i32]
|
|
403
|
+
|
|
404
|
+
lib.bethkit_load_order_len.restype = _sz
|
|
405
|
+
lib.bethkit_load_order_len.argtypes = [_vp]
|
|
406
|
+
|
|
407
|
+
lib.bethkit_load_order_resolve.restype = _i32
|
|
408
|
+
lib.bethkit_load_order_resolve.argtypes = [
|
|
409
|
+
_vp, _u32, _c, ctypes.POINTER(BethkitGlobalFormId)
|
|
410
|
+
]
|
|
411
|
+
|
|
412
|
+
lib.bethkit_plugin_cache_new.restype = _vp
|
|
413
|
+
lib.bethkit_plugin_cache_new.argtypes = []
|
|
414
|
+
|
|
415
|
+
lib.bethkit_plugin_cache_free.restype = None
|
|
416
|
+
lib.bethkit_plugin_cache_free.argtypes = [_vp]
|
|
417
|
+
|
|
418
|
+
lib.bethkit_plugin_cache_add.restype = _i32
|
|
419
|
+
lib.bethkit_plugin_cache_add.argtypes = [_vp, _c, _vp]
|
|
420
|
+
|
|
421
|
+
lib.bethkit_plugin_cache_len.restype = _sz
|
|
422
|
+
lib.bethkit_plugin_cache_len.argtypes = [_vp]
|
|
423
|
+
|
|
424
|
+
lib.bethkit_plugin_cache_record_count.restype = _sz
|
|
425
|
+
lib.bethkit_plugin_cache_record_count.argtypes = [_vp]
|
|
426
|
+
|
|
427
|
+
lib.bethkit_plugin_cache_resolve.restype = _vp
|
|
428
|
+
lib.bethkit_plugin_cache_resolve.argtypes = [_vp, _c, _u32]
|
|
429
|
+
|
|
430
|
+
lib.bethkit_plugin_cache_find_by_editor_id.restype = _vp
|
|
431
|
+
lib.bethkit_plugin_cache_find_by_editor_id.argtypes = [
|
|
432
|
+
_vp, _c, ctypes.POINTER(BethkitGlobalFormId)
|
|
433
|
+
]
|
|
434
|
+
|
|
435
|
+
lib.bethkit_string_table_new.restype = _vp
|
|
436
|
+
lib.bethkit_string_table_new.argtypes = [_i32]
|
|
437
|
+
|
|
438
|
+
lib.bethkit_string_table_open.restype = _vp
|
|
439
|
+
lib.bethkit_string_table_open.argtypes = [_c]
|
|
440
|
+
|
|
441
|
+
lib.bethkit_string_table_free.restype = None
|
|
442
|
+
lib.bethkit_string_table_free.argtypes = [_vp]
|
|
443
|
+
|
|
444
|
+
lib.bethkit_string_table_kind.restype = _i32
|
|
445
|
+
lib.bethkit_string_table_kind.argtypes = [_vp]
|
|
446
|
+
|
|
447
|
+
lib.bethkit_string_table_len.restype = _sz
|
|
448
|
+
lib.bethkit_string_table_len.argtypes = [_vp]
|
|
449
|
+
|
|
450
|
+
lib.bethkit_string_table_get.restype = ctypes.POINTER(_u8)
|
|
451
|
+
lib.bethkit_string_table_get.argtypes = [_vp, _u32, ctypes.POINTER(_sz)]
|
|
452
|
+
|
|
453
|
+
lib.bethkit_string_table_insert.restype = _i32
|
|
454
|
+
lib.bethkit_string_table_insert.argtypes = [
|
|
455
|
+
_vp, _u32, ctypes.POINTER(_u8), _sz
|
|
456
|
+
]
|
|
457
|
+
|
|
458
|
+
lib.bethkit_string_table_insert_new.restype = _i32
|
|
459
|
+
lib.bethkit_string_table_insert_new.argtypes = [
|
|
460
|
+
_vp, ctypes.POINTER(_u8), _sz, ctypes.POINTER(_u32)
|
|
461
|
+
]
|
|
462
|
+
|
|
463
|
+
lib.bethkit_string_table_remove.restype = _bl
|
|
464
|
+
lib.bethkit_string_table_remove.argtypes = [_vp, _u32]
|
|
465
|
+
|
|
466
|
+
lib.bethkit_string_table_write_to_file.restype = _i32
|
|
467
|
+
lib.bethkit_string_table_write_to_file.argtypes = [_vp, _c]
|
|
468
|
+
|
|
469
|
+
lib.bethkit_localization_set_new.restype = _vp
|
|
470
|
+
lib.bethkit_localization_set_new.argtypes = []
|
|
471
|
+
|
|
472
|
+
lib.bethkit_localization_set_open.restype = _vp
|
|
473
|
+
lib.bethkit_localization_set_open.argtypes = [_c, _c]
|
|
474
|
+
|
|
475
|
+
lib.bethkit_localization_set_free.restype = None
|
|
476
|
+
lib.bethkit_localization_set_free.argtypes = [_vp]
|
|
477
|
+
|
|
478
|
+
lib.bethkit_localization_set_get.restype = ctypes.POINTER(_u8)
|
|
479
|
+
lib.bethkit_localization_set_get.argtypes = [
|
|
480
|
+
_vp, _i32, _u32, ctypes.POINTER(_sz)
|
|
481
|
+
]
|
|
482
|
+
|
|
483
|
+
lib.bethkit_localization_set_set.restype = _i32
|
|
484
|
+
lib.bethkit_localization_set_set.argtypes = [
|
|
485
|
+
_vp, _i32, _u32, ctypes.POINTER(_u8), _sz
|
|
486
|
+
]
|
|
487
|
+
|
|
488
|
+
lib.bethkit_localization_set_write.restype = _i32
|
|
489
|
+
lib.bethkit_localization_set_write.argtypes = [_vp, _c, _c]
|
|
490
|
+
|
|
491
|
+
lib.bethkit_schema_registry_sse.restype = _vp
|
|
492
|
+
lib.bethkit_schema_registry_sse.argtypes = []
|
|
493
|
+
|
|
494
|
+
lib.bethkit_schema_registry_has.restype = _bl
|
|
495
|
+
lib.bethkit_schema_registry_has.argtypes = [_vp, ctypes.POINTER(_u8)]
|
|
496
|
+
|
|
497
|
+
lib.bethkit_record_view_new.restype = _vp
|
|
498
|
+
lib.bethkit_record_view_new.argtypes = [_vp, ctypes.POINTER(_u8), _bl]
|
|
499
|
+
|
|
500
|
+
lib.bethkit_record_view_free.restype = None
|
|
501
|
+
lib.bethkit_record_view_free.argtypes = [_vp]
|
|
502
|
+
|
|
503
|
+
lib.bethkit_record_view_field_count.restype = _sz
|
|
504
|
+
lib.bethkit_record_view_field_count.argtypes = [_vp]
|
|
505
|
+
|
|
506
|
+
lib.bethkit_record_view_field_get.restype = ctypes.POINTER(BethkitNamedField)
|
|
507
|
+
lib.bethkit_record_view_field_get.argtypes = [_vp, _sz]
|
|
508
|
+
|
|
509
|
+
lib.bethkit_field_entries_len.restype = _sz
|
|
510
|
+
lib.bethkit_field_entries_len.argtypes = [_vp]
|
|
511
|
+
|
|
512
|
+
lib.bethkit_field_entries_get.restype = ctypes.POINTER(BethkitNamedField)
|
|
513
|
+
lib.bethkit_field_entries_get.argtypes = [_vp, _sz]
|
|
514
|
+
|
|
515
|
+
lib.bethkit_field_entries_free.restype = None
|
|
516
|
+
lib.bethkit_field_entries_free.argtypes = [_vp]
|
|
517
|
+
|
|
518
|
+
lib.bethkit_field_values_len.restype = _sz
|
|
519
|
+
lib.bethkit_field_values_len.argtypes = [_vp]
|
|
520
|
+
|
|
521
|
+
lib.bethkit_field_values_get.restype = ctypes.POINTER(BethkitFieldValue)
|
|
522
|
+
lib.bethkit_field_values_get.argtypes = [_vp, _sz]
|
|
523
|
+
|
|
524
|
+
lib.bethkit_field_values_free.restype = None
|
|
525
|
+
lib.bethkit_field_values_free.argtypes = [_vp]
|
|
526
|
+
|
|
527
|
+
lib.bethkit_plugin_writer_new.restype = _vp
|
|
528
|
+
lib.bethkit_plugin_writer_new.argtypes = [_i32, _f32]
|
|
529
|
+
|
|
530
|
+
lib.bethkit_plugin_writer_free.restype = None
|
|
531
|
+
lib.bethkit_plugin_writer_free.argtypes = [_vp]
|
|
532
|
+
|
|
533
|
+
lib.bethkit_plugin_writer_add_group.restype = _i32
|
|
534
|
+
lib.bethkit_plugin_writer_add_group.argtypes = [_vp, _vp]
|
|
535
|
+
|
|
536
|
+
lib.bethkit_plugin_writer_write_to_file.restype = _i32
|
|
537
|
+
lib.bethkit_plugin_writer_write_to_file.argtypes = [_vp, _c]
|
|
538
|
+
|
|
539
|
+
lib.bethkit_plugin_writer_write_to_bytes.restype = ctypes.POINTER(_u8)
|
|
540
|
+
lib.bethkit_plugin_writer_write_to_bytes.argtypes = [
|
|
541
|
+
_vp, ctypes.POINTER(_sz)
|
|
542
|
+
]
|
|
543
|
+
|
|
544
|
+
lib.bethkit_writable_group_new.restype = _vp
|
|
545
|
+
lib.bethkit_writable_group_new.argtypes = [ctypes.POINTER(_u8), _i32]
|
|
546
|
+
|
|
547
|
+
lib.bethkit_writable_group_free.restype = None
|
|
548
|
+
lib.bethkit_writable_group_free.argtypes = [_vp]
|
|
549
|
+
|
|
550
|
+
lib.bethkit_writable_group_add_record.restype = _i32
|
|
551
|
+
lib.bethkit_writable_group_add_record.argtypes = [_vp, _vp]
|
|
552
|
+
|
|
553
|
+
lib.bethkit_writable_group_add_group.restype = _i32
|
|
554
|
+
lib.bethkit_writable_group_add_group.argtypes = [_vp, _vp]
|
|
555
|
+
|
|
556
|
+
lib.bethkit_writable_record_new.restype = _vp
|
|
557
|
+
lib.bethkit_writable_record_new.argtypes = [
|
|
558
|
+
ctypes.POINTER(_u8), _u32, _u32, _u16
|
|
559
|
+
]
|
|
560
|
+
|
|
561
|
+
lib.bethkit_writable_record_free.restype = None
|
|
562
|
+
lib.bethkit_writable_record_free.argtypes = [_vp]
|
|
563
|
+
|
|
564
|
+
lib.bethkit_writable_record_add_subrecord.restype = _i32
|
|
565
|
+
lib.bethkit_writable_record_add_subrecord.argtypes = [
|
|
566
|
+
_vp, ctypes.POINTER(_u8), ctypes.POINTER(_u8), _sz
|
|
567
|
+
]
|
|
568
|
+
|
bethkit/_ffi/_types.py
ADDED
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
"""ctypes Structure and Union definitions mirroring bethkit.h."""
|
|
2
|
+
from __future__ import annotations
|
|
3
|
+
|
|
4
|
+
import ctypes
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class BethkitSlice(ctypes.Structure):
|
|
8
|
+
"""A non-owning view of a byte slice passed across the FFI boundary."""
|
|
9
|
+
|
|
10
|
+
_fields_ = [
|
|
11
|
+
("ptr", ctypes.POINTER(ctypes.c_uint8)),
|
|
12
|
+
("len", ctypes.c_size_t),
|
|
13
|
+
]
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class BethkitGlobalFormId(ctypes.Structure):
|
|
17
|
+
"""A globally unique FormID (plugin name + 24-bit object ID)."""
|
|
18
|
+
|
|
19
|
+
_fields_ = [
|
|
20
|
+
# Borrowed from the owning LoadOrder / PluginCache.
|
|
21
|
+
("plugin_name", ctypes.c_char_p),
|
|
22
|
+
("object_id", ctypes.c_uint32),
|
|
23
|
+
]
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
class BethkitTypedFormId(ctypes.Structure):
|
|
27
|
+
"""A FormID together with the record signatures it is allowed to reference."""
|
|
28
|
+
|
|
29
|
+
_fields_ = [
|
|
30
|
+
("raw", ctypes.c_uint32),
|
|
31
|
+
# Pointer to a static array of 4-byte signatures; ctypes inserts the
|
|
32
|
+
# necessary 4-byte padding before this field automatically.
|
|
33
|
+
("allowed_sigs", ctypes.c_void_p),
|
|
34
|
+
("allowed_count", ctypes.c_size_t),
|
|
35
|
+
]
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
class BethkitEnumVal(ctypes.Structure):
|
|
39
|
+
"""An enumeration field value with its raw integer and optional name."""
|
|
40
|
+
|
|
41
|
+
_fields_ = [
|
|
42
|
+
("value", ctypes.c_int64),
|
|
43
|
+
# Points to static memory; never free.
|
|
44
|
+
("name", ctypes.c_char_p),
|
|
45
|
+
]
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
class BethkitFlagsVal(ctypes.Structure):
|
|
49
|
+
"""A flags field value with the raw integer and the names of active bits."""
|
|
50
|
+
|
|
51
|
+
_fields_ = [
|
|
52
|
+
("raw_value", ctypes.c_uint64),
|
|
53
|
+
# Heap-allocated array of static string pointers; freed with the view.
|
|
54
|
+
("active_names", ctypes.POINTER(ctypes.c_char_p)),
|
|
55
|
+
("active_count", ctypes.c_size_t),
|
|
56
|
+
]
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
class BethkitFieldValuePayload(ctypes.Union):
|
|
60
|
+
"""The payload union inside BethkitFieldValue."""
|
|
61
|
+
|
|
62
|
+
_fields_ = [
|
|
63
|
+
("int_val", ctypes.c_int64),
|
|
64
|
+
("float_val", ctypes.c_double),
|
|
65
|
+
# Borrowed from the owning view; never free.
|
|
66
|
+
("str_val", ctypes.c_char_p),
|
|
67
|
+
("form_id", ctypes.c_uint32),
|
|
68
|
+
("form_id_typed", BethkitTypedFormId),
|
|
69
|
+
("bytes", BethkitSlice),
|
|
70
|
+
("enum_val", BethkitEnumVal),
|
|
71
|
+
("flags_val", BethkitFlagsVal),
|
|
72
|
+
# Owned; freed with bethkit_field_entries_free (or via view free).
|
|
73
|
+
("struct_entries", ctypes.c_void_p),
|
|
74
|
+
# Owned; freed with bethkit_field_values_free (or via view free).
|
|
75
|
+
("array_values", ctypes.c_void_p),
|
|
76
|
+
("localized_id", ctypes.c_uint32),
|
|
77
|
+
("_pad", ctypes.c_uint64),
|
|
78
|
+
]
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
class BethkitFieldValue(ctypes.Structure):
|
|
82
|
+
"""A decoded field value stored as a tagged union."""
|
|
83
|
+
|
|
84
|
+
_fields_ = [
|
|
85
|
+
("kind", ctypes.c_int32),
|
|
86
|
+
("payload", BethkitFieldValuePayload),
|
|
87
|
+
]
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
class BethkitNamedField(ctypes.Structure):
|
|
91
|
+
"""A named field snapshot inside a BethkitRecordView or BethkitFieldEntries."""
|
|
92
|
+
|
|
93
|
+
_fields_ = [
|
|
94
|
+
# Points to static memory; never free.
|
|
95
|
+
("name", ctypes.c_char_p),
|
|
96
|
+
("value", BethkitFieldValue),
|
|
97
|
+
]
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Copyright (c) Modding Forge
|
|
3
|
+
|
|
4
|
+
Archive subpackage — reading and writing BSA and BA2 archive files.
|
|
5
|
+
"""
|
|
6
|
+
from __future__ import annotations
|
|
7
|
+
|
|
8
|
+
from .archive import Archive, ArchiveEntry, Ba2Dx10Writer, Ba2GnrlWriter, BsaWriter
|
|
9
|
+
|
|
10
|
+
__all__ = [
|
|
11
|
+
"Archive",
|
|
12
|
+
"ArchiveEntry",
|
|
13
|
+
"Ba2Dx10Writer",
|
|
14
|
+
"Ba2GnrlWriter",
|
|
15
|
+
"BsaWriter",
|
|
16
|
+
]
|