Aller au contenu principal

Session 59 — VectObj : fix critique format part list

Bug decouvert via VectObjDumper

Un dump de passkey a revele que les bodyOfs lus pointaient dans le milieu
de la part list elle-meme (au lieu de pointer vers des polygones) :

part[0] bodyOfs=0x0050 -> file+0x0052   (INVALIDE : numLines=1202)
part[5] bodyOfs=0x0208 -> file+0x020A   (INVALIDE)
...

Mais les premiers WORDs des entrees (qu’on lisait comme sortKey) etaient
110, 292, 474, … avec delta constant de 182 bytes = les vrais bodyOfs !

Verification : file+2+110 = file+0x70 contient 00 03 00 00 00 03 20 10...
→ numLines=3, flags=0, vertex[0]=(ptIdx=3, u=0x20, v=0x10), etc. Coherent !

Re-analyse ASM stricte (putinunsorted l.2116-2131)

putinunsorted:
    move.w  (a1)+, d7        ; d7 = PREMIER WORD
    blt     doneallparts     ; si negatif -> fin
    lsr.l   #1, d5           ; test onOff bit
    bcs.s   .yeson
    addq    #2, a1           ; skip second WORD si pas actif
    bra     putinunsorted
.yeson:
    move.w  (a1)+, d6        ; d6 = DEUXIEME WORD
    move.l  #0, (a0)+
    move.w  d7, (a0)         ; <-- stocke d7 (PREMIER WORD) dans PartBuffer
    addq    #4, a0
    bra     putinunsorted

Puis @ l.2183-2186 dans .part_loop :

    move.w  (a0), d0             ; lit le WORD stocke dans PartBuffer (= d7)
    add.l   draw_StartOfObjPtr_l, d0  ; rend absolu
    move.l  d0, a1               ; a1 pointe au polygone

Le PREMIER WORD est le bodyOfs du polygone.
Le DEUXIEME WORD est un refPointOfs (index byte dans draw_3DPointsRotated_vl
utilise par PutinParts @ l.2145 pour calculer la profondeur de tri).

Correction appliquee

VectObjConverter.java :

// AVANT (inverse)
short partSortKey = b.getShort(pos);         // WRONG: ce n'est pas un sortKey
int   bodyOfs     = b.getShort(pos+2) & ...; // WRONG: c'est le refPoint

// APRES (conforme ASM)
short firstWord  = b.getShort(pos);          // bodyOfs (termine par -1)
int   refPoint   = b.getShort(pos+2) & ...;  // point reference pour tri
int   bodyOfs    = startOfs + (firstWord & 0xFFFF);

onOffMask : comportement modifie

L’ASM utilise onOffMask pour skipper les parts inactives pour la frame
courante
. Un passkey anime (13 frames) a mask=0x001FE001 en frame 0 montrant
uniquement part 0 (vue frontale). D’autres frames affichent d’autres parts.

Pour l’export d’asset statique on force forceAllParts=true → rend la
geometrie complete de toutes les parts. En runtime il faudra reactiver le
masquage par frame pour l’animation.

Outil de diagnostic : VectObjDumper.java

Nouveau ./gradlew dumpVectObj [-Pvectobj=<nom>] qui dump :
– Hex dump header et polygones
– Decodage detaille de chaque champ avec validation
– Comparaison WORD vs byte+byte pour les vertex
– Valeurs du footer (texOffset, brightness, polyAngle, gouraud)

Pipeline

./gradlew dumpVectObj -Pvectobj=passkey  # diagnostic
./gradlew convertVectObj                  # conversion

Laisser un commentaire

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