Talk:BRRES Index Group (File Format)

From Custom Mario Kart
Jump to: navigation, 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)