Aller au contenu principal

Session 132duodecimus (suite 12bis) — Longueur mur « ASM-style » max(|dx|,|dz|)

Approche methodique demandee par l’utilisateur

Reverse engineering rigoureux : comparaison des coords brutes du mur de
casiers (zone 0 Level A) entre les 3 representations :
1. Binaire {@code .lvl} original Amiga ({@code twolev.bin})
2. JSON converti ({@code level_A.json})
3. J3O final ({@code scene_A.j3o})

Postulat utilisateur : « la longueur de ce mur = exactement 1 cycle de
texture » (1 cycle = 128 texels U pour {@code wall_04_brownspeakers}).

Decouverte

L’ASM original ne calcule jamais la longueur euclidienne d’un mur.

Dans {@code hireswall.s::Draw_Wall} (lignes 1395-1500), le subdivision-LoD
est decide par {@code abs(dx)}, {@code abs(dz)} et {@code min(z1,z2)}
separement, jamais combinees en {@code sqrt(dx^2 + dz^2)} :

.not_good:
    move.l  a2,d0
    sub.l   a0,d0           ; d0 = abs(a2 - a0) = dx en X projetee
    cmp.l   #256*128,d0     ; seuil X

.not_negative_z_difference:
    cmp.w   #512,d0         ; seuil Z
    cmp.w   #256,d0
    cmp.w   #128,d0

Le rendu Amiga se fait par strips d’ecran. La longueur « effective » pour
le texturage suit donc la projection axiale, pas la diagonale.

Probleme observe

Mur diagonal de zone 0 : pt2(-768,512) -> pt4(-512,256), delta=(256,-256) :
– Euclidean : sqrt(256^2 + 256^2) = 362 X/Z
– Avec WALL_TEXEL_TO_XZ=2.0 (valeur README): xzPerTile = 256
– numRepeats = ceil(362/256) = 2 repetitions -> 6 ventilateurs

Mais sur l’Amiga ORIGINAL : 1 repetition = 3 ventilateurs.

Fix

Dans {@code LevelSceneBuilder.java::buildScene} loop walls :

// AVANT
float len = (float)Math.sqrt(dx*dx + dz*dz);  // 362 sur mur diagonal

// APRES
float lenEucl = (float)Math.sqrt(dx*dx+dz*dz);  // garde pour clip 8192f
float len = Math.max(Math.abs(dx), Math.abs(dz));  // 256 sur mur diagonal

Effet sur le mur de zone 0 :
– len = max(256, 256) = 256
– xzPerTile = 128 * 2.0 = 256
numRepeats = ceil(256/256) = 1 -> 3 ventilateurs comme l’Amiga ✓

Effet sur les murs droits (cas usuel, mur aligné sur X ou Z) :
– max(|dx|, 0) = |dx| = euclidean -> aucun changement ✓

Effet sur les murs diagonaux : reduit de sqrt(2) le nombre de repetitions
par rapport a notre version precedente, ce qui matche l’Amiga.

Constantes

  • {@code WALL_TEXEL_TO_XZ = 2.0f} restauree (valeur litterale du README
    « every 256 X/Z = 1 repeat »)
  • Aspect ratio U/V = 1:1 (ASM-fidele)
  • Pas de stretch horizontal sur les longs couloirs

Files modified

  • {@code WorldScale.java} : restaure 2.0, doc complete avec justification
    ASM (mention de la mesure max axes)
  • {@code LevelSceneBuilder.java} : split {@code lenEucl} (clip de validite)
    vs {@code len} (UV ASM-style), commentaire complet
  • {@code CHANGELOG.md} : cette entree

Methodologie pour sessions futures

Pour les questions de calage texture/scale, ne pas se contenter de la
doc theorique. La verification visuelle WinUAE + analyse ASM (chercher
les seuils {@code cmp.l #256*128}, {@code cmp.w #128/256/512}) revele les
formules reelles. La doc README peut etre vraie en theorie mais incomplete
sur les details d’implementation.

Laisser un commentaire

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