1300 } |
1300 } |
1301 |
1301 |
1302 /* Action 0x02 */ |
1302 /* Action 0x02 */ |
1303 static void NewSpriteGroup(byte *buf, int len) |
1303 static void NewSpriteGroup(byte *buf, int len) |
1304 { |
1304 { |
1305 byte *bufend = buf + len; |
|
1306 |
|
1307 /* <02> <feature> <set-id> <type/num-entries> <feature-specific-data...> |
1305 /* <02> <feature> <set-id> <type/num-entries> <feature-specific-data...> |
1308 * |
1306 * |
1309 * B feature see action 1 |
1307 * B feature see action 1 |
1310 * B set-id ID of this particular definition |
1308 * B set-id ID of this particular definition |
1311 * B type/num-entries |
1309 * B type/num-entries |
1312 * if 80 or greater, this is a randomized or variational |
1310 * if 80 or greater, this is a randomized or variational |
1313 * list definition, see below |
1311 * list definition, see below |
1314 * otherwise it specifies a number of entries, the exact |
1312 * otherwise it specifies a number of entries, the exact |
1315 * meaning depends on the feature |
1313 * meaning depends on the feature |
1316 * V feature-specific-data (huge mess, don't even look it up --pasky) */ |
1314 * V feature-specific-data (huge mess, don't even look it up --pasky) */ |
1317 /* TODO: No 0x80-types (ugh). */ |
|
1318 /* TODO: Also, empty sprites aren't handled for now. Need to investigate |
|
1319 * the "opacity" rules for these, that is which sprite to fall back to |
|
1320 * when. --pasky */ |
|
1321 uint8 feature; |
1315 uint8 feature; |
1322 uint8 setid; |
1316 uint8 setid; |
1323 /* XXX: For stations, these two are "little cargo" and "lotsa cargo" sets. */ |
1317 uint8 type; |
1324 uint8 numloaded; |
1318 SpriteGroup *group = NULL; |
1325 uint8 numloading; |
1319 byte *bufend = buf + len; |
1326 SpriteGroup *group; |
|
1327 RealSpriteGroup *rg; |
|
1328 byte *loaded_ptr; |
|
1329 byte *loading_ptr; |
|
1330 int i; |
|
1331 |
1320 |
1332 check_length(len, 5, "NewSpriteGroup"); |
1321 check_length(len, 5, "NewSpriteGroup"); |
1333 feature = buf[1]; |
1322 buf++; |
1334 setid = buf[2]; |
1323 |
1335 numloaded = buf[3]; |
1324 feature = grf_load_byte(&buf); |
1336 numloading = buf[4]; |
1325 setid = grf_load_byte(&buf); |
|
1326 type = grf_load_byte(&buf); |
1337 |
1327 |
1338 if (setid >= _cur_grffile->spritegroups_count) { |
1328 if (setid >= _cur_grffile->spritegroups_count) { |
1339 // Allocate memory for new sprite group references. |
1329 // Allocate memory for new sprite group references. |
1340 _cur_grffile->spritegroups = realloc(_cur_grffile->spritegroups, (setid + 1) * sizeof(*_cur_grffile->spritegroups)); |
1330 _cur_grffile->spritegroups = realloc(_cur_grffile->spritegroups, (setid + 1) * sizeof(*_cur_grffile->spritegroups)); |
1341 // Initialise new space to NULL |
1331 // Initialise new space to NULL |
1342 for (; _cur_grffile->spritegroups_count < (setid + 1); _cur_grffile->spritegroups_count++) |
1332 for (; _cur_grffile->spritegroups_count < (setid + 1); _cur_grffile->spritegroups_count++) |
1343 _cur_grffile->spritegroups[_cur_grffile->spritegroups_count] = NULL; |
1333 _cur_grffile->spritegroups[_cur_grffile->spritegroups_count] = NULL; |
1344 } |
1334 } |
1345 |
1335 |
1346 if (numloaded == 0x81 || numloaded == 0x82) { |
1336 switch (type) { |
1347 DeterministicSpriteGroup *dg; |
1337 /* Deterministic Sprite Group */ |
1348 uint16 groupid; |
1338 case 0x81: // Self scope, byte |
1349 int i; |
1339 case 0x82: // Parent scope, byte |
1350 |
1340 { |
1351 // Ok, this is gonna get a little wild, so hold your breath... |
1341 DeterministicSpriteGroup *dg; |
1352 |
1342 uint16 groupid; |
1353 /* This stuff is getting actually evaluated in |
1343 int i; |
1354 * EvalDeterministicSpriteGroup(). */ |
1344 |
1355 |
1345 check_length(bufend - buf, 6, "NewSpriteGroup 0x81/0x82"); |
1356 buf += 4; len -= 4; |
1346 |
1357 check_length(len, 6, "NewSpriteGroup 0x81/0x82"); |
1347 group = AllocateSpriteGroup(); |
1358 |
1348 group->type = SGT_DETERMINISTIC; |
1359 group = AllocateSpriteGroup(); |
1349 dg = &group->g.determ; |
1360 group->type = SGT_DETERMINISTIC; |
1350 |
1361 dg = &group->g.determ; |
1351 dg->var_scope = type == 0x82 ? VSG_SCOPE_PARENT : VSG_SCOPE_SELF; |
1362 |
1352 dg->variable = grf_load_byte(&buf); |
1363 /* XXX: We don't free() anything, assuming that if there was |
1353 /* Variables 0x60 - 0x7F include an extra parameter */ |
1364 * some action here before, it got associated by action 3. |
1354 if (IS_BYTE_INSIDE(dg->variable, 0x60, 0x80)) |
1365 * We should perhaps keep some refcount? --pasky */ |
1355 dg->parameter = grf_load_byte(&buf); |
1366 |
1356 |
1367 dg->var_scope = numloaded == 0x82 ? VSG_SCOPE_PARENT : VSG_SCOPE_SELF; |
1357 dg->shift_num = grf_load_byte(&buf); |
1368 dg->variable = grf_load_byte(&buf); |
1358 dg->and_mask = grf_load_byte(&buf); |
1369 /* Variables 0x60 - 0x7F include an extra parameter */ |
1359 dg->operation = dg->shift_num >> 6; /* w00t */ |
1370 if (IS_BYTE_INSIDE(dg->variable, 0x60, 0x80)) |
1360 dg->shift_num &= 0x3F; |
1371 dg->parameter = grf_load_byte(&buf); |
1361 if (dg->operation != DSG_OP_NONE) { |
1372 |
1362 dg->add_val = grf_load_byte(&buf); |
1373 dg->shift_num = grf_load_byte(&buf); |
1363 dg->divmod_val = grf_load_byte(&buf); |
1374 dg->and_mask = grf_load_byte(&buf); |
1364 } |
1375 dg->operation = dg->shift_num >> 6; /* w00t */ |
1365 |
1376 dg->shift_num &= 0x3F; |
1366 /* (groupid & 0x8000) means this is callback result. */ |
1377 if (dg->operation != DSG_OP_NONE) { |
1367 |
1378 dg->add_val = grf_load_byte(&buf); |
1368 dg->num_ranges = grf_load_byte(&buf); |
1379 dg->divmod_val = grf_load_byte(&buf); |
1369 dg->ranges = calloc(dg->num_ranges, sizeof(*dg->ranges)); |
1380 } |
1370 for (i = 0; i < dg->num_ranges; i++) { |
1381 |
1371 groupid = grf_load_word(&buf); |
1382 /* (groupid & 0x8000) means this is callback result. */ |
1372 if (HASBIT(groupid, 15)) { |
1383 |
1373 dg->ranges[i].group = NewCallBackResultSpriteGroup(groupid); |
1384 dg->num_ranges = grf_load_byte(&buf); |
1374 } else if (groupid >= _cur_grffile->spritegroups_count || _cur_grffile->spritegroups[groupid] == NULL) { |
1385 dg->ranges = calloc(dg->num_ranges, sizeof(*dg->ranges)); |
1375 grfmsg(GMS_WARN, "NewSpriteGroup(0x%02X:0x%02X): Groupid 0x%04X does not exist, leaving empty.", setid, type, groupid); |
1386 for (i = 0; i < dg->num_ranges; i++) { |
1376 dg->ranges[i].group = NULL; |
|
1377 } else { |
|
1378 dg->ranges[i].group = _cur_grffile->spritegroups[groupid]; |
|
1379 } |
|
1380 |
|
1381 dg->ranges[i].low = grf_load_byte(&buf); |
|
1382 dg->ranges[i].high = grf_load_byte(&buf); |
|
1383 } |
|
1384 |
1387 groupid = grf_load_word(&buf); |
1385 groupid = grf_load_word(&buf); |
1388 if (HASBIT(groupid, 15)) { |
1386 if (HASBIT(groupid, 15)) { |
1389 dg->ranges[i].group = NewCallBackResultSpriteGroup(groupid); |
1387 dg->default_group = NewCallBackResultSpriteGroup(groupid); |
1390 } else if (groupid >= _cur_grffile->spritegroups_count || _cur_grffile->spritegroups[groupid] == NULL) { |
1388 } else if (groupid >= _cur_grffile->spritegroups_count || _cur_grffile->spritegroups[groupid] == NULL) { |
1391 grfmsg(GMS_WARN, "NewSpriteGroup(0x%02X:0x%02X): Groupid 0x%04X does not exist, leaving empty.", setid, numloaded, groupid); |
1389 grfmsg(GMS_WARN, "NewSpriteGroup(0x%02X:0x%02X): Groupid 0x%04X does not exist, leaving empty.", setid, type, groupid); |
1392 dg->ranges[i].group = NULL; |
1390 dg->default_group = NULL; |
1393 } else { |
1391 } else { |
1394 dg->ranges[i].group = _cur_grffile->spritegroups[groupid]; |
1392 dg->default_group = _cur_grffile->spritegroups[groupid]; |
1395 } |
1393 } |
1396 |
1394 |
1397 dg->ranges[i].low = grf_load_byte(&buf); |
1395 break; |
1398 dg->ranges[i].high = grf_load_byte(&buf); |
|
1399 } |
1396 } |
1400 |
1397 |
1401 groupid = grf_load_word(&buf); |
1398 /* Randomized Sprite Group */ |
1402 if (HASBIT(groupid, 15)) { |
1399 case 0x80: // Self scope |
1403 dg->default_group = NewCallBackResultSpriteGroup(groupid); |
1400 case 0x83: // Parent scope |
1404 } else if (groupid >= _cur_grffile->spritegroups_count || _cur_grffile->spritegroups[groupid] == NULL) { |
1401 { |
1405 grfmsg(GMS_WARN, "NewSpriteGroup(0x%02X:0x%02X): Groupid 0x%04X does not exist, leaving empty.", setid, numloaded, groupid); |
1402 RandomizedSpriteGroup *rg; |
1406 dg->default_group = NULL; |
1403 int i; |
1407 } else { |
1404 |
1408 dg->default_group = _cur_grffile->spritegroups[groupid]; |
1405 /* This stuff is getting actually evaluated in |
|
1406 * EvalRandomizedSpriteGroup(). */ |
|
1407 |
|
1408 check_length(bufend - buf, 6, "NewSpriteGroup 0x80/0x83"); |
|
1409 |
|
1410 group = AllocateSpriteGroup(); |
|
1411 group->type = SGT_RANDOMIZED; |
|
1412 rg = &group->g.random; |
|
1413 |
|
1414 rg->var_scope = type == 0x83 ? VSG_SCOPE_PARENT : VSG_SCOPE_SELF; |
|
1415 |
|
1416 rg->triggers = grf_load_byte(&buf); |
|
1417 rg->cmp_mode = rg->triggers & 0x80; |
|
1418 rg->triggers &= 0x7F; |
|
1419 |
|
1420 rg->lowest_randbit = grf_load_byte(&buf); |
|
1421 rg->num_groups = grf_load_byte(&buf); |
|
1422 |
|
1423 rg->groups = calloc(rg->num_groups, sizeof(*rg->groups)); |
|
1424 for (i = 0; i < rg->num_groups; i++) { |
|
1425 uint16 groupid = grf_load_word(&buf); |
|
1426 |
|
1427 if (HASBIT(groupid, 15)) { |
|
1428 rg->groups[i] = NewCallBackResultSpriteGroup(groupid); |
|
1429 } else if (groupid >= _cur_grffile->spritegroups_count || _cur_grffile->spritegroups[groupid] == NULL) { |
|
1430 grfmsg(GMS_WARN, "NewSpriteGroup(0x%02X:0x%02X): Groupid 0x%04X does not exist, leaving empty.", setid, type, groupid); |
|
1431 rg->groups[i] = NULL; |
|
1432 } else { |
|
1433 rg->groups[i] = _cur_grffile->spritegroups[groupid]; |
|
1434 } |
|
1435 } |
|
1436 |
|
1437 break; |
1409 } |
1438 } |
1410 |
1439 |
1411 _cur_grffile->spritegroups[setid] = group; |
1440 default: |
1412 return; |
1441 { |
1413 |
1442 RealSpriteGroup *rg; |
1414 } else if (numloaded == 0x80 || numloaded == 0x83) { |
1443 byte num_loaded = type; |
1415 RandomizedSpriteGroup *rg; |
1444 byte num_loading = grf_load_byte(&buf); |
1416 int i; |
1445 uint i; |
1417 |
1446 |
1418 /* This stuff is getting actually evaluated in |
1447 if (!_cur_grffile->spriteset_start) { |
1419 * EvalRandomizedSpriteGroup(). */ |
1448 grfmsg(GMS_ERROR, "NewSpriteGroup: No sprite set to work on! Skipping."); |
1420 |
1449 return; |
1421 buf += 4; |
1450 } |
1422 len -= 4; |
1451 |
1423 check_length(len, 6, "NewSpriteGroup 0x80/0x83"); |
1452 if (_cur_grffile->spriteset_feature != feature) { |
1424 |
1453 grfmsg(GMS_ERROR, "NewSpriteGroup: Group feature 0x%02X doesn't match set feature 0x%X! Playing it risky and trying to use it anyway.", feature, _cur_grffile->spriteset_feature); |
1425 group = AllocateSpriteGroup(); |
1454 // return; // XXX: we can't because of MB's newstats.grf --pasky |
1426 group->type = SGT_RANDOMIZED; |
1455 } |
1427 rg = &group->g.random; |
1456 |
1428 |
1457 if (_cur_grffile->first_spriteset == 0) |
1429 /* XXX: We don't free() anything, assuming that if there was |
1458 _cur_grffile->first_spriteset = _cur_grffile->spriteset_start; |
1430 * some action here before, it got associated by action 3. |
1459 |
1431 * We should perhaps keep some refcount? --pasky */ |
1460 group = AllocateSpriteGroup(); |
1432 |
1461 group->type = SGT_REAL; |
1433 rg->var_scope = numloaded == 0x83 ? VSG_SCOPE_PARENT : VSG_SCOPE_SELF; |
1462 rg = &group->g.real; |
1434 |
1463 |
1435 rg->triggers = grf_load_byte(&buf); |
1464 rg->sprites_per_set = _cur_grffile->spriteset_numents; |
1436 rg->cmp_mode = rg->triggers & 0x80; |
1465 rg->loaded_count = num_loaded; |
1437 rg->triggers &= 0x7F; |
1466 rg->loading_count = num_loading; |
1438 |
1467 |
1439 rg->lowest_randbit = grf_load_byte(&buf); |
1468 rg->loaded = calloc(rg->loaded_count, sizeof(*rg->loaded)); |
1440 rg->num_groups = grf_load_byte(&buf); |
1469 rg->loading = calloc(rg->loading_count, sizeof(*rg->loading)); |
1441 |
1470 |
1442 rg->groups = calloc(rg->num_groups, sizeof(*rg->groups)); |
1471 DEBUG(grf, 6) ("NewSpriteGroup: New SpriteGroup 0x%02hhx, %u views, %u loaded, %u loading, sprites %u - %u", |
1443 for (i = 0; i < rg->num_groups; i++) { |
1472 setid, rg->sprites_per_set, rg->loaded_count, rg->loading_count, |
1444 uint16 groupid = grf_load_word(&buf); |
1473 _cur_grffile->spriteset_start - _cur_grffile->sprite_offset, |
1445 |
1474 _cur_grffile->spriteset_start + (_cur_grffile->spriteset_numents * (num_loaded + num_loading)) - _cur_grffile->sprite_offset); |
1446 if (HASBIT(groupid, 15)) { |
1475 |
1447 rg->groups[i] = NewCallBackResultSpriteGroup(groupid); |
1476 for (i = 0; i < num_loaded; i++) { |
1448 } else if (groupid >= _cur_grffile->spritegroups_count || _cur_grffile->spritegroups[groupid] == NULL) { |
1477 uint16 spriteset_id = grf_load_word(&buf); |
1449 grfmsg(GMS_WARN, "NewSpriteGroup(0x%02X:0x%02X): Groupid 0x%04X does not exist, leaving empty.", setid, numloaded, groupid); |
1478 if (HASBIT(spriteset_id, 15)) { |
1450 rg->groups[i] = NULL; |
1479 rg->loaded[i] = NewCallBackResultSpriteGroup(spriteset_id); |
1451 } else { |
1480 } else { |
1452 rg->groups[i] = _cur_grffile->spritegroups[groupid]; |
1481 rg->loaded[i] = NewResultSpriteGroup(_cur_grffile->spriteset_start + spriteset_id * _cur_grffile->spriteset_numents, rg->sprites_per_set); |
1453 } |
1482 } |
|
1483 DEBUG(grf, 8) ("NewSpriteGroup: + rg->loaded[%i] = %u (subset %u)", i, rg->loaded[i]->g.result.result, spriteset_id); |
|
1484 } |
|
1485 |
|
1486 for (i = 0; i < num_loading; i++) { |
|
1487 uint16 spriteset_id = grf_load_word(&buf); |
|
1488 if (HASBIT(spriteset_id, 15)) { |
|
1489 rg->loading[i] = NewCallBackResultSpriteGroup(spriteset_id); |
|
1490 } else { |
|
1491 rg->loading[i] = NewResultSpriteGroup(_cur_grffile->spriteset_start + spriteset_id * _cur_grffile->spriteset_numents, rg->sprites_per_set); |
|
1492 } |
|
1493 DEBUG(grf, 8) ("NewSpriteGroup: + rg->loading[%i] = %u (subset %u)", i, rg->loading[i]->g.result.result, spriteset_id); |
|
1494 } |
|
1495 |
|
1496 break; |
1454 } |
1497 } |
1455 |
|
1456 _cur_grffile->spritegroups[setid] = group; |
|
1457 return; |
|
1458 } |
|
1459 |
|
1460 if (!_cur_grffile->spriteset_start) { |
|
1461 grfmsg(GMS_ERROR, "NewSpriteGroup: No sprite set to work on! Skipping."); |
|
1462 return; |
|
1463 } |
|
1464 |
|
1465 if (_cur_grffile->spriteset_feature != feature) { |
|
1466 grfmsg(GMS_ERROR, "NewSpriteGroup: Group feature 0x%02X doesn't match set feature 0x%X! Playing it risky and trying to use it anyway.", feature, _cur_grffile->spriteset_feature); |
|
1467 // return; // XXX: we can't because of MB's newstats.grf --pasky |
|
1468 } |
|
1469 |
|
1470 check_length(bufend - buf, 5, "NewSpriteGroup"); |
|
1471 buf += 5; |
|
1472 check_length(bufend - buf, 2 * numloaded, "NewSpriteGroup"); |
|
1473 loaded_ptr = buf; |
|
1474 loading_ptr = buf + 2 * numloaded; |
|
1475 |
|
1476 if (_cur_grffile->first_spriteset == 0) |
|
1477 _cur_grffile->first_spriteset = _cur_grffile->spriteset_start; |
|
1478 |
|
1479 group = AllocateSpriteGroup(); |
|
1480 group->type = SGT_REAL; |
|
1481 rg = &group->g.real; |
|
1482 |
|
1483 rg->sprites_per_set = _cur_grffile->spriteset_numents; |
|
1484 rg->loaded_count = numloaded; |
|
1485 rg->loading_count = numloading; |
|
1486 |
|
1487 rg->loaded = calloc(rg->loaded_count, sizeof(*rg->loaded)); |
|
1488 rg->loading = calloc(rg->loading_count, sizeof(*rg->loading)); |
|
1489 |
|
1490 DEBUG(grf, 6) ("NewSpriteGroup: New SpriteGroup 0x%02hhx, %u views, %u loaded, %u loading, sprites %u - %u", |
|
1491 setid, rg->sprites_per_set, rg->loaded_count, rg->loading_count, |
|
1492 _cur_grffile->spriteset_start - _cur_grffile->sprite_offset, |
|
1493 _cur_grffile->spriteset_start + (_cur_grffile->spriteset_numents * (numloaded + numloading)) - _cur_grffile->sprite_offset); |
|
1494 |
|
1495 for (i = 0; i < numloaded; i++) { |
|
1496 uint16 spriteset_id = grf_load_word(&loaded_ptr); |
|
1497 if (HASBIT(spriteset_id, 15)) { |
|
1498 rg->loaded[i] = NewCallBackResultSpriteGroup(spriteset_id); |
|
1499 } else { |
|
1500 rg->loaded[i] = NewResultSpriteGroup(_cur_grffile->spriteset_start + spriteset_id * _cur_grffile->spriteset_numents, rg->sprites_per_set); |
|
1501 } |
|
1502 DEBUG(grf, 8) ("NewSpriteGroup: + rg->loaded[%i] = %u (subset %u)", i, rg->loaded[i]->g.result.result, spriteset_id); |
|
1503 } |
|
1504 |
|
1505 for (i = 0; i < numloading; i++) { |
|
1506 uint16 spriteset_id = grf_load_word(&loading_ptr); |
|
1507 if (HASBIT(spriteset_id, 15)) { |
|
1508 rg->loading[i] = NewCallBackResultSpriteGroup(spriteset_id); |
|
1509 } else { |
|
1510 rg->loading[i] = NewResultSpriteGroup(_cur_grffile->spriteset_start + spriteset_id * _cur_grffile->spriteset_numents, rg->sprites_per_set); |
|
1511 } |
|
1512 DEBUG(grf, 8) ("NewSpriteGroup: + rg->loading[%i] = %u (subset %u)", i, rg->loading[i]->g.result.result, spriteset_id); |
|
1513 } |
1498 } |
1514 |
1499 |
1515 _cur_grffile->spritegroups[setid] = group; |
1500 _cur_grffile->spritegroups[setid] = group; |
1516 } |
1501 } |
1517 |
1502 |