Talk:BRRES Index Group (File Format)

From Custom Mario Kart
Jump to navigation Jump to search

Meaning of entry values

Does anyone know more about ID, left and right index? My tools can now list and extract BRRES files, but for creating I must know how to calculate them. Here is an example for discussion:

File Race/Course/ridgehighway_course.szs -> course_model.brres
 idx    ID    ? left right    name     data  magic name
-------------------------------------------------------------------------------
   0: ffff    0    f    0        0        0  -
   1:   66    0    9    5   3be0f4    866b8  TEX0  ef_arrowBumpS
   2:   5c    0    2    1   3be108    876f8  TEX0  ef_arrowGradS
   3:   56    0   14    a   3be130    87f38  TEX0  ef_prj_glow
   4:   6d    0    1    4   3be140    88f78  TEX0  ef_rainbowRed2
   5:   65    0    2    5   3be160    891b8  TEX0  ef_wave1P_Mip
   6:   6e    0    4    7   3be174    8a6f8  TEX0  ef_wave_indMip
   7:   6a    0   1c    7   3bdc3c    8d138  TEX0  ETC_DenkouTubu
   8:   95    0   10    8   3bdc50    8fc58  TEX0  ETC_Kanban_00_mod01
   9:   5e    0    3   12   3bdec0    a5098  TEX0  Mi_LightMask
   a:   54    0   11    3   3bde3c    a90d8  TEX0  M_bill_merg
   b:   7e    0    d   1e   3bde4c    b9118  TEX0  M_bill_merg_mask
   c:   52    0    c   1d   3bdd38    c1158  TEX0  M_EnkeiYama
   d:   76    0    6   13   3bdd48    d1198  TEX0  M_IwaKabe00_mip
   e:   3e    0   20    e   3bde64    e65d8  TEX0  M_jyukai
   f:   96    0    8    f   3bdd5c   1110d8  TEX0  M_Kanban2_mod01_mip
  10:   8e    0    b   10   3bdd74   166118  TEX0  M_Kanban_mod01_mip
  11:   53    0    c   11   3bdd8c   2ba158  TEX0  M_KasanDash
  12:   5d    0   12   16   3bddac   2be198  TEX0  M_Kirakira_A
  13:   74    0   13    d   3bddc0   2ce1d8  TEX0  M_Kirakira_mask
  14:   4e    0   18   14   3bdd9c   2ce618  TEX0  M_Ki_enkei
  15:   2e    0    0   17   3bde74   2d0658  TEX0  M_kusa
  16:   5b    0   16    9   3bddd4   2db158  TEX0  M_NoboriKabe
  17:   2b    0   1f   17   3bdde8   2f0598  TEX0  M_Nuki
  18:   45    0    e   1a   3bde80   3059d8  TEX0  M_road_00
  19:   40    0   18   21   3bde90   31aff8  TEX0  M_road_01
  1a:   41    0   19   1b   3bdea0   330618  TEX0  M_road_02
  1b:   40    0   22   1b   3bdeb0   345c38  TEX0  M_road_03
  1c:   5d    0    6   1c   3bddf4   347218  TEX0  M_TubeRoof_mip
  1d:   51    0   1d    a   3bde08   371a58  TEX0  M_TuchiRoad
  1e:   7c    0    b   1e   3bde18   379a98  TEX0  M_WallMerg00_mip
  1f:   24    0   1f   15   3bde30   38ead8  TEX0  M_Yama
  20:   3d    0   15   20   3be3f0   3995d8  TEX0  wl_tire2
  21:   35    0   19   21   3be02c   3b9618  TEX0  WT_taki01
  22:   35    0   1a   22   3be03c   3bb658  TEX0  WT_taki02

Wiimm 15:53, 8 April 2011 (CEST)

I haven't yet finished working them out. Brawl box has a working implementation.
Chadderz 20:51, 8 April 2011 (CEST)


Coding Example of BrawlTools

