Difference between revisions of "Network Protocol/RACEDATA"

From Custom Mario Kart
Jump to navigation Jump to search
(Some items ...)
Line 17: Line 17:
 
     d->direction[1] = be32(src+ 0x00c -1) >> 2 & 0x0001FFFFu;
 
     d->direction[1] = be32(src+ 0x00c -1) >> 2 & 0x0001FFFFu;
 
     d->direction[2] = be32(src+ 0x00e -1) >> 1 & 0x0001FFFFu;
 
     d->direction[2] = be32(src+ 0x00e -1) >> 1 & 0x0001FFFFu;
 +
    d->thundercloud    =      src[ 0x026 ]        &      0x01u;
 
     d->lakitu =      src[ 0x027 ]  >> 6 &      0x03u;
 
     d->lakitu =      src[ 0x027 ]  >> 6 &      0x03u;
     d->unknown_28 =      src[ 0x028 ];
+
     d->buttons =      src[ 0x028 ]   >> 4 &      0x0Fu;
     d->buttons =      src[ 0x028 ]  >> 4 &      0x03u;
+
    d->goldenshroom    =      src[ 0x029 ]  >> 6 &      0x01u;
 +
    d->megamushroom    =      src[ 0x029 ]        &      0x01u;
 +
    d->star            =      src[ 0x02a ]  >> 7 &      0x01u;
 +
    d->star_hit        =      src[ 0x02c ]  >> 7 &      0x01u;  
 +
     d->fakebox_hit      =      src[ 0x02c ]  >> 6 &      0x01u;  
 
     d->drift =      src[ 0x032 ]  >> 6 &      0x03u;
 
     d->drift =      src[ 0x032 ]  >> 6 &      0x03u;
 
     d->already_drifted =      src[ 0x032 ]  >> 4 &      0x01u;
 
     d->already_drifted =      src[ 0x032 ]  >> 4 &      0x01u;
Line 25: Line 30:
  
 
     return 0x40; // record size
 
     return 0x40; // record size
 
    //-------------------------------
 
    //      Reference Statistic
 
    //-------------------------------
 
    // bits : off-1 .. off-2 : usage
 
    //-------------------------------
 
    //  135 : 000.0 .. 010.6 :  1
 
    //  177 : 010.7 .. 026.7 :  -
 
    //    2 : 027.0 .. 027.1 :  1
 
    //    6 : 027.2 .. 027.7 :  -
 
    //    2 : 028.0 .. 028.1 :  1
 
    //    2 : 028.2 .. 028.3 :  2!
 
    //    4 : 028.4 .. 028.7 :  1
 
    //  72 : 029.0 .. 031.7 :  -
 
    //    2 : 032.0 .. 032.1 :  1
 
    //    1 : 032.2 .. 032.2 :  -
 
    //    1 : 032.3 .. 032.3 :  1
 
    //    1 : 032.4 .. 032.4 :  -
 
    //    4 : 032.5 .. 033.0 :  1
 
    //-------------------------------
 
 
</pre>
 
</pre>
  
Line 56: Line 41:
 
   u32 direction 3  0a  4 17 curious direction vector, see comment
 
   u32 direction 3  0a  4 17 curious direction vector, see comment
 
   ---------------------------------------------------------------------------------------
 
   ---------------------------------------------------------------------------------------
 +
  u8  thundercloud    -  26  7  1    0: lost cloud (by cloud hit?), 1: got cloud
 
   u8 lakitu -  27  0  2 0:no lakitu, 1:phase 1, 2:phase 2, 3:?
 
   u8 lakitu -  27  0  2 0:no lakitu, 1:phase 1, 2:phase 2, 3:?
   u8  buttons -  28  2 2 1:drive(A), 2:break/backward(B), 3:both
+
   u8  buttons -  28  0 4 1:drive (A or Mushroom), 2:break/backward(B), 3:A&B, 7: Hop or drift phase 1, 15: drift phase 2
 +
  u8  goldenshroom    -  29  1  1    1 when you hit the item button, 0 when the single boost is finished (not the whole golden)
 +
  u8  megamushroom    -  29  7  1    This bit flips every time you use a mega mushroom
 +
  u8  star            -  2a  0  1    This bit flips every time you use a star
 +
  u8  star_hit        -  2c  0  1    This bit flips every time you got hit by someone with a star
 +
  u8  fakebox_hit      -  2c  1  1    This bit flips every time you collide with a fake box
 
   u8 drift -  32  0  2 0:no drift, 1:drift, 2:blue, 3:yellow
 
   u8 drift -  32  0  2 0:no drift, 1:drift, 2:blue, 3:yellow
   u8 already_drifted -  32  3  1 1:driver has drifted at least once
