(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)

This commit is contained in:
peter1138 2006-05-06 22:20:16 +00:00
parent 0597c35fc1
commit 0a532f8491
2 changed files with 55 additions and 37 deletions

View File

@ -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;
}
}

View File

@ -41,8 +41,7 @@ typedef struct GRFFile {
int spritegroups_count;
SpriteGroup **spritegroups;
uint num_stations;
StationSpec *stations;
StationSpec **stations;
uint32 param[0x80];
uint param_end; /// one more than the highest set parameter