# 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 ma cztery widoki: **Katalog** (tytuły, wydania, kopie, pliki), **Skrypty** (wyszukiwanie pełnotekstowe i podgląd z listą użytych zasobów), **Dźwięk** (wyszukiwanie nagrań, odtwarzacz, transkrypcja) i **Formaty** (rozkład zawartości kolekcji). 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.