Title says it all. I am interested in discovering how games like roller coaster tycoon, sim city 2000, warcraft II, and descent (blown away by this one) managed to be created and function on computers that had 500 MB HDD, 300 MHz CPU, and 4 MB RAM.
I'd even broaden the question and ask how did windows 95 stay so small?
Is it possible to recreate this level of efficiency on modern systems? Im curious because I'm interested in creating simulation video games. Dwarf Fortress and Rimworld eventually both suffer from the same problem: CPU death.
If I create a window with C++ and SFML, 60 MB of RAM is used (not impressive at all). If I put 3,000,000 tiles on the screen (using Vertex Arrays), 1 GB of RAM is used (admittedly, that is impressive) and I can pan all the tiles around smoothly.
What other tricks are available?
We thought about things in terms of how many instructions per pixel per frame we could afford to spend. Before the 90s it was hard to even update all pixels on a 320x200x8bit (i.e. mode 13h) display at 30 fps. So you had to do stuff like only redraw the part of the screen that moved. The led to games like donkey kong where there was a static world and only a few elements updated.
In the 90s we got to the point where you had a pentium processor at 66 Mhz (woo!) At that point your 66Mhz / 320 (height) / 200 (width) / 30 (fps) gave you 34 clocks per pixel. 34 clocks was way more than needed for 2D bitblt (e.g. memcpy'ing each line of a sprite) so we could beyond 2D mario-like games to 3D ones.
With 34 clocks, you could write a texture mapper (in assembly) that was around 10-15 clocks per pixel (if memory serves) and have a few cycles left over for everything else. You also had to keep overdraw low (meaning, each part of the screen was only drawn once or maybe two times). With those techniques, you could make a game where the graphics were 3D and redrawn from scratch every frame.
The other big challenge was that floating point was slow back then (and certain processors did or didn't have floating-point coprocessors, etc.) so we used a lot of fixed point math and approximations. The hard part was dividing, which is required for perspective calculations in a 3D game, but was super slow and not amenable to fixed-point techniques. A single divide per pixel would blow your entire clock budget! "Perspective correct" texture mappers were not common in the 90s, and games like Descent that relied on them used lots of approximations to make it fast enough.
As developers, we were also forced to give the graphics guys a really hard time: "no that texture is too big! 128x128" & "you need to do it again with less polygons". We used various level of detail in textures and models to minimise calcs and rendering issues. Eg. A tank with only 12 vertices when it would only be a pixel or three on screen. I think it only used 2x2 texels as part of a 32x32 texture (or thereabouts)...
This was around mid 90's.
Any yeah, the design of the game content was absolutely affected by things like polygon count concerns: "Say, wouldn't it be cool to have a ship that shaped like a torus with a bunch of fins sticking out? Actually, on second thought... How about one that looks like a big spike? :)"
I recently spent two years on the performance team for a large indie title and a huge portion of it was asking artists to simplify meshes, improve LODs, increase the amount of culling we could do on the CPU, etc.
My own work was mainly optimising the rendering itself.
Michael Abrash's "Graphics Programming Black Book" https://github.com/jagregory/abrash-black-book
https://www.drdobbs.com/parallel/graphics-programming-black-...
As CPU power, the number of cores, RAM sizes, HDD sizes, graphics card capabilities have increased, the developers are no longer as careful to squeeze out the performance.
The source code has since been released on GitHub, if you’re ever interested in seeing it!
CPUs were simpler DOS and Windows 95 were very simple compared to Windows 10.
That means that writing optimized C or even assembler routines was pretty easy.
If we go 10 years back in time, programming Z80 or MOS Technology 6510 or Motorola 68k was even simpler.
I think the most innovative timespan was between 1950–1997'ish, and hope we get back to get the most out of hardware again as common sense.
HandmadeCon 2016 - History of Software Texture Mapping in Games
https://www.youtube.com/watch?v=xn76r0JxqNM
I think they say at one point it went from 14 to 8 instructions, and then the Duke Nukem guy (Ken Silverman) got it down to around 4.
Quake would do something where it only issued a divide every 8 pixels or something, and then only interpolate when inbetween and the out of order execution on pentium pro (I think?) would let it all work out.
Since the FPU could work in parallel with the integer instructions on the pentium, this was almost as fast as just doing affine texture mapping.
This worked even on the basic Pentium.
It was likely also the reason Quake was a unplayable on the 486 and Cyrix 586.
Does anyone know of a book like it? I'm very interested in getting started with software rendering from the ground up, mainly to scratch an intellectual itch of mine. I learn better from well-curated books than online material in general.
Also, a little later in the 90's: VTune. When VTune dropped it was a game changer. Intel started adding performance counters to the CPUs that could be queried in real-time so you could literally see what code was missing branches or stalling, etc. Source: I worked with Blizzard (pre-WoW!) developing VTune, feeding back requirements for new performance counter requests from them and developers.
You also basically knew how many cycles each instruction took (add, multiply, bit shift, memory reference, etc.) so you just added up the clock counts. (Though things got a bit harder to predict starting with Pentium as it had separate pipelines called U and V that could sometimes overlap instructions.)
It’s easy to forget that each upgrade to graphics is an exponential jump. Going from 8 colours to 256 colours on screen. Jumps in resolution. Jumps in sound, number of sprits the hardware can track. Etc.
When we look at graphics now and the tangible visible difference between 8k, 4K and HD and Moore’s Law no longer in effect it is easy to forget just how significant the jumps in tech was in the 80s and 90s if you hadn’t lived through it and/or developed code during it.
These machines don’t even have enough memory to store one frame buffer, you can’t program like a modern game where everything is customizable and you can just do whatever you want as long as it’s fast enough.
In a game like Donkey Kong you do what the hardware allows you to do (and of course the hardware is designed to allow you to do what you want to do).
How is it so small? No external dependancies (uses stock Haiku packages), uses the standard C++ system API, and written by a developer that learned their trade on restrained systems from the 80’s. Look at the old Amiga stuff from that era.
smallstepforman has submitted it before: https://news.ycombinator.com/item?id=25513557. Unfortunately, it didn't garner much attention.
Lower-res samples, if any.
Lower framerate expectations - try playing Descent 2 on an emulated computer with similar specs to the lowest specs suggested on the box. Even one in the middle of the spec range probably didn't get a constant 60fps.
More hand-tuned assembly (RCT was famously 99% assembly, according to Wikipedia; this was starting to be unusual but people who'd been in the industry a while probably did at last one game in 100% assembly, and would have been pretty comfortable with hand-optimizing stuff as needed).
Simpler worlds, with simpler AI. Victory conditions designed to be reached before the number of entities in the game overwhelmed the CPU completely.
Simpler models. Most 3d games you play now probably have more polygons in your character's weapon than Descent would have in the entire level and all the active entities; they certainly have more polys in the overall character.
I mean, really, three million tiles? That's insane by that day's standards, that's a bit more than 1700x1700 tiles, a quick search tells me the maximum map size in Roller Coaster Tycoon 3 was 256x256, and it's a fairly safe assumption that RCT1 was, at best, the same size, if not probably smaller. I can't find anything similar for Sim City 2000 but I would be surprised if it was much bigger.
Some games nowadays are built using Electron, which means they include a full web browser which will then run the game logic in JavaScript. That alone can cause +1000% CPU usage.
Unity (e.g. RimWorld) wastes quite a lot of CPU cycles on things that you'll probably never use or need, but since it's a one-size-fits-all solution, they need to include everything.
For Unreal Engine, advanced studios will actually configure compile-time flags to remove features that they don't need, and it's C++ and in general well designed, so that one can become quite efficient if you use it correctly.
And then there's script marketplaces. They will save you a lot of time getting your game ready for release quickly, but they are usually coded by motivated amateurs and super inefficient. But if CPUs are generally fast enough and the budgets for game developers are generally low, many people will trade lower release performance for a faster time to market.
=> Modern games are slow because it's cheaper and more convenient that way.
But there still are tech demos where people push efficiency to the limit. pouet.net comes to mind. And of course the UE5 demo which runs on an AMD GPU and a 8-core AMD CPU:
https://www.youtube.com/watch?v=iIDzZJpDlpA
My earliest days had the most fantastic tricks. So called game engines were useless. Now it’s the complete opposite.
I mean, it's hard to disagree when you phrase it this way, but... really? In the old days (mid-'90s) studios like id released many games per year, some of which with completely new technology.
Modern studios and indie developers (!) who "do things in a straightforward way" can be happy to release even one game per year, and that's with a lot of reuse. Forget novel technology once a year!
So maybe these tricks don't really increase time to market that much, compared to other variables that are also in play?
I'd actually like to link the YouTube channel of a person who is writing their own game engine and game at the same time: https://www.youtube.com/c/RandallThomas/videos
You can see how using Godot, Unity or Unreal (or most other engines) would have been much faster in regards to time to market.
Similar differences show up when you try to build the same project, once while using an engine and another without it, the performance can be much better if you write your own optimized code (supposing that you can do so in the first place), however the development still takes much longer, for example: https://www.youtube.com/watch?v=tInaI3pU19Y
Now, whether that matters to you or not is a different matter entirely: some care about learning a lot more about the lower level stuff, others just want to develop games and care more about the art/story/etc., while others care about selling them ASAP.
Now with CSS frameworks, JS frameworks, ad frameworks and cross-linking, pages take forever to load with even less actual content.
Pingdom reports 4.8mb (3.3mb of images), 661ms to load, and 298 requests.
GT Metrix reports 2.65mb (2mb of images), and 307 requests.
An incognito window with Firefox on my system says ~3mb and ~265 requests. Just the top six or seven media assets combined that loaded initially weigh in at about 1mb.
Certainly not the worst page ever, granted.
It’s like the General that wins every battle because he has the most elite soldiers. Could the General win with a rag tag shoddy group of soldiers?
https://en.m.wikipedia.org/wiki/The_K%C3%B6ln_Concert
Old-school games would have been forced to redesign the game so that that wasn't a problem that gets faced. For example, none of the games you list try to simulate a deep 3d space with complex pathfinding. Warcraft II I know quite well and the maps are small.
One of the reasons systems used to be highly efficient was evolutionary - it was impossible to make resource-heavy games, so people kept iterating until they found good concepts that didn't require polynomial scaling algorithms with moderate-large N inputs.
Naughty Dog Co-founder Andy Gavin discusses various hacks that were used on the Playstation to get Crash Bandicoot to run smoothly. The fuller version is also worth watching.
A PS4 was/is effectively unchanged hardware between Nov 2013 and today, yet the late lifecycle games look great. Upon release of the hardware devs had plenty of performance to play with, then 5 years in they have honed their craft and are able to use all the tricks at their disposal to squeeze as much graphical and performance life out of a limited resource budget.