Aller au contenu principal

Session 133 — Fix bug texture vectobj (passkey/mantis)

Symptome

Depuis la session 78 le passkey (et potentiellement d’autres vectobj a faces multiples) montrait des pixels d’autres modeles (mantis notamment) sur certaines faces en tournant autour. Le hack envisage en s132 (forcer Unshaded sans ColorMap) etait un contournement, pas un fix.

Diagnostic ASM (objdrawhires.s/drawpol l.2540-2559)

move.l  #$3fffff,d1
...
and.l   d1,d5              ; d5 = xbitpos & 0x3FFFFF
and.l   d1,d6              ; d6 = ybitpos & 0x3FFFFF
move.l  d6,d0
asr.l   #8,d0              ; d0[15:8] = bits[21:16] de ybitpos = V mod 64
swap    d5
move.b  d5,d0              ; d0[7:0]  = bits[21:16] de xbitpos = U mod 64
move.b  (a0,d0.w*4),d3    ; sample byte

L’adresse byte echantillonnee est :

byte_addr = base + bank*65536 + texOffset + V*1024 + U*4
          = base + bank*65536 + (rowStart + V)*1024
                              + (colStart + U)*4 + slot

avec U = U_byte & 63 et V = V_byte & 63 (mask $3FFFFF).

Conclusion ASM : (colStart + U) n’est PAS modulo 64 ; il varie librement de 0 a 318 dans le strip 256 colonnes. (rowStart + V) peut aller jusqu’a 94 (cross-bank dans le bank suivant meme slot).

Cause racine (session 78)

Le code de la session 78 avait suppose a tort que chaque strip 256×64 etait subdivise en 4 sous-tiles 64×64 et faisait :

int colRaw = colIn64 + vtxU[v];
int colFinal = colRaw % 64;       // <-- FAUX wrap dans la sous-tile
int pixelX = tileCol * 64 + colFinal;

Quand colStart % 64 + vtxU > 63, le polygone retombait au debut de SA tile (ex : colStart=50, vtxU=30 donnait col 16 au lieu de col 80). Si le pixel a col 16 etait visuellement different (ex : tile mantis voisine), la face affichait la mauvaise texture.

colStart vtxU ASM (correct) Java avant fix Java apres fix
50 30 80 16 ❌ 80 ✓
80 50 130 66 ❌ 130 ✓
80 20 100 100 ✓ 100 ✓

Fix

VectObjConverter.readPolygons() : suppression de la subdivision artificielle 4 tiles x 64 cols et utilisation des coordonnees absolues du strip 256×64.

int xh = vtxU[v] & 63;          // U byte mod 64 (mask $3FFFFF de l'ASM)
int yh = vtxV[v] & 63;          // V byte mod 64
int colFinal = colStart + xh;   // [0, 318]
int rowFinal = rowStart + yh;   // [0, 94]
// Clamp pour les cas rares (atlas actuel ne supporte pas le cross-strip)
if (colFinal > 255) colFinal = 255;
if (rowFinal > 63)  rowFinal = 63;
int pixelX = colFinal;
int pixelY = tileRow * 64 + rowFinal;

Limitations residuelles

Les deux cas suivants sont encore clampés plutôt que rendus correctement :

  1. colFinal > 255 : ASM continuerait sur la ligne suivante du meme bank/slot. Rare en pratique (polygones avec colStart eleve ET grande sweep U). Clamp a 255.
  2. rowFinal > 63 : ASM continuerait dans le bank suivant meme slot. L’atlas actuel (bank*4+slot)*64 ne place pas bank1/slot0 apres bank0/slot0 (il place bank0/slot1). Clamp a 63 en attendant une eventuelle restructuration de l’atlas vers le layout par-slot (bank0,bank1,bank0,bank1,…).

Procedure de validation

gradle convertVectobjs    # regenerer les .j3o avec les UVs corriges
gradle run                # passkey doit montrer une texture coherente

A verifier visuellement :
– Passkey : faces toutes coherentes (or/jaune), plus de pixels mantis
– Crab, mantis, autres aliens : aspect inchange (cas avec colStart % 64 + vtxU <= 63 etaient deja corrects)
– Armes, generateurs : meme verification

Fichiers modifies

  • VectObjConverter.java : suppression de tileCol/colIn64/rowIn64, remplacement par colStart/rowStart directs.

Laisser un commentaire

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