mirror of https://github.com/OpenTTD/OpenTTD
(svn r4760) - Newstations: change the way custom stations are allocated when loading from GRF, as the current way was flawed (reallocing memory which is referenced elsewhere)
parent
0597c35fc1
commit
0a532f8491
89
newgrf.c
89
newgrf.c
|
@ -85,6 +85,10 @@ static const int _vehshifts[4] = {
|
|||
/* GSF_AIRCRAFT */ AIRCRAFT_ENGINES_INDEX,
|
||||
};
|
||||
|
||||
enum {
|
||||
MAX_STATIONS = 256,
|
||||
};
|
||||
|
||||
static uint16 cargo_allowed[TOTAL_NUM_ENGINES];
|
||||
static uint16 cargo_disallowed[TOTAL_NUM_ENGINES];
|
||||
|
||||
|
@ -771,36 +775,48 @@ static bool AircraftVehicleChangeInfo(uint engine, int numinfo, int prop, byte *
|
|||
|
||||
static bool StationChangeInfo(uint stid, int numinfo, int prop, byte **bufp, int len)
|
||||
{
|
||||
StationSpec *statspec;
|
||||
StationSpec **statspec;
|
||||
byte *buf = *bufp;
|
||||
int i;
|
||||
bool ret = false;
|
||||
|
||||
/* Allocate station specs if necessary */
|
||||
if (_cur_grffile->num_stations < stid + numinfo) {
|
||||
_cur_grffile->stations = realloc(_cur_grffile->stations, (stid + numinfo) * sizeof(*_cur_grffile->stations))
|
||||
;
|
||||
|
||||
while (_cur_grffile->num_stations < stid + numinfo) {
|
||||
memset(&_cur_grffile->stations[_cur_grffile->num_stations], 0, sizeof(*_cur_grffile->stations));
|
||||
_cur_grffile->num_stations++;
|
||||
}
|
||||
if (stid + numinfo > MAX_STATIONS) {
|
||||
grfmsg(GMS_WARN, "StationChangeInfo: Station %u is invalid, max %u, ignoring.", stid + numinfo, MAX_STATIONS);
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Allocate station specs if necessary */
|
||||
if (_cur_grffile->stations == NULL) _cur_grffile->stations = calloc(MAX_STATIONS, sizeof(*_cur_grffile->stations));
|
||||
|
||||
statspec = &_cur_grffile->stations[stid];
|
||||
|
||||
if (prop != 0x08) {
|
||||
/* Check that all stations we are modifying are defined. */
|
||||
FOR_EACH_OBJECT {
|
||||
if (statspec[i] == NULL) {
|
||||
grfmsg(GMS_NOTICE, "StationChangeInfo: Attempt to modify undefined station %u, ignoring.", stid + i);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
switch (prop) {
|
||||
case 0x08: /* Class ID */
|
||||
FOR_EACH_OBJECT {
|
||||
uint32 classid;
|
||||
|
||||
/* Property 0x08 is special; it is where the station is allocated */
|
||||
if (statspec[i] == NULL) statspec[i] = calloc(1, sizeof(*statspec[i]));
|
||||
|
||||
/* Swap classid because we read it in BE meaning WAYP or DFLT */
|
||||
uint32 classid = grf_load_dword(&buf);
|
||||
statspec[i].sclass = AllocateStationClass(BSWAP32(classid));
|
||||
classid = grf_load_dword(&buf);
|
||||
statspec[i]->sclass = AllocateStationClass(BSWAP32(classid));
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x09: /* Define sprite layout */
|
||||
FOR_EACH_OBJECT {
|
||||
StationSpec *statspec = &_cur_grffile->stations[stid + i];
|
||||
StationSpec *statspec = _cur_grffile->stations[stid + i];
|
||||
uint t;
|
||||
|
||||
statspec->tiles = grf_load_extended(&buf);
|
||||
|
@ -846,9 +862,9 @@ static bool StationChangeInfo(uint stid, int numinfo, int prop, byte **bufp, int
|
|||
|
||||
case 0x0A: /* Copy sprite layout */
|
||||
FOR_EACH_OBJECT {
|
||||
StationSpec *statspec = &_cur_grffile->stations[stid + i];
|
||||
StationSpec *statspec = _cur_grffile->stations[stid + i];
|
||||
byte srcid = grf_load_byte(&buf);
|
||||
const StationSpec *srcstatspec = &_cur_grffile->stations[srcid];
|
||||
const StationSpec *srcstatspec = _cur_grffile->stations[srcid];
|
||||
|
||||
statspec->tiles = srcstatspec->tiles;
|
||||
statspec->renderdata = srcstatspec->renderdata;
|
||||
|
@ -857,20 +873,20 @@ static bool StationChangeInfo(uint stid, int numinfo, int prop, byte **bufp, int
|
|||
break;
|
||||
|
||||
case 0x0B: /* Callback mask */
|
||||
FOR_EACH_OBJECT statspec[i].callbackmask = grf_load_byte(&buf);
|
||||
FOR_EACH_OBJECT statspec[i]->callbackmask = grf_load_byte(&buf);
|
||||
break;
|
||||
|
||||
case 0x0C: /* Disallowed number of platforms */
|
||||
FOR_EACH_OBJECT statspec[i].disallowed_platforms = grf_load_byte(&buf);
|
||||
FOR_EACH_OBJECT statspec[i]->disallowed_platforms = grf_load_byte(&buf);
|
||||
break;
|
||||
|
||||
case 0x0D: /* Disallowed platform lengths */
|
||||
FOR_EACH_OBJECT statspec[i].disallowed_lengths = grf_load_byte(&buf);
|
||||
FOR_EACH_OBJECT statspec[i]->disallowed_lengths = grf_load_byte(&buf);
|
||||
break;
|
||||
|
||||
case 0x0E: /* Define custom layout */
|
||||
FOR_EACH_OBJECT {
|
||||
StationSpec *statspec = &_cur_grffile->stations[stid + i];
|
||||
StationSpec *statspec = _cur_grffile->stations[stid + i];
|
||||
|
||||
while (buf < *bufp + len) {
|
||||
byte length = grf_load_byte(&buf);
|
||||
|
@ -929,27 +945,27 @@ static bool StationChangeInfo(uint stid, int numinfo, int prop, byte **bufp, int
|
|||
break;
|
||||
|
||||
case 0x10: /* Little/lots cargo threshold */
|
||||
FOR_EACH_OBJECT statspec[i].cargo_threshold = grf_load_word(&buf);
|
||||
FOR_EACH_OBJECT statspec[i]->cargo_threshold = grf_load_word(&buf);
|
||||
break;
|
||||
|
||||
case 0x11: /* Pylon placement */
|
||||
FOR_EACH_OBJECT statspec[i].pylons = grf_load_byte(&buf);
|
||||
FOR_EACH_OBJECT statspec[i]->pylons = grf_load_byte(&buf);
|
||||
break;
|
||||
|
||||
case 0x12: /* Cargo types for random triggers */
|
||||
FOR_EACH_OBJECT statspec[i].cargo_triggers = grf_load_dword(&buf);
|
||||
FOR_EACH_OBJECT statspec[i]->cargo_triggers = grf_load_dword(&buf);
|
||||
break;
|
||||
|
||||
case 0x13: /* General flags */
|
||||
FOR_EACH_OBJECT statspec[i].flags = grf_load_byte(&buf);
|
||||
FOR_EACH_OBJECT statspec[i]->flags = grf_load_byte(&buf);
|
||||
break;
|
||||
|
||||
case 0x14: /* Overhead wire placement */
|
||||
FOR_EACH_OBJECT statspec[i].wires = grf_load_byte(&buf);
|
||||
FOR_EACH_OBJECT statspec[i]->wires = grf_load_byte(&buf);
|
||||
break;
|
||||
|
||||
case 0x15: /* Blocked tiles */
|
||||
FOR_EACH_OBJECT statspec[i].blocked = grf_load_byte(&buf);
|
||||
FOR_EACH_OBJECT statspec[i]->blocked = grf_load_byte(&buf);
|
||||
break;
|
||||
|
||||
default:
|
||||
|
@ -1569,7 +1585,7 @@ static void NewVehicle_SpriteGroupMapping(byte *buf, int len)
|
|||
|
||||
for (i = 0; i < idcount; i++) {
|
||||
uint8 stid = buf[3 + i];
|
||||
StationSpec *statspec = &_cur_grffile->stations[stid];
|
||||
StationSpec *statspec = _cur_grffile->stations[stid];
|
||||
byte *bp = &buf[4 + idcount];
|
||||
|
||||
for (c = 0; c < cidcount; c++) {
|
||||
|
@ -1601,7 +1617,7 @@ static void NewVehicle_SpriteGroupMapping(byte *buf, int len)
|
|||
|
||||
for (i = 0; i < idcount; i++) {
|
||||
uint8 stid = buf[3 + i];
|
||||
StationSpec *statspec = &_cur_grffile->stations[stid];
|
||||
StationSpec *statspec = _cur_grffile->stations[stid];
|
||||
|
||||
statspec->spritegroup[GC_DEFAULT] = _cur_grffile->spritegroups[groupid];
|
||||
statspec->grfid = _cur_grffile->grfid;
|
||||
|
@ -1782,19 +1798,19 @@ static void VehicleNewName(byte *buf, int len)
|
|||
default:
|
||||
switch (GB(id, 8, 8)) {
|
||||
case 0xC4: /* Station class name */
|
||||
if (GB(id, 0, 8) >= _cur_grffile->num_stations) {
|
||||
if (_cur_grffile->stations == NULL || _cur_grffile->stations[GB(id, 0, 8)] == NULL) {
|
||||
grfmsg(GMS_WARN, "VehicleNewName: Attempt to name undefined station 0x%X, ignoring.", GB(id, 0, 8));
|
||||
} else {
|
||||
StationClassID sclass = _cur_grffile->stations[GB(id, 0, 8)].sclass;
|
||||
StationClassID sclass = _cur_grffile->stations[GB(id, 0, 8)]->sclass;
|
||||
SetStationClassName(sclass, AddGRFString(_cur_grffile->grfid, id, lang, new_scheme, name));
|
||||
}
|
||||
break;
|
||||
|
||||
case 0xC5: /* Station name */
|
||||
if (GB(id, 0, 8) >= _cur_grffile->num_stations) {
|
||||
if (_cur_grffile->stations == NULL || _cur_grffile->stations[GB(id, 0, 8)] == NULL) {
|
||||
grfmsg(GMS_WARN, "VehicleNewName: Attempt to name undefined station 0x%X, ignoring.", GB(id, 0, 8));
|
||||
} else {
|
||||
_cur_grffile->stations[GB(id, 0, 8)].name = AddGRFString(_cur_grffile->grfid, id, lang, new_scheme, name);
|
||||
_cur_grffile->stations[GB(id, 0, 8)]->name = AddGRFString(_cur_grffile->grfid, id, lang, new_scheme, name);
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -2482,9 +2498,10 @@ static void ResetCustomStations(void)
|
|||
uint t;
|
||||
|
||||
for (file = _first_grffile; file != NULL; file = file->next) {
|
||||
for (i = 0; i < file->num_stations; i++) {
|
||||
if (file->stations[i].grfid != file->grfid) continue;
|
||||
statspec = &file->stations[i];
|
||||
if (file->stations == NULL) continue;
|
||||
for (i = 0; i < MAX_STATIONS; i++) {
|
||||
if (file->stations[i] == NULL) continue;
|
||||
statspec = file->stations[i];
|
||||
|
||||
/* Release renderdata, if it wasn't copied from another custom station spec */
|
||||
if (!statspec->copied_renderdata) {
|
||||
|
@ -2495,12 +2512,14 @@ static void ResetCustomStations(void)
|
|||
}
|
||||
|
||||
// TODO: Release platforms and layouts
|
||||
|
||||
/* Release this station */
|
||||
free(statspec);
|
||||
}
|
||||
|
||||
/* Free and reset the station data */
|
||||
free(file->stations);
|
||||
file->stations = NULL;
|
||||
file->num_stations = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue