PyCriCodecsEx 0.0.1__cp313-cp313-win32.whl → 0.0.3__cp313-cp313-win32.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.
PyCriCodecsEx/utf.py CHANGED
@@ -1,11 +1,14 @@
1
1
  from typing import BinaryIO, TypeVar, Type, List
2
+ from copy import deepcopy
2
3
 
3
4
  T = TypeVar("T")
5
+ Ty = TypeVar("Ty", bound="UTFViewer")
4
6
  from io import BytesIO, FileIO
5
7
  from struct import unpack, calcsize, pack
6
8
  from PyCriCodecsEx.chunk import *
7
9
 
8
10
  class UTF:
11
+ """Use this class to unpack @UTF table binary payload."""
9
12
 
10
13
  _dictarray: list
11
14
 
@@ -21,11 +24,11 @@ class UTF:
21
24
  recursive: bool
22
25
  encoding : str = 'utf-8'
23
26
 
24
- def __init__(self, stream, recursive=False):
27
+ def __init__(self, stream : str | BinaryIO, recursive=False):
25
28
  """Unpacks UTF table binary payload
26
29
 
27
30
  Args:
28
- stream (Union[str, bytes]): The input stream or file path to read the UTF table from.
31
+ stream (Union[str | BinaryIO]): The input stream or file path to read the UTF table from.
29
32
  recursive (bool): Whether to recursively unpack nested UTF tables.
30
33
  """
31
34
  if type(stream) == str:
@@ -288,6 +291,7 @@ class UTF:
288
291
  return self._dictarray
289
292
 
290
293
  class UTFBuilder:
294
+ """Use this class to build UTF table binary payloads from a `dictarray`."""
291
295
 
292
296
  encoding: str
293
297
  dictarray: list
@@ -302,7 +306,7 @@ class UTFBuilder:
302
306
 
