1
0
Fork 0

Codechange: Access temporary storage through ResolverObject during Resolve.

pull/14224/head
frosch 2025-05-05 21:28:51 +02:00 committed by frosch
parent 99d7a775ad
commit 85be7a4d92
9 changed files with 59 additions and 34 deletions

View File

@ -325,7 +325,7 @@ static uint8_t MapAircraftMovementAction(const Aircraft *v)
if (this->self_scope.v != nullptr && (relative != this->cached_relative_count || count == 0)) {
/* Note: This caching only works as long as the VSG_SCOPE_RELATIVE cannot be used in
* VarAct2 with procedure calls. */
if (count == 0) count = GetRegister(0x100);
if (count == 0) count = this->GetRegister(0x100);
const Vehicle *v = nullptr;
switch (GB(relative, 6, 2)) {
@ -621,14 +621,14 @@ static uint32_t VehicleGetVariable(Vehicle *v, const VehicleScopeResolver *objec
if (object->ro.callback == CBID_NO_CALLBACK || object->ro.callback == CBID_RANDOM_TRIGGER || object->ro.callback == CBID_TRAIN_ALLOW_WAGON_ATTACH ||
object->ro.callback == CBID_VEHICLE_START_STOP_CHECK || object->ro.callback == CBID_VEHICLE_32DAY_CALLBACK || object->ro.callback == CBID_VEHICLE_COLOUR_MAPPING ||
object->ro.callback == CBID_VEHICLE_SPAWN_VISUAL_EFFECT) {
Vehicle *u = v->Move(GetRegister(0x10F));
Vehicle *u = v->Move(object->ro.GetRegister(0x10F));
if (u == nullptr) return 0; // available, but zero
if (parameter == 0x5F) {
/* This seems to be the only variable that makes sense to access via var 61, but is not handled by VehicleGetVariable */
return (u->random_bits << 8) | u->waiting_random_triggers.base();
} else {
return VehicleGetVariable(u, object, parameter, GetRegister(0x10E), available);
return VehicleGetVariable(u, object, parameter, object->ro.GetRegister(0x10E), available);
}
}
/* Not available */
@ -1102,7 +1102,7 @@ static void GetCustomEngineSprite(EngineID engine, const Vehicle *v, Direction d
object.ResetState();
object.callback_param1 = image_type | (stack << 8);
const auto *group = object.Resolve<ResultSpriteGroup>();
int32_t reg100 = sprite_stack ? GetRegister(0x100) : 0;
int32_t reg100 = sprite_stack ? object.GetRegister(0x100) : 0;
if (group != nullptr && group->num_sprites != 0) {
result->seq[result->count].sprite = group->sprite + (direction % group->num_sprites);
result->seq[result->count].pal = GB(reg100, 0, 16); // zero means default recolouring
@ -1145,7 +1145,7 @@ static void GetRotorOverrideSprite(EngineID engine, const struct Aircraft *v, En
object.ResetState();
object.callback_param1 = image_type | (stack << 8);
const auto *group = object.Resolve<ResultSpriteGroup>();
int32_t reg100 = sprite_stack ? GetRegister(0x100) : 0;
int32_t reg100 = sprite_stack ? object.GetRegister(0x100) : 0;
if (group != nullptr && group->num_sprites != 0) {
result->seq[result->count].sprite = group->sprite + (rotor_pos % group->num_sprites);
result->seq[result->count].pal = GB(reg100, 0, 16); // zero means default recolouring

View File

@ -389,8 +389,8 @@ static uint32_t GetDistanceFromNearbyHouse(uint8_t parameter, TileIndex start_ti
if (!IsValidCargoType(cargo_type)) return 0;
/* Extract tile offset. */
int8_t x_offs = GB(GetRegister(0x100), 0, 8);
int8_t y_offs = GB(GetRegister(0x100), 8, 8);
int8_t x_offs = GB(this->ro.GetRegister(0x100), 0, 8);
int8_t y_offs = GB(this->ro.GetRegister(0x100), 8, 8);
TileIndex testtile = Map::WrapToMap(this->tile + TileDiffXY(x_offs, y_offs));
StationFinder stations(TileArea(testtile, 1, 1));

View File

@ -107,15 +107,16 @@ static uint32_t GetClosestIndustry(TileIndex tile, IndustryType type, const Indu
* Implementation of both var 67 and 68
* since the mechanism is almost the same, it is easier to regroup them on the same
* function.
* @param object ResolverObject owning the temporary storage.
* @param param_set_id parameter given to the callback, which is the set id, or the local id, in our terminology
* @param layout_filter on what layout do we filter?
* @param town_filter Do we filter on the same town as the current industry?
* @param current Industry for which the inquiry is made
* @return the formatted answer to the callback : rr(reserved) cc(count) dddd(manhattan distance of closest sister)
*/
static uint32_t GetCountAndDistanceOfClosestInstance(uint8_t param_set_id, uint8_t layout_filter, bool town_filter, const Industry *current)
static uint32_t GetCountAndDistanceOfClosestInstance(const ResolverObject &object, uint8_t param_set_id, uint8_t layout_filter, bool town_filter, const Industry *current)
{
uint32_t grf_id = static_cast<uint32_t>(GetRegister(0x100)); ///< Get the GRFID of the definition to look for in register 100h
uint32_t grf_id = static_cast<uint32_t>(object.GetRegister(0x100)); ///< Get the GRFID of the definition to look for in register 100h
IndustryType industry_type;
uint32_t closest_dist = UINT32_MAX;
uint8_t count = 0;
@ -311,11 +312,11 @@ static uint32_t GetCountAndDistanceOfClosestInstance(uint8_t param_set_id, uint8
uint8_t layout_filter = 0;
bool town_filter = false;
if (variable == 0x68) {
int32_t reg = GetRegister(0x101);
int32_t reg = this->ro.GetRegister(0x101);
layout_filter = GB(reg, 0, 8);
town_filter = HasBit(reg, 8);
}
return GetCountAndDistanceOfClosestInstance(parameter, layout_filter, town_filter, this->industry);
return GetCountAndDistanceOfClosestInstance(this->ro, parameter, layout_filter, town_filter, this->industry);
}
case 0x69:
@ -596,11 +597,6 @@ uint32_t GetIndustryProbabilityCallback(IndustryType type, IndustryAvailabilityC
return default_prob;
}
static int32_t DerefIndProd(int field, bool use_register)
{
return use_register ? GetRegister(field) : field;
}
/**
* Get the industry production callback and apply it to the industry.
* @param ind the industry this callback has to be called for
@ -615,6 +611,10 @@ void IndustryProductionCallback(Industry *ind, int reason)
if (spec->behaviour.Test(IndustryBehaviour::ProdMultiHandling)) multiplier = ind->prod_level;
object.callback_param2 = reason;
auto deref_ind_prod = [&object](int field, bool use_register) -> int32_t {
return use_register ? object.GetRegister(field) : field;
};
for (uint loop = 0;; loop++) {
/* limit the number of calls to break infinite loops.
* 'loop' is provided as 16 bits to the newgrf, so abort when those are exceeded. */
@ -648,27 +648,27 @@ void IndustryProductionCallback(Industry *ind, int reason)
/* Callback parameters map directly to industry cargo slot indices */
for (uint i = 0; i < group->num_input && i < ind->accepted.size(); i++) {
if (!IsValidCargoType(ind->accepted[i].cargo)) continue;
ind->accepted[i].waiting = ClampTo<uint16_t>(ind->accepted[i].waiting - DerefIndProd(group->subtract_input[i], deref) * multiplier);
ind->accepted[i].waiting = ClampTo<uint16_t>(ind->accepted[i].waiting - deref_ind_prod(group->subtract_input[i], deref) * multiplier);
}
for (uint i = 0; i < group->num_output && i < ind->produced.size(); i++) {
if (!IsValidCargoType(ind->produced[i].cargo)) continue;
ind->produced[i].waiting = ClampTo<uint16_t>(ind->produced[i].waiting + std::max(DerefIndProd(group->add_output[i], deref), 0) * multiplier);
ind->produced[i].waiting = ClampTo<uint16_t>(ind->produced[i].waiting + std::max(deref_ind_prod(group->add_output[i], deref), 0) * multiplier);
}
} else {
/* Callback receives list of cargos to apply for, which need to have their cargo slots in industry looked up */
for (uint i = 0; i < group->num_input; i++) {
auto it = ind->GetCargoAccepted(group->cargo_input[i]);
if (it == std::end(ind->accepted)) continue;
it->waiting = ClampTo<uint16_t>(it->waiting - DerefIndProd(group->subtract_input[i], deref) * multiplier);
it->waiting = ClampTo<uint16_t>(it->waiting - deref_ind_prod(group->subtract_input[i], deref) * multiplier);
}
for (uint i = 0; i < group->num_output; i++) {
auto it = ind->GetCargoProduced(group->cargo_output[i]);
if (it == std::end(ind->produced)) continue;
it->waiting = ClampTo<uint16_t>(it->waiting + std::max(DerefIndProd(group->add_output[i], deref), 0) * multiplier);
it->waiting = ClampTo<uint16_t>(it->waiting + std::max(deref_ind_prod(group->add_output[i], deref), 0) * multiplier);
}
}
int32_t again = DerefIndProd(group->again, deref);
int32_t again = deref_ind_prod(group->again, deref);
if (again == 0) break;
SB(object.callback_param2, 24, 8, again);

View File

@ -225,15 +225,16 @@ static uint32_t GetClosestObject(TileIndex tile, ObjectType type, const Object *
/**
* Implementation of var 65
* @param object ResolverObject owning the temporary storage.
* @param local_id Parameter given to the callback, which is the set id, or the local id, in our terminology.
* @param grfid The object's GRFID.
* @param tile The tile to look from.
* @param current Object for which the inquiry is made
* @return The formatted answer to the callback : rr(reserved) cc(count) dddd(manhattan distance of closest sister)
*/
static uint32_t GetCountAndDistanceOfClosestInstance(uint8_t local_id, uint32_t grfid, TileIndex tile, const Object *current)
static uint32_t GetCountAndDistanceOfClosestInstance(const ResolverObject &object, uint8_t local_id, uint32_t grfid, TileIndex tile, const Object *current)
{
uint32_t grf_id = static_cast<uint32_t>(GetRegister(0x100)); // Get the GRFID of the definition to look for in register 100h
uint32_t grf_id = static_cast<uint32_t>(object.GetRegister(0x100)); // Get the GRFID of the definition to look for in register 100h
uint32_t idx;
/* Determine what will be the object type to look for */
@ -361,7 +362,7 @@ static uint32_t GetCountAndDistanceOfClosestInstance(uint8_t local_id, uint32_t
}
/* Count of object, distance of closest instance */
case 0x64: return GetCountAndDistanceOfClosestInstance(parameter, this->ro.grffile->grfid, this->tile, this->obj);
case 0x64: return GetCountAndDistanceOfClosestInstance(this->ro, parameter, this->ro.grffile->grfid, this->tile, this->obj);
case 0x7A: return GetBadgeVariableResult(*this->ro.grffile, this->spec->badges, parameter);
}

View File

@ -303,7 +303,7 @@ void DrawRoadStopTile(int x, int y, RoadType roadtype, const RoadStopSpec *spec,
RoadStopDrawModes draw_mode;
if (spec->flags.Test(RoadStopSpecFlag::DrawModeRegister)) {
draw_mode = static_cast<RoadStopDrawMode>(GetRegister(0x100));
draw_mode = static_cast<RoadStopDrawMode>(object.GetRegister(0x100));
} else {
draw_mode = spec->draw_mode;
}

View File

@ -64,7 +64,7 @@ static inline uint32_t GetVariable(const ResolverObject &object, ScopeResolver *
case 0x5F: return (scope->GetRandomBits() << 8) | scope->GetRandomTriggers();
case 0x7D: return _temp_store.GetValue(parameter);
case 0x7D: return object.GetRegister(parameter);
case 0x7F:
if (object.grffile == nullptr) return 0;
@ -140,7 +140,7 @@ static inline uint32_t GetVariable(const ResolverObject &object, ScopeResolver *
/* Evaluate an adjustment for a variable of the given size.
* U is the unsigned type and S is the signed type to use. */
template <typename U, typename S>
static U EvalAdjustT(const DeterministicSpriteGroupAdjust &adjust, ScopeResolver *scope, U last_value, uint32_t value)
static U EvalAdjustT(const DeterministicSpriteGroupAdjust &adjust, ResolverObject &object, ScopeResolver *scope, U last_value, uint32_t value)
{
value >>= adjust.shift_num;
value &= adjust.and_mask;
@ -166,7 +166,7 @@ static U EvalAdjustT(const DeterministicSpriteGroupAdjust &adjust, ScopeResolver
case DSGA_OP_AND: return last_value & value;
case DSGA_OP_OR: return last_value | value;
case DSGA_OP_XOR: return last_value ^ value;
case DSGA_OP_STO: _temp_store.StoreValue((U)value, (S)last_value); return last_value;
case DSGA_OP_STO: object.SetRegister((U)value, (S)last_value); return last_value;
case DSGA_OP_RST: return value;
case DSGA_OP_STOP: scope->StorePSA((U)value, (S)last_value); return last_value;
case DSGA_OP_ROR: return std::rotr<uint32_t>((U)last_value, (U)value & 0x1F); // mask 'value' to 5 bits, which should behave the same on all architectures.
@ -214,9 +214,9 @@ static bool RangeHighComparator(const DeterministicSpriteGroupRange &range, uint
}
switch (this->size) {
case DSG_SIZE_BYTE: value = EvalAdjustT<uint8_t, int8_t> (adjust, scope, last_value, value); break;
case DSG_SIZE_WORD: value = EvalAdjustT<uint16_t, int16_t>(adjust, scope, last_value, value); break;
case DSG_SIZE_DWORD: value = EvalAdjustT<uint32_t, int32_t>(adjust, scope, last_value, value); break;
case DSG_SIZE_BYTE: value = EvalAdjustT<uint8_t, int8_t> (adjust, object, scope, last_value, value); break;
case DSG_SIZE_WORD: value = EvalAdjustT<uint16_t, int16_t>(adjust, object, scope, last_value, value); break;
case DSG_SIZE_DWORD: value = EvalAdjustT<uint32_t, int32_t>(adjust, object, scope, last_value, value); break;
default: NOT_REACHED();
}
last_value = value;

View File

@ -327,6 +327,30 @@ struct ResolverObject {
ScopeResolver default_scope; ///< Default implementation of the grf scope.
/**
* Gets the value of a so-called newgrf "register".
* @param i index of the register
* @return the value of the register
* @pre i < 0x110
*/
inline int32_t GetRegister(uint i) const
{
extern TemporaryStorageArray<int32_t, 0x110> _temp_store;
return _temp_store.GetValue(i);
}
/**
* Sets the value of a so-called newgrf "register".
* @param i index of the register
* @param value the value of the register
* @pre i < 0x110
*/
inline void SetRegister(uint i, int32_t value)
{
extern TemporaryStorageArray<int32_t, 0x110> _temp_store;
_temp_store.StoreValue(i, value);
}
CallbackID callback{}; ///< Callback being resolved.
uint32_t callback_param1 = 0; ///< First parameter (var 10) of the callback.
uint32_t callback_param2 = 0; ///< Second parameter (var 18) of the callback.

View File

@ -655,7 +655,7 @@ SpriteID GetCustomStationFoundationRelocation(const StationSpec *statspec, BaseS
const auto *group = object.Resolve<ResultSpriteGroup>();
/* Note: SpriteGroup::Resolve zeroes all registers, so register 0x100 is initialised to 0. (compatibility) */
uint32_t offset = static_cast<uint32_t>(GetRegister(0x100));
uint32_t offset = static_cast<uint32_t>(object.GetRegister(0x100));
if (group == nullptr || group->num_sprites <= offset) return 0;
return group->sprite + offset;

View File

@ -36,7 +36,7 @@
/* Get a variable from the persistent storage */
case 0x7C: {
/* Check the persistent storage for the GrfID stored in register 100h. */
uint32_t grfid = static_cast<uint32_t>(GetRegister(0x100));
uint32_t grfid = static_cast<uint32_t>(this->ro.GetRegister(0x100));
if (grfid == 0xFFFFFFFF) {
if (this->ro.grffile == nullptr) return 0;
grfid = this->ro.grffile->grfid;
@ -132,7 +132,7 @@
if (this->ro.grffile == nullptr) return;
/* Check the persistent storage for the GrfID stored in register 100h. */
uint32_t grfid = static_cast<uint32_t>(GetRegister(0x100));
uint32_t grfid = static_cast<uint32_t>(this->ro.GetRegister(0x100));
/* A NewGRF can only write in the persistent storage associated to its own GRFID. */
if (grfid == 0xFFFFFFFF) grfid = this->ro.grffile->grfid;