BrawlLib/SSBB/Types/Common.cs line 238
public static void Build(ResourceGroup* group, int index, VoidPtr dataAddress, BRESString* pString)
{
    ResourceEntry* list = &group->_first;
    ResourceEntry* entry = &list[index];
    ResourceEntry* prev = &list[0], current = &list[prev->_leftIndex];
    ushort currentIndex = prev->_leftIndex;
    bool isRight = false;

    int strLen = pString->_length;
    byte* pChar = (byte*)pString + 4, sChar;

    int eIndex = strLen - 1, eBits = pChar[eIndex].CompareBits(0), val;
    *entry = new ResourceEntry((eIndex << 3) 
           | eBits, index, index, (int)dataAddress - (int)group, (int)pChar - (int)group);

    //Continue while the previous id is greater than the current.
    //   Loop backs will stop the processing.
    //Continue while the entry id is less than or equal the current id.
    //   Being higher than the current id means we've found a place to insert.
    while ((entry->_id <= current->_id) && (prev->_id > current->_id))
    {
	if (entry->_id == current->_id)
	{
	    sChar = (byte*)group + current->_stringOffset;

	    //Rebuild new id relative to current entry
	    for (eIndex = strLen; (eIndex-- > 0) && (pChar[eIndex] == sChar[eIndex]); ) ;
	    eBits = pChar[eIndex].CompareBits(sChar[eIndex]);

	    entry->_id = (ushort)((eIndex << 3) | eBits);

	    if (((sChar[eIndex] >> eBits) & 1) != 0)
	    {
		entry->_leftIndex = (ushort)index;
		entry->_rightIndex = currentIndex;
	    }
	    else
	    {
		entry->_leftIndex = currentIndex;
		entry->_rightIndex = (ushort)index;
	    }
	}

	//Is entry to the right or left of current?
	isRight = ((val = current->_id >> 3) < strLen)
			&& (((pChar[val] >> (current->_id & 7)) & 1) != 0);

	prev = current;
	current = &list[currentIndex = (isRight)
		? current->_rightIndex : current->_leftIndex];
    }

    sChar = (current->_stringOffset == 0) ? null : (byte*)group + current->_stringOffset;
    val = sChar == null ? 0 : (int)(*(bint*)(sChar - 4));

    if ((val == strLen) && (((sChar[eIndex] >> eBits) & 1) != 0))
	entry->_rightIndex = currentIndex;
    else
	entry->_leftIndex = currentIndex;

    if (isRight)
	prev->_rightIndex = (ushort)index;
    else
	prev->_leftIndex = (ushort)index;
}


BrawlLib/System/ByteExtension.cs line 7

This is the CompareBits() function: it find out the highest different bit and returns the bit number (0..7):

public static int CompareBits(this Byte b1, byte b2)
{
    for (int i = 8, b = 0x80; i-- != 0; b >>= 1)
	if ((b1 & b) != (b2 & b))
	    return i;
    return 0;
}

(In my eyes) it could be written a little bit clearer (not knowing if this language supports the ^ operator:

public static int CompareBits(this Byte b1, byte b2)
{
    b1 ^= b2;
    // and now find the highest set bit
    for ( int i = 7; i > 0 && !(b1&0x80); i--, b1 <<= 1 )
        ;
    return i;
}

Wiimms code snippets

Here is my first code snippet to calculate the ID. I have done some empirical tests and it seems to work:

static u16 get_highest_bit ( u8 val )
{
    // [2do] use a lookup table if this is time critical

    u16 i;
    for ( i = 7; i > 0 && !( val & 0x80 ); i--, val <<= 1 )
	;
    return i;
}

typedef const char * ccp;

static u16 calc_brres_id
(
    ccp  prev_name,
    uint prev_len,
    ccp	 cur_name,
    uint cur_len
)
{
    if ( prev_len < cur_len )
	return cur_len - 1 << 3 | get_highest_bit(cur_name[cur_len-1]);

    while ( cur_len-- > 0 )
    {
	const u8 ch = prev_name[cur_len] ^ cur_name[cur_len];
	if (ch)
	    return cur_len << 3 | get_highest_bit(ch);
    }

    return ~(u16)0;
}


Names

I'm starting to get more information about brres files but I'm stuck at generating the id, as in I don't actually get where the filename (subject) and another filename (object) are stored in a brres. The code examples don't seem to give an answer to me.
kHacker35000vr 20:16, 5 April 2012 (CEST)

It's hard stuff and coding experience may help to understand´d it. Here is my code version:http://opensvn.wiimm.de/viewvc/wii/trunk/wiimms-szs-tools/src/lib-brres.c?view=annotate#l305
It's only a little bit different, but maybe a little bit alternative implementation may help.
Wiimm 21:38, 5 April 2012 (CEST)