Aller au contenu principal

Session 132quat — Extraction complete et fidele des niveaux

Contexte

Malgre les sessions 99 (audit donnees ignorees) et 118 (PointBrights +
ZoneBorderPoints), il restait un doute sur la fidelite COMPLETE de la conversion
twolev.bin / twolev.graph.bin -> JSON. Plusieurs structures du binaire ne sont
lues qu’en partie (champs marques TODO dans defs.i, hex dumps non interpretes
dans le parser actuel).

Objectif : ecrire un extracteur autonome qui lit absolument tous les bytes
de twolev.bin et twolev.graph.bin, et les expose en JSON, sans interpretation.
Les champs incompris sont conserves en raw word/byte ou hex dump. Permet :

  1. Audit visuel de la conversion (verifier que rien n’est perdu).
  2. Diagnostic des bugs subtils (un champ TODO peut etre la source d’un
    comportement non reproduit).
  3. Reference pour de futures sessions qui voudraient interpreter ces champs.

Choix d’architecture

Nouveau package com.ab3d2.core.level.full, completement autonome. Ne touche
pas
aux parsers existants (LevelBinaryParser, GraphicsBinaryParser,
LevelJsonExporter). Sortie JSON distincte level_X_full.json (vs
level_X.json existant). L’utilisateur pourra integrer ce qu’il veut apres.

Fichiers crees

  • core/level/full/LevelFullExtractor.java (~640 lignes, ~30 KB) : parser
    monolithique. Records nested (LvlTHeader, TLGTHeader, Vec2W,
    ControlPoint, ZoneRecord 21 champs, EdgeRecord 9 champs incluant
    word5/byte12/byte13/flags TODO, PvsTuple, ObjectRecord 29 champs
    ObjT+EntT, ZLiftable 18 champs, ZDoorWall, LiftableEntry, SwitchRecord,
    ExtractedLevel). API : extract(String levelId, byte[] bin, byte[] graph).

  • core/level/full/LevelFullJsonExporter.java (~330 lignes) : serialisation JSON
    manuelle (StringBuilder + helpers), sans dependance externe. Tous les champs
    systematiquement emis, indente.

  • core/level/full/LevelFullExtractorMain.java (~100 lignes) : entry point qui
    itere LEVEL_A..P, lit src/main/resources/levels/LEVEL_X/twolev.bin et
    twolev.graph.bin, ecrit assets/levels/level_X_full.json. Niveaux absents
    listes dans assets/levels/MISSING.md.

  • core/level/full/SmokeTest.java (~285 lignes) : test synthetique avec ~26
    assertions. Fabrique des mini twolev.bin/graph.bin avec valeurs connues, parse,
    verifie. Couvre header, messages, points, control points, zones, edges, doors
    (avec ZLiftable signe : bottom=-32 correct), switches, JSON valide. Toutes
    les assertions passent.

Constantes confirmees via /mnt/project/defs.i + zone_liftable.h + newanims.s + hires.s

  • LVLT_MESSAGE_LENGTH = 160, LVLT_MESSAGE_COUNT = 10 -> bloc messages = 1600 bytes
  • LvlT/TLBT_SizeOf = 54 bytes, TLGT_SizeOf = 20 bytes
  • ZoneT_SizeOf = 50, EdgeT_SizeOf = 16, ObjT/EntT = 64, ODefT = 40, PVST = 8
  • ZLiftable = 36 bytes (zone_liftable.h:33), ZDoorWall = 10 bytes
  • Switch = 14 bytes × 8 records fixes (newanims.s:1585 SwitchRoutine, deduit
    via move.w #7,d0)
  • PointBrights = NumZones × 80 bytes (40 words/zone, hires.s:1502 muls #40)
  • Door/Lift stream : [ZLiftable + ZDoorWall×2N + WORD -1]... terminee par
    WORD 999
  • END_OF_DOOR_LIST = 999, END_OF_DOOR_WALL_LIST = -1
  • numObjects deduit par (offsetToPlayerShot - offsetToObjects) / 64 car le
    champ TLBT_NumObjects_w (offset 20) est en realite
    Lvl_NumObjectPoints_w (confirme hires.s:413).
  • Convention numZones = field + 1 : le binaire stocke MaxZoneId, le parser
    fait +1 (LEVEL_A = 134 zones donc le binaire stocke 133). Aligne avec le
    parser existant.

Tasks Gradle ajoutees

  • extractLevelsFull : lance l’extraction sur les 16 niveaux. Genere les JSON
  • MISSING.md listant les niveaux absents.
  • extractLevelsFullSmokeTest : lance le smoke test (assertions sur donnees
    synthetiques).

Actions NetBeans : action.custom-43 et action.custom-44.

Validation locale (pre-deploiement)

En sandbox (avant integration projet) :

cd /home/claude/work
javac -d build -sourcepath src src/com/ab3d2/core/level/full/*.java
java -cp build com.ab3d2.core.level.full.SmokeTest
# Resultat : 26 assertions passees, JSON valide affiche

Reste a faire (post deploiement)

  • Copier les niveaux depuis ab3d2-tkg-original/media/levels/LEVEL_*/ vers
    ab3d2-tkg-jme/src/main/resources/levels/LEVEL_*/ (au moins twolev.bin et
    twolev.graph.bin) : actuellement les dossiers cibles sont vides.
  • Lancer ./gradlew extractLevelsFullSmokeTest puis ./gradlew extractLevelsFull
    pour generer les JSON.
  • Valider sur LEVEL_A (134 zones, 635 edges) : verifier qu’aucun parsing ne
    remonte d’erreur.

Limites connues / a verifier ensuite

  • Format Control Points : assume 4 bytes/point (WORD X + WORD Z). A
    verifier en croisant avec EntT_CurrentControlPoint_w. Le dump raw hex est
    expose en parallele pour permettre une re-interpretation si necessaire.
  • Champs EdgeT TODO (word5, byte12, byte13, flags) : conserves en raw
    signed/unsigned, mais leur usage exact n’est pas decode.
  • Champs ZLiftable word9..word12, word16 : TODO dans defs.i, conserves
    en raw. Probablement coordonnees XZ pour positionnement / animation texture.
  • Format Switch (14 bytes) : deduit de l’ASM SwitchRoutine, pas confirme
    par defs.i. Champs +11..+13 exposes en hex.

Pipeline pour tester apres deploiement

# 1. Verifier que la compilation passe
./gradlew compileJava

# 2. Lancer le smoke test (assertions deterministes)
./gradlew extractLevelsFullSmokeTest

# 3. Copier au moins LEVEL_A et LEVEL_B depuis original (si manquants) :
#    src/main/resources/levels/LEVEL_A/twolev.bin
#    src/main/resources/levels/LEVEL_A/twolev.graph.bin

# 4. Lancer l'extraction complete
./gradlew extractLevelsFull

# 5. Verifier le JSON genere
ls -lh assets/levels/level_*_full.json
head -100 assets/levels/level_A_full.json

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *