From d7d052857a8a496328ea126f89b2da7106290694 Mon Sep 17 00:00:00 2001 From: Kp Date: Thu, 26 Dec 2013 03:10:16 +0000 Subject: [PATCH] Use bitmask for hitobj_list Reduces sizeof(laser_info) from 392 to 80. --- common/main/object.h | 62 +++++++++++++++++++++++++++++++++++++++- similar/main/collide.cpp | 6 ++-- similar/main/object.cpp | 2 +- similar/main/state.cpp | 2 +- 4 files changed, 66 insertions(+), 6 deletions(-) diff --git a/common/main/object.h b/common/main/object.h index 12d97b15d..3d92d6f9f 100644 --- a/common/main/object.h +++ b/common/main/object.h @@ -36,6 +36,7 @@ COPYRIGHT 1993-1999 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. #include "dxxsconf.h" #include "compiler-array.h" #include +#include /* * CONSTANTS @@ -223,12 +224,71 @@ struct physics_info_rw struct laser_info { + struct hitobj_list_t + { + typedef unsigned objnum_t; + template + struct tproxy + { + T *addr; + uint8_t mask; + tproxy(T *a, uint8_t m) : + addr(a), mask(m) + { + assert(m); + assert(!(m & (m - 1))); + } + dxx_explicit_operator_bool operator bool() const + { + return *addr & mask; + } + }; + typedef tproxy cproxy; + struct proxy : public tproxy + { + proxy(uint8_t *a, uint8_t m) : + tproxy(a, m) + { + } + proxy &operator=(bool b) + { + if (b) + *addr |= mask; + else + *addr &= ~mask; + return *this; + } + template + void operator=(T) DXX_CXX11_EXPLICIT_DELETE; + }; + array mask; + proxy operator[](objnum_t i) + { + return make_proxy(mask, i); + } + cproxy operator[](objnum_t i) const + { + return make_proxy(mask, i); + } + void clear() + { + mask.fill(0); + } + template + static T1 make_proxy(T2 &mask, objnum_t i) + { + typename T2::size_type index = i / 8, bitshift = i % 8; + if (!(index < mask.size())) + throw std::out_of_range("index exceeds object range"); + return T1(&mask[index], 1 << bitshift); + } + }; short parent_type; // The type of the parent of this object short parent_num; // The object's parent's number int parent_signature; // The object's parent's signature... fix64 creation_time; // Absolute time of creation. + hitobj_list_t hitobj_list; // list of all objects persistent weapon has already damaged (useful in case it's in contact with two objects at the same time) short last_hitobj; // For persistent weapons (survive object collision), object it most recently hit. - ubyte hitobj_list[MAX_OBJECTS]; // list of all objects persistent weapon has already damaged (useful in case it's in contact with two objects at the same time) short track_goal; // Object this object is tracking. fix multiplier; // Power if this is a fusion bolt (or other super weapon to be added). fix track_turn_time; diff --git a/similar/main/collide.cpp b/similar/main/collide.cpp index e88084f5a..5aea575a9 100644 --- a/similar/main/collide.cpp +++ b/similar/main/collide.cpp @@ -1275,7 +1275,7 @@ static void collide_weapon_and_controlcen( object * weapon, object *controlcen, damage = weapon->shields*2; // to not alter Gameplay too much, multiply damage by 2. if (!weapon->ctype.laser_info.hitobj_list[controlcen-Objects]) { - weapon->ctype.laser_info.hitobj_list[controlcen-Objects] = 1; + weapon->ctype.laser_info.hitobj_list[controlcen-Objects] = true; weapon->ctype.laser_info.last_hitobj = controlcen-Objects; } else @@ -1655,7 +1655,7 @@ static void collide_robot_and_weapon( object * robot, object * weapon, vms_vecto { if (!weapon->ctype.laser_info.hitobj_list[robot-Objects]) { - weapon->ctype.laser_info.hitobj_list[robot-Objects] = 1; + weapon->ctype.laser_info.hitobj_list[robot-Objects] = true; weapon->ctype.laser_info.last_hitobj = robot-Objects; } else @@ -2204,7 +2204,7 @@ void collide_player_and_weapon( object * playerobj, object * weapon, vms_vector { if (!weapon->ctype.laser_info.hitobj_list[playerobj-Objects]) { - weapon->ctype.laser_info.hitobj_list[playerobj-Objects] = 1; + weapon->ctype.laser_info.hitobj_list[playerobj-Objects] = true; weapon->ctype.laser_info.last_hitobj = playerobj-Objects; } else diff --git a/similar/main/object.cpp b/similar/main/object.cpp index a8bd80adb..086da7cc6 100644 --- a/similar/main/object.cpp +++ b/similar/main/object.cpp @@ -1208,7 +1208,7 @@ int obj_create(enum object_type_t type, ubyte id,int segnum,const vms_vector *po obj->mtype.phys_info.flags |= (Weapon_info[get_weapon_id(obj)].persistent*PF_PERSISTENT); obj->ctype.laser_info.creation_time = GameTime64; obj->ctype.laser_info.last_hitobj = -1; - memset(&obj->ctype.laser_info.hitobj_list, 0, sizeof(ubyte)*MAX_OBJECTS); + obj->ctype.laser_info.hitobj_list.clear(); obj->ctype.laser_info.multiplier = F1_0; #if defined(DXX_BUILD_DESCENT_II) obj->ctype.laser_info.last_afterburner_time = 0; diff --git a/similar/main/state.cpp b/similar/main/state.cpp index 84f46f06f..8e45784f9 100644 --- a/similar/main/state.cpp +++ b/similar/main/state.cpp @@ -349,7 +349,7 @@ static void state_object_rw_to_object(object_rw *obj_rw, object *obj) obj->ctype.laser_info.parent_signature = obj_rw->ctype.laser_info.parent_signature; obj->ctype.laser_info.creation_time = obj_rw->ctype.laser_info.creation_time; obj->ctype.laser_info.last_hitobj = obj_rw->ctype.laser_info.last_hitobj; - obj->ctype.laser_info.hitobj_list[obj->ctype.laser_info.last_hitobj] = 1; // restore most recent hitobj to hitobj_list + obj->ctype.laser_info.hitobj_list[obj->ctype.laser_info.last_hitobj] = true; // restore most recent hitobj to hitobj_list obj->ctype.laser_info.track_goal = obj_rw->ctype.laser_info.track_goal; obj->ctype.laser_info.multiplier = obj_rw->ctype.laser_info.multiplier; obj->ctype.laser_info.track_turn_time = HOMING_TURN_TIME;