Files

169 lines
7.6 KiB
Markdown

# rex-catalog
Katalog kolekcji gier Aidem Media — serii *Reksio* i *Poznaj Mity*. Indeksuje obrazy płyt,
zagląda do środka i pozwala je przeglądać: odszyfrowane skrypty, odtwarzalne kwestie
mówione, podgląd grafiki i animacji oraz powiązania między nimi.
Powstał do celów archiwizacyjnych i testów emulatora. Niczego nie modyfikuje w kolekcji —
obrazy płyt otwiera wyłącznie do odczytu, a wszystko, co wytworzy, ląduje w osobnym
katalogu `data/`.
## Skąd bierze wiedzę o formatach
Formaty Aidem — zaszyfrowane skrypty CNV, obrazy `PIK\0`, animacje `NVP\0`, kompresje
CLZW i CRLE — czyta przez `:core` z [Rex-EMoolatora](https://github.com/patryk025/Rex-EMoolator),
podpiętego jako **composite build**, a nie fork. Emulator jest przypięty submodułem na
konkretnym tagu (`gradle.properties``coreVersion`), a zadanie `verifyCoreVersion`
pilnuje, żeby tag i submoduł się nie rozjechały.
Dzięki temu wiedza o formatach ma jedno źródło. Tam, gdzie katalog musiał napisać własny
parser, jest to powiedziane wprost w komentarzu razem z powodem — najczęściej dlatego,
że loader z `:core` buduje tekstury OpenGL-a i w procesie bez okna nie da się go użyć.
## Jak to jest poukładane
**Trzy poziomy tożsamości.** `title` (dzieło) → `edition` (wydanie) → `copy` (konkretny
plik na dysku). Między wydaniem a kopią stoi jeszcze `game_root`, bo jedna płyta bywa
dwupackiem z dwiema grami, każdą z własnym silnikiem.
**Plik osobno, treść osobno.** `file` mówi, gdzie coś leży, `blob` — czym jest. Porównanie
dwóch wydań jest więc operacją na zbiorach odcisków, a wszystko, co wytworzone
(odszyfrowany skrypt, miniatura), kluczuje się treścią: ten sam plik na trzech płytach
przerabiamy raz.
**Fakty z dowodem.** Detektory nie nadpisują pól, tylko dopisują wiersze do `detection`
z wartością, pewnością i dowodem. Poprawki człowieka siedzą osobno, w polach `*_override`,
i nigdy nie są nadpisywane przez kolejny przebieg.
**Nic nie wypakowujemy.** Dźwięk i klatki animacji czytamy z obrazu płyty na żądanie,
sięgając od razu na właściwą pozycję. W `data/` zostaje tylko to, co drogo policzyć:
odszyfrowane skrypty i miniatury.
## Uruchomienie
Potrzebne: **JDK 21** i submoduł z emulatorem.
```bash
git submodule update --init --recursive
./gradlew installDist
```
Dalej wygodnie przez launcher (`build/install/rex-catalog/bin/rex-catalog`) albo
`./gradlew run --args="..."`. Katalog bazy wskazuje `-Dcatalog.data` (domyślnie `./data`).
### Potok
```bash
rex-catalog ingest /ścieżka/do/kolekcji # indeksuje obrazy, katalogi gier i całe kolekcje
rex-catalog decode # odszyfrowuje skrypty do cache'u i indeksu FTS5
rex-catalog probe # dźwięk, grafika, dialogi, powiązania
rex-catalog analyze # metadane z application.def i install.ini
rex-catalog promote # tworzy tytuły i wydania z wykrytych faktów
```
Każdy krok jest **przyrostowy** — dołożenie nowej płyty przerabia tylko ją. Ponowne
uruchomienie bez `--force` nie robi nic, jeśli nic się nie zmieniło.
`ingest` przyjmuje obraz `.iso` (ISO 9660, Joliet i UDF), archiwum `.zip`, katalog
rozpakowanej gry albo katalog z całą kolekcją.
### Przeglądanie
```bash
rex-catalog serve # front i MCP na http://127.0.0.1:8765
rex-catalog find CANVAS_OBSERVER # przeszukanie skryptów (składnia FTS5)
rex-catalog cat arcade.cnv # odszyfrowany skrypt na wyjście
rex-catalog titles # lista wydań z metadanymi
```
Front otwiera się na widoku **Zasoby** — paginowanej galerii obrazów, animacji i nagrań,
filtrowanej po grze, rodzaju i nazwie. Zaznaczenie otwiera inspektor z pełnym podglądem,
parametrami i miejscami użycia. Animacje można odtwarzać w tempie zapisanym w ANN — jako
wszystkie obrazy albo konkretne nazwane zdarzenie, np. `BEZRUCH` czy `GADA_1`, razem z jego
właściwą kolejnością klatek i zakresem pętli. Dalej są **Skrypty** (wyszukiwanie
pełnotekstowe i podgląd z listą użytych zasobów), **Dźwięk** (wyszukiwanie nagrań,
odtwarzacz, transkrypcja), **Kolekcja** (tytuły, wydania, kopie, pliki) i **Statystyki**.
Pod `/mcp` stoi serwer MCP (Streamable HTTP, tylko do odczytu) z dziewięcioma narzędziami —
od `list_titles` i `search_scripts` po `get_script_assets`, które pokazuje, co dany skrypt
odtwarza, kto to mówi i jak długo trwa.
### Metadane ręczne
Tego, czego nie da się wykryć, nie zgadujemy:
```bash
rex-catalog set copy "Wojna Troj" source_kind=wlasny_zgraj rip_tool=dd
rex-catalog set edition 3 distributor="Aidem Media" release_date_override=2003-11-18
rex-catalog lang add 3 cs audio
```
## Transkrypcja mowy
Opcjonalna i uruchamiana świadomie — wymaga [whisper.cpp](https://github.com/ggerganov/whisper.cpp)
i modelu, których repozytorium nie dostarcza.
```bash
brew install whisper-cpp # albo dowolna inna instalacja
rex-catalog transcribe --limit 100 # -Dcatalog.whisper.model=ścieżka/do/ggml-medium.bin
```
Da się też wyklikać z zakładki **Dźwięk** — z paskiem postępu i zatrzymaniem, które nie
gubi tego, co już policzone.
Kwestie są sklejane po kilka w trzydziestosekundowe okna z sekundą ciszy między nimi,
a wynik rozcinany z powrotem po znacznikach czasu. Whisper koduje zawsze pełne okno,
więc podawanie mu czterosekundowych kwestii po jednej marnuje większość pracy.
Transkrypt jest **wygenerowany, nie odczytany z płyty**. Siedzi w osobnej tabeli razem
z nazwą modelu i narzędzia, a interfejs oznacza go jako maszynowy. Zdania, które model
dopisuje z siebie na ciszy — podpisy ekip od napisów — są odsiewane.
## Docker
```bash
COLLECTION=/ścieżka/do/kolekcji docker compose up -d
docker compose exec katalog /app/entrypoint.sh ingest /media
```
Kolekcja montuje się tylko do odczytu, baza i cache lądują w wolumenie. Obraz niesie
whisper.cpp i ffmpeg, ale **nie model** — ten podmontuj pod `/models` i wskaż zmienną
`WHISPER_MODEL`.
`Dockerfile.cuda` buduje wariant z akceleracją NVIDII (domyślnie pod compute capability
8.6, czyli GeForce RTX 30). Na macOS akceleracja w kontenerze nie działa — tam transkrypcję
uruchamiaj na hoście, gdzie whisper.cpp sam korzysta z Metala.
## Przenoszenie między maszynami
Baza zapisuje bezwzględne ścieżki do obrazów płyt, bo czyta z nich dźwięk i grafikę.
Po skopiowaniu `data/` na inną maszynę trzeba ją przypiąć do kolekcji:
```bash
rex-catalog relocate D:\Reksio --dry-run # najpierw pokaż, co zrobisz
rex-catalog relocate D:\Reksio
```
Dopasowuje po nazwie i sprawdza rozmiar (`--verify` dokłada SHA-256), a nazwy porównuje po
normalizacji Unicode — bez tego kolekcja z macOS nie dogaduje się z tą samą kolekcją na
Windowsie, bo `ń` jest tam zapisane inaczej.
## Co siedzi w bazie
SQLite, jeden plik obok cache'u, więc przeniesienie katalogu to skopiowanie `data/`.
| tabela | co trzyma |
|---|---|
| `title`, `edition`, `copy`, `game_root` | tożsamość: dzieło, wydanie, nośnik, korzeń gry |
| `file`, `blob` | gdzie plik leży i czym jest |
| `detection` | fakty detektorów z dowodem i pewnością |
| `artifact` | wytworzone: odszyfrowane skrypty, miniatury |
| `media` | fakty o zasobie: długość, wymiary, klatki, kodek |
| `archive_entry` | zawartość archiwów `.snd` — kwestie spakowane w jeden plik |
| `script_ref` | odwołania skryptów do zasobów |
| `dialogue_line`, `anim_event` | mówca i zdarzenie kwestii, nazwane sekwencje animacji |
| `transcript` | rozpoznana mowa, osobno od reszty |
| `script_fts`, `transcript_fts` | indeksy pełnotekstowe |
`rex-catalog stats` pokazuje, co w danej chwili jest w środku.