303
307
  def __init__(
304
308
  self,
305
- dictarray: list[dict],
309
+ dictarray_src: list[dict],
306
310
  encrypt: bool = False,
307
311
  encoding: str = "utf-8",
308
312
  table_name: str = "PyCriCodecs_table",
@@ -311,14 +315,14 @@ class UTFBuilder:
311
315
  """Packs UTF payload back into their binary form
312
316
 
313
317
  Args:
314
- dictarray: A list of dictionaries representing the UTF table.
318
+ dictarray_src: list[dict]: A list of dictionaries representing the UTF table.
315
319
  encrypt: Whether to encrypt the table (default: False).
316
320
  encoding: The character encoding to use (default: "utf-8").
317
321
  table_name: The name of the table (default: "PyCriCodecs_table").
318
322
  ignore_recursion: Whether to ignore recursion when packing (default: False).
319
323
  """
320
- assert type(dictarray) == list, "dictarray must be a list of dictionaries (see UTF.dictarray)."
321
-
324
+ assert type(dictarray_src) == list, "dictarray must be a list of dictionaries (see UTF.dictarray)."
325
+ dictarray = deepcopy(dictarray_src)
322
326
  # Preprocess for nested dictarray types
323
327
  def dfs(payload: list[dict], name: str) -> None:
324
328
  for dict in range(len(payload)):
@@ -589,36 +593,18 @@ class UTFBuilder:
589
593
  return dataarray
590
594
 
591
595
  class UTFViewer:
596
+ """Use this class to create dataclass-like access to `dictarray`s."""
597
+
592
598
  _payload: dict
593
599
 
594
600
  def __init__(self, payload):
595
601
  """Construct a non-owning read-write, deletable view of a UTF table dictarray.
602
+
596
603
  Nested classes are supported.
597
- Sorting (using .sort()) is done in-place and affects the original payload.
598
604
 
599
- Example:
600
- ```python
601
- class CueNameTable(UTFViewer):
602
- CueName : str
603
- CueIndex : int
604
- class ACBTable(UTFViewer):
605
- CueNameTable : List[CueNameTable]
606
- Awb : AWB
607
- src = ACB(ACB_sample)
608
- payload = ACBTable(src.payload)
609
- >>> Referencing items through Python is allowed
610
- name = payload.CueNameTable
611
- >>> Lists can be indexed
612
- name_str = name[0].CueName
613
- >>> Deleting items from lists is also allowed
614
- src.view.CueNameTable.pop(1)
615
- src.view.CueTable.pop(1)
616
- >>> The changes will be reflected in the original UTF payload
617
-
618
- See __new__ for the actual constructor.
619
- ```
605
+ Sorting (using .sort()) is done in-place and affects the original payload.
620
606
  """
621
- assert isinstance(payload, dict), "Payload must be a dictionary."
607
+ assert isinstance(payload, dict), "payload must be a dictionary."
622
608
  super().__setattr__("_payload", payload)
623
609
 
624
610
  def __getattr__(self, item):
@@ -643,7 +629,9 @@ class UTFViewer:
643
629
  def __setattr__(self, item, value):
644
630
  payload = super().__getattribute__("_payload")
645
631
  if item not in payload:
646
- raise AttributeError(f"{item} not in payload")
632
+ raise AttributeError(f"{item} not in payload. UTFViewer should not store extra states")
633
+ if isinstance(value, dict) or isinstance(value, list):
634
+ raise AttributeError(f"Dict or list assignment is not allowed as this may potentially change the table layout. Access by elements and use list APIs instead")
647
635
  typeof, _ = payload[item]
648
636
  payload[item] = (typeof, value)
649
637
 
@@ -659,9 +647,9 @@ class UTFViewer:
659
647
 
660
648
  class ListView(list):
661
649
  _payload : List[dict]
662
- def __init__(self, payload: list[T]):
650
+ def __init__(self, clazz : Type[Ty], payload: list[Ty]):
663
651
  self._payload = payload
664
- super().__init__([UTFViewer(item) for item in payload])
652
+ super().__init__([clazz(item) for item in payload])
665
653
 
666
654
  def pop(self, index = -1):
667
655
  self._payload.pop(index)
@@ -669,7 +657,7 @@ class UTFViewer:
669
657
 
670
658
  def append(self, o : "UTFViewer"):
671
659
  if len(self):
672
- assert type(self[0]) == type(o), "all items in the list must be of the same type."
660
+ assert isinstance(o, UTFViewer) and type(self[0]) == type(o), "all items in the list must be of the same type, and must be an instance of UTFViewer."
673
661
  self._payload.append(o._payload)
674
662
  return super().append(o)
675
663
 
@@ -677,9 +665,9 @@ class UTFViewer:
677
665
  for item in iterable:
678
666
  self.append(item)
679
667
 
680
- def insert(self, index, o : "UTFViewer"):
668
+ def insert(self, index, o : "UTFViewer"):
681
669
  if len(self):
682
- assert type(self[0]) == type(o), "all items in the list must be of the same type."
670
+ assert isinstance(o, UTFViewer) and type(self[0]) == type(o), "all items in the list must be of the same type, and must be an instance of UTFViewer."
683
671
  self._payload.insert(index, o._payload)
684
672
  return super().insert(index, o)
685
673
 
@@ -698,7 +686,7 @@ class UTFViewer:
698
686
  self._payload[:] = [self._payload[i] for x,i in p]
699
687
  self[:] = [x for x,i in p]
700
688
 
701
- def __new__(cls: Type[T], payload: list | dict, **args) -> T | List[T]:
689
+ def __new__(cls: Type[Ty], payload: list | dict, **args) -> Ty | List[Ty]:
702
690
  if isinstance(payload, list):
703
- return UTFViewer.ListView(payload)
691
+ return UTFViewer.ListView(cls, payload)
704
692
  return super().__new__(cls)
@@ -0,0 +1,35 @@
1
+ Metadata-Version: 2.4
2
+ Name: PyCriCodecsEx
3
+ Version: 0.0.3
4
+ Summary: Criware formats library for Python
5
+ Home-page: https://mos9527.github.io/PyCriCodecsEx/
6
+ Classifier: Programming Language :: Python :: 3
7
+ Classifier: License :: OSI Approved :: MIT License
8
+ Classifier: Operating System :: OS Independent
9
+ Requires-Python: >=3.10
10
+ Description-Content-Type: text/markdown
11
+ License-File: LICENSE
12
+ Provides-Extra: usm
13
+ Requires-Dist: ffmpeg-python; extra == "usm"
14
+ Dynamic: classifier
15
+ Dynamic: description
16
+ Dynamic: description-content-type
17
+ Dynamic: home-page
18
+ Dynamic: license-file
19
+ Dynamic: provides-extra
20
+ Dynamic: requires-python
21
+ Dynamic: summary
22
+
23
+ PyCriCodecsEx
24
+ ---
25
+ A continuation of @Youjose's work on Criware formats. Feautres are still in flux and subject to change. When in doubt, Refer to the [original repo](https://github.com/Youjose/PyCriCodecs) for more information.
26
+
27
+ Detailed documentation, installation instructions are available at https://mos9527.com/PyCriCodecsEx
28
+
29
+
30
+ # Credits
31
+ - https://github.com/Youjose/PyCriCodecs
32
+ - https://github.com/Mikewando/PyCriCodecs ([PR#1 on USM](https://github.com/mos9527/PyCriCodecsEx/pull/1))
33
+ - https://github.com/donmai-me/WannaCRI
34
+ - https://github.com/vgmstream/vgmstream
35
+ - https://github.com/K0lb3/UnityPy (For CI script)
@@ -0,0 +1,15 @@
1
+ CriCodecsEx.cp313-win32.pyd,sha256=Q_khnirGAPm97kw759Fnq59RBYZd5k3T2a3luYNCWOE,68096
2
+ PyCriCodecsEx/__init__.py,sha256=4dCrvStS1OgE3Vlcv-qx5-TAo377yOMEToEqCi-PwY4,23
3
+ PyCriCodecsEx/acb.py,sha256=nOWggyQTPOBArzRp_7VRO9TY1diLxr2mRPKQd-sd2s0,10723
4
+ PyCriCodecsEx/adx.py,sha256=s3gJBgKrwWjUahrxSJEy1GNHJrdz3iaylgr0TyTIi7M,5967
5
+ PyCriCodecsEx/awb.py,sha256=t6owuEOH3Be31iBuEMwriOh0cPdVtpzsNbTPfLwg_cc,6363
6
+ PyCriCodecsEx/chunk.py,sha256=xmc92tONmXpdbOW2g-KckTeppTXFo8Km0J95UYbbvQg,2810
7
+ PyCriCodecsEx/cpk.py,sha256=bMJgvzPInM95R9dEdhHGW65jR9tFBKUacyOwZS2gOyA,38206
8
+ PyCriCodecsEx/hca.py,sha256=BamujR3tRxMmgnPAYpUOamzOUOBs5hXWhkcBnj7Eeh4,19445
9
+ PyCriCodecsEx/usm.py,sha256=LWSXXkfV1FZpymV0X6UH-lyS5gV6ecBHlLLXXXN9wMc,36972
10
+ PyCriCodecsEx/utf.py,sha256=0LBzpIbJiyL_4KOf_QpEJytr3PbHj8_M4Bd-Lay4wuk,28247
11
+ pycricodecsex-0.0.3.dist-info/licenses/LICENSE,sha256=B47Qr_82CmMyuL-wNFAH_P6PNJWaonv5dxo9MfgjEXw,1083
12
+ pycricodecsex-0.0.3.dist-info/METADATA,sha256=buywcqSll1E63mnWNtEgwHiyAY8NbvMyP8CDLXAJLH0,1291
13
+ pycricodecsex-0.0.3.dist-info/WHEEL,sha256=0ABLuJ37exXk5N_efmYNs2NU9NK1K2Qlod_6bYkofEA,97
14
+ pycricodecsex-0.0.3.dist-info/top_level.txt,sha256=mSrrEse9hT0s6nl-sWAQWAhNRuZ6jo98pbFoN3L2MXk,26
15
+ pycricodecsex-0.0.3.dist-info/RECORD,,
@@ -1,81 +0,0 @@
1
- Metadata-Version: 2.4
2
- Name: PyCriCodecsEx
3
- Version: 0.0.1
4
- Summary: Criware formats library for Python
5
- Home-page: https://github.com/mos9527/PyCriCodecsEx
6
- Classifier: Programming Language :: Python :: 3
7
- Classifier: License :: OSI Approved :: MIT License
8
- Classifier: Operating System :: OS Independent
9
- Requires-Python: >=3.10
10
- Description-Content-Type: text/markdown
11
- License-File: LICENSE
12
- Provides-Extra: usm
13
- Requires-Dist: ffmpeg-python; extra == "usm"
14
- Dynamic: classifier
15
- Dynamic: description
16
- Dynamic: description-content-type
17
- Dynamic: home-page
18
- Dynamic: license-file
19
- Dynamic: provides-extra
20
- Dynamic: requires-python
21
- Dynamic: summary
22
-
23
- # PyCriCodecsEx
24
- A continuation of @Youjose's work on Criware formats. Feautres are still in flux and subject to change. When in doubt, Refer to the [original repo](https://github.com/Youjose/PyCriCodecs) for more information.
25
-
26
- # Installation
27
- ```bash
28
- pip install PyCriCodecsEx
29
- ```
30
-
31
- For USM features, you need `ffmpeg` installed and available in your PATH. See also https://github.com/kkroening/ffmpeg-python?tab=readme-ov-file#installing-ffmpeg
32
-
33
- ## Features
34
- If not otherwise mentioned, all features marked with [x] are considered working, and has been verified with official tools.
35
-
36
- ### ACB Cue sheets (also AWB)
37
- - [x] Editing & Saving (Scripting APIs. Helper functions TODO. see examples in [Tests](https://github.com/mos9527/PyCriCodecsEx/tree/main/Tests))
38
- ### USM Sofdec2 (Encode & Decode)
39
- #### Audio Stream
40
- For audio to be muxed in, you need a PCM WAV sample with NO metadata, which can be produced with e.g.:
41
- ```bash
42
- ffmpeg -i input.mp3 -vn -c:a pcm_s16le -map_metadata -1 output.wav
43
- ```
44
- Decoding and Encoded format can be the following:
45
- - [x] HCA
46
- - [x] ADX
47
- #### Video Stream
48
- **NOTE**: You definitely want to tweak these encode settings a bit.
49
- - [x] Sofdec Prime (MPEG1, from `.m1v` container)
50
- - Prepare source file with: `ffmpeg -i <input_file> -c:v mpeg1video -an <output_file>.m1v`
51
- - [x] H264 (from `.h264` raw container)
52
- - Prepare source file with: `ffmpeg -i <input_file> -c:v libx264 -an <output_file>.h264`
53
- - [x] VP9 (from `.ivf` container)
54
- - Prepare source file with: `ffmpeg -i <input_file> -c:v libvpx -an <output_file>.ivf`
55
- ### HCA Audio Codec
56
- - [x] Decoding (up to version 3.0)
57
- - [x] Encoding (up to version 3.0)
58
- ### ADX Audio Codec
59
- - [x] Decoding
60
- - [x] Encoding
61
- ### CPK
62
- - [x] Unpacking
63
- - [x] Packing
64
-
65
- ## Roadmap
66
- - [ ] ACB Extraction (Massive TODO. see also https://github.com/mos9527/PyCriCodecsEx/blob/main/Research/ACBSchema.py)
67
- - [ ] Interface for encode tasks (CLI then maybe GUI?)
68
- - [ ] Documentation
69
- - [ ] C/C++ port + FFI
70
- ## Currently Known Bugs
71
- - USM seeking does not work. Though most games don't use it anyways.
72
- - Not important, and might not fix: ADX encoding and decoding at higher bitdepths (11-15) adds popping noise.
73
- - Some CPK's that has the same filename for every file in the entry will overwrite each other.
74
- - Probably many more I am unaware of, report if you find any.
75
-
76
- # Credits
77
- - https://github.com/Youjose/PyCriCodecs
78
- - https://github.com/Mikewando/PyCriCodecs ([PR#1 on USM](https://github.com/mos9527/PyCriCodecsEx/pull/1))
79
- - https://github.com/donmai-me/WannaCRI
80
- - https://github.com/vgmstream/vgmstream
81
- - https://github.com/K0lb3/UnityPy (For CI script)
@@ -1,15 +0,0 @@
1
- CriCodecsEx.cp313-win32.pyd,sha256=q4RPqSn2gv7HkabfcUgmJETmttzgM-RP1rpUQOGXX0U,68096
2
- PyCriCodecsEx/__init__.py,sha256=ry5O5SW74ugwOUMKSV2_LbWjYa8B0IEvUm7S-lHPA2c,23
3
- PyCriCodecsEx/acb.py,sha256=v0CxjveQewxUWuila1O0qDGcAfvOxqnzYqAL4AHneqU,2706
4
- PyCriCodecsEx/adx.py,sha256=KnL4wy1ccoc6uHYZVino7cJQB2pMn4BbRhpH3r527TY,777
5
- PyCriCodecsEx/awb.py,sha256=p68tVqZOorOE1Js-w1Sqy4GMvu9gxzlBgUL2LAUNEqU,5657
6
- PyCriCodecsEx/chunk.py,sha256=nrRUANDFZ1LDszHEGDDnQDuNnAB_kGCzbpC7bsgtjqc,2504
7
- PyCriCodecsEx/cpk.py,sha256=AKShN6P7p70i3GQfKKS-VH3mkbexOLfHEJrjuxS0SQQ,37692
8
- PyCriCodecsEx/hca.py,sha256=lSslLyv1D1zM_kHFyOlKpbM7qzghmJDYRd-isP8qcyg,14192
9
- PyCriCodecsEx/usm.py,sha256=X4mv-3ksiX10C6EDACpu-dwRn9eSy3wmY7of2aO7eiA,46216
10
- PyCriCodecsEx/utf.py,sha256=Yp1Le3AS7UC4So_sGO39N5X5D23X7MsWugHo52npwR0,28256
11
- pycricodecsex-0.0.1.dist-info/licenses/LICENSE,sha256=B47Qr_82CmMyuL-wNFAH_P6PNJWaonv5dxo9MfgjEXw,1083
12
- pycricodecsex-0.0.1.dist-info/METADATA,sha256=Z4KAoITGoFoNhiiJ_YXSnrBE--W51_Q-pXt3lerFMX8,3324
13
- pycricodecsex-0.0.1.dist-info/WHEEL,sha256=0ABLuJ37exXk5N_efmYNs2NU9NK1K2Qlod_6bYkofEA,97
14
- pycricodecsex-0.0.1.dist-info/top_level.txt,sha256=mSrrEse9hT0s6nl-sWAQWAhNRuZ6jo98pbFoN3L2MXk,26
15
- pycricodecsex-0.0.1.dist-info/RECORD,,