+
   u8 already_drifted -  32  3  1 1:driver has drifted at least once
 
   u8 rank -  32  5  4 rank in race
 
   u8 rank -  32  5  4 rank in race
 
  !---------------------------------------------------------------------------------------
 
  !---------------------------------------------------------------------------------------
 
</pre>
 
</pre>
 +
 +
The values described with "This bit flips ..." do not indicate that you (for example) have a star enabled, those values start at zero and every time you enable a star, they flip.
  
 
== Position Vector ==
 
== Position Vector ==

Revision as of 19:27, 29 May 2015

This pages is related to MKWii Network Protocol and describes the record type RACEDATA.


Data Structure

RACEDATA records contain the player specific race data of a client. Depending on the number of player on a Wii, one or two records are send. The RACEDATA records follow immediately the RACE record with general racing information.

Template:MKWii Network Protocol RACE

Here is the record read function in GNU C notation. The function notation is used, because some values are bit packed. This code was created by a code generator.

    d->position[0]	= be32(src+ 0x000 )   >> 4 & 0x0FFFFFFFu;
    d->position[1]	= be32(src+ 0x003 )        & 0x0FFFFFFFu;
    d->position[2]	= be32(src+ 0x007 )   >> 4 & 0x0FFFFFFFu;
    d->direction[0]	= be32(src+ 0x00a -1) >> 3 & 0x0001FFFFu;
    d->direction[1]	= be32(src+ 0x00c -1) >> 2 & 0x0001FFFFu;
    d->direction[2]	= be32(src+ 0x00e -1) >> 1 & 0x0001FFFFu;
    d->thundercloud     =      src[ 0x026 ]        &       0x01u; 
    d->lakitu		=      src[ 0x027 ]   >> 6 &       0x03u;
    d->buttons		=      src[ 0x028 ]   >> 4 &       0x0Fu;
    d->goldenshroom     =      src[ 0x029 ]   >> 6 &       0x01u;
    d->megamushroom     =      src[ 0x029 ]        &       0x01u;
    d->star             =      src[ 0x02a ]   >> 7 &       0x01u; 
    d->star_hit         =      src[ 0x02c ]   >> 7 &       0x01u; 
    d->fakebox_hit      =      src[ 0x02c ]   >> 6 &       0x01u; 
    d->drift		=      src[ 0x032 ]   >> 6 &       0x03u;
    d->already_drifted	=      src[ 0x032 ]   >> 4 &       0x01u;
    d->rank		= be16(src+ 0x032 )   >> 7 &     0x000Fu;

    return 0x40; // record size

And here the code of a self written code generator script. The script creates data structures and the read function above. The byte offset is hex, all others are decimal numbers.

 !---------------------------------------------------------------------------------------
 !                        byte+bit
 ! type	name		 N offset bits	comment
 !---------------------------------------------------------------------------------------
   s32	position	 3   0  0 28	x+y+z positions in 1/16 units, 0x9f42410 is 0.0
   u32	direction	 3  0a  4 17	curious direction vector, see comment
  ---------------------------------------------------------------------------------------
   u8   thundercloud     -  26  7  1    0: lost cloud (by cloud hit?), 1: got cloud
   u8	lakitu		 -  27  0  2	0:no lakitu, 1:phase 1, 2:phase 2, 3:?
   u8   buttons		 -  28  0  4	1:drive (A or Mushroom), 2:break/backward(B), 3:A&B, 7: Hop or drift phase 1, 15: drift phase 2
   u8   goldenshroom     -  29  1  1    1 when you hit the item button, 0 when the single boost is finished (not the whole golden)
   u8   megamushroom     -  29  7  1    This bit flips every time you use a mega mushroom
   u8   star             -  2a  0  1    This bit flips every time you use a star
   u8   star_hit         -  2c  0  1    This bit flips every time you got hit by someone with a star
   u8   fakebox_hit      -  2c  1  1    This bit flips every time you collide with a fake box
   u8	drift		 -  32  0  2	0:no drift, 1:drift, 2:blue, 3:yellow
   u8  	already_drifted	 -  32  3  1	1:driver has drifted at least once
   u8	rank		 -  32  5  4	rank in race
 !---------------------------------------------------------------------------------------

