scurest / apicula

Convert Nintendo DS .nsbmd models
BSD Zero Clause License
160 stars 19 forks source link

Fix texture matrices #25

Open scurest opened 4 years ago

scurest commented 3 years ago

The sun and some gates in the Agrabah gates from Days are wrong.

Bad sun

The UVs are wrong. The sun material should have a texture matrix. DS sends

[GXS:88000000] 0x10,  0x00000003
[GXS:88000000] 0x16,  0x00002000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00002000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xFFF00000, 0x00000000, 0x00001000,
scurest commented 2 years ago

Notes:

Hex dump

al_02c

material sun

0x17C4   +0x00   00 00        dummy
0x17C6   +0x02   3C 00        size
0x17C8   +0x04   FF FF FF 7F  dif amb
0x17CC   +0x08   9C 73 00 00  spe emi
0x17D0   +0x0C   80 00 1F 00  polygon attr
0x17D4   +0x10   FF F8 1F 3F  polygon attr mask
0x17D8   +0x14   00 00 0F 40  teximage param
0x17DC   +0x18   FF FF FF FF  ?
0x17E0   +0x1C   00 00        palette base
0x17E2   +0x1E   C5 1F        flags
0x17E4   +0x20   10 00        texture width(?)
0x17E6   +0x22   10 00        texture height(?)
0x17E8   +0x24   00 10 00 00  ?
0x17EC   +0x28   00 10 00 00  ?
0x17F0   +0x2C   00 20 00 00  ?
0x17F4   +0x30   00 20 00 00  ?
0x17F8   +0x34   00 FC FF FF  ?
0x17FC   +0x38   00 FC FF FF  ?

Some GHIDRA decompilation, taken from a memory dump while in Agrabah Gates

// Function that gets called when running command 0x4 (Material Setup)
void FUN_01ffbbf0(int *param_1,int param_2,undefined4 param_3,undefined4 param_4)

