241 * to prevent leaks. But first we need to refcount the SpriteGroup. |
241 * to prevent leaks. But first we need to refcount the SpriteGroup. |
242 * --pasky */ |
242 * --pasky */ |
243 _engine_custom_sprites[engine][cargo] = *group; |
243 _engine_custom_sprites[engine][cargo] = *group; |
244 } |
244 } |
245 |
245 |
|
246 static struct RealSpriteGroup * |
|
247 ResolveVehicleSpriteGroup(struct SpriteGroup *spritegroup, struct Vehicle *veh) |
|
248 { |
|
249 switch (spritegroup->type) { |
|
250 case SGT_REAL: |
|
251 return &spritegroup->g.real; |
|
252 |
|
253 case SGT_DETERMINISTIC: { |
|
254 struct DeterministicSpriteGroup *dsg = &spritegroup->g.determ; |
|
255 struct SpriteGroup *target; |
|
256 int value = -1; |
|
257 |
|
258 //debug("[%p] Having fun resolving variable %x", dsg->variable); |
|
259 |
|
260 if ((dsg->variable >> 6) == 0) { |
|
261 /* General property */ |
|
262 value = GetDeterministicSpriteValue(dsg->variable); |
|
263 |
|
264 } else { |
|
265 /* Station-specific property. */ |
|
266 if (dsg->var_scope == VSG_SCOPE_PARENT) { |
|
267 /* First engine in the vehicle chain */ |
|
268 if (veh != NULL && veh->type == VEH_Train) |
|
269 veh = GetFirstVehicleInChain(veh); |
|
270 } |
|
271 |
|
272 if (dsg->variable == 0x40) { |
|
273 if (veh && veh->type == VEH_Train) { |
|
274 Vehicle *u = GetFirstVehicleInChain(veh); |
|
275 byte chain_before = 0, chain_after = 0; |
|
276 |
|
277 while (u != veh) { |
|
278 u = u->next; |
|
279 chain_before++; |
|
280 } |
|
281 while (u->next != NULL) { |
|
282 u = u->next; |
|
283 chain_after++; |
|
284 }; |
|
285 |
|
286 value = chain_before << 16 | chain_after << 8 |
|
287 | (chain_before + chain_after + 1); |
|
288 } else { |
|
289 value = 1; /* 1 vehicle in the chain */ |
|
290 } |
|
291 |
|
292 } else { |
|
293 // TTDPatch runs on little-endian arch; |
|
294 // Variable is 0x80 + offset in TTD's vehicle structure |
|
295 switch (dsg->variable - 0x80) { |
|
296 #define veh_prop(id_, value_) case id_: if (veh != NULL) value = value_; break /* XXX factorise "if" */ |
|
297 veh_prop(0x00, veh->type); |
|
298 veh_prop(0x01, veh->subtype); |
|
299 veh_prop(0x04, veh->index); |
|
300 veh_prop(0x05, veh->index & 0xFF); |
|
301 /* XXX? Is THIS right? */ |
|
302 veh_prop(0x0A, veh->next_order_param << 8 | veh->next_order); |
|
303 veh_prop(0x0B, veh->next_order); |
|
304 veh_prop(0x0C, veh->num_orders); |
|
305 veh_prop(0x0D, veh->cur_order_index); |
|
306 veh_prop(0x10, veh->load_unload_time_rem); |
|
307 veh_prop(0x11, veh->load_unload_time_rem & 0xFF); |
|
308 veh_prop(0x12, veh->date_of_last_service); |
|
309 veh_prop(0x13, veh->date_of_last_service & 0xFF); |
|
310 veh_prop(0x14, veh->service_interval); |
|
311 veh_prop(0x15, veh->service_interval & 0xFF); |
|
312 veh_prop(0x16, veh->last_station_visited); |
|
313 veh_prop(0x17, veh->tick_counter); |
|
314 veh_prop(0x18, veh->max_speed); |
|
315 veh_prop(0x19, veh->max_speed & 0xFF); |
|
316 veh_prop(0x1F, veh->direction); |
|
317 veh_prop(0x28, veh->cur_image); |
|
318 veh_prop(0x29, veh->cur_image & 0xFF); |
|
319 veh_prop(0x32, veh->vehstatus); |
|
320 veh_prop(0x33, veh->vehstatus); |
|
321 veh_prop(0x34, veh->cur_speed); |
|
322 veh_prop(0x35, veh->cur_speed & 0xFF); |
|
323 veh_prop(0x36, veh->subspeed); |
|
324 veh_prop(0x37, veh->acceleration); |
|
325 veh_prop(0x39, veh->cargo_type); |
|
326 veh_prop(0x3A, veh->cargo_cap); |
|
327 veh_prop(0x3B, veh->cargo_cap & 0xFF); |
|
328 veh_prop(0x3C, veh->cargo_count); |
|
329 veh_prop(0x3D, veh->cargo_count & 0xFF); |
|
330 veh_prop(0x3E, veh->cargo_source); // Probably useless; so what |
|
331 veh_prop(0x3F, veh->cargo_days); |
|
332 veh_prop(0x40, veh->age); |
|
333 veh_prop(0x41, veh->age & 0xFF); |
|
334 veh_prop(0x42, veh->max_age); |
|
335 veh_prop(0x43, veh->max_age & 0xFF); |
|
336 veh_prop(0x44, veh->build_year); |
|
337 veh_prop(0x45, veh->unitnumber); |
|
338 veh_prop(0x46, veh->engine_type); |
|
339 veh_prop(0x47, veh->engine_type & 0xFF); |
|
340 veh_prop(0x48, veh->spritenum); |
|
341 veh_prop(0x49, veh->day_counter); |
|
342 veh_prop(0x4A, veh->breakdowns_since_last_service); |
|
343 veh_prop(0x4B, veh->breakdown_ctr); |
|
344 veh_prop(0x4C, veh->breakdown_delay); |
|
345 veh_prop(0x4D, veh->breakdown_chance); |
|
346 veh_prop(0x4E, veh->reliability); |
|
347 veh_prop(0x4F, veh->reliability & 0xFF); |
|
348 veh_prop(0x50, veh->reliability_spd_dec); |
|
349 veh_prop(0x51, veh->reliability_spd_dec & 0xFF); |
|
350 veh_prop(0x52, veh->profit_this_year); |
|
351 veh_prop(0x53, veh->profit_this_year & 0xFFFFFF); |
|
352 veh_prop(0x54, veh->profit_this_year & 0xFFFF); |
|
353 veh_prop(0x55, veh->profit_this_year & 0xFF); |
|
354 veh_prop(0x56, veh->profit_last_year); |
|
355 veh_prop(0x57, veh->profit_last_year & 0xFF); |
|
356 veh_prop(0x58, veh->profit_last_year); |
|
357 veh_prop(0x59, veh->profit_last_year & 0xFF); |
|
358 veh_prop(0x5A, veh->next_in_chain_old); |
|
359 veh_prop(0x5B, veh->next_in_chain_old & 0xFF); |
|
360 veh_prop(0x5C, veh->value); |
|
361 veh_prop(0x5D, veh->value & 0xFFFFFF); |
|
362 veh_prop(0x5E, veh->value & 0xFFFF); |
|
363 veh_prop(0x5F, veh->value & 0xFF); |
|
364 veh_prop(0x60, veh->string_id); |
|
365 veh_prop(0x61, veh->string_id & 0xFF); |
|
366 /* 00h..07h=sub image? 40h=in tunnel; actually some kind of status |
|
367 * aircraft: >=13h when in flight |
|
368 * train, ship: 80h=in depot |
|
369 * rv: 0feh=in depot */ |
|
370 /* TODO veh_prop(0x62, veh->???); */ |
|
371 |
|
372 /* TODO: The rest is per-vehicle, I hope no GRF file looks so far. |
|
373 * But they won't let us have an easy ride so surely *some* GRF |
|
374 * file does. So someone needs to do this too. --pasky */ |
|
375 |
|
376 #undef veh_prop |
|
377 } |
|
378 } |
|
379 } |
|
380 |
|
381 target = value != -1 ? EvalDeterministicSpriteGroup(dsg, value) : dsg->default_group; |
|
382 //debug("Resolved variable %x: %d", dsg->variable, value); |
|
383 return ResolveVehicleSpriteGroup(target, veh); |
|
384 } |
|
385 |
|
386 default: |
|
387 case SGT_RANDOM: |
|
388 error("I don't know how to handle random spritegroups yet!"); |
|
389 return NULL; |
|
390 } |
|
391 } |
|
392 |
246 int GetCustomEngineSprite(byte engine, Vehicle *v, byte direction) |
393 int GetCustomEngineSprite(byte engine, Vehicle *v, byte direction) |
247 { |
394 { |
248 struct SpriteGroup *group; |
395 struct SpriteGroup *group; |
249 struct RealSpriteGroup *rsg; |
396 struct RealSpriteGroup *rsg; |
250 uint16 overriding_engine = -1; |
397 uint16 overriding_engine = -1; |