[HN Gopher] Let's write a video game from scratch like it's 1987
       ___________________________________________________________________
        
       Let's write a video game from scratch like it's 1987
        
       Author : LorenDB
       Score  : 112 points
       Date   : 2024-06-20 11:21 UTC (11 hours ago)
        
 (HTM) web link (gaultier.github.io)
 (TXT) w3m dump (gaultier.github.io)
        
       | ferrantim wrote:
       | Different topic but this article got me lost down a rabbit hole
       | looking for something similar for the TI86. Ah, memories...
        
         | Sohcahtoa82 wrote:
         | My 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 wrote:
           | I was just listening to this podcast the other day:
           | 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).
        
       | musha68k wrote:
       | Great "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 wrote:
         | One 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.
        
         | bsder wrote:
         | The 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?
        
       | deaddodo wrote:
       | I 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 wrote:
         | "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 wrote:
           | You'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 wrote:
             | The 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 wrote:
               | It'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 wrote:
       | That 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....
        
         | metadat wrote:
         | This 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
        
           | LorenDB wrote:
           | Look at the R_MapPlane function. Indentation in if statements
           | is non-existent.
        
             | metadat wrote:
             | What? What's a pretty severe nit pick. Especially for 30
             | year old C code.
             | 
             | They didn't have no gofmt back then. We are spoiled today
             | with the extreme consistency :) the skill of reading code
             | includes reading even when it deviates from one's own
             | preferred formatting (within reason, maliciously formatted
             | code can be challenging, to say the least).
             | 
             | I must respectfully disagree about this being an issue
             | worthy of anyone's attention, especially yours and mine.
        
           | caseyy wrote:
           | I must admit, despite programming games for a long time
           | commercially, that code is not clear to me.
           | 
           | If the code is readable to you, can you explain how
           | R_DrawPlanes draws the ceiling and the floor, step by step,
           | as a practical illustration? If it is perfectly legible to
           | you, it shouldn't take more than a minute.
           | 
           | I think just about every function I read every day is easier
           | to comprehend. And I review a lot of game engine code. I make
           | no claims I'm a fantastic programmer, of course.
        
         | LorenDB wrote:
         | Man, that could use a healthy dose of clang-format.
        
       | wslh wrote:
       | I 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.
        
       | Jare wrote:
       | I have an actual commercial game from 1987 :)
       | https://github.com/TheJare/stardust-48k
        
         | pan69 wrote:
         | Actual? Is this not reversed engineered?
        
           | MrLeap wrote:
           | I think the "actual" in this case points to "commercial
           | game".
        
             | axus wrote:
             | From 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."
        
           | Jare wrote:
           | We 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.
        
         | 0xf00ff00f wrote:
         | Wow, that's pretty cool. The game looks great!
         | 
         | Was it developed on an actual ZX Spectrum? I think I read that
         | the development environment for the Spectrum port of R-Type was
         | running on a 80286 PC, curious if this was common back in the
         | day.
        
       | Razengan wrote:
       | Even 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 wrote:
         | The complexity and creativity of early video games from the
         | 1980s and even earlier are truly impressive
        
         | Razengan wrote:
         | And 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 wrote:
         | Passion + skill > Total compensation optimization + Javascript.
        
       | spacecadet wrote:
       | I did this last year, built a zero player pixellated space
       | simulator using pygame.
        
       | jandrese wrote:
       | > 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 wrote:
         | You 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.
        
       | agumonkey wrote:
       | I'm often curious about how people organized / conceptualized
       | development in the 60s, 70s and 80s.
        
       | pan69 wrote:
       | Writing 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/
        
         | bsder wrote:
         | Erm, there was a reason why Turbo Pascal (and the other Borland
         | stuff) was such a _big deal_.
         | 
         | And that dates to 1983.
        
           | switchbak wrote:
           | TP 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 wrote:
             | Thank 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. :(
        
       | ceronman wrote:
       | > 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 wrote:
         | In 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.
        
         | Doctor_Fegg wrote:
         | Yes. 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 wrote:
       | It'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 wrote:
         | Not true. Here's how to send pixel data: https://wayland-
         | book.com/surfaces/shared-memory.html
        
       ___________________________________________________________________
       (page generated 2024-06-20 23:00 UTC)