Aller au contenu principal

Session 116 — Format HQN sans header, derivation HOFF depuis .HQN

Probleme

Apres le fix session 115, les exports worm/robotright echouaient avec :

ERR: pas de marqueur header $FFFF a -8 (trouve $0000)

Cause racine : le format HQN n’a pas le header PTR documente

Le commentaire de leved303.amos sur les 8 derniers bytes du PTR (marqueur
$FFFF + NOFF/WOFF/HOFF) decrit le format de l’editeur AMOS pour les sprites
standards. Les fichiers du dossier {@code media/hqn} (worm, robotright,
guard, ashnarg, etc.) utilisent un format different qui ne stocke pas ces
dimensions dans le PTR.

Verification math : HOFF derivable depuis .HQN

Le dossier {@code media/hqn} contient en plus du couple wad+ptr un fichier
.HQN qui est le pixel data brut (1 byte/pixel, column-major). Les
relations exactes :

total_cols       = ptr_size / 4              (4 bytes par entree PTR)
NOFF * WOFF      = total_cols                (les colonnes tilent les frames)
NOFF * WOFF * HOFF = HQN_size                (pixel data brut)
=> HOFF          = HQN_size / total_cols

Verification avec guard (frame size LH=80 connu via LNK) :

guard.HQN  = 134400 bytes
guard.PTR  =   6720 bytes -> 1680 cols
HOFF       = 134400 / 1680 = 80                  CORRESPOND a LH du LNK
21 frames  * 80 wide       = 1680 cols           CORRESPOND a NOFF*WOFF

Derivations pour worm et robotright :

worm.HQN     = 180000 bytes,  worm.ptr     = 7200 bytes  -> HOFF = 100
robotright.HQN = 393216 bytes, robotright.ptr = 12288 bytes -> HOFF = 128

Probleme residuel : NOFF inconnu

Meme avec HOFF connu, on ne peut pas separer NOFF (nb frames) de WOFF
(largeur frame) sans connaissance externe. Pour AB3D2 les conventions
usuelles sont :
– 5 vues directionnelles * 4 frames anim = 20
– 5 vues * 5 frames = 25
– 5 vues * 6 frames = 30
– 8 vues (boss) * variations = 24, 32

Fix : sheet complete + candidats NOFF multiples

{@code WadConverter.convertObjectStandalone} re-ecrite :

  1. Genere une spritesheet complete {@code _sheet.png}
    (largeur = total_cols, hauteur = HOFF) qui montre tout le sprite
    en un seul PNG. Le user peut visuellement compter les frames.

  2. Pour chaque {@code candidateNoff} qui divise exactement {@code total_cols} :
    – calcule {@code WOFF = total_cols / NOFF}
    – genere {@code NOFF} fichiers PNG individuels
    – le premier candidate utilise le nom standard {@code _f0..fN-1.png}
    – les suivants sont prefixes {@code _n24_f0.png}, etc., pour
    ne pas ecraser le premier ensemble

Candidates choisies par sprite :
– worm : 20, 24, 25, 30 (probablement 30 d’apres la taille fine 60×100)
– robotright : 20, 24, 32 (probablement 32 d’apres 96×128)

Validation attendue

Apres re-export par {@code ./gradlew convertWads} :

[EXTRA] TKG1:HQN/WORM
  WAD=95527 bytes, PTR=7200 bytes, 256pal=1024 bytes, HQN=180000 bytes
  Derive HOFF=100 depuis HQN=180000 / totalCols=1800 (residu=0)
  Mode HQN: 1 byte/pixel, index direct
    sheet: worm_sheet.png (1800x100, totalCols=1800)
    candidate NOFF=20, WOFF=90, HOFF=100 : 20 frames
    candidate NOFF=24, WOFF=75, HOFF=100 : 24 frames
    candidate NOFF=25, WOFF=72, HOFF=100 : 25 frames
    candidate NOFF=30, WOFF=60, HOFF=100 : 30 frames

Le user inspecte {@code worm_sheet.png}, compte les frames, indique le bon
NOFF, et la liste {@code candidateNoffs} sera reduite a une seule valeur
dans une session ulterieure.

TODO Phase suivante

Une fois NOFF identifie pour worm et robotright :
– Reduire {@code extraAlienSprites[*][2]} a la seule valeur correcte
– Le nom des fichiers sera alors {@code worm_f0..fN-1.png} sans prefixe
– Mettre a jour {@code LevelSceneBuilder.ALIEN_WAD_BY_GFXTYPE} si necessaire

Laisser un commentaire

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