Difference between revisions of "Network Protocol/RACEDATA"
(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-> | + | d->buttons = src[ 0x028 ] >> 4 & 0x0Fu; |
− | d-> | + | 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 | ||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
</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 | + | 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