Archives for posts with tag: OpenRCT2

After working mainly on the windows for OpenRCT2 I am at the point where I can not go any further. Not every window is finished at this point but it is close to being complete. Annoyingly not much was learned in the process of finishing off the windows as none of them did anything too exciting. There is one major window that has not been completed and that is the editor. When that is finished we can finally start to move the windows into more regular C like functions (At present variables have to be passed on registers instead of by the stack). This will increase the clarity of the code but does not change the function.

The other area of OpenRCT2 I have been participating in is the peep logic. Whenever a peep does anything it goes through the peep_update function. This function then calls the relevant state function such as peep_update_watching. The watching function has its own sub state and from the sub state will decide if the peep should take a drink or photo. If it is going to take a photo it then sets an action state to photo. Every call to peep_update_watching will increment the action until it is finished it will then move onto the next watching sub state. It sounds a bit complex when written out so I will try create a diagram to explain this.

update

The best thing about the peep_update functions are they use a large variety of code and they are relatively easy to work out. If a peep is throwing up for example you know the next function will probably be placing a sick sprite on the ground.

In terms of the project as a whole we are nearing 50% done. Hopefully the process will only increase in speed as more of the structure becomes known. There are also a couple people who are playing on the existing builds so it’s getting important to insure that there are no game breaking bugs before merges.

I’m still working on OpenRCT2 and it has been coming along nicely. The other week I completed a new feature for the project, the text input window. In the normal RCT2 whenever you want to label something such as a ride or an individual guest you would be presented with a classic windows input dialog box. Apart from being not very cross platform compatible it also does not match the RCT2 look. I decided that we should probably implement a new window that would match the existing style.  The final window ended up looking like the below.

New input window

The colours match the window that opened it and although not shown in that picture there is a cursor indicating where the text will be inserted.

I used the SDL2.0 text input API which ended up being much simpler than I was expecting. By using the SDL API I did not need to have to worry about if CAPS LOCK or shift was pressed and it even handles ‘é’ correctly. I’m quite proud of the results and it shows the sort of simple features that OpenRCT2 can bring in. IntelOrca has suggested creating a save and load game dialog in a similar way but for now I think it would be best to focus in other areas.

One of the other parts I have been working on in OpenRCT2 is the windows and peep related update functions. It is quite enjoyable reversing these functions as you start to get an understanding of all of the available options that a peep has and why it does them. One interesting note is that peeps have a potential of becoming unhappy if you keep picking them up. You also can generate a “I feel like i am being watched” thought if you keep the peep viewport window open. To reset what a peep is doing the game puts them in a falling state. This happens every time they leave a ride/enter the park or generally do any action. When queuing in lines there are a whole host of rules related to how long before they started generating the “I’ve been queuing for ages” thought. Another interesting note is they will only give up queuing if the ride closes or there happiness falls below a certain value. When a peep sits down the length of time they stay seated is related to there tiredness. If they have any food on them they are required to finish eating it all before they can sit up.

I’m not close to finishing all of the peep related functions so I am sure there will be lots of discoveries still to come. See this branch for the latest (in terms of peep functions).

Todays mission was to squash the following bug. https://github.com/IntelOrca/OpenRCT2/issues/317. From the dump we are able to work out that it is coming from 0x66478e which is part of the larger function 0x6646E1. This is called after climate_update() in the game logic update function. From looking around the area at the code it would appear that it is some sort of issue with the map elements. The first task is to work out what reproduces the bug. As it is something to do with map elements we can have a look at what has changed that involves that. Recently I had added mouse click that used map elements so that may be a source of the issue. After trying a couple different clicking about techniques the issue was not reproducing. Strangely the issue was being caused by the information kiosk. The way this was picked up was that there was another issue raised about how the information kiosk was causing unexpected news items. The way to reproduce the bug is to place an information kiosk and make sure the direction it is facing is not towards a path. This will cause a mistaken news item about peeps not being able to reach the kiosk. When you look at the news about the kiosk it will crash. The bug was narrowed down further by removing certain functions that the news window uses. Eventually the bug was found in the paint function. On inspecting the paint function by stepping through it I noticed that the draw_string for a news item was not performing correctly. By following it all the way through I noticed that a pointer we passed into the draw_string function is also used internally in the function. This was causing unexpected issues. To remove this all that was required was to change where the original pointer was pointing to. Job done.

So its been quite a while since my last post. I stopped working on my NASM OpenGL implementations for a while after encountering too many issues with maths. I will return to that eventually but I have lost interest for now.

The latest project I have been working on is OpenRCT2. The project aims to rewrite Roller Coaster Tycoon 2 in C code by looking at the assembly instructions. After spending so much time playing in NASM I felt this was right up my alley.

This post is about how I went about decompiling the draw rain function. I haven’t quite decided the name of the function yet so it will be called sub_684027. Earlier this week I noticed that someone was working on the rain drawing functions. He decompiled all of the functions up until sub_684027. This is a snapshot of what was decompiled.

I had a quick look in ollyDbg at the 684027 address and realised it didn’t call anything else. This is always a good sign as it generally means that the function will not be too difficult to decompile. I made some initial notes on decompiling it and uploaded the changes. You will notice that the code is horribly formatted and does not compile. This was just a very rough draft of the function to try work out how it was working.

The next stage was to convert it into actual compilable code. Normally at this stage I would try iron out all of the bugs in the code. It just so happened that I didn’t have access to my dev machine that day so this code was never actually tested. When I did test it I noticed it was still a bit incorrect hence why I produced this version. Eagle eyed readers will notice I have also removed a bunch of global variable assignments that just created backups of the functions parameters. One part I always enjoy is searching for the address’s of every global variable to see if we have already labelled them. It was during this searching exercise that the drawpixelinfo struct appeared. This struct contains information about the screen and has a pointer to the actual pixels that are displayed. As soon as I spotted this it started to simplify the code greatly. I can immediately see which variables are  for height, width, left, right, pointers.

At this stage I normally iron out every single possible bug I can find. I encountered an odd bug at this stage that caused rain drops to stay on the screen. It took me approx 2 hours to work out what caused this. After fixing all of the bugs now came the fun part of figuring out names for every variable and generally increasing readability. This is the code after the final cleanup sweep. There are still one or two variables that have not been renamed but I had to stop at this point as it was getting late. One not very obvious change is modifying the following lines:

eax = *((uint8*)ebp);
eax--;
edi &= eax;
RCT2_GLOBAL(0xEE7870,uint32) = edi;

to
 
uint8 pattern_x_space = *pattern++;
uint8 pattern_start_x_offset = edi % pattern_x_space;

Its not immediatly obvious but edi&(eax-1) is the same as edi%eax. EAX in this situation will always be 2^n. I only know this from playing about with the code for a while. This shortcut has been cleverly created to save on doing a divide instruction that at the time of RCT2 was expensive. For us it just makes the code harder to read so there is no need for it.

The very final version of the code has now labelled all of the variables. I’ve replaced the while loop with a for loop and I’ve tried to group together anything that operates on the same variable. At this stage I can start labelling the input parameters and assigning an RCT2_ADDRESS name to each of the left over addresses.

Eventually when all of RCT2 has been decompiled we will go over all of the global variables and either remove them or convert them into normal C variables. I hope this brief guid on decompiling helps people get interested in OpenRCT2.