reduce use of gActiveTrackDesign

This commit is contained in:
Ted John 2016-04-30 19:55:13 +01:00
parent f00d7daef5
commit 993ef35508
6 changed files with 311 additions and 334 deletions

View File

@ -54,51 +54,6 @@ typedef struct {
sint16 y; // 0x08 sint16 y; // 0x08
} rct_track_coordinates; } 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{ enum{
TRACK_ELEMENT_FLAG_TERMINAL_STATION = 1 << 3, TRACK_ELEMENT_FLAG_TERMINAL_STATION = 1 << 3,
TRACK_ELEMENT_FLAG_INVERTED = 1 << 6, TRACK_ELEMENT_FLAG_INVERTED = 1 << 6,

View File

@ -120,14 +120,14 @@ static bool track_design_open_from_buffer(rct_track_td6 *td6, uint8 *src, size_t
if (version < 2) { if (version < 2) {
// Set any element passed the tracks to 0xFF // Set any element passed the tracks to 0xFF
if (td6->type == RIDE_TYPE_MAZE) { 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) { while (maze_element->all != 0) {
maze_element++; maze_element++;
} }
maze_element++; maze_element++;
memset(maze_element, 255, final_track_element_location - (uint8*)maze_element); memset(maze_element, 255, final_track_element_location - (uint8*)maze_element);
} else { } 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) { while (track_element->type != 255) {
track_element++; 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) 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; 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) static bool td4_track_has_boosters(rct_track_td6* track_design, uint8* track_elements)
{ {
if (track_design->type != RCT1_RIDE_TYPE_HEDGE_MAZE) { if (track_design->type != RCT1_RIDE_TYPE_HEDGE_MAZE) {
rct_track_element *track_element = (rct_track_element*)track_elements; rct_td6_track_element *track = (rct_td6_track_element*)track_elements;
for (; track_element->type != 0xFF; track_element++) { for (; track->type != 0xFF; track++) {
if (track_element->type == RCT1_TRACK_ELEM_BOOSTER) { if (track->type == RCT1_TRACK_ELEM_BOOSTER) {
return true; return true;
} }
} }
@ -278,7 +305,7 @@ void track_update_max_min_coordinates(sint16 x, sint16 y, sint16 z)
* *
* rct2: 0x006ABDB0 * rct2: 0x006ABDB0
*/ */
void load_track_scenery_objects() void load_track_scenery_objects(rct_track_td6 *td6)
{ {
uint8 entry_index = RCT2_GLOBAL(0xF44157, uint8); uint8 entry_index = RCT2_GLOBAL(0xF44157, uint8);
rct_object_entry_extended* object_entry = &object_entry_groups[0].entries[entry_index]; 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); find_object_in_entry_group(copied_entry, &entry_type, &entry_index);
RCT2_GLOBAL(0xF44157, uint8) = entry_index; RCT2_GLOBAL(0xF44157, uint8) = entry_index;
rct_track_td6 *track_design = gActiveTrackDesign; rct_td6_scenery_element *scenery = td6->scenery_elements;
uint8 *track_elements = gActiveTrackDesign->elements; for (; (scenery->scenery_object.flags & 0xFF) != 0xFF; scenery++) {
if (!find_object_in_entry_group(&scenery->scenery_object, &entry_type, &entry_index)) {
if (track_design->type == RIDE_TYPE_MAZE){ object_load_chunk(-1, &scenery->scenery_object, 0);
// 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);
} }
// Skip object and location/direction/colour
track_elements += sizeof(rct_track_scenery);
} }
reset_loaded_objects(); reset_loaded_objects();
@ -327,37 +333,31 @@ void load_track_scenery_objects()
* *
* rct2: 0x006D247A * rct2: 0x006D247A
*/ */
void track_mirror_scenery(uint8** track_elements){ void track_mirror_scenery(rct_track_td6 *td6)
rct_track_scenery* scenery = (rct_track_scenery*)*track_elements; {
for (; (scenery->scenery_object.flags & 0xFF) != 0xFF; scenery++){ rct_td6_scenery_element *scenery = td6->scenery_elements;
for (; (scenery->scenery_object.flags & 0xFF) != 0xFF; scenery++) {
uint8 entry_type, entry_index; 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; entry_type = scenery->scenery_object.flags & 0xF;
if (entry_type != OBJECT_TYPE_PATHS) if (entry_type != OBJECT_TYPE_PATHS) {
continue; continue;
}
} }
rct_scenery_entry* scenery_entry = (rct_scenery_entry*)object_entry_groups[entry_type].chunks[entry_index]; rct_scenery_entry *scenery_entry = (rct_scenery_entry*)object_entry_groups[entry_type].chunks[entry_index];
switch (entry_type) {
switch (entry_type){
case OBJECT_TYPE_LARGE_SCENERY: case OBJECT_TYPE_LARGE_SCENERY:
{ {
sint16 x1 = 0, x2 = 0, y1 = 0, y2 = 0; sint16 x1 = 0, x2 = 0, y1 = 0, y2 = 0;
for (rct_large_scenery_tile* tile = scenery_entry->large_scenery.tiles; for (rct_large_scenery_tile* tile = scenery_entry->large_scenery.tiles; tile->x_offset != -1; tile++) {
tile->x_offset != -1; if (x1 > tile->x_offset) x1 = tile->x_offset;
tile++) if (x2 < tile->x_offset) x2 = tile->x_offset;
{ if (y1 > tile->y_offset) y1 = tile->y_offset;
if (x1 > tile->x_offset) if (y2 > tile->y_offset) y2 = tile->y_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: case 0:
scenery->y = (-(scenery->y * 32 + y1) - y2) / 32; scenery->y = (-(scenery->y * 32 + y1) - y2) / 32;
break; break;
@ -380,38 +380,39 @@ void track_mirror_scenery(uint8** track_elements){
case OBJECT_TYPE_SMALL_SCENERY: case OBJECT_TYPE_SMALL_SCENERY:
scenery->y = -scenery->y; 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); 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); scenery->flags ^= (1 << 2);
} }
break; break;
} }
if (scenery->flags & (1 << 0)) if (scenery->flags & (1 << 0)) {
scenery->flags ^= (1 << 1); scenery->flags ^= (1 << 1);
}
scenery->flags ^= (1 << 2); scenery->flags ^= (1 << 2);
break; break;
case OBJECT_TYPE_WALLS: case OBJECT_TYPE_WALLS:
scenery->y = -scenery->y; scenery->y = -scenery->y;
if (scenery->flags & (1 << 0)) if (scenery->flags & (1 << 0)) {
scenery->flags ^= (1 << 1); scenery->flags ^= (1 << 1);
}
break; break;
case OBJECT_TYPE_PATHS: case OBJECT_TYPE_PATHS:
scenery->y = -scenery->y; scenery->y = -scenery->y;
if (scenery->flags & (1 << 5)){ if (scenery->flags & (1 << 5)) {
scenery->flags ^= (1 << 6); scenery->flags ^= (1 << 6);
} }
uint8 flags = scenery->flags; 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 &= 0xF5;
scenery->flags |= flags; scenery->flags |= flags;
} }
} }
} }
@ -419,34 +420,34 @@ void track_mirror_scenery(uint8** track_elements){
* *
* rct2: 0x006D2443 * rct2: 0x006D2443
*/ */
void track_mirror_ride(uint8** track_elements){ void track_mirror_ride(rct_track_td6 *td6)
rct_track_element* track = (rct_track_element*)*track_elements; {
for (; track->type != 0xFF; track++){ rct_td6_track_element *track = td6->track_elements;
for (; track->type != 0xFF; track++) {
track->type = RCT2_ADDRESS(0x0099EA1C, uint8)[track->type]; track->type = RCT2_ADDRESS(0x0099EA1C, uint8)[track->type];
} }
*track_elements = (uint8*)track + 1;
rct_track_entrance* entrance = (rct_track_entrance*)*track_elements; rct_td6_entrance_element *entrance = td6->entrance_elements;
for (; entrance->z != -1; entrance++){ for (; entrance->z != -1; entrance++) {
entrance->y = -entrance->y; entrance->y = -entrance->y;
if (entrance->direction & 1){ if (entrance->direction & 1) {
entrance->direction ^= (1 << 1); entrance->direction ^= (1 << 1);
} }
} }
*track_elements = (uint8*)entrance + 1;
} }
/** /**
* *
* rct2: 0x006D25FA * rct2: 0x006D25FA
*/ */
void track_mirror_maze(uint8** track_elements){ void track_mirror_maze(rct_track_td6 *td6)
rct_maze_element* maze = (rct_maze_element*)*track_elements; {
for (; maze->all != 0; maze++){ rct_td6_maze_element *maze = td6->maze_elements;
for (; maze->all != 0; maze++) {
maze->y = -maze->y; maze->y = -maze->y;
if (maze->type == 0x8 || maze->type == 0x80){ if (maze->type == 0x8 || maze->type == 0x80) {
if (maze->unk_2 & 1){ if (maze->unk_2 & 1) {
maze->unk_2 ^= (1 << 1); maze->unk_2 ^= (1 << 1);
} }
continue; continue;
@ -454,29 +455,26 @@ void track_mirror_maze(uint8** track_elements){
uint16 maze_entry = maze->maze_entry; uint16 maze_entry = maze->maze_entry;
uint16 new_entry = 0; uint16 new_entry = 0;
for (uint8 position = bitscanforward(maze_entry); for (uint8 position = bitscanforward(maze_entry); position != 0xFF; position = bitscanforward(maze_entry)) {
position != 0xFF;
position = bitscanforward(maze_entry)){
maze_entry &= ~(1 << position); maze_entry &= ~(1 << position);
new_entry |= (1 << RCT2_ADDRESS(0x00993EDC, uint8)[position]); new_entry |= (1 << RCT2_ADDRESS(0x00993EDC, uint8)[position]);
} }
maze->maze_entry = new_entry; maze->maze_entry = new_entry;
} }
*track_elements = (uint8*)maze + 4;
} }
/** /**
* *
* rct2: 0x006D2436 * rct2: 0x006D2436
*/ */
void track_mirror() void track_mirror(rct_track_td6 *td6)
{ {
if (gActiveTrackDesign->type == RIDE_TYPE_MAZE) { if (td6->type == RIDE_TYPE_MAZE) {
track_mirror_maze(gActiveTrackDesign->elements); track_mirror_maze(td6);
} else { } 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) 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 * rct2: 0x006D0964
*/ */
int track_place_scenery(rct_track_scenery* scenery_start, uint8 rideIndex, int originX, int originY, int originZ){ int track_place_scenery(rct_td6_scenery_element *scenery_start, uint8 rideIndex, int originX, int originY, int originZ)
RCT2_GLOBAL(0x00F44050, rct_track_scenery*) = scenery_start; {
RCT2_GLOBAL(0x00F44050, rct_td6_scenery_element*) = scenery_start;
// mode // mode
RCT2_GLOBAL(0x00F44154, uint8) = 0; RCT2_GLOBAL(0x00F44154, uint8) = 0;
for (uint8 mode = 0; mode <= 1; mode++){ for (uint8 mode = 0; mode <= 1; mode++) {
if ((scenery_start->scenery_object.flags & 0xFF) != 0xFF) if ((scenery_start->scenery_object.flags & 0xFF) != 0xFF) {
RCT2_GLOBAL(0x00F4414E, uint8) |= 1 << 2; RCT2_GLOBAL(0x00F4414E, uint8) |= 1 << 2;
}
if (RCT2_GLOBAL(0x00F4414E, uint8) & (1 << 7)) if (RCT2_GLOBAL(0x00F4414E, uint8) & (1 << 7)) {
continue; 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; uint8 rotation = _currentTrackPieceDirection;
rct_xy8 tile = { .x = originX / 32, .y = originY / 32 }; rct_xy8 tile = { .x = originX / 32, .y = originY / 32 };
switch (rotation & 3){ switch (rotation & 3){
case MAP_ELEMENT_DIRECTION_WEST: 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 && if (RCT2_GLOBAL(0x00F440D4, uint8) == 6 && mode == 0) {
mode == 0){
uint8 entry_type, entry_index; 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; entry_type = scenery->scenery_object.flags & 0xF;
if (entry_type != OBJECT_TYPE_PATHS) if (entry_type != OBJECT_TYPE_PATHS) {
entry_type = 0xFF; entry_type = 0xFF;
if (gScreenFlags&SCREEN_FLAGS_TRACK_DESIGNER) }
if (gScreenFlags & SCREEN_FLAGS_TRACK_DESIGNER) {
entry_type = 0xFF; 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; entry_type = 0xFF;
}
} }
int z; int z;
switch (entry_type){ switch (entry_type) {
case OBJECT_TYPE_SMALL_SCENERY: case OBJECT_TYPE_SMALL_SCENERY:
//bl //bl
rotation += scenery->flags; rotation += scenery->flags;
@ -860,7 +862,7 @@ int track_place_scenery(rct_track_scenery* scenery_start, uint8 rideIndex, int o
return 1; 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){ if (RCT2_GLOBAL(0x00F440D4, uint8) == 0){
gMapSelectionTiles->x = -1; 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; 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++){ for (; maze->all != 0; maze++){
uint8 rotation = _currentTrackPieceDirection; uint8 rotation = _currentTrackPieceDirection & 3;
rct_xy16 mapCoord = { .x = maze->x * 32, .y = maze->y * 32 }; rct_xy16 mapCoord = { .x = maze->x * 32, .y = maze->y * 32 };
rotate_map_coordinates(&mapCoord.x, &mapCoord.y, rotation);
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;
}
mapCoord.x += x; mapCoord.x += x;
mapCoord.y += y; mapCoord.y += y;
track_update_max_min_coordinates(mapCoord.x, mapCoord.y, z); track_update_max_min_coordinates(mapCoord.x, mapCoord.y, z);
if (RCT2_GLOBAL(0x00F440D4, uint8) == 0){ if (RCT2_GLOBAL(0x00F440D4, uint8) == 0) {
uint8 new_tile = 1; track_add_selection_tile(mapCoord.x, mapCoord.y);
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) == 1 || if (RCT2_GLOBAL(0x00F440D4, uint8) == 1 ||
RCT2_GLOBAL(0x00F440D4, uint8) == 2 || RCT2_GLOBAL(0x00F440D4, uint8) == 2 ||
RCT2_GLOBAL(0x00F440D4, uint8) == 4 || RCT2_GLOBAL(0x00F440D4, uint8) == 4 ||
RCT2_GLOBAL(0x00F440D4, uint8) == 5){ RCT2_GLOBAL(0x00F440D4, uint8) == 5
) {
uint8 bl; uint8 bl;
money32 cost = 0; money32 cost = 0;
uint16 maze_entry; uint16 maze_entry;
switch (maze->type) {
switch (maze->type){
case 0x08: case 0x08:
// entrance // entrance
rotation += maze->unk_2; 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) == 4)bl = 0x69;
if (RCT2_GLOBAL(0x00F440D4, uint8) == 1){ 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); 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); 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){ 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 (RCT2_GLOBAL(0x00F440D4, uint8) == 3){
if (mapCoord.x > 0x1FFF) if (mapCoord.x < 0) continue;
continue; if (mapCoord.y < 0) continue;
if (mapCoord.y > 0x1FFF) if (mapCoord.x >= 256 * 32) continue;
continue; if (mapCoord.y >= 256 * 32) 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);
rct_map_element *map_element = map_get_surface_element_at(mapCoord.x / 32, mapCoord.y / 32);
sint16 map_height = map_element->base_height * 8; 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; map_height += 16;
if (map_element->properties.surface.slope & 0x10){ if (map_element->properties.surface.slope & 0x10) {
map_height += 16; 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; sint16 water_height = map_element->properties.surface.terrain & MAP_ELEMENT_WATER_HEIGHT_MASK;
water_height *= 16; water_height *= 16;
if (water_height > map_height) if (water_height > map_height) {
map_height = water_height; map_height = water_height;
}
} }
sint16 temp_z = z + RCT2_GLOBAL(0x00F440D5, sint16) - map_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; 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); game_do_command(0, 0x69, 0, rideIndex, GAME_COMMAND_DEMOLISH_RIDE, 0, 0);
} }
RCT2_GLOBAL(0x00F44142, sint16) = x; RCT2_GLOBAL(0x00F44142, sint16) = x;
RCT2_GLOBAL(0x00F44144, sint16) = y; RCT2_GLOBAL(0x00F44144, sint16) = y;
RCT2_GLOBAL(0x00F44146, sint16) = z; RCT2_GLOBAL(0x00F44146, sint16) = z;
*track_elements = (uint8*)maze + 4;
return 1; 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(0x00F44142, sint16) = x;
RCT2_GLOBAL(0x00F44144, sint16) = y; 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; RCT2_GLOBAL(0x00F440D5, uint32) = 0;
uint8 rotation = _currentTrackPieceDirection; 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++) { for (; track->type != 0xFF; track++) {
uint8 trackType = track->type; uint8 trackType = track->type;
if (trackType == TRACK_ELEM_INVERTED_90_DEG_UP_TO_FLAT_QUARTER_LOOP) { 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 // Entrance elements
//0x6D06D8 //0x6D06D8
*track_elements = (uint8*)track + 1; rct_td6_entrance_element *entrance = td6->entrance_elements;
rct_track_entrance* entrance = (rct_track_entrance*)(*track_elements); for (; entrance->z != -1; entrance++) {
for (; entrance->z != -1; entrance++){
rotation = _currentTrackPieceDirection & 3; rotation = _currentTrackPieceDirection & 3;
x = entrance->x; x = entrance->x;
y = entrance->y; 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); user_string_free(ride->name);
ride->type = RIDE_TYPE_NULL; ride->type = RIDE_TYPE_NULL;
} }
*track_elements = ((uint8*)(entrance)) + 1;
return 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(RCT2_ADDRESS_TRACK_PREVIEW_Z_MAX, sint16) = z;
RCT2_GLOBAL(0x00F44129, uint16) = 0; RCT2_GLOBAL(0x00F44129, uint16) = 0;
uint8* track_elements = td6->elements;
uint8 track_place_success = 0; 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 // Scenery elements
rct_track_scenery* scenery = (rct_track_scenery*)track_elements; rct_td6_scenery_element *scenery = td6->scenery_elements;
if (track_place_success) {
if (track_place_success){
if (!track_place_scenery( if (!track_place_scenery(
scenery, scenery,
rideIndex, 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){ if (RCT2_GLOBAL(0x00F440D4, uint8) == 0){
RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_FLAGS, uint16) |= 0x6; RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_FLAGS, uint16) |= 0x6;
RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_FLAGS, uint16) &= ~(1 << 3); RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_FLAGS, uint16) &= ~(1 << 3);
map_invalidate_map_selection_tiles(); map_invalidate_map_selection_tiles();
} }
if (bl == 3) if (bl == 3) {
return RCT2_GLOBAL(0x00F440D5, sint16); return RCT2_GLOBAL(0x00F440D5, sint16);
}
return RCT2_GLOBAL(0x00F440D5, money32); 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) void draw_track_preview(rct_track_td6 *td6, uint8** preview)
{ {
// Make a copy of the map // 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(); track_design_preview_clear_map();
if (gScreenFlags & SCREEN_FLAGS_TRACK_MANAGER){ if (gScreenFlags & SCREEN_FLAGS_TRACK_MANAGER) {
load_track_scenery_objects(); load_track_scenery_objects(td6);
} }
money32 cost; 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_track_td6 *td6 = gActiveTrackDesign;
rct_object_entry* ride_object = &track_design->vehicle_object; rct_object_entry *ride_object = &td6->vehicle_object;
uint8 entry_type, entry_index; uint8 entry_type, entry_index;
if (!find_object_in_entry_group(ride_object, &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, int _eax = 0,
_ebx = GAME_COMMAND_FLAG_APPLY, _ebx = GAME_COMMAND_FLAG_APPLY,
_ecx = 0, _ecx = 0,
_edx = track_design->type | (entry_index << 8), _edx = td6->type | (entry_index << 8),
_esi = GAME_COMMAND_CREATE_RIDE, _esi = GAME_COMMAND_CREATE_RIDE,
_edi = 0, _edi = 0,
_ebp = 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; money32 cost = 0;
if (!(flags & GAME_COMMAND_FLAG_APPLY)){ if (!(flags & GAME_COMMAND_FLAG_APPLY)){
RCT2_GLOBAL(0x00F44150, uint8) = 0; 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)){ if (RCT2_GLOBAL(0x00F4414E, uint8) & (1 << 1)){
RCT2_GLOBAL(0x00F44150, uint8) |= 1 << 7; 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{ 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 = PTD_OPERATION_2;
} }
bl |= RCT2_GLOBAL(0x00F44150, uint8); 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 || 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 | (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; 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); 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->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){ if (version >= 2){
ride->entrance_style = track_design->entrance_style; ride->entrance_style = td6->entrance_style;
} }
if (version >= 1){ if (version >= 1){
for (int i = 0; i < 4; ++i){ for (int i = 0; i < 4; ++i){
ride->track_colour_main[i] = track_design->track_spine_colour[i]; ride->track_colour_main[i] = td6->track_spine_colour[i];
ride->track_colour_additional[i] = track_design->track_rail_colour[i]; ride->track_colour_additional[i] = td6->track_rail_colour[i];
ride->track_colour_supports[i] = track_design->track_support_colour[i]; ride->track_colour_supports[i] = td6->track_support_colour[i];
} }
} }
else{ else{
for (int i = 0; i < 4; ++i){ for (int i = 0; i < 4; ++i){
ride->track_colour_main[i] = track_design->track_spine_colour_rct1; ride->track_colour_main[i] = td6->track_spine_colour_rct1;
ride->track_colour_additional[i] = track_design->track_rail_colour_rct1; ride->track_colour_additional[i] = td6->track_rail_colour_rct1;
ride->track_colour_supports[i] = track_design->track_support_colour_rct1; ride->track_colour_supports[i] = td6->track_support_colour_rct1;
} }
} }
for (int i = 0; i < 32; ++i){ for (int i = 0; i < 32; ++i){
ride->vehicle_colours[i].body_colour = track_design->vehicle_colours[i].body_colour; ride->vehicle_colours[i].body_colour = td6->vehicle_colours[i].body_colour;
ride->vehicle_colours[i].trim_colour = track_design->vehicle_colours[i].trim_colour; ride->vehicle_colours[i].trim_colour = td6->vehicle_colours[i].trim_colour;
ride->vehicle_colours_extended[i] = track_design->vehicle_additional_colour[i]; ride->vehicle_colours_extended[i] = td6->vehicle_additional_colour[i];
} }
ride_set_name(rideIndex, RCT2_ADDRESS(0x009E3504,const char)); ride_set_name(rideIndex, RCT2_ADDRESS(0x009E3504,const char));

View File

@ -8,6 +8,49 @@
#define TRACK_PREVIEW_IMAGE_SIZE (370 * 217) #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. * Track design structure.
* size: 0x4E72B * size: 0x4E72B
@ -74,6 +117,11 @@ typedef struct {
uint8 lift_hill_speed_num_circuits; // 0xA2 0bCCCL_LLLL uint8 lift_hill_speed_num_circuits; // 0xA2 0bCCCL_LLLL
void *elements; // 0xA3 (data starts here in file) void *elements; // 0xA3 (data starts here in file)
size_t elementsSize; 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; } rct_track_td6;
typedef struct{ typedef struct{

View File

@ -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; 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; *((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 // 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++; } while (!track_design_save_scenery_is_null(trackScenery)) { trackScenery++; }
if (trackScenery >= (rct_track_scenery*)0x9DE207) { if (trackScenery >= (rct_td6_scenery_element*)0x9DE207) {
return false; 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) 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++; } while (!track_design_save_scenery_is_null(item)) { item++; }
item->scenery_object = *entry; 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 removeIndex = -1;
int totalItems = 0; int totalItems = 0;
rct_track_scenery *items = (rct_track_scenery*)0x009DA193; rct_td6_scenery_element *items = (rct_td6_scenery_element*)0x009DA193;
rct_track_scenery *item = items; rct_td6_scenery_element *item = items;
for (; !track_design_save_scenery_is_null(item); item++, totalItems++) { for (; !track_design_save_scenery_is_null(item); item++, totalItems++) {
if (item->x != x / 32) continue; if (item->x != x / 32) continue;
if (item->y != y / 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 // Remove item and shift rest up one item
if (removeIndex < totalItems - 1) { 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]); 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 */ /* Based on rct2: 0x006D2897 */
static bool track_design_save_copy_scenery_to_track(uint8 **track_pointer) static bool track_design_save_copy_scenery_to_track(uint8 **track_pointer)
{ {
rct_track_scenery* track_scenery = (rct_track_scenery*)(*track_pointer - 1); rct_td6_scenery_element *track_scenery = (rct_td6_scenery_element*)(*track_pointer - 1);
rct_track_scenery* scenery_source = RCT2_ADDRESS(0x009DA193, rct_track_scenery); rct_td6_scenery_element* scenery_source = RCT2_ADDRESS(0x009DA193, rct_td6_scenery_element);
while (true) { 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; if ((track_scenery->scenery_object.flags & 0xFF) == 0xFF) break;
//0x00F4414D is direction of track? //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(0x00F44144, sint16) = startY;
RCT2_GLOBAL(0x00F44146, sint16) = mapElement->base_height * 8; 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 // x is defined here as we can start the search
// on tile start_x, start_y but then the next row // 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->y = (y - startY) / 32;
maze++; 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; gGameCommandErrorText = STR_TRACK_TOO_LARGE_OR_TOO_MUCH_SCENERY;
return false; 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(0x00F44144, sint16) = start_y;
RCT2_GLOBAL(0x00F44146, sint16) = start_z; 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{ do{
track->type = trackElement.element->properties.track.type; track->type = trackElement.element->properties.track.type;
if (track->type == 0xFF) { 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. // Mark the elements as finished.
*trackElements++ = 0xFF; *trackElements++ = 0xFF;
rct_track_entrance *entrance = (rct_track_entrance*)trackElements; rct_td6_entrance_element *entrance = (rct_td6_entrance_element*)trackElements;
// First entrances, second exits // First entrances, second exits
for (int i = 0; i < 2; i++) { for (int i = 0; i < 2; i++) {

View File

@ -621,7 +621,6 @@ static bool track_list_load_design_for_preview(utf8 *path)
if (track_design_open(&_loadedTrackDesign, path)) { if (track_design_open(&_loadedTrackDesign, path)) {
// Load in a new preview image, calculate cost variable, calculate var_06 // Load in a new preview image, calculate cost variable, calculate var_06
gActiveTrackDesign = &_loadedTrackDesign;
draw_track_preview(&_loadedTrackDesign, (uint8**)_loadedTrackDesignPreview); draw_track_preview(&_loadedTrackDesign, (uint8**)_loadedTrackDesignPreview);
_loadedTrackDesign.cost = gTrackDesignCost; _loadedTrackDesign.cost = gTrackDesignCost;

View File

@ -105,14 +105,19 @@ static sint16 _window_track_place_last_valid_y;
static sint16 _window_track_place_last_valid_z; static sint16 _window_track_place_last_valid_z;
static money32 _window_track_place_last_cost; static money32 _window_track_place_last_cost;
static rct_track_td6 *_trackDesign;
static void window_track_place_clear_provisional(); static void window_track_place_clear_provisional();
static int window_track_place_get_base_z(int x, int y); 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_clear_mini_preview();
static void window_track_place_draw_mini_preview(); static void window_track_place_draw_mini_preview(rct_track_td6 *td6);
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);
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);
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(); window_close_construction_windows();
gActiveTrackDesign = malloc(sizeof(rct_track_td6)); _trackDesign = malloc(sizeof(rct_track_td6));
if (!track_design_open(gActiveTrackDesign, tdPath)) { if (!track_design_open(_trackDesign, tdPath)) {
SafeFree(gActiveTrackDesign); SafeFree(_trackDesign);
return; return;
} }
@ -163,7 +168,7 @@ void window_track_place_open(utf8 *tdPath)
_window_track_place_last_cost = MONEY32_UNDEFINED; _window_track_place_last_cost = MONEY32_UNDEFINED;
_window_track_place_last_x = 0xFFFF; _window_track_place_last_x = 0xFFFF;
_currentTrackPieceDirection = (2 - get_current_rotation()) & 3; _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; RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_FLAGS, uint16) &= ~6;
hide_gridlines(); hide_gridlines();
SafeFree(_window_track_place_mini_preview); 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; _currentTrackPieceDirection = (_currentTrackPieceDirection + 1) & 3;
window_invalidate(w); window_invalidate(w);
_window_track_place_last_x = 0xFFFF; _window_track_place_last_x = 0xFFFF;
window_track_place_draw_mini_preview(); window_track_place_draw_mini_preview(_trackDesign);
break; break;
case WIDX_MIRROR: case WIDX_MIRROR:
track_mirror(); track_mirror();
_currentTrackPieceDirection = (0 - _currentTrackPieceDirection) & 3; _currentTrackPieceDirection = (0 - _currentTrackPieceDirection) & 3;
window_invalidate(w); window_invalidate(w);
_window_track_place_last_x = 0xFFFF; _window_track_place_last_x = 0xFFFF;
window_track_place_draw_mini_preview(); window_track_place_draw_mini_preview(_trackDesign);
break; break;
case WIDX_SELECT_DIFFERENT_DESIGN: case WIDX_SELECT_DIFFERENT_DESIGN:
window_close(w); 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 // Check if tool map position has changed since last update
if (mapX == _window_track_place_last_x && mapY == _window_track_place_last_y) { 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; 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 // Try increasing Z until a feasible placement is found
for (i = 0; i < 7; i++) { 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) { if (cost != MONEY32_UNDEFINED) {
RCT2_GLOBAL(0x00F440EB, uint16) = rideIndex; RCT2_GLOBAL(0x00F440EB, uint16) = rideIndex;
_window_track_place_last_valid_x = mapX; _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); 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); mapZ = window_track_place_get_base_z(mapX, mapY);
for (i = 0; i < 7; i++) { for (i = 0; i < 7; i++) {
RCT2_GLOBAL(0x009A8C29, uint8) |= 1; 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; RCT2_GLOBAL(0x009A8C29, uint8) &= ~1;
if (cost != MONEY32_UNDEFINED) { 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) 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) 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) { if (_window_track_place_last_was_valid) {
sub_6D01B3( sub_6D01B3(
gActiveTrackDesign, _trackDesign,
PTD_OPERATION_CLEAR_OUTLINES, PTD_OPERATION_CLEAR_OUTLINES,
RCT2_GLOBAL(0x00F440EB, uint8), RCT2_GLOBAL(0x00F440EB, uint8),
_window_track_place_last_valid_x, _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) if (mapElement->properties.surface.terrain & 0x1F)
z = max(z, (mapElement->properties.surface.terrain & 0x1F) << 4); 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; int eax, ebx, ecx, edx, esi, edi, ebp;
money32 result; money32 result;
@ -415,7 +420,10 @@ static void window_track_place_attempt_placement(int x, int y, int z, int bl, mo
ebx = bl; ebx = bl;
ecx = y; ecx = y;
edi = z; edi = z;
gActiveTrackDesign = _trackDesign;
result = game_do_command_p(GAME_COMMAND_PLACE_TRACK_DESIGN, &eax, &ebx, &ecx, &edx, &esi, &edi, &ebp); 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 (cost != NULL) *cost = result;
if (rideIndex != NULL) *rideIndex = edi & 0xFF; if (rideIndex != NULL) *rideIndex = edi & 0xFF;
@ -454,12 +462,10 @@ static void window_track_place_paint(rct_window *w, rct_drawpixelinfo *dpi)
* *
* rct2: 0x006D1845 * 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(); 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 // 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 min = { 0, 0 };
rct_xy16 max = { 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; origin.y -= ((max.y + min.y) >> 6) << 5;
} }
if (isMaze) { if (td6->type == RIDE_TYPE_MAZE) {
window_track_place_draw_mini_preview_maze(pass, origin, &min, &max); window_track_place_draw_mini_preview_maze(td6, pass, origin, &min, &max);
} else { } 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(); uint8 rotation = (_currentTrackPieceDirection + get_current_rotation()) & 3;
rct_track_element *trackElement = (rct_track_element*)gActiveTrackDesign->elements; rct_td6_track_element *trackElement = td6->track_elements;
while (trackElement->type != 255) { while (trackElement->type != 255) {
int trackType = trackElement->type; int trackType = trackElement->type;
if (trackType == TRACK_ELEM_INVERTED_90_DEG_UP_TO_FLAT_QUARTER_LOOP) { if (trackType == TRACK_ELEM_INVERTED_90_DEG_UP_TO_FLAT_QUARTER_LOOP) {
trackType = 255; 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 // Follow a single track piece shape
const rct_preview_track *trackBlock = TrackBlocks[trackType]; const rct_preview_track *trackBlock = TrackBlocks[trackType];
while (trackBlock->index != 255) { 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); min->y = min(min->y, y);
max->y = max(max->y, y); max->y = max(max->y, y);
} else { } else {
int pixelX = 80 + ((y / 32) - (x / 32)) * 4; rct_xy16 pixelPosition = draw_mini_preview_get_pixel_position(x, y);
int pixelY = 38 + ((y / 32) + (x / 32)) * 2; if (draw_mini_preview_is_pixel_in_bounds(pixelPosition)) {
if (pixelX >= 0 && pixelY >= 0 && pixelX <= 160 && pixelY <= 75) { uint8 *pixel = draw_mini_preview_get_pixel_ptr(pixelPosition);
uint8 *pixel = &_window_track_place_mini_preview[pixelY * TRACK_MINI_PREVIEW_WIDTH + pixelX];
uint8 bits = trackBlock->var_08 << (rotation & 3); uint8 bits = trackBlock->var_08 << (rotation & 3);
bits = (bits & 0x0F) | ((bits & 0xF0) >> 4); 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++) { for (int i = 0; i < 4; i++) {
if (bits & 1) pixel[338 + i] = colour; if (bits & 1) pixel[338 + i] = colour;
if (bits & 2) pixel[168 + 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); 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 += track_coordinate->rotation_end - track_coordinate->rotation_begin;
rotation &= 3; rotation &= 3;
if (track_coordinate->rotation_end & 4) if (track_coordinate->rotation_end & 4) {
rotation |= 4; rotation |= 4;
}
if (!(rotation & 4)) { if (!(rotation & 4)) {
origin.x += TileDirectionDelta[rotation].x; origin.x += TileDirectionDelta[rotation].x;
origin.y += TileDirectionDelta[rotation].y; 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; uint8 rotation = (_currentTrackPieceDirection + get_current_rotation()) & 3;
rct_maze_element *mazeElement = gActiveTrackDesign->elements; rct_td6_maze_element *mazeElement = td6->maze_elements;
while (mazeElement->all != 0) { while (mazeElement->all != 0) {
sint16 x = mazeElement->x * 32; sint16 x = mazeElement->x * 32;
sint16 y = mazeElement->y * 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; x += origin.x;
y += origin.y; y += origin.y;
// Entrance or exit is a lighter colour
uint8 colour = mazeElement->type == 8 || mazeElement->type == 128 ? 222 : 218;
if (pass == 0) { if (pass == 0) {
min->x = min(min->x, x); min->x = min(min->x, x);
max->x = max(max->x, x); max->x = max(max->x, x);
min->y = min(min->y, y); min->y = min(min->y, y);
max->y = max(max->y, y); max->y = max(max->y, y);
} else { } else {
int pixelX = 80 + ((y / 32) - (x / 32)) * 4; rct_xy16 pixelPosition = draw_mini_preview_get_pixel_position(x, y);
int pixelY = 38 + ((y / 32) + (x / 32)) * 2; if (draw_mini_preview_is_pixel_in_bounds(pixelPosition)) {
if (pixelX <= 160 && pixelY <= 75) { uint8 *pixel = draw_mini_preview_get_pixel_ptr(pixelPosition);
uint8 *pixel = &_window_track_place_mini_preview[pixelY * TRACK_MINI_PREVIEW_WIDTH + pixelX];
// Entrance or exit is a lighter colour
uint8 colour = mazeElement->type == 8 || mazeElement->type == 128 ? 222 : 218;
for (int i = 0; i < 4; i++) { for (int i = 0; i < 4; i++) {
pixel[338 + i] = colour; pixel[338 + i] = colour;
pixel[168 + 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++; 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];
}