{
  undefined2 *puVar1;
  byte bVar2;
  ushort uVar3;
  uint uVar4;
  uint *puVar5;
  uint uVar6;
  int *piVar7;
  int iVar8;
  int iVar9;
  int iVar10;
  uint uVar11;
  int iVar12;
  uint *puVar13;
  int iVar14;
  bool bVar15;
  uint local_34;
  uint local_30;
  uint local_2c;
  undefined *local_28;
  uint local_24;
  uint local_20;
  undefined4 uStack28;

  uVar6 = param_1[2];
  if ((uVar6 & 0x200) != 0) goto LAB_01ffc0a0;
  bVar2 = *(byte *)(*param_1 + 1);
  uVar11 = (uint)bVar2;
  if ((((uVar6 & 1) == 0) && ((uVar6 & 8) != 0)) && (uVar11 == *(byte *)((int)param_1 + 0xad)))
  goto LAB_01ffc0a0;
  iVar12 = param_1[0x36];
  if (iVar12 == 0) {
LAB_01ffbc78:
    iVar12 = 0;
  }
  else {
    iVar9 = iVar12 + 4;
    if ((iVar9 == 0) || (*(byte *)(iVar12 + 5) <= uVar11)) {
      piVar7 = (int *)0x0;
    }
    else {
      piVar7 = (int *)(*(ushort *)(iVar9 + (uint)*(ushort *)(iVar12 + 10)) * uVar11 +
                      iVar9 + (uint)*(ushort *)(iVar12 + 10) + 4);
    }
    if (piVar7 == (int *)0x0) goto LAB_01ffbc78;
    iVar12 = iVar12 + *piVar7;
  }
  *(byte *)((int)param_1 + 0xad) = bVar2;
  param_1[2] = param_1[2] | 8;
  iVar8 = param_1[1];
  iVar9 = *(int *)(iVar8 + 0x38);
  uStack28 = param_4;
  if ((iVar9 == 0) || ((param_1[2] & 0x80U) != 0)) {
    if ((param_2 == 0x20 || param_2 == 0x40) &&
       ((param_1[(bVar2 >> 5) + 0x2f] & 1 << (uVar11 & 0x1f)) != 0)) {
      if (iVar9 == 0) {
        puVar13 = (uint *)(PTR_DAT_01ffc0b4 + uVar11 * 0x38);
      }
      else {
        puVar13 = (uint *)(uVar11 * 0x38 + iVar9);
      }
    }
    else {
      if (iVar9 == 0) {
        if (param_2 == 0x40) {
          puVar13 = (uint *)(PTR_DAT_01ffc0b4 + uVar11 * 0x38);
          param_1[(bVar2 >> 5) + 0x2f] = param_1[(bVar2 >> 5) + 0x2f] | 1 << (uVar11 & 0x1f);
        }
        else {
          puVar13 = (uint *)(param_1 + 0x3d);
        }
      }
      else {
        param_1[(bVar2 >> 5) + 0x2f] = param_1[(bVar2 >> 5) + 0x2f] | 1 << (uVar11 & 0x1f);
        puVar13 = (uint *)(uVar11 * 0x38 + *(int *)(iVar8 + 0x38));
      }
      *puVar13 = 0;
      iVar9 = _FUN_01ffc0b8;
      iVar14 = param_1[0x36];
      if (iVar14 == 0) {
LAB_01ffbdb4:
        iVar14 = 0;
      }
      else {
        iVar10 = iVar14 + 4;
        if ((iVar10 == 0) || (*(byte *)(iVar14 + 5) <= uVar11)) {
          piVar7 = (int *)0x0;
        }
        else {
          piVar7 = (int *)(*(ushort *)(iVar10 + (uint)*(ushort *)(iVar14 + 10)) * uVar11 +
                          iVar10 + (uint)*(ushort *)(iVar14 + 10) + 4);
        }
        if (piVar7 == (int *)0x0) goto LAB_01ffbdb4;
        iVar14 = iVar14 + *piVar7;
      }
      if ((*(ushort *)(iVar14 + 0x1e) & 0x20) != 0) {
        *puVar13 = *puVar13 | 0x20;
      }

      ///////////

      // This loads some GPU commands into a buffer?
      // iVar12 points to the start of the material (dummy)
01ffbdd0:
      iVar14 = iRam01ffc0bc;
      uVar6 = *(uint *)(iRam01ffc0bc + ((int)(uint)*(ushort *)(iVar12 + 0x1e) >> 6 & 7U) * 4);
      puVar13[1] = *(uint *)(iVar9 + 0x80) & ~uVar6 | *(uint *)(iVar12 + 4) & uVar6;
      // *(ushort*)(iVar12 + 0x1e) is flags
      // so (flags >> 6)&7 is an index into a table that gives a mask for dif amb
      // presumably *(uint *)(iVar9 + 0x80) lets you control the dif amb from outside,
      // eg for animation, programmatic control

      uVar6 = *(uint *)(iVar14 + ((int)(uint)*(ushort *)(iVar12 + 0x1e) >> 9 & 7U) * 4);
      puVar13[2] = *(uint *)(iVar9 + 0x84) & ~uVar6 | *(uint *)(iVar12 + 8) & uVar6;
      // same thing for spe emi, (flags >> 9)&7 is the mask index (note: same table)

      uVar6 = *(uint *)(iVar9 + 0x88) & ~*(uint *)(iVar12 + 0x10);
      puVar13[3] = uVar6 | *(uint *)(iVar12 + 0xc) & *(uint *)(iVar12 + 0x10);
      // polygon attr and mask

      puVar13[4] = *(uint *)(iVar12 + 0x14);
      // teximage param

      puVar13[5] = (uint)*(ushort *)(iVar12 + 0x1c);
      // palette base

      ////////////

      if ((*(ushort *)(iVar12 + 0x1e) & 1) != 0) {    // if (flags & 1)  NOTE: this is true for sun

        bVar15 = (*(ushort *)(iVar12 + 0x1e) & 2) != 0;
        if (bVar15) {  // if (flags & 2)  NOTE: false for sun
          uVar6 = *puVar13;
        }
        puVar5 = (uint *)(iVar12 + 0x2c);
        if (bVar15) {
          *puVar13 = uVar6 | 1;
        }
        else {
          puVar13[6] = *puVar5;
          puVar5 = (uint *)(iVar12 + 0x34);
          puVar13[7] = *(uint *)(iVar12 + 0x30);
        }
        // if (flags & 2) then puVar13[0] |= 1
        // else puVar13[6] = next u32() (starting at *(iVar12 + 0x2c))
        //      puVar13[7] = next u32()

        if ((*(ushort *)(iVar12 + 0x1e) & 4) == 0) {
          *(undefined2 *)(puVar13 + 8) = *(undefined2 *)puVar5;
          puVar1 = (undefined2 *)((int)puVar5 + 2);
          puVar5 = puVar5 + 1;
          *(undefined2 *)((int)puVar13 + 0x22) = *puVar1;
        }
        else {
          *puVar13 = *puVar13 | 2;
        }
        // if (flags & 4) then puVar13[0] |= 2
        // else puVar13[8] = next u16() | (next u16() << 16)   (?)

        if ((*(ushort *)(iVar12 + 0x1e) & 8) == 0) {
          puVar13[9] = *puVar5;
          puVar13[10] = puVar5[1];
        }
        else {
          *puVar13 = *puVar13 | 4;
        }
        // if (flags & 8) then puVar13[0] |= 4
        // else puVar13[9] = next u32()
        //      puVar13[10] = next u32()

        *puVar13 = *puVar13 | 8;
      }
      uVar6 = *(uint *)(iVar8 + 8);
      if (uVar6 != 0) {
        uVar4 = *(uint *)(iVar8 + (uint)(bVar2 >> 5) * 4 + 0x3c) & 1 << (uVar11 & 0x1f);
        while (uVar4 != 0) {
          if (((uVar11 < *(byte *)(uVar6 + 0x19)) &&
              (uVar3 = *(ushort *)(uVar6 + uVar11 * 2 + 0x1a), (uVar3 & 0x300) == 0x100)) &&
             (*(code **)(uVar6 + 0xc) != Reset)) {
            (**(code **)(uVar6 + 0xc))(puVar13,uVar6,uVar3 & 0xff);
          }
          uVar6 = *(uint *)(uVar6 + 0x10);
          uVar4 = uVar6;
        }
      }
      if ((*puVar13 & 0x18) != 0) {
        *(undefined2 *)(puVar13 + 0xb) = *(undefined2 *)(iVar12 + 0x20);
        *(undefined2 *)((int)puVar13 + 0x2e) = *(undefined2 *)(iVar12 + 0x22);
        puVar13[0xc] = *(uint *)(iVar12 + 0x24);
        puVar13[0xd] = *(uint *)(iVar12 + 0x28);
      }
    }
  }
  else {
    puVar13 = (uint *)(uVar11 * 0x38 + iVar9);
  }
  param_1[0x2c] = (int)puVar13;
  if ((puVar13[3] & 0x1f0000) == 0) {
    param_1[2] = param_1[2] | 2;
  }
  else {
    if ((*puVar13 & 0x20) != 0) {
      puVar13[3] = puVar13[3] & 0xffe0ffff;
    }
    uVar6 = param_1[2];
    param_1[2] = uVar6 & 0xfffffffd;
    if ((uVar6 & 0x100) == 0) {
      local_34 = puVar13[1];
      if (*(short *)PTR_DAT_01ffc0c0 != 0) {
        local_34 = local_34 & 0xffff8000 |
                   (local_34 & 0x1f) * (uint)*(ushort *)PTR_DAT_01ffc0c8 * 0x800 >> 0x10 |
                   (uint)(((int)((local_34 >> 5 & 0x1f) * (uint)*(ushort *)(PTR_DAT_01ffc0c8 + 2))
                          >> 5) << 0x10) >> 0xb |
                   (uint)(((int)((local_34 >> 10 & 0x1f) * (uint)*(ushort *)(PTR_DAT_01ffc0c8 + 4))
                          >> 5) << 0x10) >> 6;
      }
      local_30 = puVar13[2];
      local_2c = puVar13[3];
      local_28 = PTR_DAT_01ffc0cc;
      local_24 = puVar13[4];
      local_20 = puVar13[5];
      FUN_01ff9f00(PTR_LAB_01ffc0c4,&local_34,6);
      if ((*puVar13 & 0x18) != 0) {
        (*(code *)param_1[0x3c])(puVar13);  // this calls FUN_01ffa5dc
      }
    }
  }
LAB_01ffc0a0:
  *param_1 = *param_1 + 2;
  return;
}

