Structures
Walker
/*
* size: 0x68 = 104 bytes
* Dmitry: struct IdentityData
*/
typedef struct {
/* +0x00 */ uint32_t le_unk0;
/* +0x04 */ uint32_t le_unk1;
/* +0x08 */ uint16_t le_unk2;
/* +0x0a */ uint16_t le_unk3;
/* +0x0c */ uint16_t le_tid;
/* +0x0e */ uint16_t le_sid;
/* +0x10 */ unique_identity_data_t identity_data;
/* +0x38 */ event_bitmap_t event_bitmap;
/* +0x48 */ uint16_t le_trainer_name[8];
/* +0x58 */ uint8_t unk4[2];
/* +0x5a */ uint8_t event_index;
/* +0x5b */ uint8_t flags; // [0]=init, [1]=has_pokemon, [2]=pokemon_joined, [3..7]=end_of_day_hour
/* +0x5c */ uint8_t protocol_ver;
/* +0x5d */ uint8_t unk5;
/* +0x5e */ uint8_t protocol_subver;
/* +0x5f */ uint8_t unk8;
/* +0x60 */ uint32_t be_last_sync;
/* +0x64 */ uint32_t be_step_count;
} walker_info_t;
/*
* size: 0x18 = 24 bytes
* dmitry: struct HealthData
*/
typedef struct { // strut HealthData
/* +0x00 */ uint32_t be_total_steps;
/* +0x04 */ uint32_t be_today_steps;
/* +0x08 */ uint32_t be_last_sync; // seconds since 1 Jan 2001
/* +0x0c */ uint16_t be_total_days;
/* +0x0e */ uint16_t be_current_watts;
/* +0x10 */ uint16_t le_walk_minute_counter; // only used internally
/* +0x12 */ uint8_t steps_this_watt; // only used internally
/* +0x13 */ uint8_t event_log_write_idx; // only used internally
/* +0x14 */ uint8_t padding[3];
/* +0x17 */ uint8_t settings; // [0]=special_map, [1..2]=volume, [3..6]=contrast
} health_data_t;
/*
* size: 64 bytes
* dmitry: struct LcdConfigCmds
*/
typedef struct {
uint8_t flags;
uint8_t commands[0x3f];
} lcd_config_t;
/*
* size: 256 bytes
* dmitry: RELIABLE_DATA
*
* Warning: gcc will add padding by default
* since members aren't aligned
*/
typedef struct {
/* +0x00 */ uint8_t factory_data[2];
/* +0x02 */ uint8_t factory_data_checksum;
/* +0x03 */ unique_identity_data_t unique_data;
/* +0x2b */ uint8_t unique_data_checksum;
/* +0x2c */ lcd_config_t lcd_config;
/* +0x6c */ uint8_t lcd_config_checksum;
/* +0x6d */ walker_info_t walker_info;
/* +0xd5 */ uint8_t walker_info_checksum;
/* +0xd6 */ health_data_t health_data;
/* +0xee */ uint8_t health_data_checksum;
/* +0xef */ uint8_t copy_marker;
/* +0xf0 */ uint8_t padding[16];
} reliable_data_t;
/*
* size: 1 byte
*
*/
typedef struct {
uint8_t stamp_heart: 1;
uint8_t stamp_space: 1;
uint8_t stamp_diamond: 1;
uint8_t stamp_club: 1;
uint8_t special_map: 1;
uint8_t event_pokemon: 1;
uint8_t evet_item: 1;
uint8_t special_route: 1;
} special_inventory_t;
Notes:
- Walker refuses walk end when walker_info_t.le_unk{1,3} are not {1,7} respectively, stating "not the correct pokewalker"
Pokemon
/*
* size: 0x38 = 56 bytes
* dmitry: struct PeerPlayData
*/
typedef struct { // Dmitry struct PeerPlayData
/* +0x00 */ uint32_t le_current_steps;
/* +0x04 */ uint16_t le_current_watts;
/* +0x06 */ uint8_t padding[2];
/* +0x08 */ uint32_t le_unk0;
/* +0x0c */ uint16_t le_unk2;
/* +0x0e */ uint16_t le_species;
/* +0x10 */ uint16_t pokemon_name[11];
/* +0x26 */ uint16_t trainer_name[8];
/* +0x36 */ uint8_t pokemon_flags_1;
/* +0x37 */ uint8_t pokemon_flags_2;
} peer_play_data_t;
/*
* size: 16 bytes
* dmitry: struct PokemonSummary
*/
typedef struct {
/* +0x00 */ uint16_t le_species;
/* +0x02 */ uint16_t le_held_item;
/* +0x04 */ uint16_t le_moves[4];
/* +0x0c */ uint8_t level;
/* +0x0d */ uint8_t pokemon_flags_1; // [0..5] = variant (spinda, arceus, unown, etc.) [6] = female
/* +0x0e */ uint8_t pokemon_flags_2; // [0] = has form, [1] = shiny
/* +0x0f */ uint8_t padding;
} pokemon_summary_t;
/*
* size: 0x38 = 56 bytes
* dmitry: struct TeamPokeData
*/
typedef struct {
/* +0x00 */ uint16_t le_species;
/* +0x02 */ uint16_t le_held_item;
/* +0x04 */ uint16_t le_moves[4];
/* +0x0c */ uint16_t le_ot_tid;
/* +0x0e */ uint16_t le_ot_sid;
/* +0x10 */ uint32_t le_pid;
/* +0x14 */ uint32_t ivs; // packed to 5-bits each
/* +0x18 */ uint8_t evs[6];
/* +0x1e */ uint8_t pokemon_flags_1;
/* +0x1f */ uint8_t source_game;
/* +0x20 */ uint8_t ability;
/* +0x21 */ uint8_t happiness;
/* +0x22 */ uint8_t level;
/* +0x23 */ uint8_t padding;
/* +0x24 */ uint16_t nickname[10];
} pokemon_info_t;
/*
* size: 0x2c = 44 bytes
* dmitry: struct EventPokeExtraData
*/
typedef struct {
/* +0x00 */ uint32_t le_unk0;
/* +0x04 */ uint16_t le_ot_tid;
/* +0x06 */ uint16_t le_ot_sid;
/* +0x08 */ uint16_t le_unk1;
/* +0x0a */ uint16_t le_location_met;
/* +0x0c */ uint16_t le_unk2;
/* +0x0e */ uint16_t ot_name[8];
/* +0x1e */ uint8_t encounter_type;
/* +0x1f */ uint8_t ability;
/* +0x20 */ uint16_t le_pokeball_item;
/* +0x22 */ uint8_t unk3[10];
} special_pokemon_info_t;
Note: special_pokemon_info_t cannot contain PID because ability, gender, shininess, spinda spots all depend on PID.
So PID must be generated/inferred from the data given.
Unsure if it's random each time, or if the same gifted pokemon gives the same PID.
The le_unk1 and le_unk2 change PV somehow, since I can see nature and characteristics changes.
Nothing seems to grant ribbons, marks or pokerus.
Routes
typedef enum {
/* 0x00 */ ROUTE_IMAGE_FIELD_AND_TREES,
/* 0x01 */ ROUTE_IMAGE_FOREST_AND_TREES,
/* 0x02 */ ROUTE_IMAGE_SUBURBS,
/* 0x03 */ ROUTE_IMAGE_URBAN,
/* 0x04 */ ROUTE_IMAGE_MOUNTAIN,
/* 0x05 */ ROUTE_IMAGE_CAVE,
/* 0x06 */ ROUTE_IMAGE_LAKE,
/* 0x07 */ ROUTE_IMAGE_BEACH,
} route_image_index_t;
/*
* size: 0xbe = 190 bytes
* dmitry: struct RouteInfo
*/
typedef struct {
/* +0x00 */ pokemon_summary_t pokemon_summary;
/* +0x10 */ uint16_t pokemon_nickname[11];
/* +0x26 */ uint8_t pokemon_happiness;
/* +0x27 */ uint8_t route_image_index;
/* +0x28 */ uint16_t route_name[21];
/* +0x52 */ pokemon_summary_t route_pokemon[3];
/* +0x82 */ uint16_t le_route_pokemon_steps[3];
/* +0x88 */ uint8_t route_pokemon_percent[3];
/* +0x8b */ uint8_t padding;
/* +0x8c */ uint16_t le_route_items[10];
/* +0xa0 */ uint16_t le_route_item_steps[10];
/* +0xb4 */ uint8_t route_item_percent[10];
} route_info_t;
/*
* size: 0x6ac = 1708 bytes
* dmitry: struct SpecialRoute
*/
typedef struct {
/* +0x0000 */ uint8_t item_info[6];
/* +0x0006 */ uint8_t route_image_index;
/* +0x0007 */ uint8_t padding_1;
/* +0x0008 */ pokemon_summary_t special_pokemon;
/* +0x0018 */ special_pokemon_info_t special_pokemon_extra;
/* +0x0044 */ uint16_t le_special_pokemon_steps;
/* +0x0046 */ uint8_t special_pokemon_percent;
/* +0x0047 */ uint8_t padding_2;
/* +0x0048 */ uint16_t le_special_item;
/* +0x004a */ uint16_t le_special_item_steps;
/* +0x004c */ uint8_t special_item_percent;
/* +0x004d */ uint8_t padding_3[3];
/* +0x0050 */ uint16_t route_name[21];
/* +0x007a */ uint8_t pokemon_event_number;
/* +0x007b */ uint8_t item_event_number;
/* +0x007c */ uint8_t special_pokemon_sprite_data[0x170]; // should be 0x180 bytes, truncated
/* +0x01ec */ uint8_t special_pokemon_name_image[0x140];
/* +0x032c */ uint8_t special_area_icon[0xc0];
/* +0x03ec */ uint8_t special_area_name_image[0x140];
/* +0x052c */ uint8_t special_item_name_image[0x180];
} special_route_info_t;
Logs
/*
* size: 0x88 = 136 bytes
* dmitry: struct EventLogItem
* Modified from dmitry's version
*/
typedef struct {
/* 0x00 */ uint32_t be_time;
/* 0x04 */ uint32_t le_unk0;
/* 0x08 */ uint16_t le_unk2;
/* 0x0a */ uint16_t le_our_species;
/* 0x0c */ uint16_t le_other_species;
/* 0x0e */ uint16_t le_extra;
/* 0x10 */ uint16_t other_trainer_name[8];
/* 0x20 */ uint16_t our_pokemon_name[11];
/* 0x36 */ uint16_t other_pokemon_name[11];
/* 0x4c */ uint16_t route_name[21];
/* 0x76 */ uint8_t route_image_index;
/* 0x77 */ uint8_t pokemon_friendship;
/* 0x78 */ uint16_t be_our_watts;
/* 0x7a */ uint16_t be_other_watts;
/* 0x7c */ uint32_t be_steps;
/* 0x80 */ uint32_t be_other_steps;
/* 0x84 */ uint8_t event_type;
/* 0x85 */ uint8_t our_pokemon_flags;
/* 0x86 */ uint8_t other_pokemon_flags;
/* 0x87 */ uint8_t padding;
} event_log_item_t;
typedef enum {
/* 0x00 */ EVENT_TYPE_EMPTY_ENTRY,
/* 0x01 */ EVENT_TYPE_PEER_PLAY_1,
/* 0x02 */ EVENT_TYPE_PEER_PLAY_2,
/* 0x03 */ EVENT_TYPE_PEER_PLAY_3,
/* 0x04 */ EVENT_TYPE_PEER_PLAY_4,
/* 0x05 */ EVENT_TYPE_PEER_PLAY_5,
/* 0x06 */ EVENT_TYPE_PEER_PLAY_6,
/* 0x07 */ EVENT_TYPE_PEER_PLAY_7,
/* 0x08 */ EVENT_TYPE_PEER_PLAY_8,
/* 0x09 */ EVENT_TYPE_PEER_PLAY_9,
/* 0x0a */ EVENT_TYPE_PEER_PLAY_10,
/* 0x0b */ EVENT_TYPE_ITEM_DOWSED,
/* 0x0c */ EVENT_TYPE_SPECIAL_ITEM_DOWSED,
/* 0x0d */ EVENT_TYPE_POKEMON_CAUGHT,
/* 0x0e */ EVENT_TYPE_SPECIAL_POKEMON_CAUGHT,
/* 0x0f */ EVENT_TYPE_POKEMON_RAN,
/* 0x10 */ EVENT_TYPE_POKEMON_LOST,
/* 0x11 */ EVENT_TYPE_POKEMON_FOUND_ITEM,
/* 0x12 */ EVENT_TYPE_MOOD_HAPPY,
/* 0x13 */ EVENT_TYPE_MOOD_RUNNING,
/* 0x14 */ EVENT_TYPE_MOOD_LOOKING_AWAY,
/* 0x15 */ EVENT_TYPE_MOOD_BORED,
/* 0x16 */ EVENT_TYPE_MOOD_GO_HOME,
/* 0x17 */ EVENT_TYPE_POKEMON_JOINED,
/* 0x18 */ EVENT_TYPE_WALK_ENDED,
/* 0x19 */ EVENT_TYPE_WALK_STARTED,
/* 0x1a */ EVENT_TYPE_PLAYED_ALOT,
/* 0x1b */ EVENT_TYPE_FELL_ASLEEP,
/* 0x1c */ EVENT_TYPE_ITEM_GIFTED,
} event_log_type_t;
IR
/*
* size: 0x88 = 136 bytes
*/
typedef struct {
/* +0x00 */ uint8_t cmd;
/* +0x01 */ uint8_t extra;
/* +0x02 */ uint16_t le_checksum;
/* +0x04 */ uint32_t le_session_id;
/* +0x08 */ uint8_t payload[128];
} pw_packet_t;
Audio
/*
* size: 0x02 = 2 bytes
*/
typedef struct {
/* +0x00 */ uint8_t info; // ? used in calculating note duration
/* +0x01 */ uint8_t period_idx; // [7] = negative duration?, [6:0] = index into period table
} pw_sound_frame_t;
/*
* size: 0x03 = 3 bytes
*/
typedef struct {
/* 0x00 */ uint16_t offset; // byte offset into SOUND_DATA for start of sound
/* 0x02 */ uint8_t length; // number of bytes this sound effect uses
/* 0x03 */ uint8_t pad;
} pw_sound_info_t;
enum sound_type {
SOUND_NAVIGATE_MENU = 0,
SOUND_NAVIGATE_BACK = 1,
SOUND_CURSOR_MOVE = 2,
SOUND_POKERADAR_FOUND_SOMETHING = 3,
SOUND_SELECTION_MISS = 4,
SOUND_DOWSING_FOUND_ITEM = 5,
SOUND_POKEMON_CAUGHT = 7,
SOUND_POKEMON_ENCOUNTER = 10,
SOUND_MINIGAME_FAIL = 14,
SOUND_POKEBALL_THROW = 15,
}
Notes:
- What does
pw_sound_frame_tstore exactly? what'sinfoand why doesperiod_idxseem to be used to calculate a negative(?) duration? - It would be interesting to see what the missing sounds are. m8 has a wav file, maybe they're mystery gift/ir stuff.