(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, /* GSF_AIRCRAFT */ AIRCRAFT_ENGINES_INDEX,
}; };
enum {
MAX_STATIONS = 256,
};
static uint16 cargo_allowed[TOTAL_NUM_ENGINES]; static uint16 cargo_allowed[TOTAL_NUM_ENGINES];
static uint16 cargo_disallowed[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) static bool StationChangeInfo(uint stid, int numinfo, int prop, byte **bufp, int len)
{ {
StationSpec *statspec; StationSpec **statspec;
byte *buf = *bufp; byte *buf = *bufp;
int i; int i;
bool ret = false; bool ret = false;
/* Allocate station specs if necessary */ if (stid + numinfo > MAX_STATIONS) {
if (_cur_grffile->num_stations < stid + numinfo) { grfmsg(GMS_WARN, "StationChangeInfo: Station %u is invalid, max %u, ignoring.", stid + numinfo, MAX_STATIONS);
_cur_grffile->stations = realloc(_cur_grffile->stations, (stid + numinfo) * sizeof(*_cur_grffile->stations)) return false;
;
while (_cur_grffile->num_stations < stid + numinfo) {
memset(&_cur_grffile->stations[_cur_grffile->num_stations], 0, sizeof(*_cur_grffile->stations));
_cur_grffile->num_stations++;
}
} }
/* 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]; 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) { switch (prop) {
case 0x08: /* Class ID */ case 0x08: /* Class ID */
FOR_EACH_OBJECT { 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 */ /* Swap classid because we read it in BE meaning WAYP or DFLT */
uint32 classid = grf_load_dword(&buf); classid = grf_load_dword(&buf);
statspec[i].sclass = AllocateStationClass(BSWAP32(classid)); statspec[i]->sclass = AllocateStationClass(BSWAP32(classid));
} }
break; break;
case 0x09: /* Define sprite layout */ case 0x09: /* Define sprite layout */
FOR_EACH_OBJECT { FOR_EACH_OBJECT {
StationSpec *statspec = &_cur_grffile->stations[stid + i]; StationSpec *statspec = _cur_grffile->stations[stid + i];
uint t; uint t;
statspec->tiles = grf_load_extended(&buf); 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 */ case 0x0A: /* Copy sprite layout */
FOR_EACH_OBJECT { FOR_EACH_OBJECT {
StationSpec *statspec = &_cur_grffile->stations[stid + i]; StationSpec *statspec = _cur_grffile->stations[stid + i];
byte srcid = grf_load_byte(&buf); 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->tiles = srcstatspec->tiles;
statspec->renderdata = srcstatspec->renderdata; statspec->renderdata = srcstatspec->renderdata;
@ -857,20 +873,20 @@ static bool StationChangeInfo(uint stid, int numinfo, int prop, byte **bufp, int
break; break;
case 0x0B: /* Callback mask */ 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; break;
case 0x0C: /* Disallowed number of platforms */ 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; break;
case 0x0D: /* Disallowed platform lengths */ 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; break;
case 0x0E: /* Define custom layout */ case 0x0E: /* Define custom layout */
FOR_EACH_OBJECT { FOR_EACH_OBJECT {
StationSpec *statspec = &_cur_grffile->stations[stid + i]; StationSpec *statspec = _cur_grffile->stations[stid + i];
while (buf < *bufp + len) { while (buf < *bufp + len) {
byte length = grf_load_byte(&buf); byte length = grf_load_byte(&buf);
@ -929,27 +945,27 @@ static bool StationChangeInfo(uint stid, int numinfo, int prop, byte **bufp, int
break; break;
case 0x10: /* Little/lots cargo threshold */ 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; break;
case 0x11: /* Pylon placement */ 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; break;
case 0x12: /* Cargo types for random triggers */ 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; break;
case 0x13: /* General flags */ 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; break;
case 0x14: /* Overhead wire placement */ 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; break;
case 0x15: /* Blocked tiles */ 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; break;
default: default:
@ -1569,7 +1585,7 @@ static void NewVehicle_SpriteGroupMapping(byte *buf, int len)
for (i = 0; i < idcount; i++) { for (i = 0; i < idcount; i++) {
uint8 stid = buf[3 + i]; uint8 stid = buf[3 + i];
StationSpec *statspec = &_cur_grffile->stations[stid]; StationSpec *statspec = _cur_grffile->stations[stid];
byte *bp = &buf[4 + idcount]; byte *bp = &buf[4 + idcount];
for (c = 0; c < cidcount; c++) { for (c = 0; c < cidcount; c++) {
@ -1601,7 +1617,7 @@ static void NewVehicle_SpriteGroupMapping(byte *buf, int len)
for (i = 0; i < idcount; i++) { for (i = 0; i < idcount; i++) {
uint8 stid = buf[3 + 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->spritegroup[GC_DEFAULT] = _cur_grffile->spritegroups[groupid];
statspec->grfid = _cur_grffile->grfid; statspec->grfid = _cur_grffile->grfid;
@ -1782,19 +1798,19 @@ static void VehicleNewName(byte *buf, int len)
default: default:
switch (GB(id, 8, 8)) { switch (GB(id, 8, 8)) {
case 0xC4: /* Station class name */ 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)); grfmsg(GMS_WARN, "VehicleNewName: Attempt to name undefined station 0x%X, ignoring.", GB(id, 0, 8));
} else { } 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)); SetStationClassName(sclass, AddGRFString(_cur_grffile->grfid, id, lang, new_scheme, name));
} }
break; break;
case 0xC5: /* Station name */ 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)); grfmsg(GMS_WARN, "VehicleNewName: Attempt to name undefined station 0x%X, ignoring.", GB(id, 0, 8));
} else { } 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; break;
@ -2482,9 +2498,10 @@ static void ResetCustomStations(void)
uint t; uint t;
for (file = _first_grffile; file != NULL; file = file->next) { for (file = _first_grffile; file != NULL; file = file->next) {
for (i = 0; i < file->num_stations; i++) { if (file->stations == NULL) continue;
if (file->stations[i].grfid != file->grfid) continue; for (i = 0; i < MAX_STATIONS; i++) {
statspec = &file->stations[i]; if (file->stations[i] == NULL) continue;
statspec = file->stations[i];
/* Release renderdata, if it wasn't copied from another custom station spec */ /* Release renderdata, if it wasn't copied from another custom station spec */
if (!statspec->copied_renderdata) { if (!statspec->copied_renderdata) {
@ -2495,12 +2512,14 @@ static void ResetCustomStations(void)
} }
// TODO: Release platforms and layouts // TODO: Release platforms and layouts
/* Release this station */
free(statspec);
} }
/* Free and reset the station data */ /* Free and reset the station data */
free(file->stations); free(file->stations);
file->stations = NULL; file->stations = NULL;
file->num_stations = 0;
} }
} }

View File

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