Hi all! Thanks for the great comments and feedback, having watched it back I'm inclined to agree the background music is a bit egregious. Still figuring UA-cam out so will be rebalancing things in the next video. Thanks again for watching (: I have another low-level video you might enjoy as well - ua-cam.com/video/9_n6CBoEZwg/v-deo.html
I don’t know how I came across your video, know of reverse engineering but have never done it myself… yet I watched the entire video. It is a very good video! I look forward to all your new content!
I was coming here to mention the looping audio distraction but it was already mentioned. I find that if you use ambient music at low volume that doesn't have any defined notes, it can add mental focus to the audience. This is why you hear that type of music in video games about space travel.
I used to play this for hours and hours as a kid. Got a CD in a cereal box. This was a blast from the past. Man life goes by quick. I loved this game *loved* it its up there with all the . Didn't know a *single* guy made this in assembly. Wow. Just wow. Needs way more publicity for that.
From what I understand of the author is that he is a prodigy in assembly language for the x86 architecture. I’m pretty sure voodoo and other weird juju was invoked because for the code to run as smoothly as it did on old hardware even without fancy 3d graphics cards, made this code some of the most amazing code written for the intel platform in the history of the platform. Of all games, excel, you name it, this is the pinnacle of advanced and efficient coding for performance and size. Of course, he later had a breakdown and disappeared from the world for a while so was it worth it? Probably….cause I think the anxiety came from dealing with publishers who wanted him to update and re-invent the magic over and over again for different venues and versions of RCT.
He was also unsurprising a massive roller-coaster fan and travelled worldwide to go on them. An old work colleague knew him from his own roller-coaster trips around the world.
I haven't heard anything about a breakdown, are you sure you're not spreading misinformation or speculation? If you could provide a source, I'd be curious to read more about it.
15:35 - Probably the best thing about windows is this dedication to not breaking the APIs. It's why you're able to just run rollercoaster tycoon decades and several windows versions later. It's outstanding really.
Windows occasionally sometimes breaks stuff and compatibility to the point of things like mmsys.cpl still stay even today in Windows 11...the audio mixer was one notable example
@@pikachuchujelly7628it.. is still the case on linux, idk where you got that, if you mean gtk and qt, there are old and compatible versions that work with older software, id say backwards compat works even better on linux than windows
@@pikachuchujelly7628Linux is not an OS, it is a collection of software made by different people that uses the same kernel. You can't enforce backwards compatibility standards on Linux because it is not a unified environment
DirectX is a famous user of COM, so you will not be making much progress without learning that. As for the strings, the game is localizable. All user interfacing strings are stored in a locale specific function. This is very common for commercial programs.
Great video! In case it helps, the 40-byte BITMAPINFOHEADER structure seen in the hex dump defines a top-down 1280 * 1024 8-bit buffer which gives a total back-buffer size of 1,310,720 bytes. Immediately following the 40-byte header is a 256-entry palette of RGB(A) quads, and the image data itself is a one byte lookup per pixel into this palette array. For debugging this sort of data, the .bmp format is essentially a DIB with an additional 14-byte BITMAPFILEHEADER header, so just dump that along with the DIB header, palette and image data into a file and it should be a valid image.
Very nice informative video on various strategies for reverse engineering. When working on the beginnings of OpenRCT2, I found it useful to look at the source code for the very first version of OpenTTD 0.1 as the engine was very similar, and therefore many of the structures, and patterns, were the same as RCT1, and RCT2. For some games, you can quite often get lucky and find a debug version of the game or a port that have left the symbol names in which makes it so much easier to identify what each function does. For example, when working on OpenLoco, we found that the Android port contained the function names, which helped us understand the binary a bit more. I am surprised about RCT1 loading in the code segments, I wonder if that is unique to the particular version you have. This was certainly not the case for RCT2.
I was suprised too, especially as some of the research I did suggested it would "just work" in ghidra. This was the version from Steam, so maybe they added some bootstrapper? Like I said I didn't want to spend too long on it as it wasn't progressing me towards my end goal. Thanks for reaching out, OpenRCT2 is an incredible project (:
@@nathanbaggs The original CD versions of RCT and expansion packs loaded in IDA just fine without any boostrapping. So it is probably the stream version that added that, perhaps some extra DRM.
@IntelOrca Adding DRM to a game that was released without would only make economic sense, if new updates are released, someone wants to protect. Otherwise in the piracy world, copyable released once, is released forever.
I think you explain everything very logically and it is easy to follow. Perhaps a tutorial on how to start on reverse engineering, the tools, the registers, the stack etc and what they mean would be really good. Maybe even solving a few crackmes.
In the beginning, when you were looking for strings, I noticed that each string was preceded by the sequence { 0x0a, 0x8e }. Now it could be that this is some prefix used to indicate what kind of object follows, but it could also be part of the string itself, which could be the reason you were unable to find any references to it. 0x0a is the ASCII code for newline. What then remains is the mystery of what this 0x8e character code is (other than the ASCII code for a A with diacritics). It could be a marker or something like that. Back in the day it was not unheard of to indicate, for instance, the hotkey for a specific action by prefixing the character in the string with an unprintable character that would then be interpreted by the render / handler function to see if that key was pressed, filtering out the prefix byte.
RCT is such an amazing piece of software, maybe even classified as a work of art because of its playability even after so many years. Thanks for digging into it. There's a lot to unpack here and the work you've done is as impressive as the code you debugged.
Pretty sure I got it for free. Thought it was a demo, and as I kept playing it, I noticed other parks and rides unlocking. Ended up putting quite a bit of time into it on my old Celeron processor and the fancy newish Windows 98 in glorious 1024 x 768.
Such a nice walk down the memory lane when I used SofICE 386 to crack games... I remember I was able to convince my boss at work that it was useful at work and he bought it... No Ghidra back then.... Awesome content, kudos...😎
If you haven't discovered it yet, Ghidra also has a dark theme now, in the settings on the main small window where you import files into your project 🤙Great video!
Here are some ideas for topics: - How does TTDPatch change the original TTD executable to allow for mammoth trains? (TTDPatch pretty much relies on reverse engineered knowledge, I have no idea if this knowledge has been documented anywhere.) - How does The Settlers II handle it's palette color cycling? (The game reads PBM formatted LBM files = Amiga IFF that supports including palette cycling information, and the game's palette file has this information, but the game seems to have it hardcoded and thus ignores the file data.)
I really loved the video and analysis, thanks doing it. The only thing I was not a fan of was the music in the background, I don't think it added anything to the video. But that's a minor complain to an otherwise great video.
Great video. Have done some reverse engineering of Z80 and 6502 games, that gets complicated and time consuming enough with only a handful of 8-bit registers, 16-bit addresses and maybe only 24kb of code. It's very satisfying to piece together the puzzle but ultimately quite a waste of time, at least with programming I get a game at the end of it!
Absolutely loved this! Getting to know a bit more about the inner workings of one of my favorite games is awesome. I'd personally love to see Factorio reverse-engineered, specifically because it as you probably know is crazily optimized, where one is able to have stupendous amounts of machines, belts, trains, bots, etc. all running at once. Maybe reverse-engineering its update loop could be interesting for a video? :-)
@@sanderbos4243 Which is not to blame to the developer but mostly to blame to the management or other parties in a company who demands to have the product (game) finished yesterday. Most developers on the other hand would love to optimize where possible.
You are forgetting that most developers do not know how to properly utilize those fast modern cpus. Whether that is because companies are not prioritizing those things or not, the fact is that modern programming practices like Object Oriented programming are not condusive to writing fast code. Even if their boss let them optimize, knowledge of how to really utilize modern cpus is few and far between. Using what are currently considered "good practices" for programming, you still don't get very far, performance wise. Now I'm not saying that I do know how to do all of those things, just that I've become painstakingly aware of how little the entire industry currently knows and cares about it. Casey Muratori often makes very good points about this topic.
Amazing to watch - and you have a great way of organizing thought and taking one by the hand to follow along. Never thought I'd watch an entire video of reverse engineering 20yo code. Came for the legend, stayed for the insights you provide! subbed!
I don't know if you looked into this further, but you can use GDI and DirectX together. GDI can do a lot of stuff that the video card may not be able to do, especially back then. That image you created looked like a memory surface that he draws to before he redraws that on the final surface. You should look for the buffer swap (you're in windowed mode, so I don't think that can be done in old directx) or the Blt function that would be the video card actually bit blitting the final surface. In directx 7, it's a function/method from the directdrawsurface interface, but I don't know about directx 5.
I really enjoy the journey discovering the inner workings of old software. For those of us not familiar with assembler jargon, it could be useful to show a small panel on the side detailing some of the CPU instructions (or registers) of note. Also, I have two small curiosities regarding old Windows games: (1) in the game SkiFree, once you finished the map, I always wondered exactly when would the yeti spawn and start hunting you (2) in the game Dangerous Dave, I always wondered if there were cheats that gave you the gun or even the cup to proceed to the next level. Maybe you can find those cheats or hook the game to force it to give you those items, without causing memory leaks. These are some niche nostalgic games, but maybe your audience will enjoy watching you dig through them.
Really interesting video. I've not done debugging of DOS games for a good number of years, so seeing what tools are now available is fantastic. Would love to see more videos like this - it might be a niche topic, but one that's absolutely fascinating.
This is fascinating! Ever since I heard a few years ago that it was written entirely in assembly, I’ve been incredibly curious as to what Ghidra would do trying to disassemble it back in to C! I’m only a couple of minutes in to the video, but I’m looking forward to see the answer!
This is really neat. I know next to nothing about x86 and this was easy to understand and enlightening. RE: Text being loaded dynamically, I would be shocked if that wasn’t to make localization easier. That way you only need to load one language’s worth of strings, and the program itself can call the same address for the same intended string. This is generally the way it’s done to this day, and similar audio is done for localized VO.
This is half-true in RCT. DX is only used in fullscreen mode but even then it doesn't use true hardware rendering. The image is still rendered in software and then the DX API is only used to output the image.
I love this video and your other breakdown content. I'm not in the field, understand maybe 10% or what you're doing, but it's really fun watching the process. Just wanted to let you know that this video format has more general appeal than just as an instructional video for specialists.
I enjoyed watching the video, but I do have a suggestion. Having music in the background in the introduction to set the tone is acceptable for setting the style. Still, while you're teaching and delving into the assembly process, the music distracts the explanation. When I watch or read complicated content, I need uninterrupted focus on the instructor's voice, without music or visual distractions. Setting these changes would improve the video a lot. So far, you're teaching is excellent, thank you.
Cool, iMac 1998 changed the computer's design. What apps do you and did you program in your day job which seems to be computer engineering or computer science. God bless.
Just leaving a comment and a like because I quickly realised the video wasn’t about what I expected and am moving on (I’m not into coding at all). Didn’t want the algorithm to think it’s because it wasn’t a good video. Cheers!
@@nathanbaggs ah no that's on me - it was a combination of nostalgia (don't see much RCT these days!) and intrigue. I guess I thought maybe reverse engineering in terms of strategy, looking at a fully successful park and how it gets that way or something! Props to you though - great idea 👍
It looks like the screenbuffer image is still an 8bit indexed color image, not 8 bit RGB as it used to be done in DOS games. The DirectX call was probably added later in development to just get info on the variations of players screens.
There's actually a much better way to dump memory, with scylla in x32dbg. You pause the game and dump the memory and you can also dump all the heap allocations. You can also make a tool to dump all of it, yourself. You can then import these heap allocations into your dumped ghidra decomp, and see the actual data that was being pointed to. You can even type the data, etc.
Thank you for this demonstration. I've personally never played that game, but have played variations of Sim City, as well as Sim Tower. And the Sims. Either way, I'm also a Delphi developer, and as unfamiliar as I am with assembly, I understood a great deal of this. Such as handling bitmaps. I was yelling "RGB!" at my TV when you had 3 grayscale images side by side.
And struggle to do so.. haha... creating something with such complexity in straight assembly is an achievement. I wonder how he designed it, with pad and pencil maybe?
Way back in the day I saw the website of guy that was 18 max and he had coded three 3D games fully in x86 assembly. In that day I could barely make a cube appear in a GLUT window and I was so puzzled why we needed to pop and push all these matrices, made no sense to me. It really disheartened me lol. I'm a Java dev nowadays but your videos make me want to learn x64 assembly and understand all that, seems cool. Not sure what I would do with that knowledge though ^^ Cool video
22:10 "Going back to our DirectX 5 tutorials" *proceeds to head to the actual code instead of a tutorial* 😂 I guess the code can be counted as a tutorial, if you're tenacious enough. loved this video mate
I'll admit that attempt at decoding the DIB header (which is the same as a BMP header, actually) gave me a good chuckle :P You got it almost right, but at the same time, not quite... But anyway, the image is 1280×1024, you got that right (the -1024 height means that the image is top-down instead of bottom-up), but the 8 bits per pixel value was literal. Not 8 bits per component! This image is a paletted image; you'll find the palette itself in the DIB header, a bit further down. Each pixel is a one-byte index into that palette data. The palette data itself is RGB triplets, as 32-bit values (where the fourth byte is ignored, although some tools mistakenly treat it as alpha). If you're curious about that "planes = 1" field, I'm curious about it too... I don't know what it was intended for, but in practice it's a "must be 1" field.
The 'planes=1' field is for planar graphics which are never in a Windows Device _Independent_ Bitmap, however it is used in some device _dependent_ graphics. VGA 640x480x4bit has planar graphics. You would expect each byte in memory to be two pixels but actually each byte is one bit each from eight different pixels. Each plane is a 640x480x1bpp image and when the card outputs a pixel it takes one bit from each plane.
@@eDoc2020 Ah, I didn't know the same format was used for planar formats like the in-memory layout of VGA. My experience comes from .bmp files, and those never have a value other than 1 in that field. Nice to know!
@@therealax6 I don't know if the same structures were ever used like that. My gut feeling is they were going to support planar graphics in BMP files but then changed their mind. "Device-dependent bitmaps are supported only for compatibility with applications written for Windows versions earlier than 3.0. A developer writing a new application, or porting an application written for a previous version of Windows to the Win32 platform, should use DIBs."
The fact that the game lists display modes and then doesn't use them made me suspect that there were multiple rendering systems and the game was deciding which to use, and based on some property of your system, it decides not to use dx5. Finding later that it uses GdiFlush on your system lines up with that nicely. I might be wrong and even if I'm not, that creates several new questions, but it's what I'd bet on (no more than a insignificant amount though)
Get yourself a legacy windows 98 emulator with DirectX 5 and run. The game will set video mode to exclusive and take direct control. Only if this fails the game will flush a window and if you debug even harder or use kd... You will learn something about shims and backwards compatibility too
You're mostly right. From my testing RCT uses GDI for output in windowed mode and DirectDraw for output in windowed mode. What's interesting to me is that it uses StretchDIBits instead of SetDIBitsToDevice. That explains why (on contemporary hardware) there is a massive performance hit in windowed mode.
I'm only 14 minutes in at the moment; but I suspect the string lookup code is for localization purposes? I distinctly remember playing this game in my native tongue.
Great Video, but why did you chose to disassemble the DirectX renderer, that must have been I assume added later to the game with all the windows baggage, on top of the original render that ran under dos and was probably much simpler?
Really great vids, and these not only takes me back to mis-spent 5th form and college days, 1985?- 1988, building cheats for games using pokes, or jumps to other sections of code. So, theres three games for me, to reverse engineer: Origional Doom II, Firebirds Elite using vector graphics animation and rendering finally, Cannon Folder, rendering and scroll techniques.
Seeing assembly code interacting with COM objects is just crazy. Is it known, why the author went this way instead of going with a higher level language?
eax*4+X makes sense for getting a 32-bit value from a pointer to X. It's probably an array of pointers, like a char[][] in C (but obv he wrote it in asm)
As someone who just does standard software design this is really wild. I often thought games were very much just like really advanced websites with functions, classes and images but clearly not. Watched the whole video and understood basically nothing! 😂 enjoyed it all the same though
It does say ExeLock Executable File Protector in the beginning when you start searching for strings. It would have been a lot easier to search for a cracked and unpacked executable.
Great video, awesome memories about the game. Came to complain about the music though, but I see I'm not the only one that got distracted and a little annoyed by it ;-)
I would like to see more on this. I would also like to see something on DrainStorm(2D Tile Based game, with ammo/abilities and special levels where defeat onslaughts of enemies) if you ever get the chance.
New game dev on site, first day on the job... *Jr. Dev standing around not knowing what to do* Sr. Dev: "Quick! Go get me a pixel stetcher!" Jr. Dev: Ok! On it! *comes back an hour later with obscure Win9x call* Sr. Dev: Well, that backfired.
Regarding the all-caps, I think it is due to it being a preprocessor macro. They use those a lot to alias types (like here, where you have a long pointer - LP)
I have a suspicion that the code as initially loaded is packed by some kind of EXE packer. I believe UPX is one of the common ones. If you can identify the packer, there is likely to be an unpacker for it somewhere around the web.
No. This isn't executable packer. This is result of almost any 1995 year assembly linker and programmer writing manual mapping and manual library loading. You manually write code to dynamically and manually map a library into your address space. Nowadays only cheats, trainers and C devs doing Load Library / Get Proc Address do this sometimes. But it was a norm back at the days when games had to reside on floppy drives and writing in native assembly was a thing. True assembly game. Dont expect it look like any modern compiler artifact.
@@nathanbaggs at the beginning of the video where you show strings found in the executable, there's one that says "ExeLock". This is an old packer, known most commonly as Neolite. You can find unpackers for it online (GUW32 - Generic Unpacker by Christoph Gabler, or ProcDump32). It's also rather easy to unpack it manually in a debugger (dump after extraction, fix the original EIP and then fix import table) and there are OllyDbg scripts that partly automate the process. Lastly, if you Google "RollerCoaster ExeLock" you will find a forum with the full tutorial on how to the unpack RTC binary.
Double comment here but editing a comment on the tablet be stanky~ wanted to add, fun fact when I was first getting into computers, I had this "downloader" thing that can continue downloads and I downloaded the roller coaster tycoon 3 demo with dialup, took literal days lol, BUT After all that waiting, I was missing d3d.dll (i think?) anyway my fresh-a* called walmart xD asking the electronics center wtf that was Edit: ok I managed to click the teeny tiny "edit" button Yet another addition - you're the first person I actually ever -wanted- to click the bell on
On this UA-cam thumbnail, you look very similar to Edward, a French youtuber that review old games. It's so close that every time I saw on recommandations I believe it is his channel.
33:51 The bmiColors member of the BITMAPINFO structure consists of an array of RGBQUAD structures and RGBQUAD has size of 4 bytes (rgb channels and extra BYTE rgbReserved which can be used for alpha channel but probably(?) is there for DWORD alignment). So I guess the calculation here would have been something like 20*16^4 / 4 / 640 = 512 (20*16^4 = 0x14 00 00)?
Great work! Espacially that you kept in the dead end about DirectX is a nice example, of how this stuff actually works. It's not like opening a binary an after 10 minutes you understand it (like other show of in their videos). Most of the time it's a lot of confusion, poking around and at some point you find the actual path to your goal. :)
Could you make a video on reverse engineering a NDS game? Preferably one that hasn't been done before like pokemon. I'd love to see your process for something like that. I'm working on my own project with Cooking Mama 2 but I'm struggling a little bit. Wish me luck.
Great narration, was so much fun to watch. Wish I could use a debugger that well. I'd love to see you tackle Operation Neptune (or any of the Super Solvers), Oregon Trail II, or DinoPark Tycoon.
great video, one of my favs too from my childhood. One criticism i have though is your resolution! it was hard at times to see what you're doing at times when you don't zoom in... found myself actually zooming in in the browser!
theres an old retro game called Sub Cultures, it has no compability and no release from gog. could you look into it on how to make it run on modern windows?
Hi all! Thanks for the great comments and feedback, having watched it back I'm inclined to agree the background music is a bit egregious. Still figuring UA-cam out so will be rebalancing things in the next video. Thanks again for watching (:
I have another low-level video you might enjoy as well - ua-cam.com/video/9_n6CBoEZwg/v-deo.html
I don’t know how I came across your video, know of reverse engineering but have never done it myself… yet I watched the entire video. It is a very good video! I look forward to all your new content!
I’d recommend not having music at all - the pros don’t use it, or they hire Hans Zimmerman 😅
Better don't use any music on reverse engineering. Let us listen to our own. Our enter a hyper focus - my brain literally shuts down on music
idk, I kind of like the music. Although, I think the particular song you chose was a bit too active and and loud.
I was coming here to mention the looping audio distraction but it was already mentioned. I find that if you use ambient music at low volume that doesn't have any defined notes, it can add mental focus to the audience. This is why you hear that type of music in video games about space travel.
this man as knowledgeable as he is had us listen to the same song for 40 minutes.
criminal.
(: this has been pretty common feedback, next video will have a different audio balance
This has me rolling!!!
I used to play this for hours and hours as a kid. Got a CD in a cereal box. This was a blast from the past. Man life goes by quick. I loved this game *loved* it its up there with all the . Didn't know a *single* guy made this in assembly. Wow. Just wow. Needs way more publicity for that.
What? A cd in a cereal box? Damn what a treasure. I bet you American 😂
Here in Brazil, I used to play a flight game that came in a cereal box for a long time during my childhood
Awesome video, my only criticism is the looping audio in the background. That tune seven minutes in was too much lol
Thanks for the feedback!
@@nathanbaggs also volume is super high compared to your voice, but yeah this few tunes was pain :D
I loved the music, but it needs to be quieter as it’s all I can focus on haha
++ for no music, great video otherwise!
I thought the music was just fine. It was calming and peaceful, just right for this breakdown.
From what I understand of the author is that he is a prodigy in assembly language for the x86 architecture. I’m pretty sure voodoo and other weird juju was invoked because for the code to run as smoothly as it did on old hardware even without fancy 3d graphics cards, made this code some of the most amazing code written for the intel platform in the history of the platform. Of all games, excel, you name it, this is the pinnacle of advanced and efficient coding for performance and size. Of course, he later had a breakdown and disappeared from the world for a while so was it worth it? Probably….cause I think the anxiety came from dealing with publishers who wanted him to update and re-invent the magic over and over again for different venues and versions of RCT.
He was also unsurprising a massive roller-coaster fan and travelled worldwide to go on them. An old work colleague knew him from his own roller-coaster trips around the world.
I love Transport Tycoon and Deluxe that he wrote! 😍 OpenTTD now, too!
Its not a 3d game, so that is probably why it runs good on older hardware.
I haven't heard anything about a breakdown, are you sure you're not spreading misinformation or speculation? If you could provide a source, I'd be curious to read more about it.
@@nomindseye Have not heard about a breakdown either, but I know he took a break from development, so maybe it was just the wrong words used :)
15:35 - Probably the best thing about windows is this dedication to not breaking the APIs. It's why you're able to just run rollercoaster tycoon decades and several windows versions later. It's outstanding really.
Windows occasionally sometimes breaks stuff and compatibility to the point of things like mmsys.cpl still stay even today in Windows 11...the audio mixer was one notable example
If only that was the case on Linux. But the Gnome and Qt developers have other plans.
@@pikachuchujelly7628 same kernel. Gnome and KDE are just softwares.
@@pikachuchujelly7628it.. is still the case on linux, idk where you got that, if you mean gtk and qt, there are old and compatible versions that work with older software, id say backwards compat works even better on linux than windows
@@pikachuchujelly7628Linux is not an OS, it is a collection of software made by different people that uses the same kernel.
You can't enforce backwards compatibility standards on Linux because it is not a unified environment
DirectX is a famous user of COM, so you will not be making much progress without learning that. As for the strings, the game is localizable. All user interfacing strings are stored in a locale specific function. This is very common for commercial programs.
Great video! In case it helps, the 40-byte BITMAPINFOHEADER structure seen in the hex dump defines a top-down 1280 * 1024 8-bit buffer which gives a total back-buffer size of 1,310,720 bytes. Immediately following the 40-byte header is a 256-entry palette of RGB(A) quads, and the image data itself is a one byte lookup per pixel into this palette array. For debugging this sort of data, the .bmp format is essentially a DIB with an additional 14-byte BITMAPFILEHEADER header, so just dump that along with the DIB header, palette and image data into a file and it should be a valid image.
Very nice informative video on various strategies for reverse engineering. When working on the beginnings of OpenRCT2, I found it useful to look at the source code for the very first version of OpenTTD 0.1 as the engine was very similar, and therefore many of the structures, and patterns, were the same as RCT1, and RCT2. For some games, you can quite often get lucky and find a debug version of the game or a port that have left the symbol names in which makes it so much easier to identify what each function does. For example, when working on OpenLoco, we found that the Android port contained the function names, which helped us understand the binary a bit more. I am surprised about RCT1 loading in the code segments, I wonder if that is unique to the particular version you have. This was certainly not the case for RCT2.
I was suprised too, especially as some of the research I did suggested it would "just work" in ghidra. This was the version from Steam, so maybe they added some bootstrapper? Like I said I didn't want to spend too long on it as it wasn't progressing me towards my end goal.
Thanks for reaching out, OpenRCT2 is an incredible project (:
@@nathanbaggs The original CD versions of RCT and expansion packs loaded in IDA just fine without any boostrapping. So it is probably the stream version that added that, perhaps some extra DRM.
@IntelOrca Thanks for your work on those projects! I always wanted to chip in but never felt like I had quite the level of skill needed.
@IntelOrca Adding DRM to a game that was released without would only make economic sense, if new updates are released, someone wants to protect. Otherwise in the piracy world, copyable released once, is released forever.
OpenRTC2 is an amazing project! Thank you!
I think you explain everything very logically and it is easy to follow. Perhaps a tutorial on how to start on reverse engineering, the tools, the registers, the stack etc and what they mean would be really good. Maybe even solving a few crackmes.
100% - would love to get my hands dirty but I don’t know how to start really
In the beginning, when you were looking for strings, I noticed that each string was preceded by the sequence { 0x0a, 0x8e }. Now it could be that this is some prefix used to indicate what kind of object follows, but it could also be part of the string itself, which could be the reason you were unable to find any references to it.
0x0a is the ASCII code for newline. What then remains is the mystery of what this 0x8e character code is (other than the ASCII code for a A with diacritics). It could be a marker or something like that. Back in the day it was not unheard of to indicate, for instance, the hotkey for a specific action by prefixing the character in the string with an unprintable character that would then be interpreted by the render / handler function to see if that key was pressed, filtering out the prefix byte.
RCT is such an amazing piece of software, maybe even classified as a work of art because of its playability even after so many years.
Thanks for digging into it. There's a lot to unpack here and the work you've done is as impressive as the code you debugged.
roller coaster tycoon is absolutely amazing :D
Pretty sure I got it for free. Thought it was a demo, and as I kept playing it, I noticed other parks and rides unlocking. Ended up putting quite a bit of time into it on my old Celeron processor and the fancy newish Windows 98 in glorious 1024 x 768.
Such a nice walk down the memory lane when I used SofICE 386 to crack games... I remember I was able to convince my boss at work that it was useful at work and he bought it... No Ghidra back then.... Awesome content, kudos...😎
If you haven't discovered it yet, Ghidra also has a dark theme now, in the settings on the main small window where you import files into your project 🤙Great video!
Here are some ideas for topics:
- How does TTDPatch change the original TTD executable to allow for mammoth trains?
(TTDPatch pretty much relies on reverse engineered knowledge, I have no idea if this knowledge has been documented anywhere.)
- How does The Settlers II handle it's palette color cycling?
(The game reads PBM formatted LBM files = Amiga IFF that supports including palette cycling information, and the game's palette file has this information, but the game seems to have it hardcoded and thus ignores the file data.)
Never had anyone explain the decompile process before and it's fantastic. Thanks. Especially on one of my favourite games ever.
I'm a big fan of your presentation style, the way you put your video togheter is amazing. I hope to learn this too one day.
I really loved the video and analysis, thanks doing it.
The only thing I was not a fan of was the music in the background, I don't think it added anything to the video.
But that's a minor complain to an otherwise great video.
Thanks for the feedback!
Just watched the full video not realizing it only had ~200 views. This is amazing! Really enjoyed watching through
Great video. Have done some reverse engineering of Z80 and 6502 games, that gets complicated and time consuming enough with only a handful of 8-bit registers, 16-bit addresses and maybe only 24kb of code.
It's very satisfying to piece together the puzzle but ultimately quite a waste of time, at least with programming I get a game at the end of it!
Absolutely loved this! Getting to know a bit more about the inner workings of one of my favorite games is awesome. I'd personally love to see Factorio reverse-engineered, specifically because it as you probably know is crazily optimized, where one is able to have stupendous amounts of machines, belts, trains, bots, etc. all running at once. Maybe reverse-engineering its update loop could be interesting for a video? :-)
Actually it's not that crazy, cpus are just blazingly fast nowdays
Glad you enjoyed it!
@@Merlin-gl7zp True, but unfortunately many devs don't spend nearly as much time optimizing their games to make proper use of the power of CPUs
@@sanderbos4243 Which is not to blame to the developer but mostly to blame to the management or other parties in a company who demands to have the product (game) finished yesterday. Most developers on the other hand would love to optimize where possible.
You are forgetting that most developers do not know how to properly utilize those fast modern cpus. Whether that is because companies are not prioritizing those things or not, the fact is that modern programming practices like Object Oriented programming are not condusive to writing fast code. Even if their boss let them optimize, knowledge of how to really utilize modern cpus is few and far between. Using what are currently considered "good practices" for programming, you still don't get very far, performance wise.
Now I'm not saying that I do know how to do all of those things, just that I've become painstakingly aware of how little the entire industry currently knows and cares about it. Casey Muratori often makes very good points about this topic.
Amazing to watch - and you have a great way of organizing thought and taking one by the hand to follow along. Never thought I'd watch an entire video of reverse engineering 20yo code. Came for the legend, stayed for the insights you provide! subbed!
Glad you enjoyed it!
Would be interested to see what you make of 3D Lemmings. It was also written entirely in x86 but without DirectX
I don't know if you looked into this further, but you can use GDI and DirectX together. GDI can do a lot of stuff that the video card may not be able to do, especially back then. That image you created looked like a memory surface that he draws to before he redraws that on the final surface. You should look for the buffer swap (you're in windowed mode, so I don't think that can be done in old directx) or the Blt function that would be the video card actually bit blitting the final surface. In directx 7, it's a function/method from the directdrawsurface interface, but I don't know about directx 5.
I really enjoy the journey discovering the inner workings of old software. For those of us not familiar with assembler jargon, it could be useful to show a small panel on the side detailing some of the CPU instructions (or registers) of note.
Also, I have two small curiosities regarding old Windows games:
(1) in the game SkiFree, once you finished the map, I always wondered exactly when would the yeti spawn and start hunting you
(2) in the game Dangerous Dave, I always wondered if there were cheats that gave you the gun or even the cup to proceed to the next level. Maybe you can find those cheats or hook the game to force it to give you those items, without causing memory leaks.
These are some niche nostalgic games, but maybe your audience will enjoy watching you dig through them.
Really interesting video. I've not done debugging of DOS games for a good number of years, so seeing what tools are now available is fantastic. Would love to see more videos like this - it might be a niche topic, but one that's absolutely fascinating.
Working on a new one now (:
Same. It was soft ice for me back in the 90s. This brought back some memories.
too much with the music...otherwise great
please continue this lovely series!
Bro 've never seen this level of quality put into reverse enginierin video♥
Glad you liked it
This is fascinating! Ever since I heard a few years ago that it was written entirely in assembly, I’ve been incredibly curious as to what Ghidra would do trying to disassemble it back in to C! I’m only a couple of minutes in to the video, but I’m looking forward to see the answer!
Ghidra is now 3 months into the analysis and also looking forward to getting an answer.
This is really neat. I know next to nothing about x86 and this was easy to understand and enlightening.
RE: Text being loaded dynamically, I would be shocked if that wasn’t to make localization easier. That way you only need to load one language’s worth of strings, and the program itself can call the same address for the same intended string. This is generally the way it’s done to this day, and similar audio is done for localized VO.
A lot of older games run software rendering when in windowed mode, and only used direct X when in full screen.
This is half-true in RCT. DX is only used in fullscreen mode but even then it doesn't use true hardware rendering. The image is still rendered in software and then the DX API is only used to output the image.
I love this video and your other breakdown content. I'm not in the field, understand maybe 10% or what you're doing, but it's really fun watching the process. Just wanted to let you know that this video format has more general appeal than just as an instructional video for specialists.
Fascinating to watch. I have a very limited understanding of x86 so it's very impressive to watch you go over it.
I enjoyed watching the video, but I do have a suggestion. Having music in the background in the introduction to set the tone is acceptable for setting the style. Still, while you're teaching and delving into the assembly process, the music distracts the explanation. When I watch or read complicated content, I need uninterrupted focus on the instructor's voice, without music or visual distractions. Setting these changes would improve the video a lot. So far, you're teaching is excellent, thank you.
Thanks for the feedback!
Your videos are really enjoyable to watch. Very well explained and enlightening.
Would love to see a complete series where you reverse engineer a game from start to finish!
One of my other tricks is to run a profiler liker superluminal against it to see what interesting functions get called a lot
Yup, the nice thing about this project is there’s multiple different approaches and techniques
Cool, iMac 1998 changed the computer's design.
What apps do you and did you program in your day job which seems to be computer engineering or computer science.
God bless.
Just leaving a comment and a like because I quickly realised the video wasn’t about what I expected and am moving on (I’m not into coding at all). Didn’t want the algorithm to think it’s because it wasn’t a good video. Cheers!
Thanks for being so considerate! I’m curious what you thought the video was about though? I hope the title and thumbnail aren’t misleading?
@@nathanbaggs ah no that's on me - it was a combination of nostalgia (don't see much RCT these days!) and intrigue. I guess I thought maybe reverse engineering in terms of strategy, looking at a fully successful park and how it gets that way or something!
Props to you though - great idea 👍
It looks like the screenbuffer image is still an 8bit indexed color image, not 8 bit RGB as it used to be done in DOS games. The DirectX call was probably added later in development to just get info on the variations of players screens.
There's actually a much better way to dump memory, with scylla in x32dbg. You pause the game and dump the memory and you can also dump all the heap allocations.
You can also make a tool to dump all of it, yourself. You can then import these heap allocations into your dumped ghidra decomp, and see the actual data that was being pointed to. You can even type the data, etc.
And yes, it was because Ghidra didn't finish analyzing. Otherwise it would have atleast typed the string to be a char[n]
Cool I’ll check that out, thanks!
This brings back memories of spending hours in SoftIce, trying to NOP game CD checks. Soo much respect for Chris Sawyer for doing all this in ASM.
Thank you for this demonstration. I've personally never played that game, but have played variations of Sim City, as well as Sim Tower. And the Sims. Either way, I'm also a Delphi developer, and as unfamiliar as I am with assembly, I understood a great deal of this. Such as handling bitmaps. I was yelling "RGB!" at my TV when you had 3 grayscale images side by side.
Glad you came along for the ride :) my aim is to make these deep dives as accessible as possible
Great content, loved it. Amazing and clear explanations, super interesting.
I find the background music too loud, hence distracting.
Imagine being the person who programmed the game and watching someone piece together how you did.
And struggle to do so.. haha... creating something with such complexity in straight assembly is an achievement. I wonder how he designed it, with pad and pencil maybe?
Fingers crossed 😂🤞
Nathan you look like Tom Greens son lol
Way back in the day I saw the website of guy that was 18 max and he had coded three 3D games fully in x86 assembly. In that day I could barely make a cube appear in a GLUT window and I was so puzzled why we needed to pop and push all these matrices, made no sense to me. It really disheartened me lol. I'm a Java dev nowadays but your videos make me want to learn x64 assembly and understand all that, seems cool. Not sure what I would do with that knowledge though ^^ Cool video
Amazing vidoes, looks like im going to binge watch all your content!
22:10 "Going back to our DirectX 5 tutorials" *proceeds to head to the actual code instead of a tutorial*
😂 I guess the code can be counted as a tutorial, if you're tenacious enough. loved this video mate
I'll admit that attempt at decoding the DIB header (which is the same as a BMP header, actually) gave me a good chuckle :P You got it almost right, but at the same time, not quite...
But anyway, the image is 1280×1024, you got that right (the -1024 height means that the image is top-down instead of bottom-up), but the 8 bits per pixel value was literal. Not 8 bits per component! This image is a paletted image; you'll find the palette itself in the DIB header, a bit further down. Each pixel is a one-byte index into that palette data. The palette data itself is RGB triplets, as 32-bit values (where the fourth byte is ignored, although some tools mistakenly treat it as alpha).
If you're curious about that "planes = 1" field, I'm curious about it too... I don't know what it was intended for, but in practice it's a "must be 1" field.
Thanks for the clarification!
The 'planes=1' field is for planar graphics which are never in a Windows Device _Independent_ Bitmap, however it is used in some device _dependent_ graphics. VGA 640x480x4bit has planar graphics. You would expect each byte in memory to be two pixels but actually each byte is one bit each from eight different pixels. Each plane is a 640x480x1bpp image and when the card outputs a pixel it takes one bit from each plane.
@@eDoc2020 Ah, I didn't know the same format was used for planar formats like the in-memory layout of VGA. My experience comes from .bmp files, and those never have a value other than 1 in that field. Nice to know!
@@therealax6 I don't know if the same structures were ever used like that. My gut feeling is they were going to support planar graphics in BMP files but then changed their mind.
"Device-dependent bitmaps are supported only for compatibility with applications written for Windows versions earlier than 3.0. A developer writing a new application, or porting an application written for a previous version of Windows to the Win32 platform, should use DIBs."
Extremely interesting!
You really got me interested in programming.
I'd suggest to drop the background music volume by 25%/50%... its really distracting from your actual content... otherwise super cool info!
The fact that the game lists display modes and then doesn't use them made me suspect that there were multiple rendering systems and the game was deciding which to use, and based on some property of your system, it decides not to use dx5. Finding later that it uses GdiFlush on your system lines up with that nicely. I might be wrong and even if I'm not, that creates several new questions, but it's what I'd bet on (no more than a insignificant amount though)
Get yourself a legacy windows 98 emulator with DirectX 5 and run. The game will set video mode to exclusive and take direct control. Only if this fails the game will flush a window and if you debug even harder or use kd... You will learn something about shims and backwards compatibility too
You're mostly right. From my testing RCT uses GDI for output in windowed mode and DirectDraw for output in windowed mode. What's interesting to me is that it uses StretchDIBits instead of SetDIBitsToDevice. That explains why (on contemporary hardware) there is a massive performance hit in windowed mode.
Loved Tycoon as a kid, the only annoying part was getting charged extra when you built rides on top of trees and scenery.
I'm only 14 minutes in at the moment; but I suspect the string lookup code is for localization purposes? I distinctly remember playing this game in my native tongue.
Cheers bro loved this game, bit of a developer myself so loving watching this deep dive! really appreciate it! good work!
Great Video, but why did you chose to disassemble the DirectX renderer, that must have been I assume added later to the game with all the windows baggage, on top of the original render that ran under dos and was probably much simpler?
Really great vids, and these not only takes me back to mis-spent 5th form and college days, 1985?- 1988, building cheats for games using pokes, or jumps to other sections of code.
So, theres three games for me, to reverse engineer:
Origional Doom II,
Firebirds Elite using vector graphics animation and rendering
finally, Cannon Folder, rendering and scroll techniques.
I've been running the original DOS CGA version of 'lines' elite through Ghidra. It's been a mixed result effort at best so far.
Seeing assembly code interacting with COM objects is just crazy.
Is it known, why the author went this way instead of going with a higher level language?
Presumably a higher level language would have been too slow for all the processes this game is meant to run
EnBigguned is my new favourite word.
eax*4+X makes sense for getting a 32-bit value from a pointer to X. It's probably an array of pointers, like a char[][] in C (but obv he wrote it in asm)
As someone who just does standard software design this is really wild. I often thought games were very much just like really advanced websites with functions, classes and images but clearly not. Watched the whole video and understood basically nothing! 😂 enjoyed it all the same though
RTC is a bit of an edge case as it was written by one guy entirely in assembly, most games do have classes and functions (:
It does say ExeLock Executable File Protector in the beginning when you start searching for strings. It would have been a lot easier to search for a cracked and unpacked executable.
WOW I thought this channel at 73K SUBS not 7.3 bravo my new fav channel
the guy that created that game is one of the best programmers to ever lived
When C and C++ are considered high level you know how far we've come
Great video, awesome memories about the game. Came to complain about the music though, but I see I'm not the only one that got distracted and a little annoyed by it ;-)
Yup going to rebalance things in the next video (:
I would like to see more on this. I would also like to see something on DrainStorm(2D Tile Based game, with ammo/abilities and special levels where defeat onslaughts of enemies) if you ever get the chance.
DrainStorm is a brutally difficult game.
I hope more video about game Reverse Engineering! Really cool
Strings/text is loaded into a dictionary at run time to support multiple languages.
New game dev on site, first day on the job...
*Jr. Dev standing around not knowing what to do*
Sr. Dev: "Quick! Go get me a pixel stetcher!"
Jr. Dev: Ok! On it! *comes back an hour later with obscure Win9x call*
Sr. Dev: Well, that backfired.
This video is great! It helped me understand the reverse engineering process better. Thank you :)
Regarding the all-caps, I think it is due to it being a preprocessor macro. They use those a lot to alias types (like here, where you have a long pointer - LP)
Not always. These types are sometimes directly defined after their struct type.
so glad i found this... made me feel smarter... hahahahaha
great video... great job
Awesome video! Would love some time stamps for those of us that get lost easily
I have a suspicion that the code as initially loaded is packed by some kind of EXE packer. I believe UPX is one of the common ones. If you can identify the packer, there is likely to be an unpacker for it somewhere around the web.
I think you might be right, my current theory is that this is something Steam have done
Oh, so it could also be Steam's DRM. That's a lot less legal (in some countries) to undo.
@@ovalteen4404Steam doesn't force DRM on games
No. This isn't executable packer. This is result of almost any 1995 year assembly linker and programmer writing manual mapping and manual library loading. You manually write code to dynamically and manually map a library into your address space. Nowadays only cheats, trainers and C devs doing Load Library / Get Proc Address do this sometimes. But it was a norm back at the days when games had to reside on floppy drives and writing in native assembly was a thing. True assembly game. Dont expect it look like any modern compiler artifact.
@@nathanbaggs at the beginning of the video where you show strings found in the executable, there's one that says "ExeLock". This is an old packer, known most commonly as Neolite. You can find unpackers for it online (GUW32 - Generic Unpacker by Christoph Gabler, or ProcDump32). It's also rather easy to unpack it manually in a debugger (dump after extraction, fix the original EIP and then fix import table) and there are OllyDbg scripts that partly automate the process. Lastly, if you Google "RollerCoaster ExeLock" you will find a forum with the full tutorial on how to the unpack RTC binary.
dude you're like a british me
its awesome
Double comment here but editing a comment on the tablet be stanky~
wanted to add, fun fact when I was first getting into computers, I had this "downloader" thing that can continue downloads and I downloaded the roller coaster tycoon 3 demo with dialup, took literal days lol, BUT
After all that waiting, I was missing d3d.dll (i think?) anyway my fresh-a* called walmart xD asking the electronics center wtf that was
Edit:
ok I managed to click the teeny tiny "edit" button
Yet another addition - you're the first person I actually ever -wanted- to click the bell on
i love content like this, thank you!
Sorry if it's already been said, but can you not set your screen resolution to 640x480/1024x768 etc for recording videos? To enlarge text
You should totally do this for Warcraft 2 and Starcraft!
I rate your vids lad, you speak my language. Albeit, a language I understand about 15% of.
On this UA-cam thumbnail, you look very similar to Edward, a French youtuber that review old games. It's so close that every time I saw on recommandations I believe it is his channel.
33:51 The bmiColors member of the BITMAPINFO structure consists of an array of RGBQUAD structures and RGBQUAD has size of 4 bytes (rgb channels and extra BYTE rgbReserved which can be used for alpha channel but probably(?) is there for DWORD alignment). So I guess the calculation here would have been something like 20*16^4 / 4 / 640 = 512 (20*16^4 = 0x14 00 00)?
Can't you just save the entire struct to a .bmp file?
You can save the entire struct to a dib file and Ms Paint will deal with it
Great work! Espacially that you kept in the dead end about DirectX is a nice example, of how this stuff actually works. It's not like opening a binary an after 10 minutes you understand it (like other show of in their videos). Most of the time it's a lot of confusion, poking around and at some point you find the actual path to your goal. :)
Where is the followup to this video?! I need to know how those bitmaps are generated!
Could you make a video on reverse engineering a NDS game? Preferably one that hasn't been done before like pokemon. I'd love to see your process for something like that. I'm working on my own project with Cooking Mama 2 but I'm struggling a little bit. Wish me luck.
Championship Manager 1997/98 please!!! There is ongoing fan mod updates plus a Twitter community for it. Would be awesome to see under the hood
Great vid! I’d love to see you dive into an old Future Crew demo! Unreal or Second Reality…?
It would have been nice to put a summary of "How does Rollercoaster Tycoon do its rendering?" at the end as a recap. Otherwise, cool video.
Love low level stuff , thanks
Great narration, was so much fun to watch. Wish I could use a debugger that well.
I'd love to see you tackle Operation Neptune (or any of the Super Solvers), Oregon Trail II, or DinoPark Tycoon.
Instant sub - was praying this would happen!
I’d love to see something like this for simgolf, but in any case thanks for this videp! Very entertaining and educational :)
Another quality video.
12:40 Vegeta, what does the scouter say about ax's power level?
great video, one of my favs too from my childhood. One criticism i have though is your resolution! it was hard at times to see what you're doing at times when you don't zoom in... found myself actually zooming in in the browser!
I tried to zoom on on the relevant bits, but thanks for the feedback!
theres an old retro game called Sub Cultures, it has no compability and no release from gog. could you look into it on how to make it run on modern windows?