explain a few of the unknown player_flags bits

This commit is contained in:
Martin Michelsen
2026-03-30 18:00:47 -07:00
parent b7819413b0
commit a05971017d
5 changed files with 51 additions and 50 deletions
+5 -6
View File
@@ -1136,9 +1136,8 @@ Action a_decrypt_dcv2_executable(
executable (DP_ADDRESS.JPN), INDEXES should be the path to the index fixup\n\ executable (DP_ADDRESS.JPN), INDEXES should be the path to the index fixup\n\
table (KATSUO.SEA), and VALUES should be the path to the value fixup table\n\ table (KATSUO.SEA), and VALUES should be the path to the value fixup table\n\
(IWASHI.SEA). The output is written to EXEC.dec.\n\ (IWASHI.SEA). The output is written to EXEC.dec.\n\
If --simple is given, uses the simpler encryption method used in some\n\ If --simple is given, uses the encryption method used in Ives\' Enhancement\n\
community modifications of the game (Enhancement Pack, for example). In\n\ Pack. In this case, --seed is not required; if not given, finds the seed\n\
this case, --seed is not required; if not given, finds the seed\n\
automatically, and prints it to stderr so you will be able to use it when\n\ automatically, and prints it to stderr so you will be able to use it when\n\
re-encrypting.\n", re-encrypting.\n",
+[](phosg::Arguments& args) { +[](phosg::Arguments& args) {
@@ -1166,8 +1165,8 @@ Action a_encrypt_dcv2_executable(
executable (DP_ADDRESS.JPN) and INDEXES should be the path to the index\n\ executable (DP_ADDRESS.JPN) and INDEXES should be the path to the index\n\
fixup table (KATSUO.SEA). The output is written to EXEC.enc and\n\ fixup table (KATSUO.SEA). The output is written to EXEC.enc and\n\
INDEXES.enc.\n\ INDEXES.enc.\n\
If --simple is given, uses the simpler encryption method used in some\n\ If --simple is given, uses the simpler encryption method used in Ives\'\n\
community modifications of the game. In this case, --seed is required.\n", Enhancement Pack. In this case, --seed is required.\n",
+[](phosg::Arguments& args) { +[](phosg::Arguments& args) {
string executable_filename = args.get<string>("executable", true); string executable_filename = args.get<string>("executable", true);
string executable_data = phosg::load_file(executable_filename); string executable_data = phosg::load_file(executable_filename);
@@ -1188,7 +1187,7 @@ Action a_encrypt_dcv2_executable(
Action a_decode_gci_snapshot( Action a_decode_gci_snapshot(
"decode-gci-snapshot", "\ "decode-gci-snapshot", "\
decode-gci-snapshot [INPUT-FILENAME [OUTPUT-FILENAME]]\n\ decode-gci-snapshot [INPUT-FILENAME [OUTPUT-FILENAME]]\n\
Decode a PSO GC snapshot file into a Windows BMP image.\n", Decode a PSO GC snapshot file (in GCI format) into a Windows BMP image.\n",
+[](phosg::Arguments& args) { +[](phosg::Arguments& args) {
auto data = read_input_data(args); auto data = read_input_data(args);
phosg::StringReader r(data); phosg::StringReader r(data);
+5 -4
View File
@@ -866,9 +866,10 @@ static const vector<DATEntityDefinition> dat_object_definitions({
// param5; if the dot product is positive, param2 is used) // param5; if the dot product is positive, param2 is used)
// param3 = room ID to use if the dot product described above is zero or negative // param3 = room ID to use if the dot product described above is zero or negative
// param5 = angle (see param2) // param5 = angle (see param2)
// param6 = if equal to 0x00010000, only the player's room_id field is set, and game flag 0x02000000 is set on // param6 = on v2 and before, this is ignored; on v3 and later, if param6 is equal to 0x00010000, only the
// the player; if not equal to 0x00010000, then both room_id and room_id2 are set and no game flag is set // player's room_id field is set, and player flag 0x02000000 is set on the player; if not equal to 0x00010000,
// (TODO: What are the visible behavior differences due to this parameter?) // then both room_id and room_id_in_custom_area (if in a non-rearrangeable area, like Pioneer 2 or Forest) are
// set and no game flag is set (TODO: What are the visible behavior differences due to this parameter?)
{0x000E, F_V0_V4, 0x00005FFFFFF83FFE, "TObjRoomId"}, {0x000E, F_V0_V4, 0x00005FFFFFF83FFE, "TObjRoomId"},
// Sensor of some kind (TODO). Params: // Sensor of some kind (TODO). Params:
@@ -6607,7 +6608,7 @@ void MapState::import_enemy_states_from_sync(Version from_version, const SyncEne
// Only set the state if it's not an alias // Only set the state if it's not an alias
if (ene_st->super_ene == ene) { if (ene_st->super_ene == ene) {
if (ene_st->game_flags != entry.flags) { if (ene_st->game_flags != entry.flags) {
this->log.warning_f("({:04X} => E-{:03X}) Flags from client ({:08X}) do not match game flags from map ({:08X})", this->log.warning_f("({:04X} => E-{:03X}) Game flags from client ({:08X}) do not match game flags from map ({:08X})",
enemy_index, ene_st->e_id, entry.flags, ene_st->game_flags); enemy_index, ene_st->e_id, entry.flags, ene_st->game_flags);
ene_st->game_flags = entry.flags; ene_st->game_flags = entry.flags;
} }
+2 -2
View File
@@ -721,7 +721,7 @@ const ChallengeTemplateDefinition& get_challenge_template_definition(Version ver
} }
PlayerHoldState::PlayerHoldState(const PlayerHoldState_DCProtos& proto) PlayerHoldState::PlayerHoldState(const PlayerHoldState_DCProtos& proto)
: unknown_a1(proto.unknown_a1), : expiration_frames(proto.expiration_frames),
unknown_a2(proto.unknown_a2), unknown_a2(proto.unknown_a2),
unknown_a3(0), unknown_a3(0),
trigger_radius2(proto.trigger_radius2), trigger_radius2(proto.trigger_radius2),
@@ -730,7 +730,7 @@ PlayerHoldState::PlayerHoldState(const PlayerHoldState_DCProtos& proto)
PlayerHoldState::operator PlayerHoldState_DCProtos() const { PlayerHoldState::operator PlayerHoldState_DCProtos() const {
PlayerHoldState_DCProtos ret; PlayerHoldState_DCProtos ret;
ret.unknown_a1 = this->unknown_a1; ret.expiration_frames = this->expiration_frames;
ret.unknown_a2 = this->unknown_a2; ret.unknown_a2 = this->unknown_a2;
ret.trigger_radius2 = this->trigger_radius2; ret.trigger_radius2 = this->trigger_radius2;
ret.x = this->x; ret.x = this->x;
+2 -2
View File
@@ -1129,7 +1129,7 @@ struct TelepipeState {
struct PlayerHoldState_DCProtos { struct PlayerHoldState_DCProtos {
// This is used in all versions of this command except DCNTE and 11/2000. // This is used in all versions of this command except DCNTE and 11/2000.
/* 00 */ le_uint16_t unknown_a1 = 0; /* 00 */ le_uint16_t expiration_frames = 0;
/* 02 */ le_uint16_t unknown_a2 = 0; /* 02 */ le_uint16_t unknown_a2 = 0;
// unknown_a3 is missing in this format, unlike the v1+ format below // unknown_a3 is missing in this format, unlike the v1+ format below
/* 04 */ le_float trigger_radius2 = 0.0f; /* 04 */ le_float trigger_radius2 = 0.0f;
@@ -1140,7 +1140,7 @@ struct PlayerHoldState_DCProtos {
struct PlayerHoldState { struct PlayerHoldState {
// This is used in all versions of this command except DCNTE and 11/2000. // This is used in all versions of this command except DCNTE and 11/2000.
/* 00 */ le_uint16_t unknown_a1 = 0; /* 00 */ le_uint16_t expiration_frames = 0;
/* 02 */ le_uint16_t unknown_a2 = 0; /* 02 */ le_uint16_t unknown_a2 = 0;
/* 04 */ le_uint32_t unknown_a3 = 0; /* 04 */ le_uint32_t unknown_a3 = 0;
/* 08 */ le_float trigger_radius2 = 0.0f; /* 08 */ le_float trigger_radius2 = 0.0f;
+37 -36
View File
@@ -1148,42 +1148,43 @@ uint32_t Parsed6x70Data::convert_player_flags(uint32_t player_flags, bool to_v3)
// other bits were added, so it doesn't suffice to simply store the most complete format of this field - we have to // other bits were added, so it doesn't suffice to simply store the most complete format of this field - we have to
// be able to convert between the two. What's known about these bits (? indicates meaning/behavior is unverified): // be able to convert between the two. What's known about these bits (? indicates meaning/behavior is unverified):
// V1/V2 V3/V4 // V1/V2 V3/V4
// 00000001 00000001 = player hold is set (see notes on 6x2C and 6x2D in CommandFormats.hh) // 00000001 00000001 = player hold is set (see notes on 6x2C and 6x2D in CommandFormats.hh)
// 00000002 00000002 = player hold is set for the purpose of dropping an item // 00000002 00000002 = player hold is set for the purpose of dropping an item
// 00000004 00000004 = is on a different floor from the local player (or is loading into game) // 00000004 00000004 = is on a different floor from the local player (or is loading into game)
// 00000008 00000008 ? = unknown (TODO: appears to be entirely unused, at least in v3) // 00000008 00000008 = unknown (TODO: appears to be entirely unused, at least in v2 and later)
// 00000010 00000010 = player has sent any update command (position, attack, etc.) this frame // 00000010 00000010 = player has sent any update command (position, attack, etc.) this frame
// 00000020 00000020 ? = unknown (TODO: appears to be entirely unused, at least in v3) // 00000020 00000020 = unknown (TODO: appears to be entirely unused, at least in v2 and later)
// 00000040 00000040 ? = unknown (TODO: appears to be entirely unused, at least in v3) // 00000040 00000040 = unknown (TODO: appears to be entirely unused, at least in v2 and later)
// 00000080 00000080 = is in windup animation for technique or PB // 00000080 00000080 = is in windup animation for technique or PB
// 00000100 -------- ? = unknown (TODO) // 00000100 -------- = unknown (TODO: appears to be entirely unused, at least in v2)
// 00000200 00000100 = chat, pause, or quick menu is open (suppresses action palette) // 00000200 00000100 = chat, pause, or quick menu is open (suppresses action palette)
// 00000400 00000200 = is in PB cutscene // 00000400 00000200 = is in PB cutscene
// 00000800 -------- ? = unknown (TODO) // 00000800 -------- = player is standing in water (steps create splash particles)
// 00001000 -------- ? = unknown (TODO) // 00001000 -------- = player is standing in grass (steps create grass particles)
// 00002000 00000400 = action palette is disabled by p_action_disable or one of the TObjQuestColA* objects // 00002000 00000400 = action palette is disabled by p_action_disable or one of the TObjQuestColA* objects
// 00004000 00000800 = is about to return to Pioneer 2 after a death (TODO: also set by p_return_guild) // 00004000 00000800 = is about to return to Pioneer 2 after a death (TODO: also set by p_return_guild)
// 00008000 00001000 = cannot use telepipe / Ryuker (e.g. boss warps set this flag when the player is nearby) // 00008000 00001000 = cannot use telepipe / Ryuker (e.g. boss warps set this flag when the player is nearby)
// 00010000 00002000 ? = unknown (TODO: appears to be entirely unused, at least in v3) // 00010000 00002000 = unknown (TODO: appears to be entirely unused, at least in v3)
// 00020000 00004000 = is teleporting as a result of 6x24 (set only briefly after appearing at destination) // 00020000 00004000 = is teleporting as a result of 6x24 (set only briefly after appearing at destination)
// 00040000 00008000 = is dead NPC (set by e.g. npc_crptalk_id when regsA[4] == 1) // 00040000 00008000 = is dead NPC (set by e.g. npc_crptalk_id when regsA[4] == 1)
// 00080000 -------- ? = unknown (TODO) // 00080000 -------- = unknown (TODO: appears to be entirely unused, at least in v2)
// 00100000 00010000 = has permanent trap vision (e.g. is android) // 00100000 00010000 = has permanent trap vision (e.g. is android)
// 00200000 00020000 = equipped items are invisible / intangible (e.g. in Pioneer 2) // 00200000 00020000 = equipped items are invisible / intangible (e.g. in Pioneer 2)
// 00400000 00040000 = is loading / changing floors (set by 6x22 and at game join, cleared by 6x23) // 00400000 00040000 = is loading / changing floors (set by 6x22 and at game join, cleared by 6x23)
// 00800000 00080000 = player data is in the process of being exported to save file format // 00800000 00080000 = player data is in the process of being exported to save file format
// 01000000 00100000 = initial cutscene with the Principal has started in offline free-play single-mode // 01000000 00100000 = initial cutscene with the Principal has started in offline free-play single-mode
// 02000000 00200000 = is visible (set shortly after warping into a floor; remains set until next warp) // 02000000 00200000 = is visible (set shortly after warping into a floor; remains set until next warp)
// 04000000 00400000 = position is valid (therefore player can be rendered) // 04000000 00400000 = position is valid (therefore player can be rendered)
// 08000000 00800000 = player is invisible if not local, but items are still visible (TODO: what about on BB?) // 08000000 00800000 = player is invisible if not local, but items are still visible (TODO: what about on BB?)
// 10000000 01000000 = if set, player does not drop weapon on death // 10000000 01000000 = if set, player does not drop weapon on death
// -------- 02000000 ? = used by TObjRoomId when param6 == 0x00010000 (TODO: figure out what this does) // -------- 02000000 = player's room_id_in_custom_area does not match player's room_id (used by TObjRoomId when
// -------- 04000000 = is sitting in lobby chair // param6 == 0x00010000; TODO: figure out what this does)
// -------- 08000000 = using male animations / poses in lobby chair // -------- 04000000 = is sitting in lobby chair
// -------- 10000000 = using alternate lobby chair pose (X+B instead of X+A on GC, for example) // -------- 08000000 = using male animations / poses in lobby chair
// -------- 20000000 ? = if set, the player will freeze when attempting any lobby animation (TODO: what does this // -------- 10000000 = using alternate lobby chair pose (X+B instead of X+A on GC, for example)
// actually do? it doesn't appear to be set anywhere normally) // -------- 20000000 = appears to be unused (there is no codepath that sets this flag); if set, the player will
// -------- 40000000 ? = unknown (TODO: used in offline multi-player Challenge mode; see tree from 3OE1:801BE594) // freeze when attempting any lobby animation
// -------- 40000000 = unknown (TODO: used in offline multi-player Challenge mode; see tree from 3OE1:801BE594)
if (to_v3) { if (to_v3) {
return (player_flags & 0x000000FF) | return (player_flags & 0x000000FF) |