void FUN_01ffa5dc(uint *param_1,undefined4 param_2,undefined4 param_3,undefined4 param_4)

{
  longlong lVar1;
  undefined *local_58;
  undefined4 local_54;
  uint local_50;
  uint local_4c;
  undefined4 local_48;
  undefined4 local_44;
  uint local_40;
  uint local_3c;
  undefined4 local_38;
  undefined4 local_34;
  undefined4 local_30;
  undefined4 local_2c;
  undefined4 local_28;
  undefined4 local_24;
  uint local_20;
  uint local_1c;
  undefined4 local_18;
  undefined4 local_14;
  undefined4 local_10;
  undefined4 uStack12;

  if ((*param_1 & 8) == 0) {
    local_58 = DAT_01ffa71c;
  }
  else {
    local_58 = PTR_LAB_01ffa718;
  }

  // looks like this is setting up the texture matrix on the stack?

  local_14 = 0x1000;
  local_54 = 3;
  local_10 = 2;
  local_18 = 0;
  local_24 = 0;
  local_28 = 0;
  local_2c = 0;
  local_30 = 0;
  local_34 = 0;
  local_38 = 0;
  local_44 = 0;
  local_48 = 0;
  uStack12 = param_4;
  (**(code **)(PTR_PTR_LAB_01ffa720 + (*param_1 & 7) * 4))(&local_50,param_1);
  if (param_1[0xc] != 0x1000) {
    lVar1 = (longlong)(int)param_1[0xc] * (longlong)(int)local_50;
    local_50 = (uint)lVar1 >> 0xc | (int)((ulonglong)lVar1 >> 0x20) << 0x14;
    local_4c = (uint)((longlong)(int)param_1[0xc] * (longlong)(int)local_4c) >> 0xc |
               (int)((ulonglong)((longlong)(int)param_1[0xc] * (longlong)(int)local_4c) >> 0x20) <<
               0x14;
    local_20 = (uint)((longlong)(int)param_1[0xc] * (longlong)(int)local_20) >> 0xc |
               (int)((ulonglong)((longlong)(int)param_1[0xc] * (longlong)(int)local_20) >> 0x20) <<
               0x14;
  }
  if (param_1[0xd] != 0x1000) {
    lVar1 = (longlong)(int)param_1[0xd] * (longlong)(int)local_40;
    local_40 = (uint)lVar1 >> 0xc | (int)((ulonglong)lVar1 >> 0x20) << 0x14;
    local_3c = (uint)((longlong)(int)param_1[0xd] * (longlong)(int)local_3c) >> 0xc |
               (int)((ulonglong)((longlong)(int)param_1[0xd] * (longlong)(int)local_3c) >> 0x20) <<
               0x14;
    local_1c = (uint)((longlong)(int)param_1[0xd] * (longlong)(int)local_1c) >> 0xc |
               (int)((ulonglong)((longlong)(int)param_1[0xd] * (longlong)(int)local_1c) >> 0x20) <<
               0x14;
  }
  FUN_01ff9f00(local_58,&local_54,0x12);
  return;
}