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