The values described with "This bit flips ..." do not indicate that you (for example) have a star enabled, those values start at zero and every time you enable a star, they flip.

Position Vector

The 3 coordinates of the position vector are send as three 28 bit unsigned integers packed without padding. The following function calculates the real position:

double CalcRacePos ( uint val )
{
    // NULL is not transformed
    return val ? ( (int)val - 0x9f42410 ) / 16.0 : 0.0;
}

The constant 0x9f42410 (decimal: 166 994 960) for position 0.0 looks curious. It was found by analyzing respawn points in all 4 main directions. The first player is always respawned at the defined position, but 150 units shifted to the left.

Direction Vector

The direction vector is curious. It is a 17 bit signed integer number. Negative values are only seen for respawn points. See the following table; the second part are only the 4 main directions:

------------------------------------------
  3D vector in hex   horizontal
    x     y     z     direction  comment
------------------------------------------
[ 8000, 8000, c000]    0    S
[ ad41, 8000, ad41]   45    SO
[ b76b, 8000, a001]   60
[ bb20, 8000, 987d]   67.5 
[ c000, 8000, 7fff]   90    O
[ bb20, 8000, 4f04]  112.5 
[ b76b, 8000, 4006]  120
[ ad41, 8000, 257d]  135    NO
[ 9ffe, 8000, 112e]  150
[ 987d, 8000,  9be]  157.5 
[ 8000, 8000,    0]  180    N
[ 4f04, 8000,  9be]  202.5 
[ 4002, 8000, 112e]  210
[ 257d, 8000, 257d]  225    NW
[1ffff, 8000, 7fff]  270    W    1ffff=-1
[    0, 8000, 8000] ~270   ~W    a guess
[ 257d, 8000, ad41]  315    SW
------------------------------------------
[ 8000, 8000, c000]    0    S
[ c000, 8000, 7fff]   90    O
[1ffff, 8000, 7fff]  270    W    1ffff=-1
[ 8000, 8000,    0]  180    N
------------------------------------------

The following function print_direction() prints the X and Z direction for a given angle in degree, assuming tht the Y value is 0x8000 for a horizontal direction:

int calc_direction_vector ( double degree )
{
    // normalize degree (0 .. 359.9999)
    degree = fmod(degree,360.0);
    if ( degree < 0.0 )
	degree += 360.0;

    // math lib needs radiant and not degree
    const double rad = degree * M_PI / 180.0;

    return degree < 180.0
	? sin(rad) * 0x4000 + 0x8000
	: sin(rad) * 0x8000 + 0x8000;
	//: (int)( sin(rad) * 0x8000 + 0x7fff ) & 0x1ffff;
}

int normalze_direction_coordinate ( int val )
{
    // fix negative numbers and mask positive
    if ( val & 0x10000 )
	val = -(val & 0xffff);
    else
	val &= 0x0ffff;

    // subtract 0x8000
    val -= 0x8000;			

    // return normalized value
    return val >= 0 ? 2*val : val;
}

double calc_direction_degree ( int x, int z )
{
    //--- normalize  coordinates
    x = normalze_direction_coordinate(x);
    z = normalze_direction_coordinate(z);

    // calculate angle and covert into degree
    const double degree = atan2(x,z) * 180.0 / M_PI;

    // return a value between 0 and 360.00
    return degree < 0 ? degree + 360.0 : degree;
}

void print_direction ( double degree )
{
    // first: calc x and z positions
    const int x = calc_direction_vector( degree );
    const int z = calc_direction_vector( degree + 90.0 );

    // second: use x and z values toclauclate direction in degree
    const double degree2 = calc_direction_degree(x,z);

    // print out all results
    printf("%8.2f -> %5x %5x -> %6.2f\n",
	degree, x & 0x1ffff, z & 0x1ffff, degree2 );
}

Example run:

    0.00 ->  8000  c000 ->   0.00
   45.00 ->  ad41  ad41 ->  45.00
   90.00 ->  c000  8000 ->  90.00
  135.00 ->  ad41  257d -> 135.00
  180.00 ->  8000     0 -> 180.00
  225.00 ->  257d  257d -> 225.00
  270.00 ->     0  8000 -> 270.00
  315.00 ->  257d  ad41 -> 315.00
  360.00 ->  8000  c000 ->   0.00


Template:MKWii Network Protocol