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.