8 ms·
Let's write a video game from scratch like it's 1987
- musha68k 2y agoGreat "old-school" article! Intrigued to try Odin sometime. > One interesting thing: in Odin, similarly to Zig, allocators are passed to functions wishing to allocate memory. Contrary to Zig though, Odin has a mechanism to make that less tedious (and more implicit as a result) by essentially passing the allocator as the last function argument which is optional.
- wredue 2y agoOne of zigs core tenets is “no hidden allocations”. You’ll never see zig language supporting a default value for allocator parameters to support hiding it at first glance. Zig does have support for empowering library users to push coded settings in to libraries, and you could conceivably use this for writing this type of code. Although it’s probably not worthwhile. Or you can just straight up default your library to using a specific allocator, fuck the calling code. Anyway. Zig has patterns to do stuff like this, but it’s probably unwieldy in large projects and you’re better off just making it a parameter. You can also look in to the std ArrayList, which provides managed and unmanaged variants for yet another way that you might write code that empowers users to set an allocator once, or set it every time.
- deleted 2y ago[deleted]
- bsder 2y agoThe problem with "implicit allocation" is always multithreading. An allocation library cannot serve two masters. Maximizing single thread performance is anathema to multithreaded performance. I'd go further. If allocators don't matter, why are you using a systems programming language in the first place?
- kragen 2y agoit sounds like implicitly passing the allocator as an extra parameter in every call would solve the problems you identify. if it's passed in a call-preserved register, it doesn't even make that implicit passing slower, because it requires zero instructions to not change the register before calling a subroutine (when i've done similar things, it's been to pass an arena for inlined pointer-bumping allocation, a strategy widely used by runtimes that want to make allocation fast. normally this requires two registers, though chicken gets by with just one)
- bsder 2y agoSure, it does, sorta. However, again, if you don't care about your allocators, why are you using a systems programming language? If you're willing to give up control over allocation, you are way, way better off in a managed memory (garbage collected or reference counted) language. Systems programming is pain for gain. You give up a lot of convenience in order to have strict control over things--control of latency, control of memory, control of threading, etc. The price for that control is programming with a lot fewer abstractions and far less help from the language/compiler/interpreter to keep you from shooting yourself in the foot. If you aren't using that "control" then you're just making life painful for yourself for no good reason. Obviously, people can use whatever language they perfectly well want for whatever reason they want. Given how much I talk about and use C, Rust and Zig, people are always surprised that if they ask if they should use any of the systems languages (C/C++/Rust/Zig/etc.) my first response is always "Oh, hell, no."
- kragen 2y agopassing an allocator as an implicit parameter doesn't give up any control over allocation; with that mechanism you can still pass a different allocator when you want (and i assume odin allows that, though i haven't tried it) but i disagree pretty comprehensively with your comment. i don't agree that systems programming is pain, i don't agree with your definition of systems programming as programming with tight low-level control, i don't agree that tight low-level control is pain, i don't agree that abstraction is a necessary or useful thing to give up either for systems programming or to get tight low-level control (though it certainly is expedient), i don't agree that garbage collection (including reference counting) is the only way to simplify memory management, and i don't agree that either systems programming or tight low-level control requires accident-prone languages (and i'm especially surprised to see that assertion coming from an apparent rustacean) that is, i recognize that these tradeoffs are possible. i just disagree that they're necessary
- deaddodo 2y agoI will say, while this is interesting and fun to see, using a trivial library like SDL adds almost nothing to the overhead and expands support to non *nix OSes. There is definitely something to be said of bloat but probably not in this case. You could even keep supporting Linux versions as old as this promises by using legacy 1.x SDL.
- jandrese 2y ago"adds almost nothing to the overhead" is not always true. In the example code in the article he kept the pixbuf in the local X Server memory for low overhead and fast performance over the network. SDL always wants to send the pixmaps over the network. This is not a big deal for Minesweeper, but can be tough for action games.
- deaddodo 2y agoYou're just outlining a major flaw in the X Server protocol, not SDL. That's a unique situation to that specific system due to it's intrinsic network-oriented design and specifically the issue Wayland was designed to handle, which doesn't have this issue. In addition, there are solutions for cache locality of the pixbuf for SDL that you can code around, if you specifically need higher performance X11 code on Linux.
- jandrese 2y agoThe article just described how he was able to avoid this flaw in X11 by being mildly careful in how he structured his code. Making sure to do the bitmap copy only once and then issuing copyrect() calls to the server to have it do all of the blitting locally. With SDL it generally wants to do all of the blitting on the client and then push the whole window over as a giant pixmap for every frame. At least that's what it has done when I've tried to use it.
- immibis 2y agoIt's debatably even a flaw. Network transparency is pretty cool. This Minesweeper probably runs faster over an internet SSH tunnel to Australia than any pixel-based remote desktop protocol. You feel it's a flaw because you only ever run applications locally. But more constraints are a side effect of more possibilities, because you have to program the lowest common denominator of all possible scenarios, so your program works in all of them. That's how APIs work. They all have this tradeoff.
- caseyy 2y agoThat code is a bit too readable for that time period in games, hehe. See Doom: https://github.com/id-Software/DOOM/blob/master/linuxdoom-1.10/r_plane.c https://github.com/id-Software/DOOM/blob/master/linuxdoom-1....
- freestyle24147 2y agoIt's pretty easy to post a link to a codebase and say "this is unreadable". What do you find unreadable about it? What would you do differently now that there have been 30 years of software development between then and now?
- caseyy 2y agoIn the games industry, we generally try to write code that can be maintained by an average programmer. I would at least add more comments for context. Some teams have other ideas, like self-documenting paradigms with small functions and descriptive names. If a typical programmer doesn’t at a glance understand what each line of each function does on screen, what all the variables mean, what changing any line would do, what is the usual data flowing through the function, and what are the limitations of the function, then it either can’t be maintained quickly and cheaply, or maintaining it will introduce unforeseen bugs. But the key point is to not have a codebase that only a small core team can maintain. If you want to see examples of the difference between this and modern in C-like code, see Unreal Engine’s source code. It will generally, at least in areas of frequent change, be much easier to read. I would expect a mid-level programmer to understand 90% of UE’s functions in 10 seconds each. And more experienced programmers usually understand most functions they’ve not seen in UE in a couple of seconds. That’s not the case with Doom code. It took me up to 5 minutes to understand some of them. That means significantly worse readability. And I work in C++, C, C#, and other programming languages at a quite senior level in AAA games. So I don’t think this is a skill issue. It could be, of course.
- metadat 2y agoThis source code looks perfectly legible to me. In fact, for C, it's the equivalent of T-Ball. Nicely and consistently formatted, relevant comments, sane structure, along with decent fn, and var names. What is your definition of "good, readable code?" P.s. I've emailed the mods, but a currently dead child comment from a new account states essentially the same thing (my vouch was insufficient to rez): https://news.ycombinator.com/item?id=40742493 https://news.ycombinator.com/item?id=40742493
- wslh 2y agoI Remember that around 1985 was more simple to write basic games in the TI99/4A in TI Extended BASIC or Logo. The sprite support was an advantage from writing basic games on PCs without sprites support. I remember a performance similar to the Atari 2600 and not using Assembler.
- 0xcde4c3db 2y agoThe graphics chip of the TI99/4A (TMS9918A) was turned into a separate product line for other computer manufacturers, and became hugely influential in the 1980s. Sega used it in the SG-1000 and SC-3000, which led to enhanced clones being used in the Master System, Game Gear, and Genesis. It also became part of the MSX computer standard, which spawned another lineage from Yamaha. The overall design of the graphics hardware of the NES, Game Boy, and TurboGrafx-16 are also strikingly similar despite none of those systems being descended from anything that used the TI chips.
- wslh 2y agoGreat insight! I always saw the TI99/4A as one of the "zillions" of "microcomputers" in the 70s/80s but from your comment I now learnt that it was not so simple regarding Texas Instruments, one of the leaders (if I remember well) of the semiconductor industry at that time. Also the ColecoVision [2] used a variant of that chip. The ColecoVision had the best version of Donkey Kong [3] available in game consoles. Reading about the TMS9918A[1] now. Thank you very much. [1] https://en.wikipedia.org/wiki/TMS9918 https://en.wikipedia.org/wiki/TMS9918 [2] https://en.wikipedia.org/wiki/ColecoVision https://en.wikipedia.org/wiki/ColecoVision [3] https://archive.org/details/donkey-kong-game-manual-coleco-vision-1982_202105/mode/2up https://archive.org/details/donkey-kong-game-manual-coleco-v...
- Jare 2y agoI have an actual commercial game from 1987 :) https://github.com/TheJare/stardust-48k https://github.com/TheJare/stardust-48k
- pan69 2y agoActual? Is this not reversed engineered?
- MrLeap 2y agoI think the "actual" in this case points to "commercial game".
- axus 2y agoFrom the README.md: "Also thank to Roberto Carlos Fernandez, who many years ago made me promise I'd give him a printed copy of the sources. That copy is buried in some box in storage somewhere, and we'd rather do this than go search for it."
- SilasX 2y agoTo adapt the old saying, 3 months of reverse engineering can save you 3 hours in the storage room.
- Jare 2y agoWe lost the source code in any usable form. Even if we dug up the printed copy, scanning it would be tedious as hell. :) So we ended up reverse engineering our own game, fun times. But yeah, "actual" in that it's a real commercial game (30k copies or so) developed and released in 1987. If memory serves right, we started in late autumn'86 and it was published around November'87.
- kotojo 2y agoThis is awesome. I listen to a video game history podcast with the founder of the video game history foundation, https://gamehistory.org/ https://gamehistory.org/ , and the one thing he constantly brings up is to send him any and every person in the game industry with fun stories, weird bits and bobs of prototypes, and anything in between. If you've got the time I know that dude would love to pick your brain!
- Razengan 2y agoEven some games from 1984 or even earlier are amazingly complex, making you wonder how they made them in such short time with limited tools and manpower.
- space_oddity 2y agoThe complexity and creativity of early video games from the 1980s and even earlier are truly impressive
- another2another 2y agoYes, what people managed in pure assembly language was really impressive. Unsurprisingly though they also spent a lot of time developing a lot of time-saving tools, like macro assemblers and higher level languages like C. Probably the games on the Amiga and Atari ST was the last heyday of these kinds of development.
- Razengan 2y agoAnd little prior art to draw inspiration from! The 1980-2000 era was just a raw font of imagination for video games. Since then things have become more iterative and tend to focus on maximizing profits, though thankfully there is a lot of creativity in indie studios/solo devs being empowered by the increasing ease of modern game engines, and even some bigger studios here and there, like FromSoftware.
- ilrwbwrkhv 2y agoPassion + skill > Total compensation optimization + Javascript.
- shiroiushi 2y agoThey didn't get distracted by phones, the internet, or multitasking. When you sat in front of your computer, you could only do one thing at a time on it, and you dedicated all your attention to it. You didn't have a company chat or email window popping up notifications about irrelevant stuff, you didn't get the urge to look up random things on Wikipedia, etc. You probably also got to sit in a small room without a lot of distractions too, instead of sitting in a huge open-office area next to the sales group.
- spacecadet 2y agoI did this last year, built a zero player pixellated space simulator using pygame.
- jandrese 2y ago> X11 is old and crufty, but also gets out of the way. Once a few utility functions to open the window, receive events, etc have been implemented, it can be forgotten and we can focus all our attention on the game. That’s very valuable. How many libraries, frameworks and development environments can say the same? This is my thought as well. You can even avoid some of the grotty details of this article if you use Xlib as your interface instead of going in raw over a socket. Basic Xlib is surprisingly nice to work with, albeit with the caveat that you're managing every single pixel on the screen. For something like a game where you're not using system widgets it is all you need. Where people ran into trouble is when they try to add the X Toolkit, which is far more opinionated and intrusive.
- immibis 2y agoYou might also consider using xcb, which is more of a simple wrapper around the X11 binary protocol, rather than Xlib which leakily tries to abstract it. The famous example (noted in XCB's documentation) is calling XInternAtom in a loop to intern many atoms. Xlib forces you to send request, wait for response, send request, wait for response. XCB lets you send all the requests, then wait for all the responses.
- account42 2y agoXlib is definitely custy but that example isn't really that convincing as you're not going to be interning atoms all the time but ideally only during initialization - after all the whole point of atoms is that you only pass the strings once over the protocol and then use the numeric IDs in subsequent requests.
- immibis 2y agoYes, but when you have 100 atoms and a 300ms round trip time (New Zealand to anywhere, or a satellite link in any part of the world) that's the difference between the application starting in 0.3 seconds or 30 seconds. Add a few more round trips for other stuff: 2 seconds or 32 seconds. Of course interning atoms isn't the only thing apps do on startup that is unnecessarily serialized. There could well be another 100 unnecessary round trips. If you've ever actually tried using that configuration, you might notice that every part of every application suffers from this same problem. Almost all slowness of remote X11 used to be caused by stacking up round trip delays. Probably still is, though there's another cause now, which is transferring all the pixel data because apps treat it as a dumb pixel pipe. This isn't a niche problem and it doesn't only affect application startup.
- agumonkey 2y agoI'm often curious about how people organized / conceptualized development in the 60s, 70s and 80s.
- pan69 2y agoWriting a game, or any software in 1987 would be painstaking compared to the luxury we have today. Back then it was normal to run DOS and DOS can only do one thing at the time. You open your editor, write code, close your editor, run the compiler, run your program, test your program, exit program, re-launch editor, etc. Over time small improvements where made to this flow like a DOS Shell and even things like DESQView that allow for basic multitasking. This is probably a better description (from a code point of view) on what you had to do as a programmer to write a game in the late 80s / early 90s: https://cosmodoc.org/ https://cosmodoc.org/
- bsder 2y agoErm, there was a reason why Turbo Pascal (and the other Borland stuff) was such a big deal. And that dates to 1983.
- switchbak 2y agoTP was just so awesome, it was like a superpower compared to others waiting 10-20x as long for each build. For me the big thing was all the latencies stacked together. Slow hard drives, slow floppies, god help you if you swapped, etc. The era was mostly waiting around for the beige machine to finally do its thing.
- toast0 2y agoThank goodness for modernity. Now we wait for white, black, or unpainted aluminum machines to finally do their thing. Sometimes, we never even get to see the machines. :(
- M95D 2y agoNo modernity for me, thank you! Now every time I add a component to my PC, it's a different color than the rest. It looks like a zebra, I swear. Back then it was just "new" beige and "yellow-ish old worn" beige.
- ceronman 2y ago> The result is a ~300 KiB statically linked executable, that requires no libraries, and uses a constant ~1 MiB of resident heap memory (allocated at the start, to hold the assets). That’s roughly a thousand times smaller in size than Microsoft’s. And it only is a few hundred lines of code. And even with this impressive reduction in resource usage, it's actually huge for 1987! A PC of that age probably had 1 or 2 MB of RAM. The Super NES from 1990 only had 128Kb of RAM. Super Mario Word is only 512KB. A PlayStation from 1994 had only 2MB of system RAM. And you had games like Metal Gear Solid or Silent Hill.
- switchbak 2y agoIn 1987, I think you'd be very lucky to have that much RAM. 4MB and higher only started becoming standard as people ran Windows more - so Win 3.1 and beyond, and that was only released in 1992.
- II2II 2y ago4 MB was considered a large amount of memory until the release of Windows 95. There were people who had that much, but it tended to be the domain of the workplace or people who ran higher end applications. If I recall correctly, home computers tended to ship with between 4 MB and 8 MB of RAM just before the release of Windows 95. There were also plenty of people scrambling to upgrade their old PCs to meet the requirements of the new operating system, which was a minimum of 4 MB RAM.
- aidenn0 2y agoIt was over $100/MB for RAM in 1987. The price was declining until about 1990, then froze at about $40/MB for many years do to cartel-like behavior, then plummeted when competition increased around 1995. I was there when the price of RAM dropped 90% in a single year.
- Doctor_Fegg 2y agoYes. I wrote a version of Minesweeper for the Amstrad CPC, a home computer popular in 1987 (though I wrote it a few years later). I think it was about 5-10Kb in size, not 300. The CPC only had 64k of memory anyway, though a 128k model was available.
- immibis 2y agoIt's noteworthy that it's impossible, by design, to write a statically linked Wayland executable. You have to load graphics drivers, because there's no way to just send either pixel data or drawing commands to the display server, like you can in X11. You have to put the pixel data in a GPU buffer using a GPU driver, then send the GPU buffer reference.
- fallingsquirrel 2y agoNot true. Here's how to send pixel data: https://wayland-book.com/surfaces/shared-memory.html https://wayland-book.com/surfaces/shared-memory.html
- kragen 2y agothank you!
- Lerc 2y agoOne of the first DOS PC programs I made was a MineSweeper clone. It was done as a special request for some friends who had machines that were not up to running Windows, but were addicted to minesweeper from school computers. It was a little weird trying to implement a game I hadn't seen myself, but they gave me very precise descriptions (I think most of them have Math PhDs now) I did it in Turbo Pascal with BGI graphics. I remember having problems with recursively uncovering empty tiles in large levels where mines were sparse. Recursive algorithms turned out to be rather tricky in general when the stack segment is 64k. I added a starting disk of various diameters which let you pick a starting location without risk of explosion, which I think was appreciated.
- rkagerer 2y agoMicrosoft’s official Minesweeper app has ads, pay-to-win, and is hundreds of MBs WTF? This is a showcase of everything wrong with the company today.
- shiroiushi 2y agoYou sound like someone who doesn't own any MSFT stock.
- zephyrfalcon 2y agoMore generally, an example of what is wrong with the experience of using computers/internet today.
- tedunangst 2y ago> Since authentication entries can be large, we have to allocate - the stack is only so big. It would be unfortunate to stack overflow because a hostname is a tiny bit too long in this file. What? How big are your hostnames?
- shmerl 2y agoOh, the author has a cool example of a minimalistsic Wayland GUI application: https://gaultier.github.io/blog/wayland_from_scratch.html https://gaultier.github.io/blog/wayland_from_scratch.html
- sublinear 2y agoI heard some hype lately about Godot so took a look today... I'm super bummed that the wasm is 50MB minimum just to get the engine rendering a blank scene. Seems like that could be further optimized especially for simple 2D games that don't use many features. I was impressed overall though. I hadn't looked at Godot in a long time.
- kragen 2y agoalso you need https and some tweaks to your web server's cors parameters to permit wasm to multithread. godot is amazing tho
- Aeolun 2y agoIf you run on web, yes. But on desktop 50mb to get a whole game engine seems pretty awesome.
- account42 2y agoWhat is a "whole game engine"? Ideally an exported game only includes the parts that are actually used and those should be much smaller than 50 MB for a simple example or even for most games.
- manchmalscott 2y agoThe official “export templates” that you use need to be able to run any game you create with the stock engine, so they are fully featured. You have the option (and it’s recommended) to compile your own export templates, at which point you can specify which parts of the engine your specific game does and does not need (e.g. turn off the 3D, turn off the more advanced UI components, etc…)
- Aeolun 2y agoIt might be, but it’s extremely rare I see an app below 300mb these days.
- pkphilip 2y ago50MB is nothing. Consider that a "small" footprint Electron app is at least 120mb.
- mrdanielricci 2y agoGood job!! I did a 1-1 replica of the Windows 95 version of Minesweeper. You can find it at https://github.com/danielricci/minesweeper https://github.com/danielricci/minesweeper I didn’t do anything fancy in terms of reducing the size of the output file, but it was fun to try and replicate that game as best as I could.
- jamesdhutton 2y agoWould love to try it but, knowing nothing about Java, I don't know how to run it. Could you add instructions to your github page on how to run it?
- demondemidi 2y ago1 MB of assets? Huh?
- Joker_vD 2y agoYeah, the entirety of Chip's Challenge for Windows 3.1 was less than half megabyte.
- ngcc_hk 2y agoCan I say when you said “video game” am thinking arcade, dos, windows … or even mac (1984). Xwindows!!! … as someone said Sdl based … and unix curses based. It is legitimate but by 1987 …
- steve1977 2y ago"Let’s write a video game from scratch like it’s 1987" "We will implement this in the Odin programming language" checks Odin homepage... "The project started one evening in late July 2016"
- tzot 2y agoSimon Tatham's Mines Windows exe stands at ~180KiB as seen at https://www.chiark.greenend.org.uk/~sgtatham/puzzles/ https://www.chiark.greenend.org.uk/~sgtatham/puzzles/
- Isamu 2y agoHonestly at that time I remember getting fed up using a library for the graphics of a simulation I was doing over a weekend. So I just threw out the graphics library and wrote directly to the screen memory. Lots of games did that
- mproud 2y ago> I don’t exactly remember the rules though so it’s a best approximation. What?
- pjmlp 2y agoIn 1987 the game would have been written in Assembly. This is more like 1992. Michael Abrash's book was published in 1990.
- aidenn0 2y agoFun fact: the Windows 3.1 minesweeper had a cheat code! Typing: x y z z y S-Return would cause the top left pixel of the screen to change color depending on whether the cursor was over a safe square or a bomb. Since you could plant flags before the timer started, it was possible to get rather unrealistic times.
- lagniappe 2y agoThat's awesome :) I used to cheat by setting the match to a custom size board with a height of 999 and width of 999. The board would not end up quite that large, however, clicking a single tile would reveal all other tiles of interest immediately, allowing me to mark them at my leisure.
- lagniappe 2y agoI really appreciate the effort and attention to detail that went into this.
- ferrantim 2y agoDifferent topic but this article got me lost down a rabbit hole looking for something similar for the TI86. Ah, memories...
- Sohcahtoa82 2y agoMy favorite TI graphing calculator story to tell was back in Algebra II class in high school, while studying polynomial expansion, I wrote a program on my TI-85 that would not only solve them, but also showed the work, so I literally only had to copy the exact output of the program and it looked exactly like I had done it by hand. I asked the teacher if using it would be cheating, and she said "If you know the material so well that you can write a program that actually shows the work, then you're going to ace the test anyway, so go ahead and use it, just don't share it with any of your friends." The joke was on her, of course, because I didn't have any friends. :-( Later I wrote a basic ray tracer for my TI-89. I even made it do 4x anti-aliasing by rendering the scene 4 times with the camera angle slightly moved and had a program that would rapidly move between the 4 rendered pics so that pixels that were dark for only some of the pictures would appear grey because of the screen's insanely slow response time. A basic "reflective sphere over a checkered plane" in that super low TI-89 resolution still took like 90 minutes and drained half the battery.
- nsguy 2y agoI was just listening to this podcast the other day: https://99percentinvisible.org/episode/empire-of-the-sum/ https://99percentinvisible.org/episode/empire-of-the-sum/ It tells the story of how TI got into the calculator market and the domination it achieved in the US classrooms (+ other interesting tidbits).
- pests 2y agoAsianometry has a good ~2 month old video on TI that goes into it's history as a chip maker, how it got into calculators and consumer products, and where it stands today. https://youtu.be/Wu3FnasuE2s?si=cnOV7oPLc_MSYyyn https://youtu.be/Wu3FnasuE2s?si=cnOV7oPLc_MSYyyn