engine.c
changeset 1883 ad68cd0a0a25
parent 1881 435d39bd6ee0
child 1891 862800791170
equal deleted inserted replaced
1882:f7d54d723d71 1883:ad68cd0a0a25
   315 	 * to prevent leaks. But first we need to refcount the SpriteGroup.
   315 	 * to prevent leaks. But first we need to refcount the SpriteGroup.
   316 	 * --pasky */
   316 	 * --pasky */
   317 	_engine_custom_sprites[engine][cargo] = *group;
   317 	_engine_custom_sprites[engine][cargo] = *group;
   318 }
   318 }
   319 
   319 
   320 typedef RealSpriteGroup *(*resolve_callback)(SpriteGroup *spritegroup,
   320 typedef SpriteGroup *(*resolve_callback)(SpriteGroup *spritegroup,
   321 	const Vehicle *veh, void *callback); /* XXX data pointer used as function pointer */
   321 	const Vehicle *veh, uint16 callback_info, void *resolve_func); /* XXX data pointer used as function pointer */
   322 
   322 
   323 static RealSpriteGroup* ResolveVehicleSpriteGroup(SpriteGroup *spritegroup,
   323 static SpriteGroup* ResolveVehicleSpriteGroup(SpriteGroup *spritegroup,
   324 	const Vehicle *veh, resolve_callback callback)
   324 	const Vehicle *veh, uint16 callback_info, resolve_callback resolve_func)
   325 {
   325 {
   326 	//debug("spgt %d", spritegroup->type);
   326 	//debug("spgt %d", spritegroup->type);
   327 	switch (spritegroup->type) {
   327 	switch (spritegroup->type) {
   328 		case SGT_REAL:
   328 		case SGT_REAL:
   329 			return &spritegroup->g.real;
   329 		case SGT_CALLBACK:
       
   330 			return spritegroup;
   330 
   331 
   331 		case SGT_DETERMINISTIC: {
   332 		case SGT_DETERMINISTIC: {
   332 			DeterministicSpriteGroup *dsg = &spritegroup->g.determ;
   333 			DeterministicSpriteGroup *dsg = &spritegroup->g.determ;
   333 			SpriteGroup *target;
   334 			SpriteGroup *target;
   334 			int value = -1;
   335 			int value = -1;
   335 
   336 
   336 			//debug("[%p] Having fun resolving variable %x", veh, dsg->variable);
   337 			//debug("[%p] Having fun resolving variable %x", veh, dsg->variable);
   337 
   338 			if (dsg->variable == 0x0C) {
   338 			if ((dsg->variable >> 6) == 0) {
   339 				/* Callback ID */
       
   340 				value = callback_info & 0xFF;
       
   341 			} else if ((dsg->variable >> 6) == 0) {
   339 				/* General property */
   342 				/* General property */
   340 				value = GetDeterministicSpriteValue(dsg->variable);
   343 				value = GetDeterministicSpriteValue(dsg->variable);
   341 			} else {
   344 			} else {
   342 				/* Vehicle-specific property. */
   345 				/* Vehicle-specific property. */
   343 
   346 
   349 					if (dsg->num_ranges > 0) {
   352 					if (dsg->num_ranges > 0) {
   350 						target = &dsg->ranges[0].group;
   353 						target = &dsg->ranges[0].group;
   351 					} else {
   354 					} else {
   352 						target = dsg->default_group;
   355 						target = dsg->default_group;
   353 					}
   356 					}
   354 					return callback(target, NULL, callback);
   357 					return resolve_func(target, NULL, callback_info, resolve_func);
   355 				}
   358 				}
   356 
   359 
   357 				if (dsg->var_scope == VSG_SCOPE_PARENT) {
   360 				if (dsg->var_scope == VSG_SCOPE_PARENT) {
   358 					/* First engine in the vehicle chain */
   361 					/* First engine in the vehicle chain */
   359 					if (veh->type == VEH_Train)
   362 					if (veh->type == VEH_Train)
   470 				}
   473 				}
   471 			}
   474 			}
   472 
   475 
   473 			target = value != -1 ? EvalDeterministicSpriteGroup(dsg, value) : dsg->default_group;
   476 			target = value != -1 ? EvalDeterministicSpriteGroup(dsg, value) : dsg->default_group;
   474 			//debug("Resolved variable %x: %d, %p", dsg->variable, value, callback);
   477 			//debug("Resolved variable %x: %d, %p", dsg->variable, value, callback);
   475 			return callback(target, veh, callback);
   478 			return resolve_func(target, veh, callback_info, resolve_func);
   476 		}
   479 		}
   477 
   480 
   478 		case SGT_RANDOMIZED: {
   481 		case SGT_RANDOMIZED: {
   479 			RandomizedSpriteGroup *rsg = &spritegroup->g.random;
   482 			RandomizedSpriteGroup *rsg = &spritegroup->g.random;
   480 
   483 
   481 			if (veh == NULL) {
   484 			if (veh == NULL) {
   482 				/* Purchase list of something. Show the first one. */
   485 				/* Purchase list of something. Show the first one. */
   483 				assert(rsg->num_groups > 0);
   486 				assert(rsg->num_groups > 0);
   484 				//debug("going for %p: %d", rsg->groups[0], rsg->groups[0].type);
   487 				//debug("going for %p: %d", rsg->groups[0], rsg->groups[0].type);
   485 				return callback(&rsg->groups[0], NULL, callback);
   488 				return resolve_func(&rsg->groups[0], NULL, callback_info, resolve_func);
   486 			}
   489 			}
   487 
   490 
   488 			if (rsg->var_scope == VSG_SCOPE_PARENT) {
   491 			if (rsg->var_scope == VSG_SCOPE_PARENT) {
   489 				/* First engine in the vehicle chain */
   492 				/* First engine in the vehicle chain */
   490 				if (veh->type == VEH_Train)
   493 				if (veh->type == VEH_Train)
   491 					veh = GetFirstVehicleInChain(veh);
   494 					veh = GetFirstVehicleInChain(veh);
   492 			}
   495 			}
   493 
   496 
   494 			return callback(EvalRandomizedSpriteGroup(rsg, veh->random_bits), veh, callback);
   497 			return resolve_func(EvalRandomizedSpriteGroup(rsg, veh->random_bits), veh, callback_info, resolve_func);
   495 		}
   498 		}
   496 
   499 
   497 		default:
   500 		default:
   498 			error("I don't know how to handle such a spritegroup %d!", spritegroup->type);
   501 			error("I don't know how to handle such a spritegroup %d!", spritegroup->type);
   499 			return NULL;
   502 			return NULL;
   541 		loaded = (v->cargo_count * 100) / capacity;
   544 		loaded = (v->cargo_count * 100) / capacity;
   542 		in_motion = (v->cur_speed != 0);
   545 		in_motion = (v->cur_speed != 0);
   543 	}
   546 	}
   544 
   547 
   545 	group = GetVehicleSpriteGroup(engine, v);
   548 	group = GetVehicleSpriteGroup(engine, v);
   546 	rsg = ResolveVehicleSpriteGroup(group, v, (resolve_callback) ResolveVehicleSpriteGroup);
   549 	group = ResolveVehicleSpriteGroup(group, v, 0, (resolve_callback) ResolveVehicleSpriteGroup);
   547 
   550 
   548 	if (rsg->sprites_per_set == 0 && cargo != 29) { /* XXX magic number */
   551 	if (group->type == SGT_REAL && group->g.real.sprites_per_set == 0 && cargo != GC_DEFAULT) {
   549 		// This group is empty but perhaps there'll be a default one.
   552 		// This group is empty but perhaps there'll be a default one.
   550 		rsg = ResolveVehicleSpriteGroup(&_engine_custom_sprites[engine][29], v,
   553 		group = ResolveVehicleSpriteGroup(&_engine_custom_sprites[engine][GC_DEFAULT], v, 0,
   551 		                                (resolve_callback) ResolveVehicleSpriteGroup);
   554 		                                (resolve_callback) ResolveVehicleSpriteGroup);
   552 	}
   555 	}
       
   556 
       
   557 	assert(group->type == SGT_REAL);
       
   558 	rsg = &group->g.real;
   553 
   559 
   554 	if (!rsg->sprites_per_set) {
   560 	if (!rsg->sprites_per_set) {
   555 		// This group is empty. This function users should therefore
   561 		// This group is empty. This function users should therefore
   556 		// look up the sprite number in _engine_original_sprites.
   562 		// look up the sprite number in _engine_original_sprites.
   557 		return 0;
   563 		return 0;
   580 
   586 
   581 	r = (in_motion ? rsg->loaded[spriteset] : rsg->loading[spriteset]) + direction;
   587 	r = (in_motion ? rsg->loaded[spriteset] : rsg->loading[spriteset]) + direction;
   582 	return r;
   588 	return r;
   583 }
   589 }
   584 
   590 
       
   591 /**
       
   592  * Evaluates a newgrf callback
       
   593  * @param callback_info info about which callback to evaluate
       
   594  *  (bit 0-7)  = CallBack id of the callback to use, see CallBackId enum
       
   595  *  (bit 8-15) = Other info some callbacks need to have, callback specific, see CallBackId enum, not used yet
       
   596  * @param engine Engine type of the vehicle to evaluate the callback for
       
   597  * @param vehicle The vehicle to evaluate the callback for, NULL if it doesnt exist (yet)
       
   598  * @return The value the callback returned, or CALLBACK_FAILED if it failed
       
   599  */
       
   600 uint16 GetCallBackResult(uint16 callback_info, byte engine, const Vehicle *v)
       
   601 {
       
   602 	SpriteGroup *group;
       
   603 	byte cargo = GC_DEFAULT;
       
   604 
       
   605 	if (v != NULL)
       
   606 		cargo = _global_cargo_id[_opt.landscape][v->cargo_type];
       
   607 
       
   608 	group = &_engine_custom_sprites[engine][cargo];
       
   609 	group = ResolveVehicleSpriteGroup(group, v, callback_info, (resolve_callback) ResolveVehicleSpriteGroup);
       
   610 
       
   611 	if (group->type == SGT_REAL && group->g.real.sprites_per_set == 0 && cargo != GC_DEFAULT) {
       
   612 		// This group is empty but perhaps there'll be a default one.
       
   613 		group = ResolveVehicleSpriteGroup(&_engine_custom_sprites[engine][GC_DEFAULT], v, callback_info,
       
   614 		                                (resolve_callback) ResolveVehicleSpriteGroup);
       
   615 	}
       
   616 
       
   617 	if (group->type != SGT_CALLBACK)
       
   618 		return CALLBACK_FAILED;
       
   619 
       
   620 	return group->g.callback.result;
       
   621 }
       
   622 
       
   623 
   585 
   624 
   586 // Global variables are evil, yes, but we would end up with horribly overblown
   625 // Global variables are evil, yes, but we would end up with horribly overblown
   587 // calling convention otherwise and this should be 100% reentrant.
   626 // calling convention otherwise and this should be 100% reentrant.
   588 static byte _vsg_random_triggers;
   627 static byte _vsg_random_triggers;
   589 static byte _vsg_bits_to_reseed;
   628 static byte _vsg_bits_to_reseed;
   590 
   629 
   591 extern int _custom_sprites_base;
   630 extern int _custom_sprites_base;
   592 
   631 
   593 static RealSpriteGroup *TriggerVehicleSpriteGroup(SpriteGroup *spritegroup,
   632 static SpriteGroup *TriggerVehicleSpriteGroup(SpriteGroup *spritegroup,
   594 	Vehicle *veh, resolve_callback callback)
   633 	Vehicle *veh, uint16 callback_info, resolve_callback resolve_func)
   595 {
   634 {
   596 	if (spritegroup->type == SGT_RANDOMIZED) {
   635 	if (spritegroup->type == SGT_RANDOMIZED) {
   597 		_vsg_bits_to_reseed |= RandomizedSpriteGroupTriggeredBits(
   636 		_vsg_bits_to_reseed |= RandomizedSpriteGroupTriggeredBits(
   598 			&spritegroup->g.random,
   637 			&spritegroup->g.random,
   599 			_vsg_random_triggers,
   638 			_vsg_random_triggers,
   600 			&veh->waiting_triggers
   639 			&veh->waiting_triggers
   601 		);
   640 		);
   602 	}
   641 	}
   603 
   642 
   604 	return ResolveVehicleSpriteGroup(spritegroup, veh, callback);
   643 	return ResolveVehicleSpriteGroup(spritegroup, veh, callback_info, resolve_func);
   605 }
   644 }
   606 
   645 
   607 static void DoTriggerVehicle(Vehicle *veh, VehicleTrigger trigger, byte base_random_bits, bool first)
   646 static void DoTriggerVehicle(Vehicle *veh, VehicleTrigger trigger, byte base_random_bits, bool first)
   608 {
   647 {
       
   648 	SpriteGroup *group;
   609 	RealSpriteGroup *rsg;
   649 	RealSpriteGroup *rsg;
   610 	byte new_random_bits;
   650 	byte new_random_bits;
   611 
   651 
   612 	_vsg_random_triggers = trigger;
   652 	_vsg_random_triggers = trigger;
   613 	_vsg_bits_to_reseed = 0;
   653 	_vsg_bits_to_reseed = 0;
   614 	rsg = TriggerVehicleSpriteGroup(GetVehicleSpriteGroup(veh->engine_type, veh), veh,
   654 	group = TriggerVehicleSpriteGroup(GetVehicleSpriteGroup(veh->engine_type, veh), veh, 0,
   615 	                                (resolve_callback) TriggerVehicleSpriteGroup);
   655 	                                  (resolve_callback) TriggerVehicleSpriteGroup);
   616 	if (rsg->sprites_per_set == 0 && veh->cargo_type != 29) { /* XXX magic number */
   656 
       
   657 	if (group->type == SGT_REAL && group->g.real.sprites_per_set == 0 && veh->cargo_type != GC_DEFAULT) {
   617 		// This group turned out to be empty but perhaps there'll be a default one.
   658 		// This group turned out to be empty but perhaps there'll be a default one.
   618 		rsg = TriggerVehicleSpriteGroup(&_engine_custom_sprites[veh->engine_type][29], veh,
   659 		group = TriggerVehicleSpriteGroup(&_engine_custom_sprites[veh->engine_type][GC_DEFAULT], veh, 0,
   619 						(resolve_callback) TriggerVehicleSpriteGroup);
   660 		                                  (resolve_callback) TriggerVehicleSpriteGroup);
   620 	}
   661 	}
       
   662 
       
   663 	assert(group->type == SGT_REAL);
       
   664 	rsg = &group->g.real;
       
   665 
   621 	new_random_bits = Random();
   666 	new_random_bits = Random();
   622 	veh->random_bits &= ~_vsg_bits_to_reseed;
   667 	veh->random_bits &= ~_vsg_bits_to_reseed;
   623 	veh->random_bits |= (first ? new_random_bits : base_random_bits) & _vsg_bits_to_reseed;
   668 	veh->random_bits |= (first ? new_random_bits : base_random_bits) & _vsg_bits_to_reseed;
   624 
   669 
   625 	switch (trigger) {
   670 	switch (trigger) {