9 ms·
The gold standard of optimization: A look under the hood of RollerCoaster Tycoon
- sroerick 7mo agoI had always heard about how RCT was built in Assembly, and thought it was very impressive. The more I actually started digging into assembly, the more this task seems monumental and impossible. I didn't know there was a fork and I'm excited to look into it
- mikkupikku 7mo agoMacros. Lots of macros.
- timschmidt 7mo agoAnd presumably generous use of code comments
- cogman10 7mo agoYup. I've done a bit of assembly and it's really only a little harder than doing C. You simply have to get familiar with your assembler and the offered macros. Heck, I might even say that it's simpler than basic.
- kevincox 7mo agoProgramming in assembly isn't really "hard" it mostly takes lots of discipline. Consistency and patterns are key. The language also provides very little implicit documentation, so always document which arguments are passed how and where, what registers are caller and callee saved. Of course it is also very tedious. Now writing very optimized assembly is very hard. Because you need to break your consistency and conventions to squeeze out all the possible performance. The larger "kernel" you optimize the more pattern breaking code you need to keep in your head at a time.
- sroerick 7mo agoThis makes sense and it's really that last step. It's one thing to do pattern matching or bit flipping routines. It's a whole different ballgame to build a game engine. Maybe if I knew gamedev better I wouldn't be as intimidated by it, but it really does seem like a herculean task. I think it'd be cool to do assembler on a Pi Pico or something, that seems like it would be a fun exercise.
- markus_zhang 7mo agoBack then a lot of people started with assembly because that was the only way to make games quick enough. Throughout the years they accumulated tons of experience and routines and tools. Not saying that it was not a huge feat, but it’s definitely a lot harder to start from scratch nowadays, even for the same platform.
- sroerick 7mo agoOne thing I really don't understand would be the ergonomics of game dev. I mean, I guess it's just an isometric drawing library, and routines for each object (though this obviously isn't OOP game Dev). But like, for example, he talks about simulating the physics of the roller coasters. I get that, and I think I could figure that out in assembly. But, in my head, connecting the dots from simulating the physics to drawing it on the screen is a huge leap. But yeah, having years of background on using assembler for game Dev would obviously be a big part of that equation.
- markus_zhang 7mo agoIIRC back then drawing on screen is simply writing into some memory mapped regions. But maybe it is more than that when the game was written, as it was in mid 90s. I happened to glance over Linux device driver 3e yesterday, and just programming GPIO is ghastly complicated — the programmer needs to request a region, use specific memory in/out functions to write/read, and then release the region, all for just reading and writing some bytes — no real business about. Not saying that was not a significant feat, but I think it’s almost impossible for anyone to do so nowadays — even with C it is a very good amount of knowledge to write an engine without libraries.
- mrguyorama 7mo ago>I didn't know there was a fork and I'm excited to look into it OpenRCT2 isn't a fork, it's like OpenTTD, a recreation. Go look at GDC's Classic Game Postmortems. They have tens of videos of the people who built famous games from the 80s and 90s who often go into technical details of how they do it. For example, Robotron goes into how the code works. It's remarkably familiar. They basically built object oriented programming and classes using convention only. You treat every actor you want to work with as a chunk of memory with standard layout that includes pointers for behavior and slots for state, and you just try really hard to only operate on the right "Types" at the right places. From there you have your standard game loop of "Get input, update all Actors, render, loop" The Pitfall postmortem is wonderful. The Atari 2600 had roughly zero RAM to work with, and barely any cartridge space to hold your game. To make their large, somewhat open world, they made each screen built off just a few parameters, and created a bidirectional psuedorandomish function that would generate the parameters on a cycle, giving you a connected map space!
- HelloUsername 7mo agoFun read, thx! I'd also recommend more about RCT: "Interview with RollerCoaster Tycoon's Creator, Chris Sawyer (2024)" https://news.ycombinator.com/item?id=46130335 https://news.ycombinator.com/item?id=46130335 "Rollercoaster Tycoon (Or, MicroProse's Last Hurrah)" https://news.ycombinator.com/item?id=44758842 https://news.ycombinator.com/item?id=44758842 "RollerCoaster Tycoon at 25: 'It's mind-blowing how it inspired me'" https://news.ycombinator.com/item?id=39792034 https://news.ycombinator.com/item?id=39792034 "RollerCoaster Tycoon was the last of its kind [video]" https://news.ycombinator.com/item?id=42346463 https://news.ycombinator.com/item?id=42346463 "The Story of RollerCoaster Tycoon" https://www.youtube.com/watch?v=ts4BD8AqD9g https://www.youtube.com/watch?v=ts4BD8AqD9g
- fweimer 7mo agoWhat language is this article talking where compilers don't optimize multiplication and division by powers of two? Even for division of signed integers, current compilers emit inline code that handles positive and negative values separately, still avoiding the division instruction (unless when optimizing for size, of course).
- cjbgkagh 7mo agoIt was written in assembly so goes through an assembler instead of a compiler.
- rawling 7mo agoI assume GP is talking about the bit in the article that goes > RCT does this trick all the time, and even in its OpenRCT2 version, this syntax hasn’t been changed, since compilers won’t do this optimization for you.
- cjbgkagh 7mo agoThat makes more sense, I second their sentiment, modern compilers will do this. I guess the trick is knowing to use numbers that have these options.
- bombcar 7mo agoThere was a recent article on HN about which compiler optimizations would occur and which wouldn't and it was surprising in two ways - first, it would make some that you might not expect, and it would not make others that you would - because in some obscure calling method, it wouldn't work. Fixing that path would usually get the expected optimization.
- shakow 7mo agoThat's what I would have thought as well, but looks like that on x86, both clang and gcc use variations of LEA. But if they're doing it this way, I'm pretty sure it must be faster, because even if you change the ×4 for a <<2, it will still generate a LEA. https://godbolt.org/z/EKj58dx9T https://godbolt.org/z/EKj58dx9T
- londons_explore 7mo ago> it turns an optimization done out of technical necessity into a gameplay feature And this folks is why an optimizing compiler can never beat sufficient quantities of human optimization. The human can decide when the abstraction layers should be deliberately broken for performance reasons. A compiler cannot do that.
- timschmidt 7mo agoAgreed. It really requires an understanding of not just the software and computer it's running on, but the goal the combined system was meant to accomplish. Maybe some of us are starting to feed that sort of information into LLMs as part of spec-driven development, and maybe an LLM of tomorrow will be capable of noticing and exploiting such optimizations.
- gwern 7mo agoEnd-to-end optimization in action! Although I'd've liked more than 1 example (pathfinding) here.
- nulltrace 7mo agoThe LEA-vs-shift thread here kind of proves the point. Compilers are insanely good at that stuff now. Where they completely fall short is data layout. I had a message parser using `std::map<int, std::string>` for field lookup and the fix was just... a flat array indexed by tag number. No compiler is ever going to suggest that. Same deal with allocation. I spent a while messing with SIMD scanning and consteval tricks chasing latency, and the single biggest win turned out to be boring. Switched from per-message heap allocs to a pre-allocated buffer with `std::span` views into the original data. ~12 allocations per message down to zero. Compiler will optimize the hell out of your allocator code, it just won't tell you to stop calling it.
- hrmtst93837 7mo ago[flagged]
- applfanboysbgon 7mo ago> Imagine a programmer asking a game designer if they could change their formula to use an 8 instead of a 9.5 because it is a number that the CPU prefers to calculate with. There is a very good argument to be made that a game designer should never have to worry about the runtime performance characteristics of binary arithmetic in their life, that’s a fate reserved for programmers Numeric characteristics are absolutely still a consideration for game designers even in 2026, one that influences what numbers they use in their game designs. The good ones, anyways. There are, of course, also countless bad developers/designers who ignore these things these days, but not because it is free to do so; rather, because they don't know better, and in many cases it is one of many silent contributing factors to a noticeable decrease in the quality of their game.
- edflsafoiewq 7mo agoExamples?
- andai 7mo agohttps://en.wikipedia.org/wiki/Nuclear_Gandhi https://en.wikipedia.org/wiki/Nuclear_Gandhi From what I heard, there was a Civilization game which suffered from an unsigned integer underflow error where Gandhi, whose aggression was set to 0, would become "less aggressive" due to some event in the game, but due to integer underflow, this would cause his aggression to go to 255, causing him to nuke the entire map. The article says this was just an urban legend though. Well, real or not, it's a perfect example of the principle!
- luaKmua 7mo agoIndeed an urban legend. Sid Meier himself debunked in his memoir, which is a pretty great read.
- mrguyorama 7mo agoIt's fascinating to live through the entire lifecycle of: Weird thing happens. People make up reasons why. One reason is possible. That becomes THE reason, and spread wildly, without confirmation, as an accurate explanation. "Actually that's not true". Now that not being the reason is widely disseminated and if we are lucky the original meme dies out! But it took 30 years. For a very meaningless rumor.
- lefty2 7mo ago> The same trick can also be used for the other direction to save a division: > NewValue = OldValue >> 3; You need to be careful, because this doesn't work if the value is negative. A
- whizzter 7mo agoMost CPU's has signed and unsigned right shift instructions (left shift is the same), so yes it works (You can test this in C by casting a signed to unsigned before shifting). The biggest caveat is that right shifting -1 still produces -1 instead of 0, but that's usually fine for much older game fixed-point maths since -1 is close enough to 0.
- deleted 7mo ago[deleted]
- lefty2 7mo ago> -1 still produces -1 instead of 0 That could be a problem depending how you are using it.
- adrian_b 7mo agoIt works fine when the value is negative. However, there is a quirk of the hardware of most CPUs that has been inherited by the C language and by other languages. There are multiple ways of defining integer division when the dividend is not a multiple of the divisor, depending on the rounding rule used for the quotient. The 2 most frequently used definitions is to have a positive remainder, which corresponds to rounding the quotient by using the floor function, and to have a remainder of the same sign with the quotient, which corresponds to rounding the quotient by truncation. In most CPUs, the hardware is designed such that for signed integers the division instruction uses the second definition, while the right shift uses the first definition. This means that when the dividend is a multiple of the divisor, division and right shift are the same, but otherwise the quotient may differ by one unit due to different rounding rules. Because of this, compilers will not replace automatically divisions with right shifts, because there are operands where the result is different. Nevertheless, the programmer can always replace a division by a power of two with a right shift. In all the programs that I have ever seen, either the rounding rule for the quotient does not matter or the desired definition for the division is the one with positive remainder, i.e. the definition implemented by right shift. In those cases when the rounding rule matters, the worrisome case is when you must use division not when you can use right shift, so you must correct the result to correspond to rounding by floor, instead of the rounding by truncation provided by the hardware. For this, you must not use the "/" operator of the C language, but one of the "div" functions from "stdlib.h", or you may use "/" but divide the absolute values of the operands, after which you compute the correct signed results.
- bluelightning2k 7mo agoGreat write up. Thank you. Really great! I was reminded of the factorio blog. That game's such a huge optimization challenge even by today's standards and I believe works with the design. One interesting thing I remember is if you have a long conveyor belt of 10,000 copper coils, you can basically simplify it to just be only the entry and exit tile are actually active. All the others don't actually have to move because nothing changes... As long as the belts are fully or uniformly saturated. So you avoid mechanics which would stop that.
- plopz 7mo agoI was pretty disappointed with how Factorio reworked how fluids worked in the expansion. The old system had its quirks and the new system is obviously more performant, but it throws realism out the window which is a bummer.
- Starlevel004 7mo agoThe old system was nonfunctional and any base that used lots of fluids (like modded ones, or new space age ones) were constantly running up against nonsensical mechanics.
- Cpoll 7mo agoI don't miss it. I also found Satisfactory's old fluid system (with concepts like sloshing) wildly unintuitive. I'll go so far as to say that accurate fluid dynamics is detrimental to any game that's not about beavers and water table management.
- rkagerer 7mo agoThat's the second time I heard the beaver game come up here... Guess I really ought to try it!
- Linosaurus 7mo agoIt’s rather neat, and recently hit 1.0. That game, Timberborn, shares some design elements with roller coaster tycoon. A block based 3d world they can be modified by the player. Units walking around on player defined paths, with their mood influenced by pretty bushes. But there are no obvious performance considerations like in the article.
- youarentrightjr 7mo ago> The same trick can also be used for the other direction to save a division: NewValue = OldValue >> 3; This is basically the same as NewValue = OldValue / 8; RCT does this trick all the time, and even in its OpenRCT2 version, this syntax hasn’t been changed, since compilers won’t do this optimization for you. (emphasis mine) Not at all true. Assuming the types are such that >> is equivalent to /, modern compilers will implement division by a power of two as a shift every single time.
- dmitrygr 7mo agothey will do it for unsigned. for signed they will do a bit more to do the same rounding as C promises
- grumbelbart2 7mo agoHere is how that looks like: https://godbolt.org/z/rooee4esd https://godbolt.org/z/rooee4esd
- account42 7mo agoIt's unfortunate that C tied overflow behavior to the signedness of integer types.
- mid-kid 7mo agoYeah. I'm surprised this along with the money thing are listed in the article at all. These are the sort of things you learn within the first month of writing assembly, and were widely used across the industry at the time (and times prior). The bit shifting optimization is performed by GCC even at -O0, and likely already was at the time, as it's one of the simpler optimizations to make. It's like calling "xor eax, eax" a masterful optimization tactic for clearing a register. Looking at the macro-level optimizations like the rest of the article does is significantly more interesting.
- ConceptJunkie 7mo ago"XOR AXAX" was my license plate in the 90s.
- deleted 7mo ago[deleted]
- sghiassy 7mo agoAnother great optimization is storing the year as two digits, because you only need the back half… … oh wait, nvm. Don’t preoptimize!
- seba_dos1 7mo agoThere's a vast space between premature optimization and not caring about optimization until it bites you, and both extremes make you (or someone else) miserable.
- neonstatic 7mo agoIt's a fun optimization to make in the 9th decade of a century :)
- ZebusJesus 7mo ago[flagged]
- MisterTea 7mo agoWhile it has been a while since playing RCT, one thing that was really nice about the game is that it runs flawlessly under Wine. I really wish I could see the source code.
- deleted 7mo ago[deleted]
- troad 7mo ago> When reading through OpenRCT2’s source, there is a common syntax that you rarely see in modern code, lines like this: > NewValue = OldValue << 2; I disagree with the framing of this section. Bit shifts are used all the time in low-level code. They're not just some archaic optimisation, they're also a natural way of working with binary data (aka all data on a computer). Modern low-level code continues to use lots of bit shifts, bitwise operators, etc. Low-level programming is absolutely crucial to performant games. Even if you're not doing low-level programming yourself, you're almost certainly using an engine or library that uses it extensively. I'm surprised an article about optimisation in gaming, of all things, would take the somewhat tired "in ye olde days" angle on low-level code.
- Rendello 7mo agoI learned these low-level bit tricks by reading TempleOS' HolyC source code. I remember feeling like a genius when I worked out what this line does: dc->color=c++&15; Hint: it's from this "Lines" demo program, whose source is here: https://web.archive.org/web/20180906060723/https://templeos.holyc.xyz/Wb/Demo/Graphics/Lines.html https://web.archive.org/web/20180906060723/https://templeos.... And this is what it looks like when it runs (ignore the fact it's running in Minecraft): https://youtu.be/pAN_Fza6Vy8?t=38 https://youtu.be/pAN_Fza6Vy8?t=38
- netcoyote 7mo agoWarcraft 1 (1994), Warcraft 2 (1995), and StarCraft (1998) all use power-of-2 aligned map sizes (64 blocks, 128 blocks, and 256 blocks) so the shift-factor could be pre-computed to avoid division/multiplication, which was dang slow on those old 386/486 computers. Each map block was 2x2 cells, and each cell, 8x8 pixels. Made rendering background cells and fog-of-war overlays very straightforward assembly language. All of Warcraft/etc. had only a few thousand lines of assembly language to render maps/sprites/fonts/fog-of-war into the offscreen buffer, and to blit from the offscreen buffer to the screen. The rest of the code didn't need to be in assembly, which is too time-consuming to write for code where the performance doesn't matter. Everything else was written in portable assembler, by which I mean C. Edit: By way of comparison, Blackthorne for Super Nintendo was all 85816 assembly. The Genesis version (Motorola 68000) and DOS version (Intel 80386) were manually transcribed into their respective assembly languages. The PC version of Blackthorne also had a lot of custom assembler macros to generate 100K of rendering code to do pixel-scrollable chunky-planar VGA mode X (written by Bryan Waters - https://www.mobygames.com/person/5641/bryan-waters/ https://www.mobygames.com/person/5641/bryan-waters/). At Blizzard we learned from working on those console app ports that writing assembly code takes too much programmer time. Edit 2: I recall that Comanche: Maximum Overkill (1992, a voxel-based helicopter simulator) was written in all assembly in DOS real mode. A huge technical feat, but so much work to port to protected mode that I think they switched to polygon-rendering for later versions.
- quietsegfault 7mo agoMaximum overkill was an amazing game. I probably played hundreds and hundreds of hours.
- CursedSilicon 7mo agoIt's a shame that when a Redditor discovered the source code for the original StarCraft "gold master" on a CD, they sent it back to Blizzard in exchange for some fucking blizzard merch [1] EA a while back released the source code to (most) of the old Command & Conquer games [2] though interestingly left out Tiberian Sun and Red Alert 2, StarCraft's closest competitors at the time. Would've been nice for historical preservation to be able to peek behind the curtain and see StarCraft's code in a similar fashion [1] https://old.reddit.com/r/gamecollecting/comments/68xzxt/starcraft_gold_master_source_code_update/ https://old.reddit.com/r/gamecollecting/comments/68xzxt/star... [2] https://github.com/electronicarts https://github.com/electronicarts
- evandale 7mo agoThe pathfinding section reminded me that there's a YouTube steamer, Marcel Vos, who goes into a deep dive of how the pathfinding works. https://youtu.be/twU1SsFP-bE https://youtu.be/twU1SsFP-bE He has lots of videos that are deep dives into how RCT works and how things are implemented!
- mmcconnell1618 7mo agoI've built a few transportation simulations where I started out with pathfinding methods like A* but the compute cost doesn't scale well with 10,000 or 100,000 agents running around. Pre-computing flow fields for common map destinations is one of those areas where you trade off storage for compute. The agents just look for the signpost telling them "this direction to destination x" instead of actually calculating a path. https://en.wikipedia.org/wiki/A*_search_algorithm# https://en.wikipedia.org/wiki/A*_search_algorithm# https://www.youtube.com/watch?v=zr6ObNVgytk https://www.youtube.com/watch?v=zr6ObNVgytk
- maxglute 7mo agoIs there a place to find stories of recent game optimization? What's most ridiculous on like quick inverse square route. As someone who spent way too much time vraying in prior life, I still can't believe we got real time ray tracing.
- egypturnash 7mo agoI have to wonder how much of the original assembly source looked a lot more succinct than whatever's in OpenRCT due to the use of macros. Looking up his gameography on Mobygames, Chris had been writing stuff since 1984 when RCT came out in 1999, it's hard to imagine he was still writing every single opcode out by hand given that I had some macros in the assembler I was fooling around with on my c64 back in the eighties.
- Validark 7mo ago"Since the number is stored in a binary system, every shift to the left means the number is doubled. At first this sounds like a strange technical obscurity" Do we not know binary in 2026? Why is this a surprise to the intended audience?
- xeonmc 7mo agohttps://xkcd.com/2501/ https://xkcd.com/2501/
- Validark 7mo agoHow many programmers don't know binary?
- TsiCClawOfLight 7mo agoEveryone who learned web dev or app dev only.
- Validark 7mo agoOkay, but are those people unaware that they skipped learning all the fundamentals? I was just surprised that someone would write an article that's supposed to be about a game written in assembly and throw in a line saying that binary arithmetic is a technical obscurity.
- raffraffraff 7mo agoOn huge games produced by large game studios, I wonder if the idea of using a real world technical challenge as a "feature" within the game is considered genius? Consider a coder and a game designer who are on different teams and don't attend the same meetings. But if you look at creative writing, story arcs are all about obstacles. A boring story is made interesting by an obstacle. It is what our protagonist needs to overcome. A one-man-band game dev who simultaneously holds the story and the technical challenge their head, might spot the opportunity to use a glitch or limitation as, I dunno, a mini game that riffs on the glitch.
- rajan2 7mo ago[flagged]
- rajan2 7mo ago[flagged]
- rajan2 7mo ago[flagged]
- atrealadam 7mo ago[flagged]
- makapuf 7mo agoCompilers won't do multiplication by power of two to bit shift for you ? I remember reading in ~2000: the only thing writing a<<2 instead of a/4 will do is make your compiler yawn
- zekica 7mo agoEven gcc's -O0 will do the bitshift, but even dividing with 5 on x86_64 will not do idiv: imul rdx, rdx, 1717986919 shr rdx, 32 sar edx sar eax, 31 sub edx, eax mov eax, edx
- bze12 7mo ago> This part is especially fascinating to me, since it turns an optimization done out of technical necessity into a gameplay feature. Reminds me of blood moons in Zelda https://www.polygon.com/legend-zelda-tears-kingdom/23834440/totk-blood-moon-hidden-trick/ https://www.polygon.com/legend-zelda-tears-kingdom/23834440/...
- pmg102 7mo agoThe article refers several times to the benefits of the game designer and the coder being the same person. I've often felt that this is the only way to build anything impressive, and in fact I'm amazed that corporations with their hierarchical organisation model ever get anything built at all but I suppose you can brute force anything with enough employees. It does make you wonder if the future of AI-assisted development will look more like the early days of coding, where one single mind can build and deliver a whole piece of software from beginning to end.
- ionwake 7mo agoalso I remember the excitement of a new game that looked different to others. Somehow even as a child I just knew that it would be a whole new emergent game play experience. Ofcourse I didnt know waht went into making Rolelrcoaster Tycoon but I could just by a couple of screenshots how this was clearly a ground up new game with new mechanics that would be extremely fun to play. I dont get this feeling anymore, as I just assyne everything is just a clone of another game in the same engine generally. Unless its been a decade in production like Breath of the Wild of GTA 5 i just dont expect much.
- almostdeadguy 7mo agoThe pathfinder algorithm is a great example of why constraints are so important for creativity and creative development. If AI has any benefit to creative endeavors at all it will be because of the challenges of coaxing a machine defined to produce an averaging of a large corpus of work (producing inherently mediocre slop) provides novel limitations, not because it makes art any more "accessible".
- derodero24 7mo ago[flagged]
- jwilliams 7mo agoDefinitely made me feel old to see bit-shifting needed an explainer! I must admit as I was reading I was "why is he explaining this? it's obvious!".
- throw_m239339 7mo agoFantastic write-up, that's exactly why I came to HN many years ago, to find such articles about mundane things or products, but the technical aspect is just fascinating.
- random__duck 7mo agoSo this is what programing on hard mode looks like ?
- itsnexis 7mo ago[dead]
- ConceptJunkie 7mo ago> The same trick can also be used for the other direction to save a division: > NewValue = OldValue >> 3; > This is basically the same as > NewValue = OldValue / 8; > RCT does this trick all the time, and even in its OpenRCT2 version, this syntax hasn’t been changed, since compilers won’t do this optimization for you. The author loses a lot of credibility by suggesting the compiler won't replace multiplying or dividing by a factor of 2 with the equivalent bit shift. That's a trivial optimization that's always been done. I'm sure compilers were doing that in the 70s.
- msk-lywenn 7mo agoI wouldn't go that far, but yes, no compiler will leave that on the table today or even twenty years ago. They do even more impressive transformations than that on basic math.
- nearbuy 7mo agoThe author is partly right here. If those values are ints, you'll get something like this: sar eax, 0x1f and eax, 7 add eax, edx sar eax, 3 You get 4 instructions instead of one because value >> 3 rounds towards negative infinity and value / 8 rounds towards zero. And while this wouldn't apply to C++, in languages with checked arithmetic, the left shift won't necessarily set the overflow flag, so the compiler often can't use it.
- TheGRS 7mo agoThis is a fun read, its one of my favorite games growing up by far, countless hours sunk into it. I didn't need this write-up to know that Chris Sawyer was god among men and that the open source version is a huge labor of love, but its a good reminder :) I will need to give OpenRCT a try some time, I've tried a little OpenTTD and really enjoy it, but RCT was always my jam. For the lesson here, I think re-contextualizing the product design in order to ease development should be a core tenant of modern software engineering (or really any form of engineering). This is why we are usually saying that we need to shift left on problems, discussing the constraints up-front lets us inform designers how we might be able to tweak a few designs early in order to save big time on the calendar. All of the projects that I loved being a part of in my career did this well, all of the slogs were ones that employed a leadership-driven approach that amounted to waterfall.
- hermitcrab 7mo ago>the game was written in the low-level language Assembly Surely it wasn't all assembly. There is little to be gained in performance from writing non-bottleneck parts of the code in assembly.
- its-summertime 7mo ago> > What language was RollerCoaster Tycoon programmed in? > It's 99% written in x86 assembler/machine code (yes, really!), with a small amount of C code used to interface to MS Windows and DirectX. https://www.chrissawyergames.com/faq3.htm https://www.chrissawyergames.com/faq3.htm
- hermitcrab 7mo agoWow. It reminds me of those guys who run a marathon carrying a fridge. Impressive, but ...
- gargalatas 7mo agoYeah but imagine that if it was writte in anything else it would never had made it to the shelves with the processor power back then.
- hermitcrab 7mo agoPrograms spend the vast amount of their cycles in a small sub-set of the code. There is generally very little to be gained by optimizing code that isn't in the small subset.
- ben7799 7mo agoI guess I'm showing my age but having read stuff like Michel Abrash's books years ago this article was a bit underwhelming. Like no one who wrote any code back in the 80s or 90s even for a homebrew game was skipping this stuff, it was in almost every book and tutorial. Stuff like bit shifting was extremely common and a lot of games would have had design choices that were informed by coding challenges. Lots and lots of code had data structures aligned on byte/word boundaries or had data massaged to fit into the limits of hardware in order to make reads happen in a certain # of cycles, etc.. certainly almost all console games had lots and lots of fascinating design choices like this. This game may have been exceptionally well optimized but it feels like if the original code is not in the public domain these weren't the best examples. When he started writing about their being a clean sheet re-implementation I thought there was going to be a benchmark comparison of the modern rewrite vs the original on old hardware or something, that would have been interesting. Thankfully or not I'm just barely young enough that I never had to write anything professional in assembly, though if I had gone into games maybe I would have.
- chihuahua 7mo ago[dead]
- WillAdams 7mo agoI'm still kind of sad that application development no longer uses much assembly language, WriteNow, which was ~100,000 lines of assembler is still my gold standard for word processor and performance.
- LiamhCryptokeys 7mo ago[dead]
- deterministic 7mo agoAnother gold standard of optimization: Factorio