tamagoarc 1.0.0__tar.gz
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.
- tamagoarc-1.0.0/.github/workflows/publish.yml +35 -0
- tamagoarc-1.0.0/.gitignore +35 -0
- tamagoarc-1.0.0/CHANGELOG.md +31 -0
- tamagoarc-1.0.0/LICENSE +7 -0
- tamagoarc-1.0.0/Makefile +13 -0
- tamagoarc-1.0.0/PKG-INFO +21 -0
- tamagoarc-1.0.0/README.md +114 -0
- tamagoarc-1.0.0/hatch_build.py +36 -0
- tamagoarc-1.0.0/local.toml.example +3 -0
- tamagoarc-1.0.0/pyproject.toml +218 -0
- tamagoarc-1.0.0/scripts/analyze_tpm.py +804 -0
- tamagoarc-1.0.0/scripts/curate_tlg_samples.py +412 -0
- tamagoarc-1.0.0/scripts/extract_tlg_samples.py +207 -0
- tamagoarc-1.0.0/scripts/extract_trial_zips.py +191 -0
- tamagoarc-1.0.0/scripts/identify_encryption.py +1025 -0
- tamagoarc-1.0.0/scripts/survey_engines.py +350 -0
- tamagoarc-1.0.0/scripts/survey_installed_games.py +432 -0
- tamagoarc-1.0.0/scripts/survey_tlg_samples.py +462 -0
- tamagoarc-1.0.0/src/tamago/__about__.py +1 -0
- tamagoarc-1.0.0/src/tamago/__init__.py +3 -0
- tamagoarc-1.0.0/src/tamago/cli.py +169 -0
- tamagoarc-1.0.0/src/tamago/formats/__init__.py +0 -0
- tamagoarc-1.0.0/src/tamago/formats/advhd/__init__.py +22 -0
- tamagoarc-1.0.0/src/tamago/formats/advhd/arcfile.py +308 -0
- tamagoarc-1.0.0/src/tamago/formats/advhd/handler.py +19 -0
- tamagoarc-1.0.0/src/tamago/formats/det/__init__.py +11 -0
- tamagoarc-1.0.0/src/tamago/formats/det/detfile.py +529 -0
- tamagoarc-1.0.0/src/tamago/formats/det/handler.py +28 -0
- tamagoarc-1.0.0/src/tamago/formats/gsp/__init__.py +17 -0
- tamagoarc-1.0.0/src/tamago/formats/gsp/gspfile.py +255 -0
- tamagoarc-1.0.0/src/tamago/formats/gsp/handler.py +19 -0
- tamagoarc-1.0.0/src/tamago/formats/gsp/spt_crypto.py +143 -0
- tamagoarc-1.0.0/src/tamago/formats/xp3/__init__.py +16 -0
- tamagoarc-1.0.0/src/tamago/formats/xp3/_tlg_accel.c +508 -0
- tamagoarc-1.0.0/src/tamago/formats/xp3/detect.py +532 -0
- tamagoarc-1.0.0/src/tamago/formats/xp3/encryption/__init__.py +29 -0
- tamagoarc-1.0.0/src/tamago/formats/xp3/encryption/base.py +33 -0
- tamagoarc-1.0.0/src/tamago/formats/xp3/encryption/cxcrypt.py +571 -0
- tamagoarc-1.0.0/src/tamago/formats/xp3/encryption/fixed_xor.py +51 -0
- tamagoarc-1.0.0/src/tamago/formats/xp3/encryption/hash_derived.py +27 -0
- tamagoarc-1.0.0/src/tamago/formats/xp3/encryption/hash_xor.py +34 -0
- tamagoarc-1.0.0/src/tamago/formats/xp3/encryption/null.py +21 -0
- tamagoarc-1.0.0/src/tamago/formats/xp3/encryption/pinpoint.py +51 -0
- tamagoarc-1.0.0/src/tamago/formats/xp3/encryption_library.toml +1783 -0
- tamagoarc-1.0.0/src/tamago/formats/xp3/handler.py +74 -0
- tamagoarc-1.0.0/src/tamago/formats/xp3/models.py +230 -0
- tamagoarc-1.0.0/src/tamago/formats/xp3/tlg.py +970 -0
- tamagoarc-1.0.0/src/tamago/formats/xp3/unencrypted_library.toml +360 -0
- tamagoarc-1.0.0/src/tamago/formats/xp3/xp3file.py +335 -0
- tamagoarc-1.0.0/src/tamago/tests/__init__.py +0 -0
- tamagoarc-1.0.0/src/tamago/tests/advhd/__init__.py +0 -0
- tamagoarc-1.0.0/src/tamago/tests/advhd/test_arcfile.py +590 -0
- tamagoarc-1.0.0/src/tamago/tests/advhd/test_lzss.py +83 -0
- tamagoarc-1.0.0/src/tamago/tests/det/__init__.py +0 -0
- tamagoarc-1.0.0/src/tamago/tests/det/test_compress.py +59 -0
- tamagoarc-1.0.0/src/tamago/tests/det/test_decompress.py +44 -0
- tamagoarc-1.0.0/src/tamago/tests/det/test_detfile.py +525 -0
- tamagoarc-1.0.0/src/tamago/tests/det/test_nonfree.py +69 -0
- tamagoarc-1.0.0/src/tamago/tests/gsp/__init__.py +0 -0
- tamagoarc-1.0.0/src/tamago/tests/gsp/test_gspfile.py +531 -0
- tamagoarc-1.0.0/src/tamago/tests/gsp/test_spt_crypto.py +120 -0
- tamagoarc-1.0.0/src/tamago/tests/test_cli.py +73 -0
- tamagoarc-1.0.0/src/tamago/tests/xp3/__init__.py +0 -0
- tamagoarc-1.0.0/src/tamago/tests/xp3/samples/cheshire_4x4.tlg +0 -0
- tamagoarc-1.0.0/src/tamago/tests/xp3/samples/cheshire_4x4_tlg0.tlg +0 -0
- tamagoarc-1.0.0/src/tamago/tests/xp3/samples/empty_file.xp3 +0 -0
- tamagoarc-1.0.0/src/tamago/tests/xp3/samples/encrypted_shift5_with_png.xp3 +0 -0
- tamagoarc-1.0.0/src/tamago/tests/xp3/samples/encrypted_with_png.xp3 +0 -0
- tamagoarc-1.0.0/src/tamago/tests/xp3/samples/multi_compressed.xp3 +0 -0
- tamagoarc-1.0.0/src/tamago/tests/xp3/samples/multi_encrypted.xp3 +0 -0
- tamagoarc-1.0.0/src/tamago/tests/xp3/samples/owari02.tlg +0 -0
- tamagoarc-1.0.0/src/tamago/tests/xp3/samples/rabbit_4x2_lzss.tlg +0 -0
- tamagoarc-1.0.0/src/tamago/tests/xp3/samples/red_2x2.tlg +0 -0
- tamagoarc-1.0.0/src/tamago/tests/xp3/samples/single_compressed.xp3 +0 -0
- tamagoarc-1.0.0/src/tamago/tests/xp3/samples/single_encrypted_compressed.xp3 +0 -0
- tamagoarc-1.0.0/src/tamago/tests/xp3/samples/single_encrypted_uncompressed.xp3 +0 -0
- tamagoarc-1.0.0/src/tamago/tests/xp3/samples/single_uncompressed.xp3 +0 -0
- tamagoarc-1.0.0/src/tamago/tests/xp3/samples/transparent_2x2.tlg +0 -0
- tamagoarc-1.0.0/src/tamago/tests/xp3/samples/with_tlg.xp3 +0 -0
- tamagoarc-1.0.0/src/tamago/tests/xp3/test_cli.py +35 -0
- tamagoarc-1.0.0/src/tamago/tests/xp3/test_cxcrypt.py +258 -0
- tamagoarc-1.0.0/src/tamago/tests/xp3/test_detect.py +303 -0
- tamagoarc-1.0.0/src/tamago/tests/xp3/test_encryption.py +356 -0
- tamagoarc-1.0.0/src/tamago/tests/xp3/test_identify_encryption.py +262 -0
- tamagoarc-1.0.0/src/tamago/tests/xp3/test_models.py +68 -0
- tamagoarc-1.0.0/src/tamago/tests/xp3/test_nonfree.py +105 -0
- tamagoarc-1.0.0/src/tamago/tests/xp3/test_nonfree_tlg.py +122 -0
- tamagoarc-1.0.0/src/tamago/tests/xp3/test_tlg.py +232 -0
- tamagoarc-1.0.0/src/tamago/tests/xp3/test_xp3file.py +354 -0
- tamagoarc-1.0.0/tamago/formats/xp3/_tlg_accel.cpython-312-x86_64-linux-gnu.so +0 -0
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
name: Publish to PyPI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
release:
|
|
5
|
+
types: [published]
|
|
6
|
+
|
|
7
|
+
jobs:
|
|
8
|
+
build:
|
|
9
|
+
runs-on: ubuntu-latest
|
|
10
|
+
steps:
|
|
11
|
+
- uses: actions/checkout@v4
|
|
12
|
+
- uses: actions/setup-python@v5
|
|
13
|
+
with:
|
|
14
|
+
python-version: "3.12"
|
|
15
|
+
- name: Install Hatch
|
|
16
|
+
run: pip install hatch
|
|
17
|
+
- name: Build
|
|
18
|
+
run: hatch build
|
|
19
|
+
- uses: actions/upload-artifact@v4
|
|
20
|
+
with:
|
|
21
|
+
name: dist
|
|
22
|
+
path: dist/
|
|
23
|
+
|
|
24
|
+
publish:
|
|
25
|
+
needs: build
|
|
26
|
+
runs-on: ubuntu-latest
|
|
27
|
+
environment: pypi
|
|
28
|
+
permissions:
|
|
29
|
+
id-token: write
|
|
30
|
+
steps:
|
|
31
|
+
- uses: actions/download-artifact@v4
|
|
32
|
+
with:
|
|
33
|
+
name: dist
|
|
34
|
+
path: dist/
|
|
35
|
+
- uses: pypa/gh-action-pypi-publish@release/v1
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
# Virtual environments
|
|
2
|
+
.venv/
|
|
3
|
+
|
|
4
|
+
# Python
|
|
5
|
+
__pycache__/
|
|
6
|
+
*.py[cod]
|
|
7
|
+
*.egg-info/
|
|
8
|
+
*.egg
|
|
9
|
+
*.so
|
|
10
|
+
dist/
|
|
11
|
+
build/
|
|
12
|
+
|
|
13
|
+
# Testing
|
|
14
|
+
.pytest_cache/
|
|
15
|
+
.coverage
|
|
16
|
+
htmlcov/
|
|
17
|
+
|
|
18
|
+
# IDE
|
|
19
|
+
.idea/
|
|
20
|
+
.vscode/
|
|
21
|
+
*.swp
|
|
22
|
+
*.swo
|
|
23
|
+
|
|
24
|
+
# OS
|
|
25
|
+
.DS_Store
|
|
26
|
+
Thumbs.db
|
|
27
|
+
|
|
28
|
+
# Local settings
|
|
29
|
+
local.toml
|
|
30
|
+
|
|
31
|
+
# frida-server, for local dev
|
|
32
|
+
frida-server.exe
|
|
33
|
+
|
|
34
|
+
# Nonfree test samples (real game data, not distributable)
|
|
35
|
+
src/tamago/tests/*/nonfree/
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to this project will be documented in this file.
|
|
4
|
+
|
|
5
|
+
## 1.0.0 — 2026-04-14
|
|
6
|
+
|
|
7
|
+
Initial release.
|
|
8
|
+
|
|
9
|
+
### Features
|
|
10
|
+
|
|
11
|
+
- Unified CLI (`tamago`) with `extract`, `create`, and `identify` commands
|
|
12
|
+
- Auto-detection of archive formats by magic bytes
|
|
13
|
+
- Python API for reading and writing archives
|
|
14
|
+
- Plugin system for format handlers and XP3 encryption schemes
|
|
15
|
+
|
|
16
|
+
### Supported formats
|
|
17
|
+
|
|
18
|
+
- **XP3** ([KiriKiri](https://github.com/kenkyuuka/research-vault/blob/main/engines/KiriKiri.md)) — extract and create, with encryption support
|
|
19
|
+
- **DET** ([μ-GameOperationSystem](https://github.com/kenkyuuka/research-vault/blob/main/engines/%CE%BC-GameOperationSystem.md)) — extract and create, ATM and AT2 index formats
|
|
20
|
+
- **GSP** ([AGSD](https://github.com/kenkyuuka/research-vault/blob/main/engines/AGSD.md)) — extract and create
|
|
21
|
+
- **ARC** (AdvHD / WillPlus V2) — extract and create, with script decryption and LZSS decompression
|
|
22
|
+
|
|
23
|
+
### XP3 encryption
|
|
24
|
+
|
|
25
|
+
- Automatic encryption detection (TPM hash lookup, XP3 structure hash, probing)
|
|
26
|
+
- Built-in schemes: hash-xor, fixed-xor, null, poringsoft, cxcrypt, pinpoint
|
|
27
|
+
- Known-game database (`encryption_library.toml`)
|
|
28
|
+
|
|
29
|
+
### Images
|
|
30
|
+
|
|
31
|
+
- TLG image decoding (TLG5, TLG6) with optional Pillow integration
|
tamagoarc-1.0.0/LICENSE
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
Copyright 2026 Kenkyuuka <kenkyuuka@proton.me>
|
|
2
|
+
|
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
|
4
|
+
|
|
5
|
+
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
|
6
|
+
|
|
7
|
+
THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
tamagoarc-1.0.0/Makefile
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
.PHONY: test
|
|
2
|
+
test:
|
|
3
|
+
hatch run test
|
|
4
|
+
|
|
5
|
+
.PHONY: reinstall
|
|
6
|
+
reinstall:
|
|
7
|
+
hatch env prune && hatch env create
|
|
8
|
+
|
|
9
|
+
.PHONY: help
|
|
10
|
+
help: ## Show this help
|
|
11
|
+
@grep -E '^[a-zA-Z_-]+:.*##' $(MAKEFILE_LIST) | awk -F ':.*## ' '{printf " \033[36m%-16s\033[0m %s\n", $$1, $$2}'
|
|
12
|
+
|
|
13
|
+
.DEFAULT_GOAL := help
|
tamagoarc-1.0.0/PKG-INFO
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: tamagoarc
|
|
3
|
+
Version: 1.0.0
|
|
4
|
+
Summary: Multi-format game archive tool
|
|
5
|
+
Project-URL: Homepage, https://github.com/kenkyuuka/tamago
|
|
6
|
+
Project-URL: Issues, https://github.com/kenkyuuka/tamago/issues
|
|
7
|
+
Project-URL: Source, https://github.com/kenkyuuka/tamago
|
|
8
|
+
Author-email: Kenkyuuka <kenkyuuka@proton.me>
|
|
9
|
+
License-Expression: MIT
|
|
10
|
+
License-File: LICENSE
|
|
11
|
+
Classifier: Development Status :: 4 - Beta
|
|
12
|
+
Classifier: Programming Language :: Python
|
|
13
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
16
|
+
Classifier: Programming Language :: Python :: Implementation :: CPython
|
|
17
|
+
Classifier: Programming Language :: Python :: Implementation :: PyPy
|
|
18
|
+
Requires-Python: >=3.10
|
|
19
|
+
Requires-Dist: construct>=2.10
|
|
20
|
+
Provides-Extra: images
|
|
21
|
+
Requires-Dist: pillow>=9.0; extra == 'images'
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
# tamago
|
|
2
|
+
|
|
3
|
+
Multi-format game archive toolkit.
|
|
4
|
+
|
|
5
|
+
Requires Python 3.10 or later.
|
|
6
|
+
|
|
7
|
+
## Supported formats
|
|
8
|
+
|
|
9
|
+
| Format | Engine | Extract | Create |
|
|
10
|
+
|--------|--------|:-------:|:------:|
|
|
11
|
+
| XP3 | [KiriKiri](https://github.com/kenkyuuka/research-vault/blob/main/engines/KiriKiri.md) | yes | yes |
|
|
12
|
+
| DET | [μ-GameOperationSystem](https://github.com/kenkyuuka/research-vault/blob/main/engines/%CE%BC-GameOperationSystem.md) | yes | yes |
|
|
13
|
+
| GSP | [AGSD](https://github.com/kenkyuuka/research-vault/blob/main/engines/AGSD.md) | yes | yes |
|
|
14
|
+
| ARC | AdvHD (WillPlus V2) | yes | yes |
|
|
15
|
+
|
|
16
|
+
## Installation
|
|
17
|
+
|
|
18
|
+
```console
|
|
19
|
+
pip install tamagoarc
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
To enable TLG image conversion, install with the `images` extra:
|
|
23
|
+
|
|
24
|
+
```console
|
|
25
|
+
pip install tamagoarc[images]
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
## Usage
|
|
29
|
+
|
|
30
|
+
### tamago CLI
|
|
31
|
+
|
|
32
|
+
tamago auto-detects archive formats by magic bytes and, for XP3 archives, automatically identifies the correct encryption scheme.
|
|
33
|
+
|
|
34
|
+
```console
|
|
35
|
+
# Identify an archive's format
|
|
36
|
+
tamago identify data.xp3
|
|
37
|
+
|
|
38
|
+
# Extract an archive (auto-detects format and encryption)
|
|
39
|
+
tamago extract data.xp3 output_dir
|
|
40
|
+
|
|
41
|
+
# Use format subcommands for format-specific options
|
|
42
|
+
tamago xp3 extract data.xp3 output_dir --encryption hash-xor --key 3
|
|
43
|
+
tamago det create source_dir output.det --index-format atm
|
|
44
|
+
|
|
45
|
+
# Create an archive (format must be specified)
|
|
46
|
+
tamago create --format xp3 source_dir output.xp3
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
### Python API
|
|
50
|
+
|
|
51
|
+
```python
|
|
52
|
+
from tamago.formats.xp3 import XP3File
|
|
53
|
+
|
|
54
|
+
# Extract an archive
|
|
55
|
+
with XP3File("data.xp3") as xp3:
|
|
56
|
+
xp3.extract_all("output_dir")
|
|
57
|
+
|
|
58
|
+
# Extract with explicit encryption
|
|
59
|
+
from tamago.formats.xp3.encryption import HashXorEncryption
|
|
60
|
+
|
|
61
|
+
enc = HashXorEncryption(shift=3)
|
|
62
|
+
with XP3File("data.xp3", encryption=enc) as xp3:
|
|
63
|
+
xp3.extract_all("output_dir")
|
|
64
|
+
|
|
65
|
+
# Auto-detect encryption
|
|
66
|
+
from tamago.formats.xp3.detect import auto_detect
|
|
67
|
+
|
|
68
|
+
enc = auto_detect("data.xp3")
|
|
69
|
+
with XP3File("data.xp3", encryption=enc) as xp3:
|
|
70
|
+
xp3.extract_all("output_dir")
|
|
71
|
+
|
|
72
|
+
# Create an archive
|
|
73
|
+
from pathlib import Path
|
|
74
|
+
|
|
75
|
+
with XP3File("output.xp3", "x") as xp3:
|
|
76
|
+
xp3.write_all(Path("source_dir"))
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
## XP3 Encryption
|
|
80
|
+
|
|
81
|
+
XP3 archives used by KiriKiri games are often encrypted with a game-specific scheme implemented in a `.tpm` plugin. tamago supports the encryption used by several games (including automatic detection of the encryption).
|
|
82
|
+
|
|
83
|
+
If the game you are interested in is not supported, please raise an issue, including a VNDB link to the game.
|
|
84
|
+
|
|
85
|
+
## Development
|
|
86
|
+
|
|
87
|
+
This project uses [Hatch](https://hatch.pypa.io/) as the build system.
|
|
88
|
+
|
|
89
|
+
### Setup
|
|
90
|
+
|
|
91
|
+
```console
|
|
92
|
+
pip install hatch
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
### Running tests
|
|
96
|
+
|
|
97
|
+
```console
|
|
98
|
+
hatch run test # run all tests
|
|
99
|
+
hatch run test -k test_name # run a single test by name
|
|
100
|
+
hatch run cov # tests + coverage report
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
### Linting and formatting
|
|
104
|
+
|
|
105
|
+
```console
|
|
106
|
+
hatch run lint:style # check style (ruff + black)
|
|
107
|
+
hatch run lint:typing # type checking (mypy)
|
|
108
|
+
hatch run lint:fmt # auto-format (black + ruff --fix)
|
|
109
|
+
hatch run lint:all # style + typing
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
## License
|
|
113
|
+
|
|
114
|
+
tamago is distributed under the terms of the [MIT license](LICENSE).
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
"""Custom hatch build hook to compile the TLG C accelerator extension."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import os
|
|
6
|
+
import subprocess
|
|
7
|
+
import sysconfig
|
|
8
|
+
|
|
9
|
+
from hatchling.builders.hooks.plugin.interface import BuildHookInterface
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class CustomBuildHook(BuildHookInterface):
|
|
13
|
+
PLUGIN_NAME = 'custom'
|
|
14
|
+
|
|
15
|
+
def initialize(self, version, build_data):
|
|
16
|
+
src = os.path.join(self.root, 'src', 'tamago', 'formats', 'xp3', '_tlg_accel.c')
|
|
17
|
+
if not os.path.exists(src):
|
|
18
|
+
return
|
|
19
|
+
|
|
20
|
+
ext_suffix = sysconfig.get_config_var('EXT_SUFFIX') or '.so'
|
|
21
|
+
out_name = f'_tlg_accel{ext_suffix}'
|
|
22
|
+
out_path = os.path.join(self.root, 'src', 'tamago', 'formats', 'xp3', out_name)
|
|
23
|
+
include = sysconfig.get_path('include')
|
|
24
|
+
|
|
25
|
+
try:
|
|
26
|
+
subprocess.check_call(
|
|
27
|
+
['gcc', '-O2', '-shared', '-fPIC', f'-I{include}', '-o', out_path, src],
|
|
28
|
+
stderr=subprocess.PIPE,
|
|
29
|
+
)
|
|
30
|
+
except (subprocess.CalledProcessError, FileNotFoundError):
|
|
31
|
+
# C compilation failed; pure-Python fallback will be used at runtime.
|
|
32
|
+
return
|
|
33
|
+
|
|
34
|
+
# Include the compiled .so in the wheel.
|
|
35
|
+
rel_path = os.path.join('tamago', 'formats', 'xp3', out_name)
|
|
36
|
+
build_data['force_include'][out_path] = rel_path
|
|
@@ -0,0 +1,218 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["hatchling"]
|
|
3
|
+
build-backend = "hatchling.build"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "tamagoarc"
|
|
7
|
+
dynamic = ["version"]
|
|
8
|
+
description = "Multi-format game archive tool"
|
|
9
|
+
requires-python = ">=3.10"
|
|
10
|
+
license = "MIT"
|
|
11
|
+
keywords = []
|
|
12
|
+
authors = [
|
|
13
|
+
{ name = "Kenkyuuka", email = "kenkyuuka@proton.me" },
|
|
14
|
+
]
|
|
15
|
+
classifiers = [
|
|
16
|
+
"Development Status :: 4 - Beta",
|
|
17
|
+
"Programming Language :: Python",
|
|
18
|
+
"Programming Language :: Python :: 3.10",
|
|
19
|
+
"Programming Language :: Python :: 3.11",
|
|
20
|
+
"Programming Language :: Python :: 3.12",
|
|
21
|
+
"Programming Language :: Python :: Implementation :: CPython",
|
|
22
|
+
"Programming Language :: Python :: Implementation :: PyPy",
|
|
23
|
+
]
|
|
24
|
+
dependencies = ["construct>=2.10"]
|
|
25
|
+
|
|
26
|
+
[project.urls]
|
|
27
|
+
Homepage = "https://github.com/kenkyuuka/tamago"
|
|
28
|
+
Issues = "https://github.com/kenkyuuka/tamago/issues"
|
|
29
|
+
Source = "https://github.com/kenkyuuka/tamago"
|
|
30
|
+
|
|
31
|
+
[project.optional-dependencies]
|
|
32
|
+
images = ["Pillow>=9.0"]
|
|
33
|
+
|
|
34
|
+
[project.scripts]
|
|
35
|
+
tamago = "tamago.cli:main"
|
|
36
|
+
|
|
37
|
+
[project.entry-points."tamago.formats"]
|
|
38
|
+
xp3 = "tamago.formats.xp3.handler:XP3Handler"
|
|
39
|
+
det = "tamago.formats.det.handler:DETHandler"
|
|
40
|
+
gsp = "tamago.formats.gsp.handler:GSPHandler"
|
|
41
|
+
advhd = "tamago.formats.advhd.handler:ARCHandler"
|
|
42
|
+
|
|
43
|
+
[project.entry-points."tamago.formats.xp3.encryption"]
|
|
44
|
+
fixed-xor = "tamago.formats.xp3.encryption.fixed_xor:FixedXorEncryption"
|
|
45
|
+
hash-xor = "tamago.formats.xp3.encryption.hash_xor:HashXorEncryption"
|
|
46
|
+
null = "tamago.formats.xp3.encryption.null:NullEncryption"
|
|
47
|
+
poringsoft = "tamago.formats.xp3.encryption.hash_derived:PoringSoftEncryption"
|
|
48
|
+
cxcrypt = "tamago.formats.xp3.encryption.cxcrypt:CxEncryption"
|
|
49
|
+
pinpoint = "tamago.formats.xp3.encryption.pinpoint:PinPointEncryption"
|
|
50
|
+
|
|
51
|
+
[tool.hatch.build.hooks.custom]
|
|
52
|
+
|
|
53
|
+
[tool.hatch.version]
|
|
54
|
+
path = "src/tamago/__about__.py"
|
|
55
|
+
|
|
56
|
+
[tool.hatch.envs.default]
|
|
57
|
+
dependencies = [
|
|
58
|
+
"coverage[toml]>=6.5",
|
|
59
|
+
"pytest",
|
|
60
|
+
"pytest-xdist",
|
|
61
|
+
"frida-tools",
|
|
62
|
+
"Pillow>=9.0",
|
|
63
|
+
]
|
|
64
|
+
|
|
65
|
+
[tool.hatch.envs.default.scripts]
|
|
66
|
+
test = "pytest -n auto --maxprocesses 8 src/tamago/tests {args}"
|
|
67
|
+
test-xp3 = "pytest -n auto --maxprocesses 8 src/tamago/tests/xp3 {args}"
|
|
68
|
+
test-det = "pytest -n auto --maxprocesses 8 src/tamago/tests/det {args}"
|
|
69
|
+
test-gsp = "pytest -n auto --maxprocesses 8 src/tamago/tests/gsp {args}"
|
|
70
|
+
test-advhd = "pytest -n auto --maxprocesses 8 src/tamago/tests/advhd {args}"
|
|
71
|
+
test-tamago = "pytest -n auto --maxprocesses 8 src/tamago/tests/test_cli.py {args}"
|
|
72
|
+
test-nonfree = "pytest -n auto --maxprocesses 8 src/tamago/tests -m nonfree {args}"
|
|
73
|
+
test-cov = "coverage run -m pytest -n auto --maxprocesses 8 src/tamago/tests {args}"
|
|
74
|
+
|
|
75
|
+
cov-report = [
|
|
76
|
+
"- coverage combine",
|
|
77
|
+
"coverage report",
|
|
78
|
+
]
|
|
79
|
+
cov = [
|
|
80
|
+
"test-cov",
|
|
81
|
+
"cov-report",
|
|
82
|
+
]
|
|
83
|
+
|
|
84
|
+
[tool.hatch.envs.hatch-test]
|
|
85
|
+
extra-dependencies = [
|
|
86
|
+
"Pillow>=9.0",
|
|
87
|
+
]
|
|
88
|
+
|
|
89
|
+
[[tool.hatch.envs.all.matrix]]
|
|
90
|
+
python = ["3.10", "3.11", "3.12"]
|
|
91
|
+
|
|
92
|
+
[tool.hatch.envs.lint]
|
|
93
|
+
dependencies = [
|
|
94
|
+
"black>=23.1.0",
|
|
95
|
+
"mypy>=1.0.0",
|
|
96
|
+
"pytest",
|
|
97
|
+
"ruff>=0.0.243",
|
|
98
|
+
]
|
|
99
|
+
[tool.hatch.envs.lint.scripts]
|
|
100
|
+
typing = "mypy --install-types --non-interactive {args:src/tamago}"
|
|
101
|
+
style = [
|
|
102
|
+
"ruff check {args:.}",
|
|
103
|
+
"black --check --diff {args:.}",
|
|
104
|
+
]
|
|
105
|
+
fmt = [
|
|
106
|
+
"black {args:.}",
|
|
107
|
+
"ruff check --fix {args:.}",
|
|
108
|
+
"style",
|
|
109
|
+
]
|
|
110
|
+
all = [
|
|
111
|
+
"style",
|
|
112
|
+
"typing",
|
|
113
|
+
]
|
|
114
|
+
|
|
115
|
+
[tool.black]
|
|
116
|
+
target-version = ["py310"]
|
|
117
|
+
line-length = 120
|
|
118
|
+
skip-string-normalization = true
|
|
119
|
+
|
|
120
|
+
[tool.ruff]
|
|
121
|
+
target-version = "py310"
|
|
122
|
+
line-length = 120
|
|
123
|
+
extend-exclude = ["scripts", "packages"]
|
|
124
|
+
[tool.ruff.lint]
|
|
125
|
+
select = [
|
|
126
|
+
"A",
|
|
127
|
+
"ARG",
|
|
128
|
+
"B",
|
|
129
|
+
"C",
|
|
130
|
+
"DTZ",
|
|
131
|
+
"E",
|
|
132
|
+
"EM",
|
|
133
|
+
"F",
|
|
134
|
+
"FBT",
|
|
135
|
+
"I",
|
|
136
|
+
"ICN",
|
|
137
|
+
"ISC",
|
|
138
|
+
"N",
|
|
139
|
+
"PLC",
|
|
140
|
+
"PLE",
|
|
141
|
+
"PLR",
|
|
142
|
+
"PLW",
|
|
143
|
+
"Q",
|
|
144
|
+
"RUF",
|
|
145
|
+
"S",
|
|
146
|
+
"T",
|
|
147
|
+
"TID",
|
|
148
|
+
"UP",
|
|
149
|
+
"W",
|
|
150
|
+
"YTT",
|
|
151
|
+
]
|
|
152
|
+
ignore = [
|
|
153
|
+
# Allow non-abstract empty methods in abstract base classes
|
|
154
|
+
"B027",
|
|
155
|
+
# Allow boolean positional values in function calls, like `dict.get(... True)`
|
|
156
|
+
"FBT002", "FBT003",
|
|
157
|
+
# Ignore checks for possible passwords
|
|
158
|
+
"S105", "S106", "S107",
|
|
159
|
+
# Ignore complexity
|
|
160
|
+
"C901", "PLR0911", "PLR0912", "PLR0913", "PLR0915",
|
|
161
|
+
# Quote style managed by black (skip-string-normalization = true)
|
|
162
|
+
"Q000",
|
|
163
|
+
# Allow string/f-string literals in exceptions
|
|
164
|
+
"EM101", "EM102",
|
|
165
|
+
# Allow implicit string concatenation on one line
|
|
166
|
+
"ISC001",
|
|
167
|
+
# Allow print() in CLI and diagnostic code
|
|
168
|
+
"T201",
|
|
169
|
+
# Allow conditional/lazy imports not at top level
|
|
170
|
+
"PLC0415",
|
|
171
|
+
# Allow raise without from in except blocks
|
|
172
|
+
"B904",
|
|
173
|
+
]
|
|
174
|
+
unfixable = [
|
|
175
|
+
# Don't touch unused imports
|
|
176
|
+
"F401",
|
|
177
|
+
]
|
|
178
|
+
|
|
179
|
+
[tool.ruff.lint.isort]
|
|
180
|
+
known-first-party = ["tamago"]
|
|
181
|
+
|
|
182
|
+
[tool.ruff.lint.flake8-tidy-imports]
|
|
183
|
+
ban-relative-imports = "all"
|
|
184
|
+
|
|
185
|
+
[tool.ruff.lint.per-file-ignores]
|
|
186
|
+
# Tests can use magic values, assertions, and relative imports
|
|
187
|
+
"**/tests/**/*" = ["ARG002", "F401", "PLR2004", "RUF059", "S101", "TID252"]
|
|
188
|
+
"**/src/**/*" = ["A002", "ARG002", "RUF023", "S101", "TID252"]
|
|
189
|
+
|
|
190
|
+
[tool.mypy]
|
|
191
|
+
[[tool.mypy.overrides]]
|
|
192
|
+
module = "identify_encryption"
|
|
193
|
+
ignore_missing_imports = true
|
|
194
|
+
|
|
195
|
+
[tool.pytest.ini_options]
|
|
196
|
+
markers = [
|
|
197
|
+
"unit: pure logic tests with no filesystem or external dependencies",
|
|
198
|
+
"integration: tests that read/write XP3 files or use the detection pipeline",
|
|
199
|
+
"nonfree: tests that require real game data in nonfree/ directories",
|
|
200
|
+
]
|
|
201
|
+
|
|
202
|
+
[tool.coverage.run]
|
|
203
|
+
source_pkgs = ["tamago"]
|
|
204
|
+
branch = true
|
|
205
|
+
parallel = true
|
|
206
|
+
omit = [
|
|
207
|
+
"src/tamago/__about__.py",
|
|
208
|
+
]
|
|
209
|
+
|
|
210
|
+
[tool.coverage.paths]
|
|
211
|
+
tamago = ["src/tamago", "*/tamago/src/tamago"]
|
|
212
|
+
|
|
213
|
+
[tool.coverage.report]
|
|
214
|
+
exclude_lines = [
|
|
215
|
+
"no cov",
|
|
216
|
+
"if __name__ == .__main__.:",
|
|
217
|
+
"if TYPE_CHECKING:",
|
|
218
|
+
]
|