-
-
Notifications
You must be signed in to change notification settings - Fork 852
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Codechange: Use vector for airport tile layouts. #12607
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -3861,32 +3861,6 @@ static ChangeInfoResult IndustriesChangeInfo(uint indid, int numinfo, int prop, | |
return ret; | ||
} | ||
|
||
/** | ||
* Create a copy of the tile table so it can be freed later | ||
* without problems. | ||
* @param as The AirportSpec to copy the arrays of. | ||
*/ | ||
static void DuplicateTileTable(AirportSpec *as) | ||
{ | ||
AirportTileTable **table_list = MallocT<AirportTileTable*>(as->num_table); | ||
for (int i = 0; i < as->num_table; i++) { | ||
uint num_tiles = 1; | ||
const AirportTileTable *it = as->table[0]; | ||
do { | ||
num_tiles++; | ||
} while ((++it)->ti.x != -0x80); | ||
table_list[i] = MallocT<AirportTileTable>(num_tiles); | ||
MemCpyT(table_list[i], as->table[i], num_tiles); | ||
} | ||
as->table = table_list; | ||
HangarTileTable *depot_table = MallocT<HangarTileTable>(as->nof_depots); | ||
MemCpyT(depot_table, as->depot_table, as->nof_depots); | ||
as->depot_table = depot_table; | ||
Direction *rotation = MallocT<Direction>(as->num_table); | ||
MemCpyT(rotation, as->rotation, as->num_table); | ||
as->rotation = rotation; | ||
} | ||
|
||
/** | ||
* Define properties for airports | ||
* @param airport Local ID of the airport. | ||
|
@@ -3942,89 +3916,68 @@ static ChangeInfoResult AirportChangeInfo(uint airport, int numinfo, int prop, B | |
as->grf_prop.grffile = _cur.grffile; | ||
/* override the default airport */ | ||
_airport_mngr.Add(airport + i, _cur.grffile->grfid, subs_id); | ||
/* Create a copy of the original tiletable so it can be freed later. */ | ||
DuplicateTileTable(as); | ||
} | ||
break; | ||
} | ||
|
||
case 0x0A: { // Set airport layout | ||
uint8_t old_num_table = as->num_table; | ||
free(as->rotation); | ||
as->num_table = buf->ReadByte(); // Number of layaouts | ||
as->rotation = MallocT<Direction>(as->num_table); | ||
uint32_t defsize = buf->ReadDWord(); // Total size of the definition | ||
AirportTileTable **tile_table = CallocT<AirportTileTable*>(as->num_table); // Table with tiles to compose the airport | ||
AirportTileTable *att = CallocT<AirportTileTable>(defsize); // Temporary array to read the tile layouts from the GRF | ||
int size; | ||
const AirportTileTable *copy_from; | ||
try { | ||
for (uint8_t j = 0; j < as->num_table; j++) { | ||
const_cast<Direction&>(as->rotation[j]) = (Direction)buf->ReadByte(); | ||
for (int k = 0;; k++) { | ||
att[k].ti.x = buf->ReadByte(); // Offsets from northermost tile | ||
att[k].ti.y = buf->ReadByte(); | ||
|
||
if (att[k].ti.x == 0 && att[k].ti.y == 0x80) { | ||
/* Not the same terminator. The one we are using is rather | ||
* x = -80, y = 0 . So, adjust it. */ | ||
att[k].ti.x = -0x80; | ||
att[k].ti.y = 0; | ||
att[k].gfx = 0; | ||
|
||
size = k + 1; | ||
copy_from = att; | ||
break; | ||
} | ||
uint8_t num_layouts = buf->ReadByte(); | ||
buf->ReadDWord(); // Total size of definition, unneeded. | ||
uint8_t size_x = 0; | ||
uint8_t size_y = 0; | ||
|
||
att[k].gfx = buf->ReadByte(); | ||
std::vector<AirportTileLayout> layouts; | ||
layouts.reserve(num_layouts); | ||
|
||
if (att[k].gfx == 0xFE) { | ||
/* Use a new tile from this GRF */ | ||
int local_tile_id = buf->ReadWord(); | ||
for (uint8_t j = 0; j != num_layouts; ++j) { | ||
auto &layout = layouts.emplace_back(); | ||
layout.rotation = static_cast<Direction>(buf->ReadByte() & 6); // Rotation can only be DIR_NORTH, DIR_EAST, DIR_SOUTH or DIR_WEST. | ||
|
||
/* Read the ID from the _airporttile_mngr. */ | ||
uint16_t tempid = _airporttile_mngr.GetID(local_tile_id, _cur.grffile->grfid); | ||
for (;;) { | ||
auto &tile = layout.tiles.emplace_back(); | ||
tile.ti.x = buf->ReadByte(); | ||
tile.ti.y = buf->ReadByte(); | ||
if (tile.ti.x == 0 && tile.ti.y == 0x80) { | ||
/* Convert terminator to our own. */ | ||
tile.ti.x = -0x80; | ||
tile.ti.y = 0; | ||
tile.gfx = 0; | ||
Comment on lines
+3941
to
+3944
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Not for this PR, but if the tile table is now a vector or span then the termination sentinel does not need to be saved in OpenTTD's state. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Agreed, I figured this already touches enough :) |
||
break; | ||
} | ||
|
||
if (tempid == INVALID_AIRPORTTILE) { | ||
GrfMsg(2, "AirportChangeInfo: Attempt to use airport tile {} with airport id {}, not yet defined. Ignoring.", local_tile_id, airport + i); | ||
} else { | ||
/* Declared as been valid, can be used */ | ||
att[k].gfx = tempid; | ||
} | ||
} else if (att[k].gfx == 0xFF) { | ||
att[k].ti.x = (int8_t)GB(att[k].ti.x, 0, 8); | ||
att[k].ti.y = (int8_t)GB(att[k].ti.y, 0, 8); | ||
} | ||
tile.gfx = buf->ReadByte(); | ||
|
||
if (as->rotation[j] == DIR_E || as->rotation[j] == DIR_W) { | ||
as->size_x = std::max<uint8_t>(as->size_x, att[k].ti.y + 1); | ||
as->size_y = std::max<uint8_t>(as->size_y, att[k].ti.x + 1); | ||
if (tile.gfx == 0xFE) { | ||
/* Use a new tile from this GRF */ | ||
int local_tile_id = buf->ReadWord(); | ||
|
||
/* Read the ID from the _airporttile_mngr. */ | ||
uint16_t tempid = _airporttile_mngr.GetID(local_tile_id, _cur.grffile->grfid); | ||
|
||
if (tempid == INVALID_AIRPORTTILE) { | ||
GrfMsg(2, "AirportChangeInfo: Attempt to use airport tile {} with airport id {}, not yet defined. Ignoring.", local_tile_id, airport + i); | ||
} else { | ||
as->size_x = std::max<uint8_t>(as->size_x, att[k].ti.x + 1); | ||
as->size_y = std::max<uint8_t>(as->size_y, att[k].ti.y + 1); | ||
/* Declared as been valid, can be used */ | ||
tile.gfx = tempid; | ||
} | ||
} else if (tile.gfx == 0xFF) { | ||
tile.ti.x = static_cast<int8_t>(GB(tile.ti.x, 0, 8)); | ||
tile.ti.y = static_cast<int8_t>(GB(tile.ti.y, 0, 8)); | ||
} | ||
|
||
/* Determine largest size. */ | ||
if (layout.rotation == DIR_E || layout.rotation == DIR_W) { | ||
size_x = std::max<uint8_t>(size_x, tile.ti.y + 1); | ||
size_y = std::max<uint8_t>(size_y, tile.ti.x + 1); | ||
} else { | ||
size_x = std::max<uint8_t>(size_x, tile.ti.x + 1); | ||
size_y = std::max<uint8_t>(size_y, tile.ti.y + 1); | ||
} | ||
tile_table[j] = CallocT<AirportTileTable>(size); | ||
memcpy(tile_table[j], copy_from, sizeof(*copy_from) * size); | ||
} | ||
/* Free old layouts in the airport spec */ | ||
for (int j = 0; j < old_num_table; j++) { | ||
/* remove the individual layouts */ | ||
free(as->table[j]); | ||
} | ||
free(as->table); | ||
/* Install final layout construction in the airport spec */ | ||
as->table = tile_table; | ||
free(att); | ||
} catch (...) { | ||
for (int i = 0; i < as->num_table; i++) { | ||
free(tile_table[i]); | ||
} | ||
free(tile_table); | ||
free(att); | ||
throw; | ||
} | ||
as->layouts = std::move(layouts); | ||
as->size_x = size_x; | ||
as->size_y = size_y; | ||
break; | ||
} | ||
|
||
|
@@ -8726,18 +8679,6 @@ static void ResetCustomHouses() | |
static void ResetCustomAirports() | ||
{ | ||
for (GRFFile * const file : _grf_files) { | ||
for (auto &as : file->airportspec) { | ||
if (as != nullptr) { | ||
/* We need to remove the tiles layouts */ | ||
for (int j = 0; j < as->num_table; j++) { | ||
/* remove the individual layouts */ | ||
free(as->table[j]); | ||
} | ||
free(as->table); | ||
free(as->depot_table); | ||
free(as->rotation); | ||
} | ||
} | ||
file->airportspec.clear(); | ||
file->airtspec.clear(); | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
would it be nicer to change
layout
to be a size_t, rather than have the cast? Might need some signature changes as well I supposeThere was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That does lead to a bit of a rabbit hole, when there's no need for for a size_t field further down.