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.

Advertisements

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.

As discussed in my last post I am working my way through some OpenGL 3+ tutorials. In the process I have had to use GLEW. GLEW is a wrapper for OpenGL functions in the newer versions of OpenGL. It means you don’t need to call glGetProcAddress a ton of times before you can actually draw anything. It is very handy but I find it does not play nice when you are trying to link to it. To begin with the dll does not strip anything from the symbol name. What that means is glewInit is called _glewInit@0 in the dll. This isn’t much of an issue in fact its quite nice to know that the @0 means that I don’t need to pass any params. Its only mildly annoying when you have got used to dlls not having it. The bigger issue is finding the function pointers.

glBindVertexArray is a function found in OpenGL 3+ it therefore has to be loaded through GLEW. The dll informs me that it is called __glewBindVertexArray. I can understand the change between gl and glew as its to prevent any collisions. The extra underscore threw me to begin with but then it is probably because this is a pointer to my function and it is an extra warning to treat it special. My main problem with it is if I am using the .lib file to link with then I can’t find the sysmbol __glewBindVertexArray. Instead the symbol happens to be __imp____glewBindVertexArray. I assume the __imp__ part is something to do with this being a variable that is filled out when GLEW inits but I will investigate this further. All in all it means I will have to create a macro if I want to be able to link my code with ALINK and MS LINK. 

Whilst looking into this issue I also played about with changing to using static lib files. They would resolve my issues but at the same time I would never be able to link with ALINK since the static libs use parts of ALINK that were never finished. A big fancy macro looks like the best solution. 

After successfully writing solutions for 1-10 of NeHe’s OpenGL tutorials I decided it was time to venture into newer technology. OpenGL 3+ is a bit harder to use compared to the older versions. The main issue is creating a render context. This was already a hard task in assembler and 3+ does not make the task any easier. First you create a context just like in NeHe’s tutorial but then you need to get function pointers for all of the OpenGL functions you plan on calling. After achieving this you destroy your context and remake it using the functions you have just found. It is a bit of tedious task I think I’m confident I could achieve it but I have decided I don’t want to focus on that for my latest endeavor.

What I plan to do instead is use GLFW and GLEW to help with OpenGL. GLFW is an OpenGL library that helps with creating windows and such. GLEW is an OpenGL extensions library that gets all of the function pointers I mentioned earlier and gets them ready for use. Again I plan to follow someone else’s tutorial as I do not have much knowledge of OpenGL at this point. The tutorials I plan to rewrite are from http://www.opengl-tutorial.org/. Their tutorials are using out of date versions of GLFW and GLEW and I plan to modify the solutions to use the latest versions.

At the same time I have decided that I will use Microsofts Incremental Linker (link.exe) instead of ALINK. My only reason for doing this is to try a different way of linking my executables. One of the changes with using the link.exe instead of alink is that NASM has to compile win32 obj files instead of borland compatible obj files. This change means that you can’t use the import directive to specify which dll you are linking with. When not using the import directive lib files are passed into the linker at link time. In the grand scheme of things it means you don’t have to specify anything in the import part. One disadvantage of this is that you have to use the correct names as specified in the lib file and these are not always the same as the names specified in documentation. For example from kernel32.dll:

_ExitProcess@4 instead of ExitProcess

The @4 informs you that the function is a std call and would like 4 bytes of information on the stack and you should clean up the stack after the call. ExitProcess( DWORD var ). If there is no @X then it is probably a cdecl call and you do not need to clean up the stack. It just so happens that the WinAPI and GLEW uses std calls and GLFW uses cdecl calls. This is important and there will probably be many bugs in my programs in the future due to me forgetting this.

All code for this can be found on my github.

The other day I had an idea to learn x86 assembler. Since I am never a fan of easy projects I decided for my first program I would try to rewrite the legacy OpenGL tutorials by NeHe. It is important to remember that these tutorials are based on very old versions of OpenGL and should not really be followed unless developing for ancient architecture. After I have rewritten NeHe’s tutorials at least up to 5 I plan to then try to change over to OpenGL 3.2 and higher. I will still stay in NASM assembler so I will have to have a few tricks up my sleeve as I can find no assembler references for newer versions of OpenGL. The new versions of OpenGL require some really extravagant techniques in order to display a simple window and most people now use a library to do all of this back end. I may have a look at the back end and see if it can be simplified in NASM but I think it will be quite likely that I will just use a library as well.

There is actually solutions to NeHe’s tutorials in assembler but it is FASM and it was made in 2000 so there is a possibility for improvements. These tutorials will hopefully give me a better understanding of x86 and how OpenGL operates. I was going to use the FASM code whenever I was unsure on how to proceed but found that it had few comments making it hard to read and follow. My attempt will hopefully have meaningful comments and will not use @@1 as a label for any loop! Another tool at my disposal is reading the assembler generated by the original c++ code.

One issue I encountered early on was alignment can cause many problems. For a long time I had a MessageBox that would display with the words in italics and rotated. It took a very long time to realise this was an alignment issue in the RAM due to me thinking that this bool I was using only required at max 1 bit so I placed it in a byte. After changing the bool to waste a dword all the MessageBox issues disappeared.

Another issue that I keep forgetting is whether something is a pointer or needs to be dereferenced. Whilst working through tutorial 2 I encountered many issues related with my box and triangle not being able to be drawn. I later realised the problem with this was not dereferencing a pointer!

I tried to use all open source programs whilst developing the tutorials some of them are very out of date nowadays such as ALINK. My reasoning for continuing to use ALINK was mainly due to being able to run it without installing anything.  I would normally have used microsofts link.exe but I would need visual studio or the windows SDK.

All code can be found on github.