implement sub_6D31A6

This commit is contained in:
IntelOrca 2015-09-13 02:59:55 +01:00
parent 5e58dc9789
commit f988f69ae0
6 changed files with 148 additions and 9 deletions

View File

@ -42,11 +42,14 @@ namespace Memory {
template<typename T>
T *Copy(T *dst, const T *src, size_t size) {
if (size == 0) return (T*)dst;
return (T*)memcpy((void*)dst, (const void*)src, size);
}
template<typename T>
T *CopyArray(T *dst, const T *src, size_t count) {
count *= sizeof(T);
if (count == 0) return (T*)dst;
return (T*)memcpy((void*)dst, (const void*)src, count * sizeof(T));
}

View File

@ -87,6 +87,7 @@ public:
* Returns the current string buffer as a new fire-and-forget string.
*/
utf8 *GetString() const {
// If buffer is null, length should be 0 which will create a new one byte memory block containing a null terminator
utf8 *result = Memory::AllocateArray<utf8>(_length + 1);
Memory::CopyArray(result, _buffer, _length);
result[_length] = 0;
@ -98,6 +99,8 @@ public:
* be deallocated when the StringBuilder is destructed.
*/
const utf8 *GetBuffer() const {
// buffer may be null, so return an immutable empty string
if (_buffer == NULL) return "";
return _buffer;
}

View File

@ -1663,7 +1663,7 @@ enum {
STR_SELECT_NEARBY_SCENERY = 3137,
STR_RESET_SELECTION = 3138,
STR_CABLE_LIFT_UNABLE_TO_WORK_IN_THIS_OPERATING_MODE = 3139,
STR_CABLE_LIFT_HILL_MUST_START_IMMEDIATELY_AFTER_STATION = 3140,
STR_MULTICIRCUIT_NOT_POSSIBLE_WITH_CABLE_LIFT_HILL = 3141,
STR_SHOW_PEOPLE_ON_MAP_TIP = 3143,

View File

@ -4181,8 +4181,8 @@ static void ride_set_block_points(rct_xy_element *startElement)
case TRACK_ELEM_CABLE_LIFT_HILL:
case TRACK_ELEM_25_DEG_UP_TO_FLAT:
case TRACK_ELEM_60_DEG_UP_TO_FLAT:
case TRACK_ELEM_DIAG_25_DEG_UP_TO_FLAT:
case TRACK_ELEM_DIAG_60_DEG_UP_TO_FLAT:
case TRACK_ELEM_DIAG_25_DEG_UP_TO_FLAT:
case TRACK_ELEM_DIAG_60_DEG_UP_TO_FLAT:
case 216: // block brakes
currentElement.element->flags &= ~(1 << 5);
break;
@ -4191,7 +4191,7 @@ static void ride_set_block_points(rct_xy_element *startElement)
}
/**
*
*
* rct2: 0x006B4D26
*/
void ride_set_start_finish_points(int rideIndex, rct_xy_element *startElement)
@ -4213,7 +4213,7 @@ void ride_set_start_finish_points(int rideIndex, rct_xy_element *startElement)
}
/**
*
*
* rct2: 0x0069ED9E
*/
static int sub_69ED9E()
@ -4224,7 +4224,7 @@ static int sub_69ED9E()
}
/**
*
*
* rct2: 0x006DD84C
*/
int ride_create_vehicles(rct_ride *ride, int rideIndex, rct_xy_element *element, int isApplying)
@ -4232,9 +4232,103 @@ int ride_create_vehicles(rct_ride *ride, int rideIndex, rct_xy_element *element,
return RCT2_CALLPROC_X(0x006DD84C, element->x, isApplying, element->y, rideIndex, (int)ride, (int)element->element, 0) & 0x100;
}
static bool sub_6D31A6(rct_ride *ride)
/**
*
* rct2: 0x006D31A6
*/
static bool sub_6D31A6(rct_ride *ride, bool isApplying)
{
return !(RCT2_CALLPROC_X(0x006D31A6, 0, 0, 0, 0, 0, (int)ride, 0) & 0x100);
return !(RCT2_CALLPROC_X(0x006D31A6, 0, isApplying ? 1 : 0, 0, 0, 0, (int)ride, 0) & 0x100);
// TODO This implementation does not work because track_block_get_previous called from track_circuit_iterator_previous seems
// to be ending prematurely and not iterating the complete track. This can be reproduced by constructing a giga coaster
// with a lift hill (pre-designed one will do) and testing it. This means other methods that use
// track_block_get_previous could be faulty. It might a particuarly track block that causes it.
uint16 xy;
int stationIndex;
for (stationIndex = 0; stationIndex < 4; stationIndex++) {
xy = ride->station_starts[stationIndex];
if (xy != 0xFFFF) break;
if (stationIndex == 3) {
RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_TEXT, rct_string_id) = STR_CABLE_LIFT_HILL_MUST_START_IMMEDIATELY_AFTER_STATION;
return false;
}
}
int x = (xy & 0xFF) * 32;
int y = (xy >> 8) * 32;
int z = ride->station_heights[stationIndex];
rct_map_element *mapElement = map_get_first_element_at(x >> 5, y >> 5);
do {
if (mapElement->type != MAP_ELEMENT_TYPE_TRACK) continue;
if (mapElement->base_height != z) continue;
int trackType = mapElement->properties.track.type;
if (!(RCT2_ADDRESS(0x0099BA64, uint8)[trackType * 16] & 0x10)) {
continue;
}
break;
} while (!map_element_is_last_for_tile(mapElement++));
enum {
STATE_FIND_CABLE_LIFT,
STATE_FIND_STATION,
STATE_REST_OF_TRACK
};
int state = STATE_FIND_CABLE_LIFT;
track_circuit_iterator it;
track_circuit_iterator_begin(&it, (rct_xy_element){
.x = x,
.y = y,
.element = mapElement
});
while (track_circuit_iterator_previous(&it)) {
mapElement = it.current.element;
int trackType = mapElement->properties.track.type;
uint16 flags = 16;
switch (state) {
case STATE_FIND_CABLE_LIFT:
// Search for a cable lift hill track element
if (trackType == TRACK_ELEM_CABLE_LIFT_HILL) {
flags = 8;
state = STATE_FIND_STATION;
}
break;
case STATE_FIND_STATION:
// Search for the start of the hill
switch (trackType) {
case TRACK_ELEM_FLAT:
case TRACK_ELEM_25_DEG_UP:
case TRACK_ELEM_60_DEG_UP:
case TRACK_ELEM_FLAT_TO_25_DEG_UP:
case TRACK_ELEM_25_DEG_UP_TO_FLAT:
case TRACK_ELEM_25_DEG_UP_TO_60_DEG_UP:
case TRACK_ELEM_60_DEG_UP_TO_25_DEG_UP:
case TRACK_ELEM_FLAT_TO_60_DEG_UP_LONG_BASE:
flags = 8;
break;
case TRACK_ELEM_END_STATION:
state = STATE_REST_OF_TRACK;
break;
default:
RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_TEXT, rct_string_id) = STR_CABLE_LIFT_HILL_MUST_START_IMMEDIATELY_AFTER_STATION;
return false;
}
break;
}
if (isApplying) {
z = mapElement->base_height * 8;
int direction = mapElement->type & 3;
trackType = mapElement->properties.track.type;
sub_6C683D(&x, &y, &z, direction, trackType, 0, &mapElement, flags);
}
}
return true;
}
/**
@ -4262,7 +4356,7 @@ bool ride_create_cable_lift(int rideIndex, bool isApplying)
return false;
}
if (!sub_6D31A6(ride)) {
if (!sub_6D31A6(ride, isApplying)) {
return false;
}

View File

@ -4709,6 +4709,44 @@ void track_circuit_iterator_begin(track_circuit_iterator *it, rct_xy_element fir
it->looped = false;
}
bool track_circuit_iterator_previous(track_circuit_iterator *it)
{
track_begin_end trackBeginEnd;
if (it->first == NULL) {
if (!track_block_get_previous(it->last.x, it->last.y, it->last.element, &trackBeginEnd))
return false;
it->current.x = trackBeginEnd.begin_x;
it->current.y = trackBeginEnd.begin_y;
it->current.element = trackBeginEnd.begin_element;
it->currentZ = trackBeginEnd.begin_z;
it->currentDirection = trackBeginEnd.begin_direction;
it->first = it->current.element;
return true;
} else {
if (!it->firstIteration && it->first == it->current.element) {
it->looped = true;
return false;
}
it->firstIteration = false;
it->last = it->current;
if (track_block_get_previous(it->last.x, it->last.y, it->last.element, &trackBeginEnd)) {
it->current.x = trackBeginEnd.begin_x;
it->current.y = trackBeginEnd.begin_y;
it->current.element = trackBeginEnd.begin_element;
it->currentZ = trackBeginEnd.begin_z;
it->currentDirection = trackBeginEnd.begin_direction;
return true;
} else {
return false;
}
}
}
bool track_circuit_iterator_next(track_circuit_iterator *it)
{
if (it->first == NULL) {

View File

@ -532,6 +532,7 @@ void game_command_remove_track(int *eax, int *ebx, int *ecx, int *edx, int *esi,
void game_command_set_brakes_speed(int *eax, int *ebx, int *ecx, int *edx, int *esi, int *edi, int *ebp);
void track_circuit_iterator_begin(track_circuit_iterator *it, rct_xy_element first);
bool track_circuit_iterator_previous(track_circuit_iterator *it);
bool track_circuit_iterator_next(track_circuit_iterator *it);
void track_get_back(rct_xy_element *input, rct_xy_element *output);