From 9cf2783785fdaf45c290d43efe65a69958a84f33 Mon Sep 17 00:00:00 2001 From: "U-ASUS-EEEPC\\Cameron Hall" Date: Thu, 12 Nov 2015 17:02:04 -0600 Subject: [PATCH 01/10] Initial work. Decompiled up to 0x663BE4 --- src/localisation/string_ids.h | 1 + src/world/map.c | 514 +++++++++++++++++++++++++++++++++- 2 files changed, 513 insertions(+), 2 deletions(-) diff --git a/src/localisation/string_ids.h b/src/localisation/string_ids.h index 1091f29339..383727d327 100644 --- a/src/localisation/string_ids.h +++ b/src/localisation/string_ids.h @@ -497,6 +497,7 @@ enum { STR_QUEUE_TIME_MINUTES = 1360, STR_TOO_HIGH_FOR_SUPPORTS = 1363, + STR_SUPPORTS_CANT_BE_EXTENDED = 1364, STR_IN_LINE_TWIST_LEFT = 1365, STR_IN_LINE_TWIST_RIGHT = 1366, diff --git a/src/world/map.c b/src/world/map.c index e909630b87..efe8b61c02 100644 --- a/src/world/map.c +++ b/src/world/map.c @@ -1667,6 +1667,265 @@ const uint8 map_element_lower_styles[5][32] = { { 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x0B, 0x00, 0x0D, 0x0E, 0x00 }, }; +//Hack: pushes variables to the stack before jumping to address +//These functions are temporary and are used for debugging the decompiled code. +static int callcode_push3(int address, int stackvar1, int stackvar2, int stackvar3, int *_eax, int *_ebx, int *_ecx, int *_edx, int *_esi, int *_edi, int *_ebp) +{ + int result; + + __asm__ ( "\ + \n\ + /* Store C's base pointer*/ \n\ + push %%ebp \n\ + push %%ebx \n\ + \n\ + /* Store %[address] to call*/ \n\ + push %[address] \n\ + \n\ + /* Set all registers to the input values*/ \n\ + mov %[_eax], %%eax \n\ + mov (%%eax), %%eax \n\ + mov %[_ebx], %%ebx \n\ + mov (%%ebx), %%ebx \n\ + mov %[_ecx], %%ecx \n\ + mov (%%ecx), %%ecx \n\ + mov %[_edx], %%edx \n\ + mov (%%edx), %%edx \n\ + mov %[_esi], %%esi \n\ + mov (%%esi), %%esi \n\ + mov %[_edi], %%edi \n\ + mov (%%edi), %%edi \n\ + push $_foo \n\ + push %[stackvar1] \n\ + push %[stackvar2] \n\ + push %[stackvar3] \n\ + mov %[_ebp], %%ebp \n\ + mov (%%ebp), %%ebp \n\ + \n\ + /* Call function*/ \n\ + /* Push registers required by function */ \n\ + /* call *(%%esp) */ \n\ + jmp *16(%%esp) \n\ + _foo: \n\ + \n\ + /* Store output eax */ \n\ + push %%eax \n\ + push %%ebp \n\ + push %%ebx \n\ + mov 20(%%esp), %%ebp \n\ + mov 16(%%esp), %%ebx \n\ + /* Get resulting ecx, edx, esi, edi registers*/ \n\ + mov %[_edi], %%eax \n\ + mov %%edi, (%%eax) \n\ + mov %[_esi], %%eax \n\ + mov %%esi, (%%eax) \n\ + mov %[_edx], %%eax \n\ + mov %%edx, (%%eax) \n\ + mov %[_ecx], %%eax \n\ + mov %%ecx, (%%eax) \n\ + /* Pop ebx reg into ecx*/ \n\ + pop %%ecx \n\ + mov %[_ebx], %%eax \n\ + mov %%ecx, (%%eax) \n\ + \n\ + /* Pop ebp reg into ecx */\n\ + pop %%ecx \n\ + mov %[_ebp], %%eax \n\ + mov %%ecx, (%%eax) \n\ + \n\ + pop %%eax \n\ + /* Get resulting eax register*/ \n\ + mov %[_eax], %%ecx \n\ + mov %%eax, (%%ecx) \n\ + \n\ + /* Save flags as return in eax*/ \n\ + lahf \n\ + /* Pop address*/ \n\ + pop %%ebp \n\ + \n\ + pop %%ebx \n\ + pop %%ebp \n\ + /* Load result with flags */ \n\ + mov %%eax, %[result] \n\ + " : [address] "+m" (address), [_eax] "+m" (_eax), [_ebx] "+m" (_ebx), [_ecx] "+m" (_ecx), [_edx] "+m" (_edx), [_esi] "+m" (_esi), [_edi] "+m" (_edi), [_ebp] "+m" (_ebp), [result] "+m" (result) + + : [stackvar1] "m" (stackvar1), [stackvar2] "m" (stackvar2), [stackvar3] "m" (stackvar3) + : "eax","ecx","edx","esi","edi" + ); + return result&0xFF00; +} + +static int callcode_push2(int address, int stackvar1, int stackvar2, int *_eax, int *_ebx, int *_ecx, int *_edx, int *_esi, int *_edi, int *_ebp) +{ + int result; + + __asm__ ( "\ + \n\ + /* Store C's base pointer*/ \n\ + push %%ebp \n\ + push %%ebx \n\ + \n\ + /* Store %[address] to call*/ \n\ + push %[address] \n\ + \n\ + /* Set all registers to the input values*/ \n\ + mov %[_eax], %%eax \n\ + mov (%%eax), %%eax \n\ + mov %[_ebx], %%ebx \n\ + mov (%%ebx), %%ebx \n\ + mov %[_ecx], %%ecx \n\ + mov (%%ecx), %%ecx \n\ + mov %[_edx], %%edx \n\ + mov (%%edx), %%edx \n\ + mov %[_esi], %%esi \n\ + mov (%%esi), %%esi \n\ + mov %[_edi], %%edi \n\ + mov (%%edi), %%edi \n\ + push $foo \n\ + push %[stackvar1] \n\ + push %[stackvar2] \n\ + mov %[_ebp], %%ebp \n\ + mov (%%ebp), %%ebp \n\ + \n\ + /* Call function*/ \n\ + /* Push registers required by function */ \n\ + /* call *(%%esp) */ \n\ + jmp *12(%%esp) \n\ + foo: \n\ + \n\ + /* Store output eax */ \n\ + push %%eax \n\ + push %%ebp \n\ + push %%ebx \n\ + mov 20(%%esp), %%ebp \n\ + mov 16(%%esp), %%ebx \n\ + /* Get resulting ecx, edx, esi, edi registers*/ \n\ + mov %[_edi], %%eax \n\ + mov %%edi, (%%eax) \n\ + mov %[_esi], %%eax \n\ + mov %%esi, (%%eax) \n\ + mov %[_edx], %%eax \n\ + mov %%edx, (%%eax) \n\ + mov %[_ecx], %%eax \n\ + mov %%ecx, (%%eax) \n\ + /* Pop ebx reg into ecx*/ \n\ + pop %%ecx \n\ + mov %[_ebx], %%eax \n\ + mov %%ecx, (%%eax) \n\ + \n\ + /* Pop ebp reg into ecx */\n\ + pop %%ecx \n\ + mov %[_ebp], %%eax \n\ + mov %%ecx, (%%eax) \n\ + \n\ + pop %%eax \n\ + /* Get resulting eax register*/ \n\ + mov %[_eax], %%ecx \n\ + mov %%eax, (%%ecx) \n\ + \n\ + /* Save flags as return in eax*/ \n\ + lahf \n\ + /* Pop address*/ \n\ + pop %%ebp \n\ + \n\ + pop %%ebx \n\ + pop %%ebp \n\ + /* Load result with flags */ \n\ + mov %%eax, %[result] \n\ + " : [address] "+m" (address), [_eax] "+m" (_eax), [_ebx] "+m" (_ebx), [_ecx] "+m" (_ecx), [_edx] "+m" (_edx), [_esi] "+m" (_esi), [_edi] "+m" (_edi), [_ebp] "+m" (_ebp), [result] "+m" (result) + + : [stackvar1] "m" (stackvar1), [stackvar2] "m" (stackvar2) + : "eax","ecx","edx","esi","edi" + ); + return result&0xFF00; +} + +static int callcode_push1(int address, int stackvar, int *_eax, int *_ebx, int *_ecx, int *_edx, int *_esi, int *_edi, int *_ebp) +{ + int result; + + __asm__ ( "\ + \n\ + /* Store C's base pointer*/ \n\ + push %%ebp \n\ + push %%ebx \n\ + \n\ + /* Store %[address] to call*/ \n\ + push %[address] \n\ + \n\ + /* Set all registers to the input values*/ \n\ + mov %[_eax], %%eax \n\ + mov (%%eax), %%eax \n\ + mov %[_ebx], %%ebx \n\ + mov (%%ebx), %%ebx \n\ + mov %[_ecx], %%ecx \n\ + mov (%%ecx), %%ecx \n\ + mov %[_edx], %%edx \n\ + mov (%%edx), %%edx \n\ + mov %[_esi], %%esi \n\ + mov (%%esi), %%esi \n\ + mov %[_edi], %%edi \n\ + mov (%%edi), %%edi \n\ + /* Hack: called code should return back to this function */ \n\ + push $__foo \n\ + /* Push variable */\n\ + push %[stackvar] \n\ + mov %[_ebp], %%ebp \n\ + mov (%%ebp), %%ebp \n\ + \n\ + /* Call function*/ \n\ + /* call *(%%esp) */ \n\ + /* int $3 */\n\ + jmp *8(%%esp) \n\ + __foo: \n\ + \n\ + /* Store output eax */ \n\ + push %%eax \n\ + push %%ebp \n\ + push %%ebx \n\ + mov 20(%%esp), %%ebp \n\ + mov 16(%%esp), %%ebx \n\ + /* Get resulting ecx, edx, esi, edi registers*/ \n\ + mov %[_edi], %%eax \n\ + mov %%edi, (%%eax) \n\ + mov %[_esi], %%eax \n\ + mov %%esi, (%%eax) \n\ + mov %[_edx], %%eax \n\ + mov %%edx, (%%eax) \n\ + mov %[_ecx], %%eax \n\ + mov %%ecx, (%%eax) \n\ + /* Pop ebx reg into ecx*/ \n\ + pop %%ecx \n\ + mov %[_ebx], %%eax \n\ + mov %%ecx, (%%eax) \n\ + \n\ + /* Pop ebp reg into ecx */\n\ + pop %%ecx \n\ + mov %[_ebp], %%eax \n\ + mov %%ecx, (%%eax) \n\ + \n\ + pop %%eax \n\ + /* Get resulting eax register*/ \n\ + mov %[_eax], %%ecx \n\ + mov %%eax, (%%ecx) \n\ + \n\ + /* Save flags as return in eax*/ \n\ + lahf \n\ + /* Pop address*/ \n\ + pop %%ebp \n\ + \n\ + pop %%ebx \n\ + pop %%ebp \n\ + /* Load result with flags */ \n\ + mov %%eax, %[result] \n\ + " : [address] "+m" (address), [_eax] "+m" (_eax), [_ebx] "+m" (_ebx), [_ecx] "+m" (_ecx), [_edx] "+m" (_edx), [_esi] "+m" (_esi), [_edi] "+m" (_edi), [_ebp] "+m" (_ebp), [result] "+m" (result) + + : [stackvar] "m" (stackvar) + : "eax","ecx","edx","esi","edi" + ); + return result&0xFF00; +} + static money32 map_set_land_height(int flags, int x, int y, int height, int style, int selectionType) { if (RCT2_GLOBAL(RCT2_ADDRESS_GAME_PAUSED, uint8) != 0 && !gConfigCheat.build_in_pause_mode) { @@ -1709,10 +1968,261 @@ static money32 map_set_land_height(int flags, int x, int y, int height, int styl return MONEY32_UNDEFINED; } } + + /* Continuing dissassembly - work in progress + * Known bugs: + * Raising the corner of a piece of land doesn't remove walls. + * Small scenery elements (ones that take up 1/4 of a tile) are not removed when changing land height. + * Original bugs: + * Lowering the land tile underneath a wall removes the wall. + * Land can be raised over flat scenery items (gardens, for example) without removing them. + */ + + int eax = x, ebx = flags, ecx = y, edi = selectionType << 5, ebp = 0; + uint32 edx = (style << 8) | height; + uint32 esi = 0; + + //Uncomment to use vanilla code + //RCT2_CALLFUNC_X(0x006639FE, &eax, &ebx, &ecx, (int *)&edx, (int *)&esi, &edi, &ebp); return ebx; + + RCT2_GLOBAL(0x9E2E18, uint32) = 0; + if(ebx&GAME_COMMAND_FLAG_APPLY) + { + footpath_remove_litter(eax, ebx, map_element_height(eax, ecx)); + //Hmmm... I have a bug in here where raising the corner of a tile doesn't remove walls on it. + map_remove_walls_at(eax, ecx, edx*8-16, edx*8+32); + } + + RCT2_GLOBAL(0x9E2E18, uint32) += 0xC8; + + //RCT2_CALLFUNC_X(0x663A3A, &eax, &ebx, &ecx, (int *)&edx, (int *)&esi, &edi, &ebp); return ebx; + + int saved_eax = eax; + int saved_ecx = ecx; + unsigned int saved_edx = edx; + + /* + esi = ecx&0xFFFF; //movzx esi, cx + esi <<= 8; + esi |= eax; + esi >>= 3; + esi = RCT2_ADDRESS(RCT2_ADDRESS_TILE_MAP_ELEMENT_POINTERS, uint32)[(int)esi/4]; + */ + esi = (int)map_get_first_element_at(eax/32, ecx/32); + + uint8 *pdl = (uint8 *)&edx; + uint8 *pdh = (uint8 *)&edx+1; + uint8 *pbl = (uint8 *)&ebx; + uint8 *pbh = (uint8 *)&ebx+1; + + *pdh = *pdl; + *pdh += 4; + +loc_663A54: + eax = map_element_get_type((rct_map_element *)esi); + if(eax!=MAP_ELEMENT_TYPE_SCENERY) + goto loc_663AA3; + if(*pdl>((rct_map_element *)esi)->clearance_height) + goto loc_663AA3; + if(*pdh<((rct_map_element *)esi)->base_height) + goto loc_663AA3; + eax = ((rct_map_element *)esi)->properties.scenery.type; + eax = RCT2_ADDRESS(RCT2_ADDRESS_SMALL_SCENERY_ENTRIES, uint32)[eax]; + if(((rct_scenery_entry *)eax)->small_scenery.height>0x40) //cmp byte ptr [eax+0Ah], 40h; jbe short loc_663A87 + { + if(RCT2_GLOBAL(RCT2_ADDRESS_PARK_FLAGS, uint32)&PARK_FLAGS_FORBID_TREE_REMOVAL) + { + //rct2: 0x663C45 + map_obstruction_set_error_text((rct_map_element *)esi); + return MONEY32_UNDEFINED; + } + } + //rct2: 0x663A87 + //callcode_push3(0x663A87, saved_eax, saved_ecx, saved_edx, &eax, &ebx, &ecx, (int *)&edx, (int *)&esi, &edi, &ebp); return ebx; + ecx = ((rct_scenery_entry *)eax)->small_scenery.removal_price*10; + RCT2_GLOBAL(0x9E2E18, uint32) += ecx; + //rct2: 0x663A94 + if((ebx&GAME_COMMAND_FLAG_APPLY)) + { + map_element_remove((rct_map_element *)esi); + esi = esi-8; + } +loc_663AA3: + esi = esi+8; + if(!((*(uint8 *)esi-7)&MAP_ELEMENT_FLAG_LAST_TILE)) + goto loc_663A54; + edx = saved_edx; + ecx = saved_ecx; + eax = saved_eax; + saved_eax = eax; + int saved_ebx = ebx; + saved_ecx = ecx; + + //callcode_push3(0x663AB2, saved_eax, saved_ebx, saved_ecx, &eax, &ebx, &ecx, (int *)&edx, (int *)&esi, &edi, &ebp); return ebx; + + /* + esi = ecx&0xFFFF; //movzx esi, cx + esi <<= 8; + esi |= eax&0xFFFF; //or si, ax + esi >>= 3; + esi = RCT2_ADDRESS(RCT2_ADDRESS_TILE_MAP_ELEMENT_POINTERS, uint32)[esi/4]; + */ + esi = (int)map_get_first_element_at(eax/32, ecx/32); + //callcode_push3(0x663AC4, saved_eax, saved_ebx, saved_ecx, &eax, &ebx, &ecx, (int *)&edx, (int *)&esi, &edi, &ebp); return ebx; + +loc_663AC4: + eax = ((rct_map_element *)esi)->type; + eax &= 0x3C; + if(eax==8) + { + ebp = ((rct_map_element *)esi)->properties.track.ride_index; //not sure what union member we need here. [esi+7] + ebp *= 0x260; + eax = RCT2_ADDRESS(RCT2_ADDRESS_RIDE_LIST, rct_ride)[ebp/0x260].subtype; + eax = RCT2_ADDRESS(RCT2_ADDRESS_RIDE_ENTRIES, uint32)[eax]; + + eax = ((rct_ride_type *)eax)->max_height; + if(eax==0) + { + eax = RCT2_ADDRESS(RCT2_ADDRESS_RIDE_LIST, rct_ride)[ebp/0x260].type; + eax = RCT2_GLOBAL(0x97D218+eax*8, uint8); + } + //rct2: 0x663AFC + ebx = ((rct_map_element *)esi)->clearance_height; + ebx -= *pdl; + if(ebx>=0) + { + ebx >>= 1; + if(ebx>eax) + { + //rct2: 0x663B09 + RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_TEXT, rct_string_id) = STR_SUPPORTS_CANT_BE_EXTENDED; + return MONEY32_UNDEFINED; + } + } + } +loc_663B1A: + esi += 8; + if(!((*(uint8 *)esi-7)&MAP_ELEMENT_FLAG_LAST_TILE)) + goto loc_663AC4; + + ecx = saved_ecx; + ebx = saved_ebx; + eax = saved_eax; + saved_ecx = ecx; + + //callcode_push1(0x663B27, saved_ecx, &eax, &ebx, &ecx, (int *)&edx, (int *)&esi, &edi, &ebp); return ebx; + + esi = ecx&0xFFFF; + esi <<= 8; + esi |= eax&0xFFFF; + esi >>= 3; + esi = RCT2_ADDRESS(RCT2_ADDRESS_TILE_MAP_ELEMENT_POINTERS, uint32)[esi/4]; + + //callcode_push1(0x663B39, saved_ecx, &eax, &ebx, &ecx, (int *)&edx, (int *)&esi, &edi, &ebp); return ebx; + + while((((rct_map_element *)esi)->type&0x3C)) + esi += 8; + if(!((rct_map_element *)esi)->type&0x40) + goto loc_663B72; + ecx = *((uint8 *)esi+5); //Don't know which union member to use yet. + ecx &= 0x1F; + if(ecx==0) + goto loc_663B72; + ecx <<= 1; + ecx -= 2; + *pbh = *pdl; + if((*pdh&0x1F)) + { + *pbh += 2; + if((*pdh&0x10)) + { + *pbh += 2; + } + } +loc_663B6A: + if(*pbh>ecx) + { + //rct2: 0x663C5A + ecx = saved_ecx; + esi += 8; + map_obstruction_set_error_text((rct_map_element *)esi); + return MONEY32_UNDEFINED; + } +loc_663B72: + ecx = saved_ecx; + + //RCT2_CALLFUNC_X(0x663B73, &eax, &ebx, &ecx, (int *)&edx, (int *)&esi, &edi, &ebp); return ebx; - int eax = x, ebx = flags, ecx = y, edx = (style << 8) | height, esi = 0, edi = selectionType << 5, ebp = 0; - RCT2_CALLFUNC_X(0x006639FE, &eax, &ebx, &ecx, &edx, &esi, &edi, &ebp); + *pbh = *pdl; + if((*pdh&0xF)) + { + *pbh += 2; + if((*pdh&0x10)) + { + *pbh += 2; + } + } +loc_663B85: + saved_ebx = ebx; + saved_edx = edx; + int saved_ebp = ebp; + + //callcode_push3(0x663B88, saved_ebx, saved_edx, saved_ebp, &eax, &ebx, &ecx, (int *)&edx, (int *)&esi, &edi, &ebp); return ebx; + + *pbl = *pdh; + *pdh = *pbh; + *pbl = 0xF; + ebp = (int)RCT2_ADDRESS(0x663CB9, void); + if(map_can_construct_with_clear_at(eax&0xFFFF, ecx&0xFFFF, *pdl, *pdh, (void *)ebp, *pbl)==false) + return MONEY32_UNDEFINED; + ebp = saved_ebp; + edx = saved_edx; + ebx = saved_ebx; + saved_eax = eax; + saved_ecx = ecx; + + //callcode_push2(0x663BA3, saved_eax, saved_ecx, &eax, &ebx, &ecx, (int *)&edx, (int *)&esi, &edi, &ebp); return ebx; + + edi = ecx&0xFFFF; + edi <<= 8; + edi = (edi|eax)&0xFFFF; + edi >>= 3; + edi = (uint32)RCT2_ADDRESS(RCT2_ADDRESS_TILE_MAP_ELEMENT_POINTERS, rct_map_element *)[edi/4]; +loc_663BB5: + //callcode_push2(0x663BB5, saved_eax, saved_ecx, &eax, &ebx, &ecx, (int *)&edx, (int *)&esi, &edi, &ebp); return ebx; + eax = ((rct_map_element *)edi)->type; + eax &= 0x3C; + if(eax==0x14) + goto loc_663BD9; + if(eax==0xC) + goto loc_663BD9; + if(((rct_map_element *)edi)->flags&0x10) + goto loc_663BD9; + if(edi==esi) + goto loc_663BD9; + if(edi>esi) + goto loc_663BD4; + if(*pdl<((rct_map_element *)edi)->clearance_height) + goto loc_663C4F; + goto loc_663BD9; +loc_663BD4: + if(*pbh>((rct_map_element *)edi)->base_height) + goto loc_663C4F; +loc_663BD9: + edi += 8; + if(!(*((uint8 *)edi-7)&MAP_ELEMENT_FLAG_LAST_TILE)) + goto loc_663BB5; + ecx = saved_ecx; + eax = saved_eax; + + //To be continued... + RCT2_CALLFUNC_X(0x663BE4, &eax, &ebx, &ecx, (int *)&edx, (int *)&esi, &edi, &ebp); return ebx; + +loc_663C4F: + esi = edi; + map_obstruction_set_error_text((rct_map_element *)esi); + return MONEY32_UNDEFINED; } void game_command_set_land_height(int *eax, int *ebx, int *ecx, int *edx, int *esi, int *edi, int *ebp) From 0757b0978114e2643d04348d6f1b4b53ec56469d Mon Sep 17 00:00:00 2001 From: "U-HP-Pavilion-PC\\Cameron" Date: Thu, 12 Nov 2015 22:47:36 -0600 Subject: [PATCH 02/10] refactor --- src/world/map.c | 107 ++++++++++++++++++++++++------------------------ 1 file changed, 53 insertions(+), 54 deletions(-) diff --git a/src/world/map.c b/src/world/map.c index efe8b61c02..332a1dd727 100644 --- a/src/world/map.c +++ b/src/world/map.c @@ -1669,6 +1669,7 @@ const uint8 map_element_lower_styles[5][32] = { //Hack: pushes variables to the stack before jumping to address //These functions are temporary and are used for debugging the decompiled code. +#ifdef __GNUC__ static int callcode_push3(int address, int stackvar1, int stackvar2, int stackvar3, int *_eax, int *_ebx, int *_ecx, int *_edx, int *_esi, int *_edi, int *_ebp) { int result; @@ -1925,6 +1926,7 @@ static int callcode_push1(int address, int stackvar, int *_eax, int *_ebx, int * ); return result&0xFF00; } +#endif //__GNUC__ static money32 map_set_land_height(int flags, int x, int y, int height, int style, int selectionType) { @@ -2001,6 +2003,11 @@ static money32 map_set_land_height(int flags, int x, int y, int height, int styl int saved_ecx = ecx; unsigned int saved_edx = edx; + uint8 *pdl = (uint8 *)&edx; + uint8 *pdh = (uint8 *)&edx+1; + uint8 *pbl = (uint8 *)&ebx; + uint8 *pbh = (uint8 *)&ebx+1; + /* esi = ecx&0xFFFF; //movzx esi, cx esi <<= 8; @@ -2010,21 +2017,12 @@ static money32 map_set_land_height(int flags, int x, int y, int height, int styl */ esi = (int)map_get_first_element_at(eax/32, ecx/32); - uint8 *pdl = (uint8 *)&edx; - uint8 *pdh = (uint8 *)&edx+1; - uint8 *pbl = (uint8 *)&ebx; - uint8 *pbh = (uint8 *)&ebx+1; - *pdh = *pdl; *pdh += 4; loc_663A54: eax = map_element_get_type((rct_map_element *)esi); - if(eax!=MAP_ELEMENT_TYPE_SCENERY) - goto loc_663AA3; - if(*pdl>((rct_map_element *)esi)->clearance_height) - goto loc_663AA3; - if(*pdh<((rct_map_element *)esi)->base_height) + if(eax!=MAP_ELEMENT_TYPE_SCENERY || *pdl>((rct_map_element *)esi)->clearance_height || *pdh<((rct_map_element *)esi)->base_height) goto loc_663AA3; eax = ((rct_map_element *)esi)->properties.scenery.type; eax = RCT2_ADDRESS(RCT2_ADDRESS_SMALL_SCENERY_ENTRIES, uint32)[eax]; @@ -2067,27 +2065,27 @@ loc_663AA3: esi >>= 3; esi = RCT2_ADDRESS(RCT2_ADDRESS_TILE_MAP_ELEMENT_POINTERS, uint32)[esi/4]; */ - esi = (int)map_get_first_element_at(eax/32, ecx/32); + rct_map_element *mapElement = map_get_first_element_at(eax/32, ecx/32); //esi + esi = (int)mapElement; //callcode_push3(0x663AC4, saved_eax, saved_ebx, saved_ecx, &eax, &ebx, &ecx, (int *)&edx, (int *)&esi, &edi, &ebp); return ebx; loc_663AC4: - eax = ((rct_map_element *)esi)->type; + eax = mapElement->type; eax &= 0x3C; if(eax==8) { - ebp = ((rct_map_element *)esi)->properties.track.ride_index; //not sure what union member we need here. [esi+7] - ebp *= 0x260; - eax = RCT2_ADDRESS(RCT2_ADDRESS_RIDE_LIST, rct_ride)[ebp/0x260].subtype; + ebp = ((rct_map_element *)mapElement)->properties.track.ride_index; //not sure what union member we need here. [esi+7] + eax = RCT2_ADDRESS(RCT2_ADDRESS_RIDE_LIST, rct_ride)[ebp].subtype; eax = RCT2_ADDRESS(RCT2_ADDRESS_RIDE_ENTRIES, uint32)[eax]; eax = ((rct_ride_type *)eax)->max_height; if(eax==0) { - eax = RCT2_ADDRESS(RCT2_ADDRESS_RIDE_LIST, rct_ride)[ebp/0x260].type; + eax = RCT2_ADDRESS(RCT2_ADDRESS_RIDE_LIST, rct_ride)[ebp].type; eax = RCT2_GLOBAL(0x97D218+eax*8, uint8); } //rct2: 0x663AFC - ebx = ((rct_map_element *)esi)->clearance_height; + ebx = mapElement->clearance_height; ebx -= *pdl; if(ebx>=0) { @@ -2101,56 +2099,61 @@ loc_663AC4: } } loc_663B1A: - esi += 8; - if(!((*(uint8 *)esi-7)&MAP_ELEMENT_FLAG_LAST_TILE)) + mapElement++; + if((mapElement-1)->flags&MAP_ELEMENT_FLAG_LAST_TILE) goto loc_663AC4; - ecx = saved_ecx; ebx = saved_ebx; eax = saved_eax; saved_ecx = ecx; + ebp *= 0x260; + esi = (int)mapElement; //callcode_push1(0x663B27, saved_ecx, &eax, &ebx, &ecx, (int *)&edx, (int *)&esi, &edi, &ebp); return ebx; + /* esi = ecx&0xFFFF; esi <<= 8; esi |= eax&0xFFFF; esi >>= 3; esi = RCT2_ADDRESS(RCT2_ADDRESS_TILE_MAP_ELEMENT_POINTERS, uint32)[esi/4]; - + */ + mapElement = map_get_first_element_at(eax/32, ecx/32); //esi + esi = (int)mapElement; //callcode_push1(0x663B39, saved_ecx, &eax, &ebx, &ecx, (int *)&edx, (int *)&esi, &edi, &ebp); return ebx; - while((((rct_map_element *)esi)->type&0x3C)) - esi += 8; - if(!((rct_map_element *)esi)->type&0x40) - goto loc_663B72; - ecx = *((uint8 *)esi+5); //Don't know which union member to use yet. - ecx &= 0x1F; - if(ecx==0) - goto loc_663B72; - ecx <<= 1; - ecx -= 2; - *pbh = *pdl; - if((*pdh&0x1F)) + while(mapElement->type&MAP_ELEMENT_TYPE_MASK) + mapElement++; + if(mapElement->type&0x40) { - *pbh += 2; - if((*pdh&0x10)) + //ecx = *((uint8 *)esi+5)&0x1F; //Don't know which union member to use yet. + ecx = mapElement->properties.scenery.age&0x1F; //Don't know if this is the correct union member. + if(ecx!=0) { - *pbh += 2; + ecx = ecx*2-2; + *pbh = *pdl; + if((*pdh&0x1F)) + { + *pbh += 2; + if((*pdh&0x10)) + { + *pbh += 2; + } + } + loc_663B6A: + if(*pbh>ecx) + { + //rct2: 0x663C5A + mapElement++; + map_obstruction_set_error_text(mapElement); + return MONEY32_UNDEFINED; + } } } -loc_663B6A: - if(*pbh>ecx) - { - //rct2: 0x663C5A - ecx = saved_ecx; - esi += 8; - map_obstruction_set_error_text((rct_map_element *)esi); - return MONEY32_UNDEFINED; - } loc_663B72: ecx = saved_ecx; + esi = (int)mapElement; //RCT2_CALLFUNC_X(0x663B73, &eax, &ebx, &ecx, (int *)&edx, (int *)&esi, &edi, &ebp); return ebx; *pbh = *pdl; @@ -2183,22 +2186,18 @@ loc_663B85: //callcode_push2(0x663BA3, saved_eax, saved_ecx, &eax, &ebx, &ecx, (int *)&edx, (int *)&esi, &edi, &ebp); return ebx; + /* edi = ecx&0xFFFF; edi <<= 8; edi = (edi|eax)&0xFFFF; edi >>= 3; edi = (uint32)RCT2_ADDRESS(RCT2_ADDRESS_TILE_MAP_ELEMENT_POINTERS, rct_map_element *)[edi/4]; + */ + edi = (int)map_get_first_element_at(eax/32, ecx/32); loc_663BB5: //callcode_push2(0x663BB5, saved_eax, saved_ecx, &eax, &ebx, &ecx, (int *)&edx, (int *)&esi, &edi, &ebp); return ebx; - eax = ((rct_map_element *)edi)->type; - eax &= 0x3C; - if(eax==0x14) - goto loc_663BD9; - if(eax==0xC) - goto loc_663BD9; - if(((rct_map_element *)edi)->flags&0x10) - goto loc_663BD9; - if(edi==esi) + eax = ((rct_map_element *)edi)->type&MAP_ELEMENT_TYPE_MASK; + if(eax==0x14 || eax==0xC || ((rct_map_element *)edi)->flags&0x10 || edi==esi) goto loc_663BD9; if(edi>esi) goto loc_663BD4; From 2cd40b025aacd15f254b84dd6e17bfae1d8b113f Mon Sep 17 00:00:00 2001 From: "U-ASUS-EEEPC\\Cameron Hall" Date: Fri, 13 Nov 2015 13:48:21 -0600 Subject: [PATCH 03/10] Fixed one of my bugs and did some refactoring. Still more refactoring to do... --- src/world/map.c | 108 ++++++++++++++++++++---------------------------- 1 file changed, 45 insertions(+), 63 deletions(-) diff --git a/src/world/map.c b/src/world/map.c index 332a1dd727..2c4734bcaa 100644 --- a/src/world/map.c +++ b/src/world/map.c @@ -1974,7 +1974,6 @@ static money32 map_set_land_height(int flags, int x, int y, int height, int styl /* Continuing dissassembly - work in progress * Known bugs: * Raising the corner of a piece of land doesn't remove walls. - * Small scenery elements (ones that take up 1/4 of a tile) are not removed when changing land height. * Original bugs: * Lowering the land tile underneath a wall removes the wall. * Land can be raised over flat scenery items (gardens, for example) without removing them. @@ -1990,7 +1989,7 @@ static money32 map_set_land_height(int flags, int x, int y, int height, int styl RCT2_GLOBAL(0x9E2E18, uint32) = 0; if(ebx&GAME_COMMAND_FLAG_APPLY) { - footpath_remove_litter(eax, ebx, map_element_height(eax, ecx)); + footpath_remove_litter(eax, ecx, map_element_height(eax, ecx)); //Hmmm... I have a bug in here where raising the corner of a tile doesn't remove walls on it. map_remove_walls_at(eax, ecx, edx*8-16, edx*8+32); } @@ -2008,47 +2007,41 @@ static money32 map_set_land_height(int flags, int x, int y, int height, int styl uint8 *pbl = (uint8 *)&ebx; uint8 *pbh = (uint8 *)&ebx+1; - /* - esi = ecx&0xFFFF; //movzx esi, cx - esi <<= 8; - esi |= eax; - esi >>= 3; - esi = RCT2_ADDRESS(RCT2_ADDRESS_TILE_MAP_ELEMENT_POINTERS, uint32)[(int)esi/4]; - */ - esi = (int)map_get_first_element_at(eax/32, ecx/32); + rct_map_element *mapElement = map_get_first_element_at(eax/32, ecx/32); //esi *pdh = *pdl; *pdh += 4; -loc_663A54: - eax = map_element_get_type((rct_map_element *)esi); - if(eax!=MAP_ELEMENT_TYPE_SCENERY || *pdl>((rct_map_element *)esi)->clearance_height || *pdh<((rct_map_element *)esi)->base_height) - goto loc_663AA3; - eax = ((rct_map_element *)esi)->properties.scenery.type; - eax = RCT2_ADDRESS(RCT2_ADDRESS_SMALL_SCENERY_ENTRIES, uint32)[eax]; - if(((rct_scenery_entry *)eax)->small_scenery.height>0x40) //cmp byte ptr [eax+0Ah], 40h; jbe short loc_663A87 - { - if(RCT2_GLOBAL(RCT2_ADDRESS_PARK_FLAGS, uint32)&PARK_FLAGS_FORBID_TREE_REMOVAL) +//loc_663A54: + do{ + int type = map_element_get_type(mapElement); //eax + rct_scenery_entry *sceneryEntry; //eax + + if(type!=MAP_ELEMENT_TYPE_SCENERY || *pdl>(mapElement)->clearance_height || *pdh<(mapElement)->base_height) + continue; + type = mapElement->properties.scenery.type; + sceneryEntry = RCT2_ADDRESS(RCT2_ADDRESS_SMALL_SCENERY_ENTRIES, rct_scenery_entry *)[type]; + if(sceneryEntry->small_scenery.height>0x40) //cmp byte ptr [eax+0Ah], 40h; jbe short loc_663A87 { - //rct2: 0x663C45 - map_obstruction_set_error_text((rct_map_element *)esi); - return MONEY32_UNDEFINED; + if(RCT2_GLOBAL(RCT2_ADDRESS_PARK_FLAGS, uint32)&PARK_FLAGS_FORBID_TREE_REMOVAL) + { + //rct2: 0x663C45 + map_obstruction_set_error_text(mapElement); + return MONEY32_UNDEFINED; + } } - } - //rct2: 0x663A87 - //callcode_push3(0x663A87, saved_eax, saved_ecx, saved_edx, &eax, &ebx, &ecx, (int *)&edx, (int *)&esi, &edi, &ebp); return ebx; - ecx = ((rct_scenery_entry *)eax)->small_scenery.removal_price*10; - RCT2_GLOBAL(0x9E2E18, uint32) += ecx; - //rct2: 0x663A94 - if((ebx&GAME_COMMAND_FLAG_APPLY)) - { - map_element_remove((rct_map_element *)esi); - esi = esi-8; - } -loc_663AA3: - esi = esi+8; - if(!((*(uint8 *)esi-7)&MAP_ELEMENT_FLAG_LAST_TILE)) - goto loc_663A54; + //rct2: 0x663A87 + RCT2_GLOBAL(0x9E2E18, money32) += ((rct_scenery_entry *)sceneryEntry)->small_scenery.removal_price*10; + //rct2: 0x663A94 + if((ebx&GAME_COMMAND_FLAG_APPLY)) + { + map_element_remove(mapElement); + mapElement--; + } + //loc_663AA3: + }while(!((mapElement++)->flags&MAP_ELEMENT_FLAG_LAST_TILE)); + + esi =(int)mapElement; edx = saved_edx; ecx = saved_ecx; eax = saved_eax; @@ -2058,35 +2051,28 @@ loc_663AA3: //callcode_push3(0x663AB2, saved_eax, saved_ebx, saved_ecx, &eax, &ebx, &ecx, (int *)&edx, (int *)&esi, &edi, &ebp); return ebx; - /* - esi = ecx&0xFFFF; //movzx esi, cx - esi <<= 8; - esi |= eax&0xFFFF; //or si, ax - esi >>= 3; - esi = RCT2_ADDRESS(RCT2_ADDRESS_TILE_MAP_ELEMENT_POINTERS, uint32)[esi/4]; - */ - rct_map_element *mapElement = map_get_first_element_at(eax/32, ecx/32); //esi + mapElement = map_get_first_element_at(eax/32, ecx/32); //esi esi = (int)mapElement; //callcode_push3(0x663AC4, saved_eax, saved_ebx, saved_ecx, &eax, &ebx, &ecx, (int *)&edx, (int *)&esi, &edi, &ebp); return ebx; -loc_663AC4: - eax = mapElement->type; - eax &= 0x3C; - if(eax==8) - { - ebp = ((rct_map_element *)mapElement)->properties.track.ride_index; //not sure what union member we need here. [esi+7] - eax = RCT2_ADDRESS(RCT2_ADDRESS_RIDE_LIST, rct_ride)[ebp].subtype; + do{ + //loc_663AC4: + //eax = mapElement->type&0x3C; + int type = mapElement->type&0x3C; //eax + if(type!=8) + continue; + int rideIndex = mapElement->properties.track.ride_index; //ebp + eax = RCT2_ADDRESS(RCT2_ADDRESS_RIDE_LIST, rct_ride)[rideIndex].subtype; eax = RCT2_ADDRESS(RCT2_ADDRESS_RIDE_ENTRIES, uint32)[eax]; eax = ((rct_ride_type *)eax)->max_height; if(eax==0) { - eax = RCT2_ADDRESS(RCT2_ADDRESS_RIDE_LIST, rct_ride)[ebp].type; + eax = RCT2_ADDRESS(RCT2_ADDRESS_RIDE_LIST, rct_ride)[rideIndex].type; eax = RCT2_GLOBAL(0x97D218+eax*8, uint8); } //rct2: 0x663AFC - ebx = mapElement->clearance_height; - ebx -= *pdl; + ebx = mapElement->clearance_height-*pdl; if(ebx>=0) { ebx >>= 1; @@ -2097,18 +2083,14 @@ loc_663AC4: return MONEY32_UNDEFINED; } } - } -loc_663B1A: - mapElement++; - if((mapElement-1)->flags&MAP_ELEMENT_FLAG_LAST_TILE) - goto loc_663AC4; + loc_663B1A:; + }while(!((mapElement++)->flags&MAP_ELEMENT_FLAG_LAST_TILE)); + ecx = saved_ecx; ebx = saved_ebx; eax = saved_eax; saved_ecx = ecx; - ebp *= 0x260; - esi = (int)mapElement; //callcode_push1(0x663B27, saved_ecx, &eax, &ebx, &ecx, (int *)&edx, (int *)&esi, &edi, &ebp); return ebx; /* @@ -5495,4 +5477,4 @@ rct_map_element *map_get_track_element_at_of_type(int x, int y, int z, int track } while (!map_element_is_last_for_tile(mapElement++)); return NULL; -} +} \ No newline at end of file From f9b1a9eeb49080a2d3f696ee1e3daf5dfd8eea79 Mon Sep 17 00:00:00 2001 From: "U-HP-Pavilion-PC\\Cameron" Date: Fri, 13 Nov 2015 19:50:20 -0600 Subject: [PATCH 04/10] Refactor some more and fix #2264 --- src/world/map.c | 191 +++++++++++++++++------------------------------- 1 file changed, 68 insertions(+), 123 deletions(-) diff --git a/src/world/map.c b/src/world/map.c index 2c4734bcaa..fb14c0ad22 100644 --- a/src/world/map.c +++ b/src/world/map.c @@ -1971,148 +1971,100 @@ static money32 map_set_land_height(int flags, int x, int y, int height, int styl } } - /* Continuing dissassembly - work in progress - * Known bugs: - * Raising the corner of a piece of land doesn't remove walls. + /* Continuing decompilation - work in progress + * Known bugs (introduced by disassembly): + * none! Still requires testing, though. * Original bugs: * Lowering the land tile underneath a wall removes the wall. * Land can be raised over flat scenery items (gardens, for example) without removing them. + * Removal price of walls is not added. + * Removal price of flat scenery is not counted when raising the center of a tile. */ int eax = x, ebx = flags, ecx = y, edi = selectionType << 5, ebp = 0; uint32 edx = (style << 8) | height; + //dl: height + //dh: flags uint32 esi = 0; + int saved_eax; + int saved_ebx; + int saved_ecx; + unsigned int saved_edx; + //Uncomment to use vanilla code //RCT2_CALLFUNC_X(0x006639FE, &eax, &ebx, &ecx, (int *)&edx, (int *)&esi, &edi, &ebp); return ebx; - RCT2_GLOBAL(0x9E2E18, uint32) = 0; + RCT2_GLOBAL(0x9E2E18, money32) = MONEY(0, 0); if(ebx&GAME_COMMAND_FLAG_APPLY) { - footpath_remove_litter(eax, ecx, map_element_height(eax, ecx)); - //Hmmm... I have a bug in here where raising the corner of a tile doesn't remove walls on it. - map_remove_walls_at(eax, ecx, edx*8-16, edx*8+32); + footpath_remove_litter(x, y, map_element_height(x, y)); + map_remove_walls_at(x, y, height*8-16, height*8+32); } + RCT2_GLOBAL(0x9E2E18, money32) += MONEY(20, 0); - RCT2_GLOBAL(0x9E2E18, uint32) += 0xC8; + rct_map_element *mapElement = map_get_first_element_at(x/32, y/32); //mapElement = esi - //RCT2_CALLFUNC_X(0x663A3A, &eax, &ebx, &ecx, (int *)&edx, (int *)&esi, &edi, &ebp); return ebx; + int zHigh = height+4; //zHigh = dh - int saved_eax = eax; - int saved_ecx = ecx; - unsigned int saved_edx = edx; +//loc_663A54: + do{ + int elementType = map_element_get_type(mapElement); //elementType = eax + rct_scenery_entry *sceneryEntry; //eax + + if(elementType!=MAP_ELEMENT_TYPE_SCENERY || height>mapElement->clearance_height || zHigh<(mapElement)->base_height) + continue; + elementType = mapElement->properties.scenery.type; + sceneryEntry = RCT2_ADDRESS(RCT2_ADDRESS_SMALL_SCENERY_ENTRIES, rct_scenery_entry *)[elementType]; + if(sceneryEntry->small_scenery.height>64 && RCT2_GLOBAL(RCT2_ADDRESS_PARK_FLAGS, uint32)&PARK_FLAGS_FORBID_TREE_REMOVAL) + { + map_obstruction_set_error_text(mapElement); + return MONEY32_UNDEFINED; + } + RCT2_GLOBAL(0x9E2E18, money32) += MONEY(sceneryEntry->small_scenery.removal_price, 0); + if(flags&GAME_COMMAND_FLAG_APPLY) + map_element_remove(mapElement--); + }while(!map_element_is_last_for_tile(mapElement++)); + + mapElement = map_get_first_element_at(x/32, y/32); //mapElement = esi + +//loc_663AC4: + do{ + if(map_element_get_type(mapElement)!=8) //eax + continue; + int rideIndex = mapElement->properties.track.ride_index; //rideIndex = ebp + int maxHeight = GET_RIDE_ENTRY(GET_RIDE(rideIndex)->subtype)->max_height; //maxHeight = eax + if(maxHeight==0) + maxHeight = RCT2_GLOBAL(0x97D218+8*GET_RIDE(rideIndex)->type, uint8); + int zDelta = mapElement->clearance_height-height; //zDelta = ebx + if(zDelta>=0 && zDelta/2>maxHeight && gCheatsDisableSupportLimits==false) + { + RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_TEXT, rct_string_id) = STR_SUPPORTS_CANT_BE_EXTENDED; + return MONEY32_UNDEFINED; + } + }while(!map_element_is_last_for_tile(mapElement++)); + + //Save variables on the stack + //saved_ecx = ecx; + //callcode_push1(0x663B27, saved_ecx, &eax, &ebx, &ecx, (int *)&edx, (int *)&esi, &edi, &ebp); return ebx; + + mapElement = map_get_first_element_at(x/32, y/32); //esi + esi = (int)mapElement; + //callcode_push1(0x663B39, saved_ecx, &eax, &ebx, &ecx, (int *)&edx, (int *)&esi, &edi, &ebp); return ebx; uint8 *pdl = (uint8 *)&edx; uint8 *pdh = (uint8 *)&edx+1; uint8 *pbl = (uint8 *)&ebx; uint8 *pbh = (uint8 *)&ebx+1; - rct_map_element *mapElement = map_get_first_element_at(eax/32, ecx/32); //esi - - *pdh = *pdl; - *pdh += 4; - -//loc_663A54: - do{ - int type = map_element_get_type(mapElement); //eax - rct_scenery_entry *sceneryEntry; //eax - - if(type!=MAP_ELEMENT_TYPE_SCENERY || *pdl>(mapElement)->clearance_height || *pdh<(mapElement)->base_height) - continue; - type = mapElement->properties.scenery.type; - sceneryEntry = RCT2_ADDRESS(RCT2_ADDRESS_SMALL_SCENERY_ENTRIES, rct_scenery_entry *)[type]; - if(sceneryEntry->small_scenery.height>0x40) //cmp byte ptr [eax+0Ah], 40h; jbe short loc_663A87 - { - if(RCT2_GLOBAL(RCT2_ADDRESS_PARK_FLAGS, uint32)&PARK_FLAGS_FORBID_TREE_REMOVAL) - { - //rct2: 0x663C45 - map_obstruction_set_error_text(mapElement); - return MONEY32_UNDEFINED; - } - } - //rct2: 0x663A87 - RCT2_GLOBAL(0x9E2E18, money32) += ((rct_scenery_entry *)sceneryEntry)->small_scenery.removal_price*10; - //rct2: 0x663A94 - if((ebx&GAME_COMMAND_FLAG_APPLY)) - { - map_element_remove(mapElement); - mapElement--; - } - //loc_663AA3: - }while(!((mapElement++)->flags&MAP_ELEMENT_FLAG_LAST_TILE)); - - esi =(int)mapElement; - edx = saved_edx; - ecx = saved_ecx; - eax = saved_eax; - saved_eax = eax; - int saved_ebx = ebx; - saved_ecx = ecx; - - //callcode_push3(0x663AB2, saved_eax, saved_ebx, saved_ecx, &eax, &ebx, &ecx, (int *)&edx, (int *)&esi, &edi, &ebp); return ebx; - - mapElement = map_get_first_element_at(eax/32, ecx/32); //esi - esi = (int)mapElement; - //callcode_push3(0x663AC4, saved_eax, saved_ebx, saved_ecx, &eax, &ebx, &ecx, (int *)&edx, (int *)&esi, &edi, &ebp); return ebx; - - do{ - //loc_663AC4: - //eax = mapElement->type&0x3C; - int type = mapElement->type&0x3C; //eax - if(type!=8) - continue; - int rideIndex = mapElement->properties.track.ride_index; //ebp - eax = RCT2_ADDRESS(RCT2_ADDRESS_RIDE_LIST, rct_ride)[rideIndex].subtype; - eax = RCT2_ADDRESS(RCT2_ADDRESS_RIDE_ENTRIES, uint32)[eax]; - - eax = ((rct_ride_type *)eax)->max_height; - if(eax==0) - { - eax = RCT2_ADDRESS(RCT2_ADDRESS_RIDE_LIST, rct_ride)[rideIndex].type; - eax = RCT2_GLOBAL(0x97D218+eax*8, uint8); - } - //rct2: 0x663AFC - ebx = mapElement->clearance_height-*pdl; - if(ebx>=0) - { - ebx >>= 1; - if(ebx>eax) - { - //rct2: 0x663B09 - RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_TEXT, rct_string_id) = STR_SUPPORTS_CANT_BE_EXTENDED; - return MONEY32_UNDEFINED; - } - } - loc_663B1A:; - }while(!((mapElement++)->flags&MAP_ELEMENT_FLAG_LAST_TILE)); - - ecx = saved_ecx; - ebx = saved_ebx; - eax = saved_eax; - saved_ecx = ecx; - - //callcode_push1(0x663B27, saved_ecx, &eax, &ebx, &ecx, (int *)&edx, (int *)&esi, &edi, &ebp); return ebx; - - /* - esi = ecx&0xFFFF; - esi <<= 8; - esi |= eax&0xFFFF; - esi >>= 3; - esi = RCT2_ADDRESS(RCT2_ADDRESS_TILE_MAP_ELEMENT_POINTERS, uint32)[esi/4]; - */ - mapElement = map_get_first_element_at(eax/32, ecx/32); //esi - esi = (int)mapElement; - //callcode_push1(0x663B39, saved_ecx, &eax, &ebx, &ecx, (int *)&edx, (int *)&esi, &edi, &ebp); return ebx; - while(mapElement->type&MAP_ELEMENT_TYPE_MASK) mapElement++; if(mapElement->type&0x40) { - //ecx = *((uint8 *)esi+5)&0x1F; //Don't know which union member to use yet. - ecx = mapElement->properties.scenery.age&0x1F; //Don't know if this is the correct union member. - if(ecx!=0) + int waterHeight = mapElement->properties.surface.terrain&MAP_ELEMENT_WATER_HEIGHT_MASK; //waterHeight = ecx + if(waterHeight!=0) { - ecx = ecx*2-2; + waterHeight = waterHeight*2-2; *pbh = *pdl; if((*pdh&0x1F)) { @@ -2123,7 +2075,7 @@ static money32 map_set_land_height(int flags, int x, int y, int height, int styl } } loc_663B6A: - if(*pbh>ecx) + if(*pbh>waterHeight) { //rct2: 0x663C5A mapElement++; @@ -2133,7 +2085,6 @@ static money32 map_set_land_height(int flags, int x, int y, int height, int styl } } loc_663B72: - ecx = saved_ecx; esi = (int)mapElement; //RCT2_CALLFUNC_X(0x663B73, &eax, &ebx, &ecx, (int *)&edx, (int *)&esi, &edi, &ebp); return ebx; @@ -2168,14 +2119,7 @@ loc_663B85: //callcode_push2(0x663BA3, saved_eax, saved_ecx, &eax, &ebx, &ecx, (int *)&edx, (int *)&esi, &edi, &ebp); return ebx; - /* - edi = ecx&0xFFFF; - edi <<= 8; - edi = (edi|eax)&0xFFFF; - edi >>= 3; - edi = (uint32)RCT2_ADDRESS(RCT2_ADDRESS_TILE_MAP_ELEMENT_POINTERS, rct_map_element *)[edi/4]; - */ - edi = (int)map_get_first_element_at(eax/32, ecx/32); + edi = (int)map_get_first_element_at(eax/32, ecx/32); //mapElement = edi loc_663BB5: //callcode_push2(0x663BB5, saved_eax, saved_ecx, &eax, &ebx, &ecx, (int *)&edx, (int *)&esi, &edi, &ebp); return ebx; eax = ((rct_map_element *)edi)->type&MAP_ELEMENT_TYPE_MASK; @@ -2204,6 +2148,7 @@ loc_663C4F: esi = edi; map_obstruction_set_error_text((rct_map_element *)esi); return MONEY32_UNDEFINED; + } void game_command_set_land_height(int *eax, int *ebx, int *ecx, int *edx, int *esi, int *edi, int *ebp) From 0a824d0957431d10441406ec512e9b46abfdc620 Mon Sep 17 00:00:00 2001 From: "U-HP-Pavilion-PC\\Cameron" Date: Sat, 14 Nov 2015 22:45:13 -0600 Subject: [PATCH 05/10] saving my work --- src/world/map.c | 101 +++++++++++++++++++++++++++--------------------- 1 file changed, 57 insertions(+), 44 deletions(-) diff --git a/src/world/map.c b/src/world/map.c index fb14c0ad22..8127e1d987 100644 --- a/src/world/map.c +++ b/src/world/map.c @@ -1984,7 +1984,7 @@ static money32 map_set_land_height(int flags, int x, int y, int height, int styl int eax = x, ebx = flags, ecx = y, edi = selectionType << 5, ebp = 0; uint32 edx = (style << 8) | height; //dl: height - //dh: flags + //dh: style uint32 esi = 0; int saved_eax; @@ -2052,30 +2052,26 @@ static money32 map_set_land_height(int flags, int x, int y, int height, int styl esi = (int)mapElement; //callcode_push1(0x663B39, saved_ecx, &eax, &ebx, &ecx, (int *)&edx, (int *)&esi, &edi, &ebp); return ebx; - uint8 *pdl = (uint8 *)&edx; - uint8 *pdh = (uint8 *)&edx+1; - uint8 *pbl = (uint8 *)&ebx; - uint8 *pbh = (uint8 *)&ebx+1; - + //Hmm... Not really sure what's going on here. while(mapElement->type&MAP_ELEMENT_TYPE_MASK) mapElement++; - if(mapElement->type&0x40) + if(mapElement->type&MAP_ELEMENT_TYPE_FLAG_HIGHLIGHT) { int waterHeight = mapElement->properties.surface.terrain&MAP_ELEMENT_WATER_HEIGHT_MASK; //waterHeight = ecx if(waterHeight!=0) { waterHeight = waterHeight*2-2; - *pbh = *pdl; - if((*pdh&0x1F)) + uint8 unk = height; //unk = bh + if((style&0x1F)) { - *pbh += 2; - if((*pdh&0x10)) + unk += 2; + if((style&0x10)) { - *pbh += 2; + unk += 2; } } - loc_663B6A: - if(*pbh>waterHeight) + //loc_663B6A: + if(unk>waterHeight) { //rct2: 0x663C5A mapElement++; @@ -2084,59 +2080,70 @@ static money32 map_set_land_height(int flags, int x, int y, int height, int styl } } } -loc_663B72: +//loc_663B72: esi = (int)mapElement; //RCT2_CALLFUNC_X(0x663B73, &eax, &ebx, &ecx, (int *)&edx, (int *)&esi, &edi, &ebp); return ebx; - - *pbh = *pdl; - if((*pdh&0xF)) + uint8 unk = height; //unk = bh + unk = height; + if((style&0xF)) { - *pbh += 2; - if((*pdh&0x10)) + unk += 2; + if((style&0x10)) { - *pbh += 2; + unk += 2; } } loc_663B85: - saved_ebx = ebx; - saved_edx = edx; - int saved_ebp = ebp; + //saved_ebx = ebx; + //saved_edx = edx; + //int saved_ebp = ebp; //callcode_push3(0x663B88, saved_ebx, saved_edx, saved_ebp, &eax, &ebx, &ecx, (int *)&edx, (int *)&esi, &edi, &ebp); return ebx; - *pbl = *pdh; - *pdh = *pbh; - *pbl = 0xF; - ebp = (int)RCT2_ADDRESS(0x663CB9, void); - if(map_can_construct_with_clear_at(eax&0xFFFF, ecx&0xFFFF, *pdl, *pdh, (void *)ebp, *pbl)==false) + /* mov bl, dh ; Hmm, odd... + * mov dh, bh + * mov bl, 0Fh + */ + + if(map_can_construct_with_clear_at(eax&0xFFFF, ecx&0xFFFF, height, unk, RCT2_ADDRESS(0x663CB9, void), 0xF)==false) return MONEY32_UNDEFINED; - ebp = saved_ebp; - edx = saved_edx; - ebx = saved_ebx; + //ebp = saved_ebp; + //edx = saved_edx; + //ebx = saved_ebx; saved_eax = eax; saved_ecx = ecx; //callcode_push2(0x663BA3, saved_eax, saved_ecx, &eax, &ebx, &ecx, (int *)&edx, (int *)&esi, &edi, &ebp); return ebx; - edi = (int)map_get_first_element_at(eax/32, ecx/32); //mapElement = edi -loc_663BB5: + rct_map_element *mapElement2 = map_get_first_element_at(x/32, y/32); //mapElement2 = edi + + + uint8 *pdl = (uint8 *)&edx; + uint8 *pdh = (uint8 *)&edx+1; + uint8 *pbl = (uint8 *)&ebx; + uint8 *pbh = (uint8 *)&ebx+1; + +//loc_663BB5: + //callcode_push2(0x663BB5, saved_eax, saved_ecx, &eax, &ebx, &ecx, (int *)&edx, (int *)&esi, &edi, &ebp); return ebx; - eax = ((rct_map_element *)edi)->type&MAP_ELEMENT_TYPE_MASK; - if(eax==0x14 || eax==0xC || ((rct_map_element *)edi)->flags&0x10 || edi==esi) - goto loc_663BD9; - if(edi>esi) +do{ + eax = ((rct_map_element *)mapElement2)->type&MAP_ELEMENT_TYPE_MASK; + if(eax==MAP_ELEMENT_TYPE_FENCE || eax==MAP_ELEMENT_TYPE_SCENERY || mapElement2->flags&0x10 || mapElement2==(rct_map_element *)esi) + continue; + if(mapElement2>(rct_map_element *)esi) goto loc_663BD4; - if(*pdl<((rct_map_element *)edi)->clearance_height) + if(*pdl<((rct_map_element *)mapElement2)->clearance_height) goto loc_663C4F; - goto loc_663BD9; + continue; loc_663BD4: - if(*pbh>((rct_map_element *)edi)->base_height) + if(*pbh>((rct_map_element *)mapElement2)->base_height) goto loc_663C4F; loc_663BD9: - edi += 8; - if(!(*((uint8 *)edi-7)&MAP_ELEMENT_FLAG_LAST_TILE)) - goto loc_663BB5; + ; +}while(!map_element_is_last_for_tile(mapElement2++)); + + edi = (int)mapElement2; ecx = saved_ecx; eax = saved_eax; @@ -4234,6 +4241,12 @@ static void map_obstruction_set_error_text(rct_map_element *mapElement) /** * * rct2: 0x0068B932 + * ax = x + * cx = y + * dl = zLow + * dh = zHigh + * ebp = clearFunc + * bl = bl */ int map_can_construct_with_clear_at(int x, int y, int zLow, int zHigh, void *clearFunc, uint8 bl) { From cfdc0cf05795c6fac943990b835837955fee3c47 Mon Sep 17 00:00:00 2001 From: "U-HP-Pavilion-PC\\Cameron" Date: Sun, 15 Nov 2015 11:01:34 -0600 Subject: [PATCH 06/10] More refactoring --- src/world/map.c | 90 +++++++++++++++++-------------------------------- 1 file changed, 30 insertions(+), 60 deletions(-) diff --git a/src/world/map.c b/src/world/map.c index 8127e1d987..c62961b160 100644 --- a/src/world/map.c +++ b/src/world/map.c @@ -2044,17 +2044,8 @@ static money32 map_set_land_height(int flags, int x, int y, int height, int styl } }while(!map_element_is_last_for_tile(mapElement++)); - //Save variables on the stack - //saved_ecx = ecx; - //callcode_push1(0x663B27, saved_ecx, &eax, &ebx, &ecx, (int *)&edx, (int *)&esi, &edi, &ebp); return ebx; + mapElement = map_get_surface_element_at(x/32, y/32); - mapElement = map_get_first_element_at(x/32, y/32); //esi - esi = (int)mapElement; - //callcode_push1(0x663B39, saved_ecx, &eax, &ebx, &ecx, (int *)&edx, (int *)&esi, &edi, &ebp); return ebx; - - //Hmm... Not really sure what's going on here. - while(mapElement->type&MAP_ELEMENT_TYPE_MASK) - mapElement++; if(mapElement->type&MAP_ELEMENT_TYPE_FLAG_HIGHLIGHT) { int waterHeight = mapElement->properties.surface.terrain&MAP_ELEMENT_WATER_HEIGHT_MASK; //waterHeight = ecx @@ -2082,10 +2073,8 @@ static money32 map_set_land_height(int flags, int x, int y, int height, int styl } //loc_663B72: - esi = (int)mapElement; - //RCT2_CALLFUNC_X(0x663B73, &eax, &ebx, &ecx, (int *)&edx, (int *)&esi, &edi, &ebp); return ebx; uint8 unk = height; //unk = bh - unk = height; + if((style&0xF)) { unk += 2; @@ -2094,68 +2083,49 @@ static money32 map_set_land_height(int flags, int x, int y, int height, int styl unk += 2; } } -loc_663B85: - //saved_ebx = ebx; - //saved_edx = edx; - - //int saved_ebp = ebp; - //callcode_push3(0x663B88, saved_ebx, saved_edx, saved_ebp, &eax, &ebx, &ecx, (int *)&edx, (int *)&esi, &edi, &ebp); return ebx; - - /* mov bl, dh ; Hmm, odd... - * mov dh, bh - * mov bl, 0Fh - */ + //rct2: 0x663B93 if(map_can_construct_with_clear_at(eax&0xFFFF, ecx&0xFFFF, height, unk, RCT2_ADDRESS(0x663CB9, void), 0xF)==false) return MONEY32_UNDEFINED; - //ebp = saved_ebp; - //edx = saved_edx; - //ebx = saved_ebx; - saved_eax = eax; - saved_ecx = ecx; - - //callcode_push2(0x663BA3, saved_eax, saved_ecx, &eax, &ebx, &ecx, (int *)&edx, (int *)&esi, &edi, &ebp); return ebx; rct_map_element *mapElement2 = map_get_first_element_at(x/32, y/32); //mapElement2 = edi - + +//loc_663BB5: + do{ + int elementType = map_element_get_type(mapElement2); //elementType = al + + if(elementType==MAP_ELEMENT_TYPE_FENCE || elementType==MAP_ELEMENT_TYPE_SCENERY || mapElement2->flags&0x10 || mapElement2==mapElement) + continue; + if(mapElement2>mapElement) + { + if(unk > mapElement2->base_height) + { + map_obstruction_set_error_text(mapElement2); + return MONEY32_UNDEFINED; + } + continue; + } + if(height < mapElement2->clearance_height) + { + map_obstruction_set_error_text(mapElement2); + return MONEY32_UNDEFINED; + } + }while(!map_element_is_last_for_tile(mapElement2++)); + + uint8 *pdl = (uint8 *)&edx; uint8 *pdh = (uint8 *)&edx+1; uint8 *pbl = (uint8 *)&ebx; uint8 *pbh = (uint8 *)&ebx+1; -//loc_663BB5: - - //callcode_push2(0x663BB5, saved_eax, saved_ecx, &eax, &ebx, &ecx, (int *)&edx, (int *)&esi, &edi, &ebp); return ebx; -do{ - eax = ((rct_map_element *)mapElement2)->type&MAP_ELEMENT_TYPE_MASK; - if(eax==MAP_ELEMENT_TYPE_FENCE || eax==MAP_ELEMENT_TYPE_SCENERY || mapElement2->flags&0x10 || mapElement2==(rct_map_element *)esi) - continue; - if(mapElement2>(rct_map_element *)esi) - goto loc_663BD4; - if(*pdl<((rct_map_element *)mapElement2)->clearance_height) - goto loc_663C4F; - continue; -loc_663BD4: - if(*pbh>((rct_map_element *)mapElement2)->base_height) - goto loc_663C4F; -loc_663BD9: - ; -}while(!map_element_is_last_for_tile(mapElement2++)); - - edi = (int)mapElement2; - ecx = saved_ecx; - eax = saved_eax; + esi = (int)mapElement; + edi = (int)mapElement2; + *pbh = unk; //To be continued... RCT2_CALLFUNC_X(0x663BE4, &eax, &ebx, &ecx, (int *)&edx, (int *)&esi, &edi, &ebp); return ebx; - -loc_663C4F: - esi = edi; - map_obstruction_set_error_text((rct_map_element *)esi); - return MONEY32_UNDEFINED; - } void game_command_set_land_height(int *eax, int *ebx, int *ecx, int *edx, int *esi, int *edi, int *ebp) From e5ad14e3f5c00925973149afa5b1f92d401385c1 Mon Sep 17 00:00:00 2001 From: "U-HP-Pavilion-PC\\Cameron" Date: Sun, 15 Nov 2015 12:20:01 -0600 Subject: [PATCH 07/10] Finished decompiling --- src/world/map.c | 39 ++++++++++++++++++++------------------- 1 file changed, 20 insertions(+), 19 deletions(-) diff --git a/src/world/map.c b/src/world/map.c index c62961b160..5015e4523d 100644 --- a/src/world/map.c +++ b/src/world/map.c @@ -1987,11 +1987,6 @@ static money32 map_set_land_height(int flags, int x, int y, int height, int styl //dh: style uint32 esi = 0; - int saved_eax; - int saved_ebx; - int saved_ecx; - unsigned int saved_edx; - //Uncomment to use vanilla code //RCT2_CALLFUNC_X(0x006639FE, &eax, &ebx, &ecx, (int *)&edx, (int *)&esi, &edi, &ebp); return ebx; @@ -2085,7 +2080,7 @@ static money32 map_set_land_height(int flags, int x, int y, int height, int styl } //rct2: 0x663B93 - if(map_can_construct_with_clear_at(eax&0xFFFF, ecx&0xFFFF, height, unk, RCT2_ADDRESS(0x663CB9, void), 0xF)==false) + if(map_can_construct_with_clear_at(x, y, height, unk, RCT2_ADDRESS(0x663CB9, void), 0xF)==false) return MONEY32_UNDEFINED; rct_map_element *mapElement2 = map_get_first_element_at(x/32, y/32); //mapElement2 = edi @@ -2113,19 +2108,25 @@ static money32 map_set_land_height(int flags, int x, int y, int height, int styl } }while(!map_element_is_last_for_tile(mapElement2++)); - - uint8 *pdl = (uint8 *)&edx; - uint8 *pdh = (uint8 *)&edx+1; - uint8 *pbl = (uint8 *)&ebx; - uint8 *pbh = (uint8 *)&ebx+1; - - esi = (int)mapElement; - edi = (int)mapElement2; - *pbh = unk; - - //To be continued... - RCT2_CALLFUNC_X(0x663BE4, &eax, &ebx, &ecx, (int *)&edx, (int *)&esi, &edi, &ebp); - return ebx; + //rct2: 0x663BE4 + if((flags&GAME_COMMAND_FLAG_APPLY)) + { + //rct2: 0x663BEB + mapElement = map_get_surface_element_at(x/32, y/32); + mapElement->base_height = height; + mapElement->clearance_height = height; + mapElement->properties.surface.slope &= MAP_ELEMENT_SLOPE_EDGE_STYLE_MASK; + mapElement->properties.surface.slope |= style; + //rct2: 0x663C17 + int slope = mapElement->properties.surface.terrain&MAP_ELEMENT_SLOPE_MASK; //slope = bh + if(slope!=0 && slope<=height/2) + mapElement->properties.surface.terrain &= MAP_ELEMENT_SURFACE_TERRAIN_MASK; + map_invalidate_tile_full(x, y); + } + //rct2: 0x663C30 + if(RCT2_GLOBAL(RCT2_ADDRESS_PARK_FLAGS, uint32)&0x800) + return 0; + return RCT2_GLOBAL(0x9E2E18, money32); } void game_command_set_land_height(int *eax, int *ebx, int *ecx, int *edx, int *esi, int *edi, int *ebp) From 1fc7793c2aea09439b0f0e91bc73023f2f662270 Mon Sep 17 00:00:00 2001 From: Cameron Date: Sun, 15 Nov 2015 15:48:27 -0600 Subject: [PATCH 08/10] Clean up and match coding style --- src/world/map.c | 466 ++++++++++-------------------------------------- 1 file changed, 94 insertions(+), 372 deletions(-) diff --git a/src/world/map.c b/src/world/map.c index 5015e4523d..b775827a6a 100644 --- a/src/world/map.c +++ b/src/world/map.c @@ -1667,267 +1667,6 @@ const uint8 map_element_lower_styles[5][32] = { { 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x0B, 0x00, 0x0D, 0x0E, 0x00 }, }; -//Hack: pushes variables to the stack before jumping to address -//These functions are temporary and are used for debugging the decompiled code. -#ifdef __GNUC__ -static int callcode_push3(int address, int stackvar1, int stackvar2, int stackvar3, int *_eax, int *_ebx, int *_ecx, int *_edx, int *_esi, int *_edi, int *_ebp) -{ - int result; - - __asm__ ( "\ - \n\ - /* Store C's base pointer*/ \n\ - push %%ebp \n\ - push %%ebx \n\ - \n\ - /* Store %[address] to call*/ \n\ - push %[address] \n\ - \n\ - /* Set all registers to the input values*/ \n\ - mov %[_eax], %%eax \n\ - mov (%%eax), %%eax \n\ - mov %[_ebx], %%ebx \n\ - mov (%%ebx), %%ebx \n\ - mov %[_ecx], %%ecx \n\ - mov (%%ecx), %%ecx \n\ - mov %[_edx], %%edx \n\ - mov (%%edx), %%edx \n\ - mov %[_esi], %%esi \n\ - mov (%%esi), %%esi \n\ - mov %[_edi], %%edi \n\ - mov (%%edi), %%edi \n\ - push $_foo \n\ - push %[stackvar1] \n\ - push %[stackvar2] \n\ - push %[stackvar3] \n\ - mov %[_ebp], %%ebp \n\ - mov (%%ebp), %%ebp \n\ - \n\ - /* Call function*/ \n\ - /* Push registers required by function */ \n\ - /* call *(%%esp) */ \n\ - jmp *16(%%esp) \n\ - _foo: \n\ - \n\ - /* Store output eax */ \n\ - push %%eax \n\ - push %%ebp \n\ - push %%ebx \n\ - mov 20(%%esp), %%ebp \n\ - mov 16(%%esp), %%ebx \n\ - /* Get resulting ecx, edx, esi, edi registers*/ \n\ - mov %[_edi], %%eax \n\ - mov %%edi, (%%eax) \n\ - mov %[_esi], %%eax \n\ - mov %%esi, (%%eax) \n\ - mov %[_edx], %%eax \n\ - mov %%edx, (%%eax) \n\ - mov %[_ecx], %%eax \n\ - mov %%ecx, (%%eax) \n\ - /* Pop ebx reg into ecx*/ \n\ - pop %%ecx \n\ - mov %[_ebx], %%eax \n\ - mov %%ecx, (%%eax) \n\ - \n\ - /* Pop ebp reg into ecx */\n\ - pop %%ecx \n\ - mov %[_ebp], %%eax \n\ - mov %%ecx, (%%eax) \n\ - \n\ - pop %%eax \n\ - /* Get resulting eax register*/ \n\ - mov %[_eax], %%ecx \n\ - mov %%eax, (%%ecx) \n\ - \n\ - /* Save flags as return in eax*/ \n\ - lahf \n\ - /* Pop address*/ \n\ - pop %%ebp \n\ - \n\ - pop %%ebx \n\ - pop %%ebp \n\ - /* Load result with flags */ \n\ - mov %%eax, %[result] \n\ - " : [address] "+m" (address), [_eax] "+m" (_eax), [_ebx] "+m" (_ebx), [_ecx] "+m" (_ecx), [_edx] "+m" (_edx), [_esi] "+m" (_esi), [_edi] "+m" (_edi), [_ebp] "+m" (_ebp), [result] "+m" (result) - - : [stackvar1] "m" (stackvar1), [stackvar2] "m" (stackvar2), [stackvar3] "m" (stackvar3) - : "eax","ecx","edx","esi","edi" - ); - return result&0xFF00; -} - -static int callcode_push2(int address, int stackvar1, int stackvar2, int *_eax, int *_ebx, int *_ecx, int *_edx, int *_esi, int *_edi, int *_ebp) -{ - int result; - - __asm__ ( "\ - \n\ - /* Store C's base pointer*/ \n\ - push %%ebp \n\ - push %%ebx \n\ - \n\ - /* Store %[address] to call*/ \n\ - push %[address] \n\ - \n\ - /* Set all registers to the input values*/ \n\ - mov %[_eax], %%eax \n\ - mov (%%eax), %%eax \n\ - mov %[_ebx], %%ebx \n\ - mov (%%ebx), %%ebx \n\ - mov %[_ecx], %%ecx \n\ - mov (%%ecx), %%ecx \n\ - mov %[_edx], %%edx \n\ - mov (%%edx), %%edx \n\ - mov %[_esi], %%esi \n\ - mov (%%esi), %%esi \n\ - mov %[_edi], %%edi \n\ - mov (%%edi), %%edi \n\ - push $foo \n\ - push %[stackvar1] \n\ - push %[stackvar2] \n\ - mov %[_ebp], %%ebp \n\ - mov (%%ebp), %%ebp \n\ - \n\ - /* Call function*/ \n\ - /* Push registers required by function */ \n\ - /* call *(%%esp) */ \n\ - jmp *12(%%esp) \n\ - foo: \n\ - \n\ - /* Store output eax */ \n\ - push %%eax \n\ - push %%ebp \n\ - push %%ebx \n\ - mov 20(%%esp), %%ebp \n\ - mov 16(%%esp), %%ebx \n\ - /* Get resulting ecx, edx, esi, edi registers*/ \n\ - mov %[_edi], %%eax \n\ - mov %%edi, (%%eax) \n\ - mov %[_esi], %%eax \n\ - mov %%esi, (%%eax) \n\ - mov %[_edx], %%eax \n\ - mov %%edx, (%%eax) \n\ - mov %[_ecx], %%eax \n\ - mov %%ecx, (%%eax) \n\ - /* Pop ebx reg into ecx*/ \n\ - pop %%ecx \n\ - mov %[_ebx], %%eax \n\ - mov %%ecx, (%%eax) \n\ - \n\ - /* Pop ebp reg into ecx */\n\ - pop %%ecx \n\ - mov %[_ebp], %%eax \n\ - mov %%ecx, (%%eax) \n\ - \n\ - pop %%eax \n\ - /* Get resulting eax register*/ \n\ - mov %[_eax], %%ecx \n\ - mov %%eax, (%%ecx) \n\ - \n\ - /* Save flags as return in eax*/ \n\ - lahf \n\ - /* Pop address*/ \n\ - pop %%ebp \n\ - \n\ - pop %%ebx \n\ - pop %%ebp \n\ - /* Load result with flags */ \n\ - mov %%eax, %[result] \n\ - " : [address] "+m" (address), [_eax] "+m" (_eax), [_ebx] "+m" (_ebx), [_ecx] "+m" (_ecx), [_edx] "+m" (_edx), [_esi] "+m" (_esi), [_edi] "+m" (_edi), [_ebp] "+m" (_ebp), [result] "+m" (result) - - : [stackvar1] "m" (stackvar1), [stackvar2] "m" (stackvar2) - : "eax","ecx","edx","esi","edi" - ); - return result&0xFF00; -} - -static int callcode_push1(int address, int stackvar, int *_eax, int *_ebx, int *_ecx, int *_edx, int *_esi, int *_edi, int *_ebp) -{ - int result; - - __asm__ ( "\ - \n\ - /* Store C's base pointer*/ \n\ - push %%ebp \n\ - push %%ebx \n\ - \n\ - /* Store %[address] to call*/ \n\ - push %[address] \n\ - \n\ - /* Set all registers to the input values*/ \n\ - mov %[_eax], %%eax \n\ - mov (%%eax), %%eax \n\ - mov %[_ebx], %%ebx \n\ - mov (%%ebx), %%ebx \n\ - mov %[_ecx], %%ecx \n\ - mov (%%ecx), %%ecx \n\ - mov %[_edx], %%edx \n\ - mov (%%edx), %%edx \n\ - mov %[_esi], %%esi \n\ - mov (%%esi), %%esi \n\ - mov %[_edi], %%edi \n\ - mov (%%edi), %%edi \n\ - /* Hack: called code should return back to this function */ \n\ - push $__foo \n\ - /* Push variable */\n\ - push %[stackvar] \n\ - mov %[_ebp], %%ebp \n\ - mov (%%ebp), %%ebp \n\ - \n\ - /* Call function*/ \n\ - /* call *(%%esp) */ \n\ - /* int $3 */\n\ - jmp *8(%%esp) \n\ - __foo: \n\ - \n\ - /* Store output eax */ \n\ - push %%eax \n\ - push %%ebp \n\ - push %%ebx \n\ - mov 20(%%esp), %%ebp \n\ - mov 16(%%esp), %%ebx \n\ - /* Get resulting ecx, edx, esi, edi registers*/ \n\ - mov %[_edi], %%eax \n\ - mov %%edi, (%%eax) \n\ - mov %[_esi], %%eax \n\ - mov %%esi, (%%eax) \n\ - mov %[_edx], %%eax \n\ - mov %%edx, (%%eax) \n\ - mov %[_ecx], %%eax \n\ - mov %%ecx, (%%eax) \n\ - /* Pop ebx reg into ecx*/ \n\ - pop %%ecx \n\ - mov %[_ebx], %%eax \n\ - mov %%ecx, (%%eax) \n\ - \n\ - /* Pop ebp reg into ecx */\n\ - pop %%ecx \n\ - mov %[_ebp], %%eax \n\ - mov %%ecx, (%%eax) \n\ - \n\ - pop %%eax \n\ - /* Get resulting eax register*/ \n\ - mov %[_eax], %%ecx \n\ - mov %%eax, (%%ecx) \n\ - \n\ - /* Save flags as return in eax*/ \n\ - lahf \n\ - /* Pop address*/ \n\ - pop %%ebp \n\ - \n\ - pop %%ebx \n\ - pop %%ebp \n\ - /* Load result with flags */ \n\ - mov %%eax, %[result] \n\ - " : [address] "+m" (address), [_eax] "+m" (_eax), [_ebx] "+m" (_ebx), [_ecx] "+m" (_ecx), [_edx] "+m" (_edx), [_esi] "+m" (_esi), [_edi] "+m" (_edi), [_ebp] "+m" (_ebp), [result] "+m" (result) - - : [stackvar] "m" (stackvar) - : "eax","ecx","edx","esi","edi" - ); - return result&0xFF00; -} -#endif //__GNUC__ - static money32 map_set_land_height(int flags, int x, int y, int height, int style, int selectionType) { if (RCT2_GLOBAL(RCT2_ADDRESS_GAME_PAUSED, uint8) != 0 && !gConfigCheat.build_in_pause_mode) { @@ -1971,160 +1710,143 @@ static money32 map_set_land_height(int flags, int x, int y, int height, int styl } } - /* Continuing decompilation - work in progress - * Known bugs (introduced by disassembly): - * none! Still requires testing, though. - * Original bugs: - * Lowering the land tile underneath a wall removes the wall. - * Land can be raised over flat scenery items (gardens, for example) without removing them. - * Removal price of walls is not added. - * Removal price of flat scenery is not counted when raising the center of a tile. - */ - - int eax = x, ebx = flags, ecx = y, edi = selectionType << 5, ebp = 0; - uint32 edx = (style << 8) | height; - //dl: height - //dh: style - uint32 esi = 0; - //Uncomment to use vanilla code - //RCT2_CALLFUNC_X(0x006639FE, &eax, &ebx, &ecx, (int *)&edx, (int *)&esi, &edi, &ebp); return ebx; + /* + registers regs = {0}; + regs.eax = x; + regs.ebx = flags; + regs.ecx = y; + regs.dl = height; + regs.dh = style; + regs.esi = 0; + regs.edi = selectionType << 5; + regs.ebp = 0; + RCT2_CALLFUNC_Y(0x006639FE, ®s); return regs.ebx; + */ RCT2_GLOBAL(0x9E2E18, money32) = MONEY(0, 0); - if(ebx&GAME_COMMAND_FLAG_APPLY) + if(flags & GAME_COMMAND_FLAG_APPLY) { footpath_remove_litter(x, y, map_element_height(x, y)); - map_remove_walls_at(x, y, height*8-16, height*8+32); + map_remove_walls_at(x, y, height * 8 - 16, height * 8 + 32); } RCT2_GLOBAL(0x9E2E18, money32) += MONEY(20, 0); - rct_map_element *mapElement = map_get_first_element_at(x/32, y/32); //mapElement = esi - - int zHigh = height+4; //zHigh = dh - -//loc_663A54: - do{ - int elementType = map_element_get_type(mapElement); //elementType = eax - rct_scenery_entry *sceneryEntry; //eax - - if(elementType!=MAP_ELEMENT_TYPE_SCENERY || height>mapElement->clearance_height || zHigh<(mapElement)->base_height) + //Check for obstructing scenery + rct_map_element *mapElement = map_get_first_element_at(x / 32, y / 32); + do{ + if(map_element_get_type(mapElement) != MAP_ELEMENT_TYPE_SCENERY) continue; - elementType = mapElement->properties.scenery.type; - sceneryEntry = RCT2_ADDRESS(RCT2_ADDRESS_SMALL_SCENERY_ENTRIES, rct_scenery_entry *)[elementType]; - if(sceneryEntry->small_scenery.height>64 && RCT2_GLOBAL(RCT2_ADDRESS_PARK_FLAGS, uint32)&PARK_FLAGS_FORBID_TREE_REMOVAL) + if(height > mapElement->clearance_height) + continue; + if(height + 4 < mapElement->base_height) + continue; + rct_scenery_entry *sceneryEntry = RCT2_ADDRESS(RCT2_ADDRESS_SMALL_SCENERY_ENTRIES, rct_scenery_entry *)[mapElement->properties.scenery.type]; //sceneryEntry = eax + if(sceneryEntry->small_scenery.height > 64 && RCT2_GLOBAL(RCT2_ADDRESS_PARK_FLAGS, uint32) & PARK_FLAGS_FORBID_TREE_REMOVAL) { map_obstruction_set_error_text(mapElement); return MONEY32_UNDEFINED; } RCT2_GLOBAL(0x9E2E18, money32) += MONEY(sceneryEntry->small_scenery.removal_price, 0); - if(flags&GAME_COMMAND_FLAG_APPLY) + if(flags & GAME_COMMAND_FLAG_APPLY) map_element_remove(mapElement--); }while(!map_element_is_last_for_tile(mapElement++)); - mapElement = map_get_first_element_at(x/32, y/32); //mapElement = esi - -//loc_663AC4: + //Check for obstructing rides + mapElement = map_get_first_element_at(x / 32, y / 32); do{ - if(map_element_get_type(mapElement)!=8) //eax + if(map_element_get_type(mapElement) != MAP_ELEMENT_TYPE_TRACK) continue; - int rideIndex = mapElement->properties.track.ride_index; //rideIndex = ebp - int maxHeight = GET_RIDE_ENTRY(GET_RIDE(rideIndex)->subtype)->max_height; //maxHeight = eax - if(maxHeight==0) - maxHeight = RCT2_GLOBAL(0x97D218+8*GET_RIDE(rideIndex)->type, uint8); - int zDelta = mapElement->clearance_height-height; //zDelta = ebx - if(zDelta>=0 && zDelta/2>maxHeight && gCheatsDisableSupportLimits==false) + int rideIndex = mapElement->properties.track.ride_index; + int maxHeight = GET_RIDE_ENTRY(GET_RIDE(rideIndex)->subtype)->max_height; + if(maxHeight == 0) + maxHeight = RCT2_GLOBAL(0x97D218 + 8 * GET_RIDE(rideIndex)->type, uint8); + int zDelta = mapElement->clearance_height - height; + if(zDelta >= 0 && zDelta/2 > maxHeight && gCheatsDisableSupportLimits == false) { RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_TEXT, rct_string_id) = STR_SUPPORTS_CANT_BE_EXTENDED; return MONEY32_UNDEFINED; } }while(!map_element_is_last_for_tile(mapElement++)); - mapElement = map_get_surface_element_at(x/32, y/32); - - if(mapElement->type&MAP_ELEMENT_TYPE_FLAG_HIGHLIGHT) + uint8 zCorner = height; //z position of highest corner of tile + rct_map_element *surfaceElement = map_get_surface_element_at(x / 32, y / 32); + if(surfaceElement->type & MAP_ELEMENT_TYPE_FLAG_HIGHLIGHT) { - int waterHeight = mapElement->properties.surface.terrain&MAP_ELEMENT_WATER_HEIGHT_MASK; //waterHeight = ecx - if(waterHeight!=0) + int waterHeight = surfaceElement->properties.surface.terrain & MAP_ELEMENT_WATER_HEIGHT_MASK; + if(waterHeight != 0) { - waterHeight = waterHeight*2-2; - uint8 unk = height; //unk = bh - if((style&0x1F)) + if(style & 0x1F) { - unk += 2; - if((style&0x10)) + zCorner += 2; + if(style & 0x10) { - unk += 2; + zCorner += 2; } } - //loc_663B6A: - if(unk>waterHeight) + if(zCorner > waterHeight * 2 - 2) + { + surfaceElement++; + map_obstruction_set_error_text(surfaceElement); + return MONEY32_UNDEFINED; + } + } + } + + zCorner = height; + if(style & 0xF) + { + zCorner += 2; + if(style & 0x10) + { + zCorner += 2; + } + } + + if(map_can_construct_with_clear_at(x, y, height, zCorner, RCT2_ADDRESS(0x663CB9, void), 0xF) == false) + return MONEY32_UNDEFINED; + + mapElement = map_get_first_element_at(x / 32, y / 32); + do{ + int elementType = map_element_get_type(mapElement); + + if(elementType == MAP_ELEMENT_TYPE_FENCE) + continue; + if(elementType == MAP_ELEMENT_TYPE_SCENERY) + continue; + if(mapElement->flags & 0x10) + continue; + if(mapElement == surfaceElement) + continue; + if(mapElement > surfaceElement) + { + if(zCorner > mapElement->base_height) { - //rct2: 0x663C5A - mapElement++; map_obstruction_set_error_text(mapElement); return MONEY32_UNDEFINED; } - } - } -//loc_663B72: - - uint8 unk = height; //unk = bh - - if((style&0xF)) - { - unk += 2; - if((style&0x10)) - { - unk += 2; - } - } - - //rct2: 0x663B93 - if(map_can_construct_with_clear_at(x, y, height, unk, RCT2_ADDRESS(0x663CB9, void), 0xF)==false) - return MONEY32_UNDEFINED; - - rct_map_element *mapElement2 = map_get_first_element_at(x/32, y/32); //mapElement2 = edi - - -//loc_663BB5: - do{ - int elementType = map_element_get_type(mapElement2); //elementType = al - - if(elementType==MAP_ELEMENT_TYPE_FENCE || elementType==MAP_ELEMENT_TYPE_SCENERY || mapElement2->flags&0x10 || mapElement2==mapElement) - continue; - if(mapElement2>mapElement) - { - if(unk > mapElement2->base_height) - { - map_obstruction_set_error_text(mapElement2); - return MONEY32_UNDEFINED; - } continue; } - if(height < mapElement2->clearance_height) + if(height < mapElement->clearance_height) { - map_obstruction_set_error_text(mapElement2); + map_obstruction_set_error_text(mapElement); return MONEY32_UNDEFINED; } - }while(!map_element_is_last_for_tile(mapElement2++)); + }while(!map_element_is_last_for_tile(mapElement++)); - //rct2: 0x663BE4 - if((flags&GAME_COMMAND_FLAG_APPLY)) + if(flags & GAME_COMMAND_FLAG_APPLY) { - //rct2: 0x663BEB - mapElement = map_get_surface_element_at(x/32, y/32); - mapElement->base_height = height; - mapElement->clearance_height = height; - mapElement->properties.surface.slope &= MAP_ELEMENT_SLOPE_EDGE_STYLE_MASK; - mapElement->properties.surface.slope |= style; - //rct2: 0x663C17 - int slope = mapElement->properties.surface.terrain&MAP_ELEMENT_SLOPE_MASK; //slope = bh - if(slope!=0 && slope<=height/2) - mapElement->properties.surface.terrain &= MAP_ELEMENT_SURFACE_TERRAIN_MASK; + surfaceElement = map_get_surface_element_at(x / 32, y / 32); + surfaceElement->base_height = height; + surfaceElement->clearance_height = height; + surfaceElement->properties.surface.slope &= MAP_ELEMENT_SLOPE_EDGE_STYLE_MASK; + surfaceElement->properties.surface.slope |= style; + int slope = surfaceElement->properties.surface.terrain & MAP_ELEMENT_SLOPE_MASK; + if(slope != 0 && slope <= height / 2) + surfaceElement->properties.surface.terrain &= MAP_ELEMENT_SURFACE_TERRAIN_MASK; map_invalidate_tile_full(x, y); } - //rct2: 0x663C30 - if(RCT2_GLOBAL(RCT2_ADDRESS_PARK_FLAGS, uint32)&0x800) + if(RCT2_GLOBAL(RCT2_ADDRESS_PARK_FLAGS, uint32) & PARK_FLAGS_NO_MONEY) return 0; return RCT2_GLOBAL(0x9E2E18, money32); } @@ -5406,4 +5128,4 @@ rct_map_element *map_get_track_element_at_of_type(int x, int y, int z, int track } while (!map_element_is_last_for_tile(mapElement++)); return NULL; -} \ No newline at end of file +} From 763a5f29388b6056c376c4e17954c18864f808be Mon Sep 17 00:00:00 2001 From: Cameron Date: Sun, 15 Nov 2015 15:50:36 -0600 Subject: [PATCH 09/10] Restore newline at end of file --- src/world/map.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/world/map.c b/src/world/map.c index b775827a6a..d5a587f4df 100644 --- a/src/world/map.c +++ b/src/world/map.c @@ -5129,3 +5129,4 @@ rct_map_element *map_get_track_element_at_of_type(int x, int y, int z, int track return NULL; } + From da79f706f386dca6a0ef686f1468f9dd9af48cc8 Mon Sep 17 00:00:00 2001 From: "U-ASUS-EEEPC\\Cameron Hall" Date: Mon, 16 Nov 2015 12:09:11 -0600 Subject: [PATCH 10/10] Hoist gCheatsDisableSupportLimits check outside of loop --- src/world/map.c | 35 +++++++++++++++++++---------------- 1 file changed, 19 insertions(+), 16 deletions(-) diff --git a/src/world/map.c b/src/world/map.c index d5a587f4df..a0b705fd65 100644 --- a/src/world/map.c +++ b/src/world/map.c @@ -1752,22 +1752,25 @@ static money32 map_set_land_height(int flags, int x, int y, int height, int styl map_element_remove(mapElement--); }while(!map_element_is_last_for_tile(mapElement++)); - //Check for obstructing rides - mapElement = map_get_first_element_at(x / 32, y / 32); - do{ - if(map_element_get_type(mapElement) != MAP_ELEMENT_TYPE_TRACK) - continue; - int rideIndex = mapElement->properties.track.ride_index; - int maxHeight = GET_RIDE_ENTRY(GET_RIDE(rideIndex)->subtype)->max_height; - if(maxHeight == 0) - maxHeight = RCT2_GLOBAL(0x97D218 + 8 * GET_RIDE(rideIndex)->type, uint8); - int zDelta = mapElement->clearance_height - height; - if(zDelta >= 0 && zDelta/2 > maxHeight && gCheatsDisableSupportLimits == false) - { - RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_TEXT, rct_string_id) = STR_SUPPORTS_CANT_BE_EXTENDED; - return MONEY32_UNDEFINED; - } - }while(!map_element_is_last_for_tile(mapElement++)); + //Check for ride support limits + if(gCheatsDisableSupportLimits==false) + { + mapElement = map_get_first_element_at(x / 32, y / 32); + do{ + if(map_element_get_type(mapElement) != MAP_ELEMENT_TYPE_TRACK) + continue; + int rideIndex = mapElement->properties.track.ride_index; + int maxHeight = GET_RIDE_ENTRY(GET_RIDE(rideIndex)->subtype)->max_height; + if(maxHeight == 0) + maxHeight = RCT2_GLOBAL(0x97D218 + 8 * GET_RIDE(rideIndex)->type, uint8); + int zDelta = mapElement->clearance_height - height; + if(zDelta >= 0 && zDelta/2 > maxHeight) + { + RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_TEXT, rct_string_id) = STR_SUPPORTS_CANT_BE_EXTENDED; + return MONEY32_UNDEFINED; + } + }while(!map_element_is_last_for_tile(mapElement++)); + } uint8 zCorner = height; //z position of highest corner of tile rct_map_element *surfaceElement = map_get_surface_element_at(x / 32, y / 32);