diff --git a/src/thingdef/thingdef.h b/src/thingdef/thingdef.h index e39d12ab0..08264e0a8 100644 --- a/src/thingdef/thingdef.h +++ b/src/thingdef/thingdef.h @@ -22,12 +22,15 @@ struct FFlagDef unsigned int flagbit; const char *name; int structoffset; + int fieldsize; }; FFlagDef *FindFlag (const PClass *type, const char *part1, const char *part2); void HandleDeprecatedFlags(AActor *defaults, FActorInfo *info, bool set, int index); -bool CheckDeprecatedFlags(AActor *actor, FActorInfo *info, int index); +bool CheckDeprecatedFlags(const AActor *actor, FActorInfo *info, int index); const char *GetFlagName(unsigned int flagnum, int flagoffset); +void ModActorFlag(AActor *actor, FFlagDef *fd, bool set); +INTBOOL CheckActorFlag(const AActor *actor, FFlagDef *fd); #define FLAG_NAME(flagnum, flagvar) GetFlagName(flagnum, myoffsetof(AActor, flagvar)) diff --git a/src/thingdef/thingdef_codeptr.cpp b/src/thingdef/thingdef_codeptr.cpp index 304d57c07..7ed85a692 100644 --- a/src/thingdef/thingdef_codeptr.cpp +++ b/src/thingdef/thingdef_codeptr.cpp @@ -3629,14 +3629,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_ChangeFlag) bool linkchange = flagp == &self->flags && (fd->flagbit == MF_NOBLOCKMAP || fd->flagbit == MF_NOSECTOR); if (linkchange) self->UnlinkFromWorld(); - if (expression) - { - *flagp |= fd->flagbit; - } - else - { - *flagp &= ~fd->flagbit; - } + ModActorFlag(self, fd, expression); if (linkchange) self->LinkToWorld(); } kill_after = self->CountsAsKill(); @@ -3721,13 +3714,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CheckFlag) if (fd != NULL) { - if (fd->structoffset == -1) - { - if (CheckDeprecatedFlags(owner, cls->ActorInfo, fd->flagbit)) { - ACTION_JUMP(jumpto); - } - } - else if ( fd->flagbit & *(DWORD*)(((char*)owner) + fd->structoffset)) + if (CheckActorFlag(owner, fd)) { ACTION_JUMP(jumpto); } diff --git a/src/thingdef/thingdef_data.cpp b/src/thingdef/thingdef_data.cpp index 301427ad4..3dbbacac0 100644 --- a/src/thingdef/thingdef_data.cpp +++ b/src/thingdef/thingdef_data.cpp @@ -55,10 +55,10 @@ static TArray variables; //========================================================================== // [RH] Keep GCC quiet by not using offsetof on Actor types. -#define DEFINE_FLAG(prefix, name, type, variable) { prefix##_##name, #name, (int)(size_t)&((type*)1)->variable - 1 } -#define DEFINE_FLAG2(symbol, name, type, variable) { symbol, #name, (int)(size_t)&((type*)1)->variable - 1 } -#define DEFINE_DEPRECATED_FLAG(name) { DEPF_##name, #name, -1 } -#define DEFINE_DUMMY_FLAG(name) { DEPF_UNUSED, #name, -1 } +#define DEFINE_FLAG(prefix, name, type, variable) { prefix##_##name, #name, (int)(size_t)&((type*)1)->variable - 1, sizeof(((type *)0)->variable) } +#define DEFINE_FLAG2(symbol, name, type, variable) { symbol, #name, (int)(size_t)&((type*)1)->variable - 1, sizeof(((type *)0)->variable) } +#define DEFINE_DEPRECATED_FLAG(name) { DEPF_##name, #name, -1, 0 } +#define DEFINE_DUMMY_FLAG(name) { DEPF_UNUSED, #name, -1, 0 } static FFlagDef ActorFlags[]= { diff --git a/src/thingdef/thingdef_parse.cpp b/src/thingdef/thingdef_parse.cpp index 11c000102..c065dfbe0 100644 --- a/src/thingdef/thingdef_parse.cpp +++ b/src/thingdef/thingdef_parse.cpp @@ -441,15 +441,7 @@ void HandleActorFlag(FScanner &sc, Baggage &bag, const char *part1, const char * } else { - DWORD * flagvar = (DWORD*) ((char*)defaults + fd->structoffset); - if (mod == '+') - { - *flagvar |= fd->flagbit; - } - else - { - *flagvar &= ~fd->flagbit; - } + ModActorFlag(defaults, fd, mod == '+'); } } else diff --git a/src/thingdef/thingdef_properties.cpp b/src/thingdef/thingdef_properties.cpp index 482a841a2..e3461792b 100644 --- a/src/thingdef/thingdef_properties.cpp +++ b/src/thingdef/thingdef_properties.cpp @@ -95,6 +95,91 @@ static const PClass *FindClassTentative(const char *name, const char *ancestor) return cls; } +//========================================================================== +// +// Sets or clears a flag, taking field width into account. +// +//========================================================================== +void ModActorFlag(AActor *actor, FFlagDef *fd, bool set) +{ + // Little-Endian machines only need one case, because all field sizes + // start at the same address. (Unless the machine has unaligned access + // exceptions, in which case you'll need multiple cases for it too.) +#ifdef __BIG_ENDIAN__ + if (fd->fieldsize == 4) +#endif + { + DWORD *flagvar = (DWORD *)((char *)actor + fd->structoffset); + if (set) + { + *flagvar |= fd->flagbit; + } + else + { + *flagvar &= ~fd->flagbit; + } + } +#ifdef __BIG_ENDIAN__ + else if (fd->fieldsize == 2) + { + WORD *flagvar = (WORD *)((char *)actor + fd->structoffset); + if (set) + { + *flagvar |= fd->flagbit; + } + else + { + *flagvar &= ~fd->flagbit; + } + } + else + { + assert(fd->fieldsize == 1); + BYTE *flagvar = (BYTE *)((char *)actor + fd->structoffset); + if (set) + { + *flagvar |= fd->flagbit; + } + else + { + *flagvar &= ~fd->flagbit; + } + } +#endif +} + +//========================================================================== +// +// Returns whether an actor flag is true or not. +// +//========================================================================== + +INTBOOL CheckActorFlag(const AActor *owner, FFlagDef *fd) +{ + if (fd->structoffset == -1) + { + return CheckDeprecatedFlags(owner, owner->GetClass()->ActorInfo, fd->flagbit); + } + else +#ifdef __BIG_ENDIAN__ + if (fd->fieldsize == 4) +#endif + { + return fd->flagbit & *(DWORD *)(((char*)owner) + fd->structoffset); + } +#ifdef __BID_ENDIAN__ + else if (fd->fieldsize == 2) + { + return fd->flagbit & *(WORD *)(((char*)owner) + fd->structoffset); + } + else + { + assert(fd->fieldsize == 1); + return fd->flagbit & *(BYTE *)(((char*)owner) + fd->structoffset); + } +#endif +} + //=========================================================================== // // HandleDeprecatedFlags @@ -170,7 +255,7 @@ void HandleDeprecatedFlags(AActor *defaults, FActorInfo *info, bool set, int ind // //=========================================================================== -bool CheckDeprecatedFlags(AActor *actor, FActorInfo *info, int index) +bool CheckDeprecatedFlags(const AActor *actor, FActorInfo *info, int index) { // A deprecated flag is false if // a) it hasn't been added here @@ -211,11 +296,11 @@ bool CheckDeprecatedFlags(AActor *actor, FActorInfo *info, int index) return (actor->BounceFlags & (BOUNCE_TypeMask|BOUNCE_UseSeeSound)) == BOUNCE_DoomCompat; case DEPF_PICKUPFLASH: - return static_cast(actor)->PickupFlash == PClass::FindClass("PickupFlash"); + return static_cast(actor)->PickupFlash == PClass::FindClass("PickupFlash"); // A pure name lookup may or may not be more efficient, but I know no static identifier for PickupFlash. case DEPF_INTERHUBSTRIP: - return !(static_cast(actor)->InterHubAmount); + return !(static_cast(actor)->InterHubAmount); } return false; // Any entirely unknown flag is not set