From 993ef35508929efa0d99a8c1d5ef265190c8dda3 Mon Sep 17 00:00:00 2001 From: Ted John Date: Sat, 30 Apr 2016 19:55:13 +0100 Subject: [PATCH] reduce use of gActiveTrackDesign --- src/ride/track.h | 45 ---- src/ride/track_design.c | 404 +++++++++++++++-------------------- src/ride/track_design.h | 48 +++++ src/ride/track_design_save.c | 30 +-- src/windows/track_list.c | 1 - src/windows/track_place.c | 117 ++++++---- 6 files changed, 311 insertions(+), 334 deletions(-) diff --git a/src/ride/track.h b/src/ride/track.h index dc5de04acd..2f48fe9811 100644 --- a/src/ride/track.h +++ b/src/ride/track.h @@ -54,51 +54,6 @@ typedef struct { sint16 y; // 0x08 } rct_track_coordinates; -/** -* Size: 0x04 -*/ -typedef struct { - union { - uint32 all; - struct { - sint8 x; - sint8 y; - union{ - uint16 maze_entry; - struct{ - uint8 unk_2; - uint8 type; - }; - }; - }; - }; -} rct_maze_element; - -/* Size: 0x02 */ -typedef struct { - uint8 type; - uint8 flags; -} rct_track_element; - -/* Track Scenery entry size: 0x16 */ -typedef struct { - rct_object_entry scenery_object; // 0x00 - sint8 x; // 0x10 - sint8 y; // 0x11 - sint8 z; // 0x12 - uint8 flags; // 0x13 direction quadrant tertiary colour - uint8 primary_colour; // 0x14 - uint8 secondary_colour; // 0x15 -} rct_track_scenery; - -/* Track Entrance entry size: 0x6 */ -typedef struct { - sint8 z; - uint8 direction; // 0x01 - sint16 x; // 0x02 - sint16 y; // 0x04 -} rct_track_entrance; - enum{ TRACK_ELEMENT_FLAG_TERMINAL_STATION = 1 << 3, TRACK_ELEMENT_FLAG_INVERTED = 1 << 6, diff --git a/src/ride/track_design.c b/src/ride/track_design.c index efb2c20d56..3bf9b6b6b5 100644 --- a/src/ride/track_design.c +++ b/src/ride/track_design.c @@ -120,14 +120,14 @@ static bool track_design_open_from_buffer(rct_track_td6 *td6, uint8 *src, size_t if (version < 2) { // Set any element passed the tracks to 0xFF if (td6->type == RIDE_TYPE_MAZE) { - rct_maze_element* maze_element = (rct_maze_element*)elementData; + rct_td6_maze_element* maze_element = (rct_td6_maze_element*)elementData; while (maze_element->all != 0) { maze_element++; } maze_element++; memset(maze_element, 255, final_track_element_location - (uint8*)maze_element); } else { - rct_track_element* track_element = (rct_track_element*)elementData; + rct_td6_track_element* track_element = (rct_td6_track_element*)elementData; while (track_element->type != 255) { track_element++; } @@ -216,6 +216,33 @@ static bool track_design_open_from_buffer(rct_track_td6 *td6, uint8 *src, size_t RCT2_GLOBAL(RCT2_ADDRESS_RIDE_FLAGS + 5 + (td6->type * 8), uint8) ); + // Set the element helper pointers + uintptr_t entranceElementsStart; + if (td6->type == RIDE_TYPE_MAZE) { + td6->track_elements = NULL; + td6->maze_elements = (rct_td6_maze_element*)td6->elements; + + rct_td6_maze_element *maze = td6->maze_elements; + for (; maze->all != 0; maze++) { } + entranceElementsStart = (uintptr_t)(++maze); + } else { + td6->maze_elements = NULL; + td6->track_elements = (rct_td6_track_element*)td6->elements; + + rct_td6_track_element *track = td6->track_elements; + for (; track->type != 0xFF; track++) { } + entranceElementsStart = (uintptr_t)track + 1; + } + + uintptr_t sceneryElementsStart; + rct_td6_entrance_element *entranceElement = (rct_td6_entrance_element*)entranceElementsStart; + td6->entrance_elements = entranceElement; + for (; entranceElement->z != -1; entranceElement++) { } + sceneryElementsStart = (uintptr_t)entranceElement + 1; + + rct_td6_scenery_element *sceneryElement = (rct_td6_scenery_element*)sceneryElementsStart; + td6->scenery_elements = sceneryElement; + return true; } @@ -227,9 +254,9 @@ static bool track_design_open_from_buffer(rct_track_td6 *td6, uint8 *src, size_t static bool td4_track_has_boosters(rct_track_td6* track_design, uint8* track_elements) { if (track_design->type != RCT1_RIDE_TYPE_HEDGE_MAZE) { - rct_track_element *track_element = (rct_track_element*)track_elements; - for (; track_element->type != 0xFF; track_element++) { - if (track_element->type == RCT1_TRACK_ELEM_BOOSTER) { + rct_td6_track_element *track = (rct_td6_track_element*)track_elements; + for (; track->type != 0xFF; track++) { + if (track->type == RCT1_TRACK_ELEM_BOOSTER) { return true; } } @@ -278,7 +305,7 @@ void track_update_max_min_coordinates(sint16 x, sint16 y, sint16 z) * * rct2: 0x006ABDB0 */ -void load_track_scenery_objects() +void load_track_scenery_objects(rct_track_td6 *td6) { uint8 entry_index = RCT2_GLOBAL(0xF44157, uint8); rct_object_entry_extended* object_entry = &object_entry_groups[0].entries[entry_index]; @@ -292,32 +319,11 @@ void load_track_scenery_objects() find_object_in_entry_group(copied_entry, &entry_type, &entry_index); RCT2_GLOBAL(0xF44157, uint8) = entry_index; - rct_track_td6 *track_design = gActiveTrackDesign; - uint8 *track_elements = gActiveTrackDesign->elements; - - if (track_design->type == RIDE_TYPE_MAZE){ - // Skip all of the maze track elements - while (*(uint32*)track_elements != 0)track_elements += sizeof(rct_maze_element); - track_elements += sizeof(rct_maze_element); - } - else{ - // Skip track_elements - while (*track_elements != 255) track_elements += sizeof(rct_track_element); - track_elements++; - - // Skip entrance exit elements - while (*track_elements != 255) track_elements += sizeof(rct_track_entrance); - track_elements++; - } - - while (*track_elements != 255){ - rct_track_scenery* scenery_entry = (rct_track_scenery*)track_elements; - - if (!find_object_in_entry_group(&scenery_entry->scenery_object, &entry_type, &entry_index)){ - object_load_chunk(-1, &scenery_entry->scenery_object, 0); + rct_td6_scenery_element *scenery = td6->scenery_elements; + for (; (scenery->scenery_object.flags & 0xFF) != 0xFF; scenery++) { + if (!find_object_in_entry_group(&scenery->scenery_object, &entry_type, &entry_index)) { + object_load_chunk(-1, &scenery->scenery_object, 0); } - // Skip object and location/direction/colour - track_elements += sizeof(rct_track_scenery); } reset_loaded_objects(); @@ -327,37 +333,31 @@ void load_track_scenery_objects() * * rct2: 0x006D247A */ -void track_mirror_scenery(uint8** track_elements){ - rct_track_scenery* scenery = (rct_track_scenery*)*track_elements; - for (; (scenery->scenery_object.flags & 0xFF) != 0xFF; scenery++){ +void track_mirror_scenery(rct_track_td6 *td6) +{ + rct_td6_scenery_element *scenery = td6->scenery_elements; + for (; (scenery->scenery_object.flags & 0xFF) != 0xFF; scenery++) { uint8 entry_type, entry_index; - if (!find_object_in_entry_group(&scenery->scenery_object, &entry_type, &entry_index)){ + if (!find_object_in_entry_group(&scenery->scenery_object, &entry_type, &entry_index)) { entry_type = scenery->scenery_object.flags & 0xF; - if (entry_type != OBJECT_TYPE_PATHS) + if (entry_type != OBJECT_TYPE_PATHS) { continue; + } } - rct_scenery_entry* scenery_entry = (rct_scenery_entry*)object_entry_groups[entry_type].chunks[entry_index]; - - switch (entry_type){ + rct_scenery_entry *scenery_entry = (rct_scenery_entry*)object_entry_groups[entry_type].chunks[entry_index]; + switch (entry_type) { case OBJECT_TYPE_LARGE_SCENERY: { sint16 x1 = 0, x2 = 0, y1 = 0, y2 = 0; - for (rct_large_scenery_tile* tile = scenery_entry->large_scenery.tiles; - tile->x_offset != -1; - tile++) - { - if (x1 > tile->x_offset) - x1 = tile->x_offset; - if (x2 < tile->x_offset) - x2 = tile->x_offset; - if (y1 > tile->y_offset) - y1 = tile->y_offset; - if (y2 > tile->y_offset) - y2 = tile->y_offset; + for (rct_large_scenery_tile* tile = scenery_entry->large_scenery.tiles; tile->x_offset != -1; tile++) { + if (x1 > tile->x_offset) x1 = tile->x_offset; + if (x2 < tile->x_offset) x2 = tile->x_offset; + if (y1 > tile->y_offset) y1 = tile->y_offset; + if (y2 > tile->y_offset) y2 = tile->y_offset; } - switch (scenery->flags & 3){ + switch (scenery->flags & 3) { case 0: scenery->y = (-(scenery->y * 32 + y1) - y2) / 32; break; @@ -380,38 +380,39 @@ void track_mirror_scenery(uint8** track_elements){ case OBJECT_TYPE_SMALL_SCENERY: scenery->y = -scenery->y; - if (scenery_entry->small_scenery.flags & SMALL_SCENERY_FLAG9){ + if (scenery_entry->small_scenery.flags & SMALL_SCENERY_FLAG9) { scenery->flags ^= (1 << 0); - if (!(scenery_entry->small_scenery.flags & SMALL_SCENERY_FLAG_FULL_TILE)){ + if (!(scenery_entry->small_scenery.flags & SMALL_SCENERY_FLAG_FULL_TILE)) { scenery->flags ^= (1 << 2); } break; } - if (scenery->flags & (1 << 0)) + if (scenery->flags & (1 << 0)) { scenery->flags ^= (1 << 1); + } scenery->flags ^= (1 << 2); break; case OBJECT_TYPE_WALLS: scenery->y = -scenery->y; - if (scenery->flags & (1 << 0)) + if (scenery->flags & (1 << 0)) { scenery->flags ^= (1 << 1); + } break; case OBJECT_TYPE_PATHS: scenery->y = -scenery->y; - if (scenery->flags & (1 << 5)){ + if (scenery->flags & (1 << 5)) { scenery->flags ^= (1 << 6); } uint8 flags = scenery->flags; - flags = ((flags& (1 << 3)) >> 2) | ((flags & (1 << 1)) << 2); + flags = ((flags & (1 << 3)) >> 2) | ((flags & (1 << 1)) << 2); scenery->flags &= 0xF5; scenery->flags |= flags; } - } } @@ -419,34 +420,34 @@ void track_mirror_scenery(uint8** track_elements){ * * rct2: 0x006D2443 */ -void track_mirror_ride(uint8** track_elements){ - rct_track_element* track = (rct_track_element*)*track_elements; - for (; track->type != 0xFF; track++){ +void track_mirror_ride(rct_track_td6 *td6) +{ + rct_td6_track_element *track = td6->track_elements; + for (; track->type != 0xFF; track++) { track->type = RCT2_ADDRESS(0x0099EA1C, uint8)[track->type]; } - *track_elements = (uint8*)track + 1; - rct_track_entrance* entrance = (rct_track_entrance*)*track_elements; - for (; entrance->z != -1; entrance++){ + rct_td6_entrance_element *entrance = td6->entrance_elements; + for (; entrance->z != -1; entrance++) { entrance->y = -entrance->y; - if (entrance->direction & 1){ + if (entrance->direction & 1) { entrance->direction ^= (1 << 1); } } - *track_elements = (uint8*)entrance + 1; } /** * * rct2: 0x006D25FA */ -void track_mirror_maze(uint8** track_elements){ - rct_maze_element* maze = (rct_maze_element*)*track_elements; - for (; maze->all != 0; maze++){ +void track_mirror_maze(rct_track_td6 *td6) +{ + rct_td6_maze_element *maze = td6->maze_elements; + for (; maze->all != 0; maze++) { maze->y = -maze->y; - if (maze->type == 0x8 || maze->type == 0x80){ - if (maze->unk_2 & 1){ + if (maze->type == 0x8 || maze->type == 0x80) { + if (maze->unk_2 & 1) { maze->unk_2 ^= (1 << 1); } continue; @@ -454,29 +455,26 @@ void track_mirror_maze(uint8** track_elements){ uint16 maze_entry = maze->maze_entry; uint16 new_entry = 0; - for (uint8 position = bitscanforward(maze_entry); - position != 0xFF; - position = bitscanforward(maze_entry)){ + for (uint8 position = bitscanforward(maze_entry); position != 0xFF; position = bitscanforward(maze_entry)) { maze_entry &= ~(1 << position); new_entry |= (1 << RCT2_ADDRESS(0x00993EDC, uint8)[position]); } maze->maze_entry = new_entry; } - *track_elements = (uint8*)maze + 4; } /** * * rct2: 0x006D2436 */ -void track_mirror() +void track_mirror(rct_track_td6 *td6) { - if (gActiveTrackDesign->type == RIDE_TYPE_MAZE) { - track_mirror_maze(gActiveTrackDesign->elements); + if (td6->type == RIDE_TYPE_MAZE) { + track_mirror_maze(td6); } else { - track_mirror_ride(gActiveTrackDesign->elements); + track_mirror_ride(td6); } - track_mirror_scenery(gActiveTrackDesign->elements); + track_mirror_scenery(td6); } static void track_add_selection_tile(sint16 x, sint16 y) @@ -500,23 +498,24 @@ static void track_add_selection_tile(sint16 x, sint16 y) * * rct2: 0x006D0964 */ -int track_place_scenery(rct_track_scenery* scenery_start, uint8 rideIndex, int originX, int originY, int originZ){ - RCT2_GLOBAL(0x00F44050, rct_track_scenery*) = scenery_start; +int track_place_scenery(rct_td6_scenery_element *scenery_start, uint8 rideIndex, int originX, int originY, int originZ) +{ + RCT2_GLOBAL(0x00F44050, rct_td6_scenery_element*) = scenery_start; // mode RCT2_GLOBAL(0x00F44154, uint8) = 0; - for (uint8 mode = 0; mode <= 1; mode++){ - if ((scenery_start->scenery_object.flags & 0xFF) != 0xFF) + for (uint8 mode = 0; mode <= 1; mode++) { + if ((scenery_start->scenery_object.flags & 0xFF) != 0xFF) { RCT2_GLOBAL(0x00F4414E, uint8) |= 1 << 2; + } - if (RCT2_GLOBAL(0x00F4414E, uint8) & (1 << 7)) + if (RCT2_GLOBAL(0x00F4414E, uint8) & (1 << 7)) { continue; + } - for (rct_track_scenery* scenery = scenery_start; (scenery->scenery_object.flags & 0xFF) != 0xFF; scenery++){ - + for (rct_td6_scenery_element *scenery = scenery_start; (scenery->scenery_object.flags & 0xFF) != 0xFF; scenery++) { uint8 rotation = _currentTrackPieceDirection; - rct_xy8 tile = { .x = originX / 32, .y = originY / 32 }; switch (rotation & 3){ case MAP_ELEMENT_DIRECTION_WEST: @@ -562,33 +561,36 @@ int track_place_scenery(rct_track_scenery* scenery_start, uint8 rideIndex, int o } } - if (RCT2_GLOBAL(0x00F440D4, uint8) == 6 && - mode == 0){ - + if (RCT2_GLOBAL(0x00F440D4, uint8) == 6 && mode == 0) { uint8 entry_type, entry_index; - if (!find_object_in_entry_group(&scenery->scenery_object, &entry_type, &entry_index)){ + if (!find_object_in_entry_group(&scenery->scenery_object, &entry_type, &entry_index)) { entry_type = scenery->scenery_object.flags & 0xF; - if (entry_type != OBJECT_TYPE_PATHS) + if (entry_type != OBJECT_TYPE_PATHS) { entry_type = 0xFF; - if (gScreenFlags&SCREEN_FLAGS_TRACK_DESIGNER) + } + if (gScreenFlags & SCREEN_FLAGS_TRACK_DESIGNER) { entry_type = 0xFF; - - entry_index = 0; - for (rct_path_type* path = g_pathTypeEntries[0]; - entry_index < object_entry_group_counts[OBJECT_TYPE_PATHS]; - path = g_pathTypeEntries[entry_index], entry_index++){ - - if (path == (rct_path_type*)-1) - continue; - if (path->flags & (1 << 2)) - continue; } - if (entry_index == object_entry_group_counts[OBJECT_TYPE_PATHS]) + entry_index = 0; + for (rct_path_type *path = g_pathTypeEntries[0]; + entry_index < object_entry_group_counts[OBJECT_TYPE_PATHS]; + path = g_pathTypeEntries[entry_index], entry_index++ + ) { + if (path == (rct_path_type*)-1) { + continue; + } + if (path->flags & (1 << 2)) { + continue; + } + } + + if (entry_index == object_entry_group_counts[OBJECT_TYPE_PATHS]) { entry_type = 0xFF; + } } int z; - switch (entry_type){ + switch (entry_type) { case OBJECT_TYPE_SMALL_SCENERY: //bl rotation += scenery->flags; @@ -860,7 +862,7 @@ int track_place_scenery(rct_track_scenery* scenery_start, uint8 rideIndex, int o return 1; } -int track_place_maze(sint16 x, sint16 y, sint16 z, uint8 rideIndex, uint8** track_elements) +int track_place_maze(rct_track_td6 *td6, sint16 x, sint16 y, sint16 z, uint8 rideIndex) { if (RCT2_GLOBAL(0x00F440D4, uint8) == 0){ gMapSelectionTiles->x = -1; @@ -873,68 +875,30 @@ int track_place_maze(sint16 x, sint16 y, sint16 z, uint8 rideIndex, uint8** trac RCT2_GLOBAL(0x00F440D5, uint32) = 0; - rct_maze_element* maze = (rct_maze_element*)(*track_elements); + rct_td6_maze_element *maze = td6->maze_elements; for (; maze->all != 0; maze++){ - uint8 rotation = _currentTrackPieceDirection; + uint8 rotation = _currentTrackPieceDirection & 3; rct_xy16 mapCoord = { .x = maze->x * 32, .y = maze->y * 32 }; - - switch (rotation & 3){ - case MAP_ELEMENT_DIRECTION_WEST: - break; - case MAP_ELEMENT_DIRECTION_NORTH:{ - int temp_x = -mapCoord.x; - mapCoord.x = mapCoord.y; - mapCoord.y = temp_x; - } - break; - case MAP_ELEMENT_DIRECTION_EAST: - mapCoord.x = -mapCoord.x; - mapCoord.y = -mapCoord.y; - break; - case MAP_ELEMENT_DIRECTION_SOUTH:{ - int temp_y = -mapCoord.y; - mapCoord.y = mapCoord.x; - mapCoord.x = temp_y; - } - break; - } - + rotate_map_coordinates(&mapCoord.x, &mapCoord.y, rotation); mapCoord.x += x; mapCoord.y += y; track_update_max_min_coordinates(mapCoord.x, mapCoord.y, z); - if (RCT2_GLOBAL(0x00F440D4, uint8) == 0){ - uint8 new_tile = 1; - rct_xy16* selectionTile = gMapSelectionTiles; - for (; selectionTile->x != -1; selectionTile++){ - if (selectionTile->x == mapCoord.x && selectionTile->y == mapCoord.y){ - new_tile = 0; - break; - } - if (selectionTile + 1 >= &gMapSelectionTiles[300]){ - new_tile = 0; - break; - } - } - if (new_tile){ - selectionTile->x = mapCoord.x; - selectionTile->y = mapCoord.y; - selectionTile++; - selectionTile->x = -1; - } + if (RCT2_GLOBAL(0x00F440D4, uint8) == 0) { + track_add_selection_tile(mapCoord.x, mapCoord.y); } if (RCT2_GLOBAL(0x00F440D4, uint8) == 1 || RCT2_GLOBAL(0x00F440D4, uint8) == 2 || RCT2_GLOBAL(0x00F440D4, uint8) == 4 || - RCT2_GLOBAL(0x00F440D4, uint8) == 5){ + RCT2_GLOBAL(0x00F440D4, uint8) == 5 + ) { uint8 bl; money32 cost = 0; uint16 maze_entry; - - switch (maze->type){ + switch (maze->type) { case 0x08: // entrance rotation += maze->unk_2; @@ -946,8 +910,7 @@ int track_place_maze(sint16 x, sint16 y, sint16 z, uint8 rideIndex, uint8** trac if (RCT2_GLOBAL(0x00F440D4, uint8) == 4)bl = 0x69; if (RCT2_GLOBAL(0x00F440D4, uint8) == 1){ cost = game_do_command(mapCoord.x, 0 | rotation << 8, mapCoord.y, (z / 16) & 0xFF, GAME_COMMAND_PLACE_RIDE_ENTRANCE_OR_EXIT, -1, 0); - } - else{ + } else { cost = game_do_command(mapCoord.x, bl | rotation << 8, mapCoord.y, rideIndex, GAME_COMMAND_PLACE_RIDE_ENTRANCE_OR_EXIT, 0, 0); } if (cost != MONEY32_UNDEFINED){ @@ -996,52 +959,46 @@ int track_place_maze(sint16 x, sint16 y, sint16 z, uint8 rideIndex, uint8** trac } if (RCT2_GLOBAL(0x00F440D4, uint8) == 3){ - if (mapCoord.x > 0x1FFF) - continue; - if (mapCoord.y > 0x1FFF) - continue; - if (mapCoord.x < 0) - continue; - if (mapCoord.y < 0) - continue; - - rct_map_element* map_element = map_get_surface_element_at(mapCoord.x / 32, mapCoord.y / 32); + if (mapCoord.x < 0) continue; + if (mapCoord.y < 0) continue; + if (mapCoord.x >= 256 * 32) continue; + if (mapCoord.y >= 256 * 32) continue; + rct_map_element *map_element = map_get_surface_element_at(mapCoord.x / 32, mapCoord.y / 32); sint16 map_height = map_element->base_height * 8; - - if (map_element->properties.surface.slope & 0xF){ + if (map_element->properties.surface.slope & 0xF) { map_height += 16; - if (map_element->properties.surface.slope & 0x10){ + if (map_element->properties.surface.slope & 0x10) { map_height += 16; } } - if (map_element->properties.surface.terrain & MAP_ELEMENT_WATER_HEIGHT_MASK){ + if (map_element->properties.surface.terrain & MAP_ELEMENT_WATER_HEIGHT_MASK) { sint16 water_height = map_element->properties.surface.terrain & MAP_ELEMENT_WATER_HEIGHT_MASK; water_height *= 16; - if (water_height > map_height) + if (water_height > map_height) { map_height = water_height; + } } sint16 temp_z = z + RCT2_GLOBAL(0x00F440D5, sint16) - map_height; - if (temp_z < 0) + if (temp_z < 0) { RCT2_GLOBAL(0x00F440D5, sint16) -= temp_z; + } } } - if (RCT2_GLOBAL(0x00F440D4, uint8) == 6){ + if (RCT2_GLOBAL(0x00F440D4, uint8) == 6) { game_do_command(0, 0x69, 0, rideIndex, GAME_COMMAND_DEMOLISH_RIDE, 0, 0); } RCT2_GLOBAL(0x00F44142, sint16) = x; RCT2_GLOBAL(0x00F44144, sint16) = y; RCT2_GLOBAL(0x00F44146, sint16) = z; - - *track_elements = (uint8*)maze + 4; return 1; } -int track_place_ride(sint16 x, sint16 y, sint16 z, uint8 rideIndex, uint8** track_elements) +int track_place_ride(rct_track_td6 *td6, sint16 x, sint16 y, sint16 z, uint8 rideIndex) { RCT2_GLOBAL(0x00F44142, sint16) = x; RCT2_GLOBAL(0x00F44144, sint16) = y; @@ -1059,7 +1016,7 @@ int track_place_ride(sint16 x, sint16 y, sint16 z, uint8 rideIndex, uint8** trac RCT2_GLOBAL(0x00F440D5, uint32) = 0; uint8 rotation = _currentTrackPieceDirection; - rct_track_element* track = (rct_track_element*)(*track_elements); + rct_td6_track_element *track = td6->track_elements; for (; track->type != 0xFF; track++) { uint8 trackType = track->type; if (trackType == TRACK_ELEM_INVERTED_90_DEG_UP_TO_FLAT_QUARTER_LOOP) { @@ -1173,9 +1130,8 @@ int track_place_ride(sint16 x, sint16 y, sint16 z, uint8 rideIndex, uint8** trac // Entrance elements //0x6D06D8 - *track_elements = (uint8*)track + 1; - rct_track_entrance* entrance = (rct_track_entrance*)(*track_elements); - for (; entrance->z != -1; entrance++){ + rct_td6_entrance_element *entrance = td6->entrance_elements; + for (; entrance->z != -1; entrance++) { rotation = _currentTrackPieceDirection & 3; x = entrance->x; y = entrance->y; @@ -1256,8 +1212,6 @@ int track_place_ride(sint16 x, sint16 y, sint16 z, uint8 rideIndex, uint8** trac user_string_free(ride->name); ride->type = RIDE_TYPE_NULL; } - - *track_elements = ((uint8*)(entrance)) + 1; return 1; } @@ -1316,20 +1270,16 @@ int sub_6D01B3(rct_track_td6 *td6, uint8 bl, uint8 rideIndex, int x, int y, int RCT2_GLOBAL(RCT2_ADDRESS_TRACK_PREVIEW_Z_MAX, sint16) = z; RCT2_GLOBAL(0x00F44129, uint16) = 0; - uint8* track_elements = td6->elements; - uint8 track_place_success = 0; + if (td6->type == RIDE_TYPE_MAZE) { + track_place_success = track_place_maze(td6, x, y, z, rideIndex); + } else { + track_place_success = track_place_ride(td6, x, y, z, rideIndex); + } - if (td6->type == RIDE_TYPE_MAZE){ - track_place_success = track_place_maze(x, y, z, rideIndex, &track_elements); - } - else{ - track_place_success = track_place_ride(x, y, z, rideIndex, &track_elements); - } // Scenery elements - rct_track_scenery* scenery = (rct_track_scenery*)track_elements; - - if (track_place_success){ + rct_td6_scenery_element *scenery = td6->scenery_elements; + if (track_place_success) { if (!track_place_scenery( scenery, rideIndex, @@ -1340,15 +1290,16 @@ int sub_6D01B3(rct_track_td6 *td6, uint8 bl, uint8 rideIndex, int x, int y, int } } - //0x6D0FE6 + // 0x6D0FE6 if (RCT2_GLOBAL(0x00F440D4, uint8) == 0){ RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_FLAGS, uint16) |= 0x6; RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_FLAGS, uint16) &= ~(1 << 3); map_invalidate_map_selection_tiles(); } - if (bl == 3) + if (bl == 3) { return RCT2_GLOBAL(0x00F440D5, sint16); + } return RCT2_GLOBAL(0x00F440D5, money32); } @@ -1448,12 +1399,13 @@ bool sub_6D2189(rct_track_td6 *td6, money32 *cost, uint8 *rideId) void draw_track_preview(rct_track_td6 *td6, uint8** preview) { // Make a copy of the map - if (!track_design_preview_backup_map())return; - + if (!track_design_preview_backup_map()) { + return; + } track_design_preview_clear_map(); - if (gScreenFlags & SCREEN_FLAGS_TRACK_MANAGER){ - load_track_scenery_objects(); + if (gScreenFlags & SCREEN_FLAGS_TRACK_MANAGER) { + load_track_scenery_objects(td6); } money32 cost; @@ -1898,8 +1850,8 @@ void game_command_place_track_design(int* eax, int* ebx, int* ecx, int* edx, int } } - rct_track_td6* track_design = gActiveTrackDesign; - rct_object_entry* ride_object = &track_design->vehicle_object; + rct_track_td6 *td6 = gActiveTrackDesign; + rct_object_entry *ride_object = &td6->vehicle_object; uint8 entry_type, entry_index; if (!find_object_in_entry_group(ride_object, &entry_type, &entry_index)){ @@ -1912,7 +1864,7 @@ void game_command_place_track_design(int* eax, int* ebx, int* ecx, int* edx, int int _eax = 0, _ebx = GAME_COMMAND_FLAG_APPLY, _ecx = 0, - _edx = track_design->type | (entry_index << 8), + _edx = td6->type | (entry_index << 8), _esi = GAME_COMMAND_CREATE_RIDE, _edi = 0, _ebp = 0; @@ -1937,10 +1889,10 @@ void game_command_place_track_design(int* eax, int* ebx, int* ecx, int* edx, int money32 cost = 0; if (!(flags & GAME_COMMAND_FLAG_APPLY)){ RCT2_GLOBAL(0x00F44150, uint8) = 0; - cost = sub_6D01B3(track_design, PTD_OPERATION_1, rideIndex, x, y, z); + cost = sub_6D01B3(td6, PTD_OPERATION_1, rideIndex, x, y, z); if (RCT2_GLOBAL(0x00F4414E, uint8) & (1 << 1)){ RCT2_GLOBAL(0x00F44150, uint8) |= 1 << 7; - cost = sub_6D01B3(track_design, 0x80 | PTD_OPERATION_1, rideIndex, x, y, z); + cost = sub_6D01B3(td6, 0x80 | PTD_OPERATION_1, rideIndex, x, y, z); } } else{ @@ -1951,7 +1903,7 @@ void game_command_place_track_design(int* eax, int* ebx, int* ecx, int* edx, int bl = PTD_OPERATION_2; } bl |= RCT2_GLOBAL(0x00F44150, uint8); - cost = sub_6D01B3(track_design, bl, rideIndex, x, y, z); + cost = sub_6D01B3(td6, bl, rideIndex, x, y, z); } if (cost == MONEY32_UNDEFINED || @@ -1969,23 +1921,23 @@ void game_command_place_track_design(int* eax, int* ebx, int* ecx, int* edx, int game_do_command(0, GAME_COMMAND_FLAG_APPLY | (2 << 8), 0, rideIndex | (entry_index << 8), GAME_COMMAND_SET_RIDE_VEHICLES, 0, 0); } - game_do_command(0, GAME_COMMAND_FLAG_APPLY | (track_design->ride_mode << 8), 0, rideIndex | (0 << 8), GAME_COMMAND_SET_RIDE_SETTING, 0, 0); + game_do_command(0, GAME_COMMAND_FLAG_APPLY | (td6->ride_mode << 8), 0, rideIndex | (0 << 8), GAME_COMMAND_SET_RIDE_SETTING, 0, 0); - game_do_command(0, GAME_COMMAND_FLAG_APPLY | (0 << 8), 0, rideIndex | (track_design->number_of_trains << 8), GAME_COMMAND_SET_RIDE_VEHICLES, 0, 0); + game_do_command(0, GAME_COMMAND_FLAG_APPLY | (0 << 8), 0, rideIndex | (td6->number_of_trains << 8), GAME_COMMAND_SET_RIDE_VEHICLES, 0, 0); - game_do_command(0, GAME_COMMAND_FLAG_APPLY | (1 << 8), 0, rideIndex | (track_design->number_of_cars_per_train << 8), GAME_COMMAND_SET_RIDE_VEHICLES, 0, 0); + game_do_command(0, GAME_COMMAND_FLAG_APPLY | (1 << 8), 0, rideIndex | (td6->number_of_cars_per_train << 8), GAME_COMMAND_SET_RIDE_VEHICLES, 0, 0); - game_do_command(0, GAME_COMMAND_FLAG_APPLY | (track_design->depart_flags << 8), 0, rideIndex | (1 << 8), GAME_COMMAND_SET_RIDE_SETTING, 0, 0); + game_do_command(0, GAME_COMMAND_FLAG_APPLY | (td6->depart_flags << 8), 0, rideIndex | (1 << 8), GAME_COMMAND_SET_RIDE_SETTING, 0, 0); - game_do_command(0, GAME_COMMAND_FLAG_APPLY | (track_design->min_waiting_time << 8), 0, rideIndex | (2 << 8), GAME_COMMAND_SET_RIDE_SETTING, 0, 0); + game_do_command(0, GAME_COMMAND_FLAG_APPLY | (td6->min_waiting_time << 8), 0, rideIndex | (2 << 8), GAME_COMMAND_SET_RIDE_SETTING, 0, 0); - game_do_command(0, GAME_COMMAND_FLAG_APPLY | (track_design->max_waiting_time << 8), 0, rideIndex | (3 << 8), GAME_COMMAND_SET_RIDE_SETTING, 0, 0); + game_do_command(0, GAME_COMMAND_FLAG_APPLY | (td6->max_waiting_time << 8), 0, rideIndex | (3 << 8), GAME_COMMAND_SET_RIDE_SETTING, 0, 0); - game_do_command(0, GAME_COMMAND_FLAG_APPLY | (track_design->var_50 << 8), 0, rideIndex | (4 << 8), GAME_COMMAND_SET_RIDE_SETTING, 0, 0); + game_do_command(0, GAME_COMMAND_FLAG_APPLY | (td6->var_50 << 8), 0, rideIndex | (4 << 8), GAME_COMMAND_SET_RIDE_SETTING, 0, 0); - game_do_command(0, GAME_COMMAND_FLAG_APPLY | ((track_design->lift_hill_speed_num_circuits & 0x1F) << 8), 0, rideIndex | (8 << 8), GAME_COMMAND_SET_RIDE_SETTING, 0, 0); + game_do_command(0, GAME_COMMAND_FLAG_APPLY | ((td6->lift_hill_speed_num_circuits & 0x1F) << 8), 0, rideIndex | (8 << 8), GAME_COMMAND_SET_RIDE_SETTING, 0, 0); - uint8 num_circuits = track_design->lift_hill_speed_num_circuits >> 5; + uint8 num_circuits = td6->lift_hill_speed_num_circuits >> 5; if (num_circuits == 0) num_circuits = 1; game_do_command(0, GAME_COMMAND_FLAG_APPLY | (num_circuits << 8), 0, rideIndex | (9 << 8), GAME_COMMAND_SET_RIDE_SETTING, 0, 0); @@ -1993,32 +1945,32 @@ void game_command_place_track_design(int* eax, int* ebx, int* ecx, int* edx, int ride->lifecycle_flags |= RIDE_LIFECYCLE_NOT_CUSTOM_DESIGN; - ride->colour_scheme_type = track_design->version_and_colour_scheme & 3; + ride->colour_scheme_type = td6->version_and_colour_scheme & 3; - uint8 version = track_design->version_and_colour_scheme >> 2; + uint8 version = td6->version_and_colour_scheme >> 2; if (version >= 2){ - ride->entrance_style = track_design->entrance_style; + ride->entrance_style = td6->entrance_style; } if (version >= 1){ for (int i = 0; i < 4; ++i){ - ride->track_colour_main[i] = track_design->track_spine_colour[i]; - ride->track_colour_additional[i] = track_design->track_rail_colour[i]; - ride->track_colour_supports[i] = track_design->track_support_colour[i]; + ride->track_colour_main[i] = td6->track_spine_colour[i]; + ride->track_colour_additional[i] = td6->track_rail_colour[i]; + ride->track_colour_supports[i] = td6->track_support_colour[i]; } } else{ for (int i = 0; i < 4; ++i){ - ride->track_colour_main[i] = track_design->track_spine_colour_rct1; - ride->track_colour_additional[i] = track_design->track_rail_colour_rct1; - ride->track_colour_supports[i] = track_design->track_support_colour_rct1; + ride->track_colour_main[i] = td6->track_spine_colour_rct1; + ride->track_colour_additional[i] = td6->track_rail_colour_rct1; + ride->track_colour_supports[i] = td6->track_support_colour_rct1; } } for (int i = 0; i < 32; ++i){ - ride->vehicle_colours[i].body_colour = track_design->vehicle_colours[i].body_colour; - ride->vehicle_colours[i].trim_colour = track_design->vehicle_colours[i].trim_colour; - ride->vehicle_colours_extended[i] = track_design->vehicle_additional_colour[i]; + ride->vehicle_colours[i].body_colour = td6->vehicle_colours[i].body_colour; + ride->vehicle_colours[i].trim_colour = td6->vehicle_colours[i].trim_colour; + ride->vehicle_colours_extended[i] = td6->vehicle_additional_colour[i]; } ride_set_name(rideIndex, RCT2_ADDRESS(0x009E3504,const char)); diff --git a/src/ride/track_design.h b/src/ride/track_design.h index d7dad00e36..71f9453e5e 100644 --- a/src/ride/track_design.h +++ b/src/ride/track_design.h @@ -8,6 +8,49 @@ #define TRACK_PREVIEW_IMAGE_SIZE (370 * 217) +/* Maze Element entry size: 0x04 */ +typedef struct { + union { + uint32 all; + struct { + sint8 x; + sint8 y; + union { + uint16 maze_entry; + struct{ + uint8 unk_2; + uint8 type; + }; + }; + }; + }; +} rct_td6_maze_element; + +/* Track Element entry size: 0x02 */ +typedef struct { + uint8 type; // 0x00 + uint8 flags; // 0x01 +} rct_td6_track_element; + +/* Track Entrance entry size: 0x06 */ +typedef struct { + sint8 z; // 0x00 + uint8 direction; // 0x01 + sint16 x; // 0x02 + sint16 y; // 0x04 +} rct_td6_entrance_element; + +/* Track Scenery entry size: 0x16 */ +typedef struct { + rct_object_entry scenery_object; // 0x00 + sint8 x; // 0x10 + sint8 y; // 0x11 + sint8 z; // 0x12 + uint8 flags; // 0x13 direction quadrant tertiary colour + uint8 primary_colour; // 0x14 + uint8 secondary_colour; // 0x15 +} rct_td6_scenery_element; + /** * Track design structure. * size: 0x4E72B @@ -74,6 +117,11 @@ typedef struct { uint8 lift_hill_speed_num_circuits; // 0xA2 0bCCCL_LLLL void *elements; // 0xA3 (data starts here in file) size_t elementsSize; + + rct_td6_maze_element *maze_elements; + rct_td6_track_element *track_elements; + rct_td6_entrance_element *entrance_elements; + rct_td6_scenery_element *scenery_elements; } rct_track_td6; typedef struct{ diff --git a/src/ride/track_design_save.c b/src/ride/track_design_save.c index 70465cf432..70beb4c963 100644 --- a/src/ride/track_design_save.c +++ b/src/ride/track_design_save.c @@ -205,12 +205,12 @@ static int map_element_get_total_element_count(rct_map_element *mapElement) } } -static bool track_design_save_scenery_is_null(rct_track_scenery *trackScenery) +static bool track_design_save_scenery_is_null(rct_td6_scenery_element *trackScenery) { return *((uint8*)trackScenery) == 0xFF; } -static void track_design_save_scenery_set_to_null(rct_track_scenery *trackScenery) +static void track_design_save_scenery_set_to_null(rct_td6_scenery_element *trackScenery) { *((uint8*)trackScenery) = 0xFF; } @@ -247,9 +247,9 @@ static bool track_design_save_can_add_map_element(rct_map_element *mapElement) } // Probably checking for spare elements in the TD6 struct - rct_track_scenery *trackScenery = (rct_track_scenery*)0x009DA193; + rct_td6_scenery_element *trackScenery = (rct_td6_scenery_element*)0x009DA193; while (!track_design_save_scenery_is_null(trackScenery)) { trackScenery++; } - if (trackScenery >= (rct_track_scenery*)0x9DE207) { + if (trackScenery >= (rct_td6_scenery_element*)0x9DE207) { return false; } @@ -276,7 +276,7 @@ static void track_design_save_push_map_element(int x, int y, rct_map_element *ma */ static void track_design_save_push_map_element_desc(rct_object_entry *entry, int x, int y, int z, uint8 flags, uint8 primaryColour, uint8 secondaryColour) { - rct_track_scenery *item = (rct_track_scenery*)0x009DA193; + rct_td6_scenery_element *item = (rct_td6_scenery_element*)0x009DA193; while (!track_design_save_scenery_is_null(item)) { item++; } item->scenery_object = *entry; @@ -447,8 +447,8 @@ static void track_design_save_pop_map_element_desc(rct_object_entry *entry, int int removeIndex = -1; int totalItems = 0; - rct_track_scenery *items = (rct_track_scenery*)0x009DA193; - rct_track_scenery *item = items; + rct_td6_scenery_element *items = (rct_td6_scenery_element*)0x009DA193; + rct_td6_scenery_element *item = items; for (; !track_design_save_scenery_is_null(item); item++, totalItems++) { if (item->x != x / 32) continue; if (item->y != y / 32) continue; @@ -465,7 +465,7 @@ static void track_design_save_pop_map_element_desc(rct_object_entry *entry, int // Remove item and shift rest up one item if (removeIndex < totalItems - 1) { - memmove(&items[removeIndex], &items[removeIndex + 1], (totalItems - removeIndex - 1) * sizeof(rct_track_scenery)); + memmove(&items[removeIndex], &items[removeIndex + 1], (totalItems - removeIndex - 1) * sizeof(rct_td6_scenery_element)); } track_design_save_scenery_set_to_null(&items[totalItems - 1]); } @@ -644,11 +644,11 @@ static void track_design_save_select_nearby_scenery_for_tile(int rideIndex, int /* Based on rct2: 0x006D2897 */ static bool track_design_save_copy_scenery_to_track(uint8 **track_pointer) { - rct_track_scenery* track_scenery = (rct_track_scenery*)(*track_pointer - 1); - rct_track_scenery* scenery_source = RCT2_ADDRESS(0x009DA193, rct_track_scenery); + rct_td6_scenery_element *track_scenery = (rct_td6_scenery_element*)(*track_pointer - 1); + rct_td6_scenery_element* scenery_source = RCT2_ADDRESS(0x009DA193, rct_td6_scenery_element); while (true) { - memcpy(track_scenery, scenery_source, sizeof(rct_track_scenery)); + memcpy(track_scenery, scenery_source, sizeof(rct_td6_scenery_element)); if ((track_scenery->scenery_object.flags & 0xFF) == 0xFF) break; //0x00F4414D is direction of track? @@ -833,7 +833,7 @@ static bool track_design_save_to_td6_for_maze(uint8 rideIndex, rct_track_td6 *td RCT2_GLOBAL(0x00F44144, sint16) = startY; RCT2_GLOBAL(0x00F44146, sint16) = mapElement->base_height * 8; - rct_maze_element *maze = (rct_maze_element*)trackElements; + rct_td6_maze_element *maze = (rct_td6_maze_element*)trackElements; // x is defined here as we can start the search // on tile start_x, start_y but then the next row @@ -850,7 +850,7 @@ static bool track_design_save_to_td6_for_maze(uint8 rideIndex, rct_track_td6 *td maze->y = (y - startY) / 32; maze++; - if (maze >= RCT2_ADDRESS(0x009DA151, rct_maze_element)) { + if (maze >= RCT2_ADDRESS(0x009DA151, rct_td6_maze_element)) { gGameCommandErrorText = STR_TRACK_TOO_LARGE_OR_TOO_MUCH_SCENERY; return false; } @@ -999,7 +999,7 @@ static bool track_design_save_to_td6_for_tracked_ride(uint8 rideIndex, rct_track RCT2_GLOBAL(0x00F44144, sint16) = start_y; RCT2_GLOBAL(0x00F44146, sint16) = start_z; - rct_track_element *track = (rct_track_element*)trackElements; + rct_td6_track_element *track = (rct_td6_track_element*)trackElements; do{ track->type = trackElement.element->properties.track.type; if (track->type == 0xFF) { @@ -1098,7 +1098,7 @@ static bool track_design_save_to_td6_for_tracked_ride(uint8 rideIndex, rct_track // Mark the elements as finished. *trackElements++ = 0xFF; - rct_track_entrance *entrance = (rct_track_entrance*)trackElements; + rct_td6_entrance_element *entrance = (rct_td6_entrance_element*)trackElements; // First entrances, second exits for (int i = 0; i < 2; i++) { diff --git a/src/windows/track_list.c b/src/windows/track_list.c index 51269ddbb4..32c59d8d91 100644 --- a/src/windows/track_list.c +++ b/src/windows/track_list.c @@ -621,7 +621,6 @@ static bool track_list_load_design_for_preview(utf8 *path) if (track_design_open(&_loadedTrackDesign, path)) { // Load in a new preview image, calculate cost variable, calculate var_06 - gActiveTrackDesign = &_loadedTrackDesign; draw_track_preview(&_loadedTrackDesign, (uint8**)_loadedTrackDesignPreview); _loadedTrackDesign.cost = gTrackDesignCost; diff --git a/src/windows/track_place.c b/src/windows/track_place.c index c1e47804d3..bef77f2539 100644 --- a/src/windows/track_place.c +++ b/src/windows/track_place.c @@ -105,14 +105,19 @@ static sint16 _window_track_place_last_valid_y; static sint16 _window_track_place_last_valid_z; static money32 _window_track_place_last_cost; +static rct_track_td6 *_trackDesign; + static void window_track_place_clear_provisional(); static int window_track_place_get_base_z(int x, int y); -static void window_track_place_attempt_placement(int x, int y, int z, int bl, money32 *cost, uint8 *rideIndex); +static void window_track_place_attempt_placement(rct_track_td6 *td6, int x, int y, int z, int bl, money32 *cost, uint8 *rideIndex); static void window_track_place_clear_mini_preview(); -static void window_track_place_draw_mini_preview(); -static void window_track_place_draw_mini_preview_track(int pass, rct_xy16 origin, rct_xy16 *min, rct_xy16 *max); -static void window_track_place_draw_mini_preview_maze(int pass, rct_xy16 origin, rct_xy16 *min, rct_xy16 *max); +static void window_track_place_draw_mini_preview(rct_track_td6 *td6); +static void window_track_place_draw_mini_preview_track(rct_track_td6 *td6, int pass, rct_xy16 origin, rct_xy16 *min, rct_xy16 *max); +static void window_track_place_draw_mini_preview_maze(rct_track_td6 *td6, int pass, rct_xy16 origin, rct_xy16 *min, rct_xy16 *max); +static rct_xy16 draw_mini_preview_get_pixel_position(sint16 x, sint16 y); +static bool draw_mini_preview_is_pixel_in_bounds(rct_xy16 pixel); +static uint8 *draw_mini_preview_get_pixel_ptr(rct_xy16 pixel); /** * @@ -135,9 +140,9 @@ void window_track_place_open(utf8 *tdPath) window_close_construction_windows(); - gActiveTrackDesign = malloc(sizeof(rct_track_td6)); - if (!track_design_open(gActiveTrackDesign, tdPath)) { - SafeFree(gActiveTrackDesign); + _trackDesign = malloc(sizeof(rct_track_td6)); + if (!track_design_open(_trackDesign, tdPath)) { + SafeFree(_trackDesign); return; } @@ -163,7 +168,7 @@ void window_track_place_open(utf8 *tdPath) _window_track_place_last_cost = MONEY32_UNDEFINED; _window_track_place_last_x = 0xFFFF; _currentTrackPieceDirection = (2 - get_current_rotation()) & 3; - window_track_place_draw_mini_preview(); + window_track_place_draw_mini_preview(_trackDesign); } /** @@ -178,7 +183,7 @@ static void window_track_place_close(rct_window *w) RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_FLAGS, uint16) &= ~6; hide_gridlines(); SafeFree(_window_track_place_mini_preview); - SafeFree(gActiveTrackDesign); + SafeFree(_trackDesign); } /** @@ -196,14 +201,14 @@ static void window_track_place_mouseup(rct_window *w, int widgetIndex) _currentTrackPieceDirection = (_currentTrackPieceDirection + 1) & 3; window_invalidate(w); _window_track_place_last_x = 0xFFFF; - window_track_place_draw_mini_preview(); + window_track_place_draw_mini_preview(_trackDesign); break; case WIDX_MIRROR: track_mirror(); _currentTrackPieceDirection = (0 - _currentTrackPieceDirection) & 3; window_invalidate(w); _window_track_place_last_x = 0xFFFF; - window_track_place_draw_mini_preview(); + window_track_place_draw_mini_preview(_trackDesign); break; case WIDX_SELECT_DIFFERENT_DESIGN: window_close(w); @@ -246,7 +251,7 @@ static void window_track_place_toolupdate(rct_window* w, int widgetIndex, int x, // Check if tool map position has changed since last update if (mapX == _window_track_place_last_x && mapY == _window_track_place_last_y) { - sub_6D01B3(gActiveTrackDesign, PTD_OPERATION_DRAW_OUTLINES, 0, mapX, mapY, 0); + sub_6D01B3(_trackDesign, PTD_OPERATION_DRAW_OUTLINES, 0, mapX, mapY, 0); return; } @@ -259,7 +264,7 @@ static void window_track_place_toolupdate(rct_window* w, int widgetIndex, int x, // Try increasing Z until a feasible placement is found for (i = 0; i < 7; i++) { - window_track_place_attempt_placement(mapX, mapY, mapZ, 105, &cost, &rideIndex); + window_track_place_attempt_placement(_trackDesign, mapX, mapY, mapZ, 105, &cost, &rideIndex); if (cost != MONEY32_UNDEFINED) { RCT2_GLOBAL(0x00F440EB, uint16) = rideIndex; _window_track_place_last_valid_x = mapX; @@ -279,7 +284,7 @@ static void window_track_place_toolupdate(rct_window* w, int widgetIndex, int x, widget_invalidate(w, WIDX_PRICE); } - sub_6D01B3(gActiveTrackDesign, PTD_OPERATION_DRAW_OUTLINES, 0, mapX, mapY, mapZ); + sub_6D01B3(_trackDesign, PTD_OPERATION_DRAW_OUTLINES, 0, mapX, mapY, mapZ); } /** @@ -305,7 +310,7 @@ static void window_track_place_tooldown(rct_window* w, int widgetIndex, int x, i mapZ = window_track_place_get_base_z(mapX, mapY); for (i = 0; i < 7; i++) { RCT2_GLOBAL(0x009A8C29, uint8) |= 1; - window_track_place_attempt_placement(mapX, mapY, mapZ, 1, &cost, &rideIndex); + window_track_place_attempt_placement(_trackDesign, mapX, mapY, mapZ, 1, &cost, &rideIndex); RCT2_GLOBAL(0x009A8C29, uint8) &= ~1; if (cost != MONEY32_UNDEFINED) { @@ -350,7 +355,7 @@ static void window_track_place_toolabort(rct_window *w, int widgetIndex) */ static void window_track_place_unknown14(rct_window *w) { - window_track_place_draw_mini_preview(); + window_track_place_draw_mini_preview(_trackDesign); } static void window_track_place_invalidate(rct_window *w) @@ -366,7 +371,7 @@ static void window_track_place_clear_provisional() { if (_window_track_place_last_was_valid) { sub_6D01B3( - gActiveTrackDesign, + _trackDesign, PTD_OPERATION_CLEAR_OUTLINES, RCT2_GLOBAL(0x00F440EB, uint8), _window_track_place_last_valid_x, @@ -402,10 +407,10 @@ static int window_track_place_get_base_z(int x, int y) if (mapElement->properties.surface.terrain & 0x1F) z = max(z, (mapElement->properties.surface.terrain & 0x1F) << 4); - return z + sub_6D01B3(gActiveTrackDesign, PTD_OPERATION_GET_PLACE_Z, 0, x, y, z); + return z + sub_6D01B3(_trackDesign, PTD_OPERATION_GET_PLACE_Z, 0, x, y, z); } -static void window_track_place_attempt_placement(int x, int y, int z, int bl, money32 *cost, uint8 *rideIndex) +static void window_track_place_attempt_placement(rct_track_td6 *td6, int x, int y, int z, int bl, money32 *cost, uint8 *rideIndex) { int eax, ebx, ecx, edx, esi, edi, ebp; money32 result; @@ -415,7 +420,10 @@ static void window_track_place_attempt_placement(int x, int y, int z, int bl, mo ebx = bl; ecx = y; edi = z; + + gActiveTrackDesign = _trackDesign; result = game_do_command_p(GAME_COMMAND_PLACE_TRACK_DESIGN, &eax, &ebx, &ecx, &edx, &esi, &edi, &ebp); + gActiveTrackDesign = NULL; if (cost != NULL) *cost = result; if (rideIndex != NULL) *rideIndex = edi & 0xFF; @@ -454,12 +462,10 @@ static void window_track_place_paint(rct_window *w, rct_drawpixelinfo *dpi) * * rct2: 0x006D1845 */ -static void window_track_place_draw_mini_preview() +static void window_track_place_draw_mini_preview(rct_track_td6 *td6) { window_track_place_clear_mini_preview(); - bool isMaze = gActiveTrackDesign->type == RIDE_TYPE_MAZE; - // First pass is used to determine the width and height of the image so it can centre it rct_xy16 min = { 0, 0 }; rct_xy16 max = { 0, 0 }; @@ -470,28 +476,24 @@ static void window_track_place_draw_mini_preview() origin.y -= ((max.y + min.y) >> 6) << 5; } - if (isMaze) { - window_track_place_draw_mini_preview_maze(pass, origin, &min, &max); + if (td6->type == RIDE_TYPE_MAZE) { + window_track_place_draw_mini_preview_maze(td6, pass, origin, &min, &max); } else { - window_track_place_draw_mini_preview_track(pass, origin, &min, &max); + window_track_place_draw_mini_preview_track(td6, pass, origin, &min, &max); } } } -static void window_track_place_draw_mini_preview_track(int pass, rct_xy16 origin, rct_xy16 *min, rct_xy16 *max) +static void window_track_place_draw_mini_preview_track(rct_track_td6 *td6, int pass, rct_xy16 origin, rct_xy16 *min, rct_xy16 *max) { - int rotation = _currentTrackPieceDirection + get_current_rotation(); - rct_track_element *trackElement = (rct_track_element*)gActiveTrackDesign->elements; - + uint8 rotation = (_currentTrackPieceDirection + get_current_rotation()) & 3; + rct_td6_track_element *trackElement = td6->track_elements; while (trackElement->type != 255) { int trackType = trackElement->type; if (trackType == TRACK_ELEM_INVERTED_90_DEG_UP_TO_FLAT_QUARTER_LOOP) { trackType = 255; } - // Station track is a lighter colour - uint8 colour = RCT2_ADDRESS(0x0099BA64, uint8)[trackType * 16] & 0x10 ? 222 : 218; - // Follow a single track piece shape const rct_preview_track *trackBlock = TrackBlocks[trackType]; while (trackBlock->index != 255) { @@ -505,14 +507,16 @@ static void window_track_place_draw_mini_preview_track(int pass, rct_xy16 origin min->y = min(min->y, y); max->y = max(max->y, y); } else { - int pixelX = 80 + ((y / 32) - (x / 32)) * 4; - int pixelY = 38 + ((y / 32) + (x / 32)) * 2; - if (pixelX >= 0 && pixelY >= 0 && pixelX <= 160 && pixelY <= 75) { - uint8 *pixel = &_window_track_place_mini_preview[pixelY * TRACK_MINI_PREVIEW_WIDTH + pixelX]; + rct_xy16 pixelPosition = draw_mini_preview_get_pixel_position(x, y); + if (draw_mini_preview_is_pixel_in_bounds(pixelPosition)) { + uint8 *pixel = draw_mini_preview_get_pixel_ptr(pixelPosition); uint8 bits = trackBlock->var_08 << (rotation & 3); bits = (bits & 0x0F) | ((bits & 0xF0) >> 4); + // Station track is a lighter colour + uint8 colour = RCT2_ADDRESS(0x0099BA64, uint8)[trackType * 16] & 0x10 ? 222 : 218; + for (int i = 0; i < 4; i++) { if (bits & 1) pixel[338 + i] = colour; if (bits & 2) pixel[168 + i] = colour; @@ -532,8 +536,9 @@ static void window_track_place_draw_mini_preview_track(int pass, rct_xy16 origin map_offset_with_rotation(&origin.x, &origin.y, track_coordinate->x, track_coordinate->y, rotation); rotation += track_coordinate->rotation_end - track_coordinate->rotation_begin; rotation &= 3; - if (track_coordinate->rotation_end & 4) + if (track_coordinate->rotation_end & 4) { rotation |= 4; + } if (!(rotation & 4)) { origin.x += TileDirectionDelta[rotation].x; origin.y += TileDirectionDelta[rotation].y; @@ -542,10 +547,10 @@ static void window_track_place_draw_mini_preview_track(int pass, rct_xy16 origin } } -static void window_track_place_draw_mini_preview_maze(int pass, rct_xy16 origin, rct_xy16 *min, rct_xy16 *max) +static void window_track_place_draw_mini_preview_maze(rct_track_td6 *td6, int pass, rct_xy16 origin, rct_xy16 *min, rct_xy16 *max) { - int rotation = (_currentTrackPieceDirection + get_current_rotation()) & 3; - rct_maze_element *mazeElement = gActiveTrackDesign->elements; + uint8 rotation = (_currentTrackPieceDirection + get_current_rotation()) & 3; + rct_td6_maze_element *mazeElement = td6->maze_elements; while (mazeElement->all != 0) { sint16 x = mazeElement->x * 32; sint16 y = mazeElement->y * 32; @@ -554,19 +559,19 @@ static void window_track_place_draw_mini_preview_maze(int pass, rct_xy16 origin, x += origin.x; y += origin.y; - // Entrance or exit is a lighter colour - uint8 colour = mazeElement->type == 8 || mazeElement->type == 128 ? 222 : 218; - if (pass == 0) { min->x = min(min->x, x); max->x = max(max->x, x); min->y = min(min->y, y); max->y = max(max->y, y); } else { - int pixelX = 80 + ((y / 32) - (x / 32)) * 4; - int pixelY = 38 + ((y / 32) + (x / 32)) * 2; - if (pixelX <= 160 && pixelY <= 75) { - uint8 *pixel = &_window_track_place_mini_preview[pixelY * TRACK_MINI_PREVIEW_WIDTH + pixelX]; + rct_xy16 pixelPosition = draw_mini_preview_get_pixel_position(x, y); + if (draw_mini_preview_is_pixel_in_bounds(pixelPosition)) { + uint8 *pixel = draw_mini_preview_get_pixel_ptr(pixelPosition); + + // Entrance or exit is a lighter colour + uint8 colour = mazeElement->type == 8 || mazeElement->type == 128 ? 222 : 218; + for (int i = 0; i < 4; i++) { pixel[338 + i] = colour; pixel[168 + i] = colour; @@ -578,3 +583,21 @@ static void window_track_place_draw_mini_preview_maze(int pass, rct_xy16 origin, mazeElement++; } } + +static rct_xy16 draw_mini_preview_get_pixel_position(sint16 x, sint16 y) +{ + return (rct_xy16) { + 80 + ((y / 32) - (x / 32)) * 4, + 38 + ((y / 32) + (x / 32)) * 2 + }; +} + +static bool draw_mini_preview_is_pixel_in_bounds(rct_xy16 pixel) +{ + return pixel.x >= 0 && pixel.y >= 0 && pixel.x <= 160 && pixel.y <= 75; +} + +static uint8 *draw_mini_preview_get_pixel_ptr(rct_xy16 pixel) +{ + return &_window_track_place_mini_preview[pixel.y * TRACK_MINI_PREVIEW_WIDTH + pixel.x]; +}