Show HN: Quake 1 ported to the Apple Watch (github.com)
I ported Quake 1 to the Apple Watch, building on top of existing ports for iOS and Mac.
Some features: * uses Quake SW renderer + blitting to WatchKit surface (~60 fps, 640x480, larger res can run on lower framerate, tested up until 1024x768) * touch + gyro + digital crown controls * new AVFoundation audio backend (quake to Watchkit audio buffer copy logic), as Watchkit does not support CoreAudio * high pass audio filter to remove clicking on Watch speaker for some of the low frequency quake .wav samples * some smaller modifications and code updates to glue Quake 1 c code to Objective C and Watchkit
228 comments
[ 2.4 ms ] story [ 245 ms ] threadBut most importantly, ID software released the original source code for it quite early. Not that many game development companies do that. I would've loved to see more Blood ports, but I don't think the source was ever released? So I believe the existing ports were reverse engineered. Duke Nukem 3D source was only released in 2003 it looks like.
The quality of the source code of Quake 2 is quite high. Doom is.. a bit messy but OK. There are already abstractions that make porting easier. I'm guessing Quake (haven't looked at the source yet) is somewhere in between. That helps too.
Also, wasn't there an official Blood port by Nightdive Studios?
edit: just looked it out, it seems this has been address. I'm linking the videos because they're entertaining :D
vid on the original: https://www.youtube.com/watch?v=EkG29e-nE-A
and the patched version: https://www.youtube.com/watch?v=oFUPNlfWiYg
That said, it had some things Doom fans dreamt of, like an interactive level editor that was built into the game engine.
I remember playing QuakeWorld when it came out, on Linux, over a dial up modem. You had ping times of 200-300ms and it was playable. You have to remember at the time Doom and other games were LAN-only. John Carmack used to keep a .plan file with some really cool details behind Quake/QuakeWorld development. Check out Aug 02, 1996 for some detail behind the netcode[1]. You can read the future of gaming being invented right there.
[1] https://github.com/ESWAT/john-carmack-plan-archive/blob/mast...
Games prior to Quake were bound to specific O/Ss and/or hardware components.
DOOM was still bound to DOS AFAIK, so it's not portable without significant changes.
Older games are even worse - not only they were bound to DOS, but also to the display adapters of the time (CGA/EGA), which required some sort of emulation (or translation, depending on the approach) in order to be ported.
Games based on the Build engine (written by Ken Silverman), like Duke Nukem 3D and Blood are... simply written in very poor form. Carmack is a tidy programmer, Silverman isn't. Quoting Fabien Sanglard:
> Looking at the innumerable ports that spawned Doom/Quake, I was always puzzled to see so few ports of Duke Nukem 3D. The same question arose when the engine was ported to OpenGL only when Ken Silverman decided to do it himself.
The answer is in his analysis: https://fabiensanglard.net/duke3d/code_legacy.php.
DOOM was always extremely portable, the DOS and PC specific parts are well separated from the other code (DOOM was actually developed on NeXT machines, so separating the platform specific parts probably came naturally).
If you look at the ancestry of SDL2-Doom, for example, there are three ancestors:
- doomgeneric, which seems not simple (https://github.com/maximevince/fbDOOM/compare/master...ozkl:...)
- the above is based on fbDOOM, which is quite simple (https://github.com/maximevince/fbDOOM)
- the above is based on insane-adding-machines/DOOM, which is also not simple (https://github.com/id-Software/DOOM/compare/master...insane-...)
The SDL port itself (https://github.com/AlexOberhofer/sdl2-doom) is definitely not simple.
Porting something that it's not based on a multiplatform library (which is commonly SDL for old game ports) is not an easy task in general.
The SDL2 audio and video libraries are just shims against 9front drawing/audio functions, and often they just work.
Some concepts are inherent to the hardware and the O/S.
Hardware example: EGA (not the case of doom, but of other, slightly older games) uses bitplanes, it's not just an array of byes; audio cards used specific drivers.
O/S: timers may need to be emulated, as the game may not have a straightforward game loop; due to this, even exiting cleanly may not be trivial to implement.
John Carmack is awesome. However, to take the next step after Doom, he brought Michael Abrash on board.
Doom was literally developed on NeXT computers (the precursors to modern Macs, ironic considering Doom was single-handhedly responsible for turning the public perception of PCs from boring office machines to cool gaming systems):
https://en.wikipedia.org/wiki/Development_of_Doom#Programmin...
This is also from an era where there wasn't that much abstraction and "software rendering" was the norm so the implementations tended to be much more straightforward, this makes it so that worst case scenario, you just write to whatever the equivalent of a framebuffer is in the target implementation.
AFAIK, Quake was originally developed on NeXT boxes and ported to PC later. The level editor was a native app using the NeXTSTEP APIs which Apple renamed Cocoa:
https://quakewiki.org/wiki/QuakeEd
So, it's a fun kind of homecoming that it now runs on the wrist-sized NeXT box.
The original NeXT computer: 25MHz Motorola 68030 plus copro, 8MB RAM, 256MB storage, 300W power usage, $15k in 2021 dollars, weighed a lot
The Apple Watch Series 7: 1800MHz t8301 CPU (but scales up and down), 1GB RAM, 32GB storage, 50-100 mW (I think?), $399, weighs 35g or so
What a difference 33 years makes!
...not very relevant for DOOM of course, because that's just plain C for the most part, but interesting little tidbit nonetheless.
Objective-C driver kit no longer exists, its C++ replacement is on its way out, being replaced by a userspace version.
The watch uses watchOS UI KIT, is isn't either UI Kit nor Cocoa, so three generations apart from NeXTSTEP UI framework, which is anyway being replaced by SwiftUI.
watchOS uses a customized version of bitcode as deployment format, which is now being transitioned to actual native code in upcoming versions.
Related to Doom, watchOS doesn't do OpenGL, or NIB files from Project Builder.
So almost nothing like NeXTSTEP.
https://cs.gmu.edu/~sean/stuff/java-objc.html
https://en.m.wikipedia.org/wiki/Distributed_Objects_Everywhe...
There's like 10 glue functions you have to write to do things like initialize your platform, get input, begin the sound loop, call the main loop, and then something to switch buffers to the display. It takes a quite short amount of time to do. Id provides a set of null functions that you can use as a starting place and incrementally add in video support, input, sound, etc. They made it super easy to port.
I've been fiddling off and on making a tiny CM-2 computer model with all the blinking lights on the front panels. Inside it's an rpi zero 2, and I'm using some 1.5", 128x128 SPI RGB OLED displays instead of trying to make itty-bitty LED arrays. Long story short I decided I should be able to run quake and quake2 on the thing. It only took two days to put in enough code to have them running.
https://www.quakeworld.nu/wiki/Quake_Shareware_License
It's not that Apple doesn't allow anything here, they just impose their own T&C which breaches some, but not all, OSS licenses. And the workaround for the former is usually to have the contributors accept a small affidavit, which effectively puts their software in compliance with App Store.
If you copy and distribute the GPLv2 code or a work based on it in object or executable form, you have to do one of:
a) Accompany it with the complete machine-readable source code; or
b) Accompany it with a written offer valid for at least three years to give any third party a complete machine-readable copy of the source code, for a charge of no more than your cost of physically distributing the source; or
c) Accompany it with the information you received to distribute such code, but only if your distribution is noncommercial and you received it in object or executable code.
See GPLv2 section 3.
A developer uploads a copy of their app to the App Store. Apple then makes copies and distributes it when people buy it (for free or for money) on the App Store.
Since Apple is copying and distributing that GPLv2 code, Apple should have an obligation under GPLv2 section 3 to distribute the source. They would not be able to punt this obligation back on the developer via option c because their distribution is not noncommercial.
This is a crucial difference between app stores (and other digital goods stores) and stores selling physical products that contain GPL code.
Best Buy for example does not run into this problem when they sell you a TV that contains a Linux kernel because although they are in fact distributing a copy of a Linux kernel to you they did not make that copy. They received that copy from the TV manufacturer or a distributor and are just passing it along.
Copyright law in most places contains an exception, often called the "first sale doctrine", which states that once the copyright owner releases a particular copy, those who legally obtain that copy can give it away or sell it or rent it without requiring permission of the copyright owner. That covers Best Buy's case.
Unless there is some way to argue that when I but an app on the Apple App Store it is the developer who uploaded the app that is making the copy I get, I'm having trouble thinking of a way to avoid Apple having to handle GPLv2 source distribution if they let third party GPLv2 code on the store.
First party GPLv2 code would be OK, because then the developer owns the copyright and so can grant Apple the rights to distribute it in binary form without source code. (It has been a long time since I've read Apple's developer agreement, but I think it requires the developer to give Apple such rights).
Judges are allowed to argue that the "equity of the license" prevails over the text in these sorts of cases. If, say, the database lawnmower company decided to sue over App Store distribution of GPL software, the judge is allowed to say "well, the developer is already complying with the offer, they're using Apple's platform to do it, and that gives you what you wanted when you put the software under GPL, which was to have modified source code remain public".
However, you could also sidestep the whole "is a link to a Git repository 'good enough'" question by bundling a source ZIP in the app itself and letting people export it to Files or whatever. That would unambiguously satisfy GPL.
Is there any write-up on that that explains how exactly they did that?
> For example, this is what iSH uses to legally ship an entire x86 Linux userland inside of an app.
An entire userland?! AFIR it only shipped the gnu toolkit, the rest is downloaded from the repositories?
So, "Subjective reasons" such as? Example?
Here is an example of a 3D game running on the Apple Watch, that was approved by Apple, on the App Store, which looks rather "Quake like". Mindkeeper: The lurking fear (Apple Watch)[https://apps.apple.com/us/app/mindkeeper-the-lurking-fear/id...]
EDIT: To clarify 'very much an edge case', I mean, you can see how a non-technical reviewer at Apple may view iSH as a program that executes remote code. While you or I may know better, and it is unfortunate that you had to go through that process in the first instance, you can see why it happened compared to a standard todo list, or a typical web-client based app.
The specific issue is that iSH did end up getting reviewed by non-technical reviewers. We went through at least four levels of appeals, and about half a dozen interactions with people doing review. Several of these people gave the obvious impression that they understood what our app did, and might even be personal familiar with Linux/the command line. The core issue was not a technical one, but a policy one: our app does execute remote code. The reviewers read this as being "any remote code". Our (correct) interpretation was that this rule was designed to prevent remote updates by the developer. A user downloading code in our app and executing it is fully within the guidelines, which we ended up confirming with the highest levels of the review team once the app had been re-approved.
The core problem is that the actual guidelines (which includes both the written guidelines, and a bunch of "case law" that supplements it) is only really known within Apple to a handful of very senior reviewers, and getting to them is very difficult and requires an exceptional appeals process. For iSH, you can see how the written guidelines were misinterpreted by technical people; for apps like these it is very possible that they get flagged by some sort of "game includes IP that's not yours" or "app is unplayable on Apple Watch" and the person who would review this Quake game could get flagged even while complying with the guidelines.
Mindkeeper: The lurking fear (Apple Watch)[https://apps.apple.com/us/app/mindkeeper-the-lurking-fear/id...]
I said "provided it used properly licensed assets". Apple has accepted compiled open source projects before, even from people other than the authors e.g. OpenTTD[0].
>Apple may reject it just based on "not matching app guidelines".
We all know Apple might reject an app for any reason it wishes. This is a poor answer to support a claim that it wouldn't want this specific app.
>Apple banned even console emulators even tho technically there's nothing legally wrong with emulator
Emulators where you add game images yourself were always forbidden.
"2.5.2 Apps […] may not download, install, or execute code which introduces or changes features or functionality of the app"[1]
>torrent downloaders, Kodi
This is an entirely different topic than Quake.
[0] - https://apps.apple.com/us/app/openttd/id1585549844
[1] - https://developer.apple.com/app-store/review/guidelines/#sof...
In the release notes for J901 iOS I saw the following:
"it is legally impossible to release a J IDE for iOS as an open source project due to restrictions imposed on app developers by both Apple Inc and the Open Source community".
https://code.jsoftware.com/wiki/User:Ian_Clark/iOS/Review_No...
Although there was no justification for this comment, but maybe it's just true due to enforcement.
Where do you live? A smartphone is $1000 or more.
Though I agree: I can't think of someone who _needs_ a $1000 smartphone.
Once you consider inflation since '95, it's probably closer to $6k of today's USD. Of course it's still possible for someone to have that much in savings, but to be able to spend it (or justify spending) on a computer is something else entirely.
Now obviously "a hell of a lot" is a very subjective term. Where would you say it starts?
I grew up relatively poor, I've come to realize, so I'm relatively frugal by nature. In a bit of a contrast to those parents I mention, I think I'm good at assessing the value I'd get out of something. So while I'm frugal, I'm happy to spend what I think is worthwhile on something. I'm currently working on a ~$3k MBP, and it serves me tremendous value, but I think the demands of the thing would need to dramatically increase, or whatever is announced next would need to be an intense upgrade for me to consider it.
and I am somewhat close, but recently trying to fix my damn beat up gaming pc that I bought off the street has reminded me how good the MBP is, even though it's 2019 and a lower specced model. No blue screens, no driver issues, the luxury of a refined OS, and it's fast. Docker is really pushing the limits of this thing though.
That said, if there was a profoundly impactful advancement in technology that did cost $500 more, then sure I'd consider the investment, but it would be a hesitant choice.
For the difference between my current equivalent phone brand new, and anything $1000 or more, I can spread that cash modestly over some of my other gear and get pretty impressive results out of it. In this case, I happen to be spending probably $500-700 CAD this month on misc surprise things that have come up. It'll mean dramatically improving the performance of both my haggard gaming pc that I got for $10 originally, and my bike that I got for $250, and a small trip out of town.
If I wasn't doing that, I could take that cash and spend it on a flight back home, or get the flight anyway and spend the cash on renting a room somewhere for a week or two.
For the PC, going from a 5400 rpm boot drive that I harvested out of a PVR, to a modest ~500gb WD SSD cost around $60 and makes the computer wildly more functional. Likewise, the power supply literally exploded (popped with sparks and fumes) so it could be replaced with another ~$120 cad
My oculus quest 1 oled display gives no black smears and even so a little smear I can tolerate. Now what lens could I buy to make this work?
FOV reduction help nausea, but in your post you were talking about how screen door effect reducing nausea, which I can't see any evidence for.
Either way, slapping a smartwatch to your eye is a very early 2010s thing to do and will maybe give you a bit of novelty for a minute but is not something that has any real use in the current world of real HMDs.
I'm enthusiastic about something you consider "a very early 2010 thing to do" and not having any real use case in the "current world of real HMD's". Like you I live in the current world of real HMD's. My use case is enjoying playing quake on the smallest waterproof device possible. Q1 on the apple watch can be considered a novelty, yes, but I would like to take it as far as possible, because I like retro and repurposing and I like the size of the apple watch compared to a quest.
Of course, QuakeVR on Q2 exists, Apple HMD's are on the radar and I could link my android phone with a lightweight HMD and play quake that way. Why bother? Good question
Maybe I can deathmatch with an apple watch from my nokia symbian 6120.
I'm suprised you get close to 60 FPS in Software Rendering. Is there some form of hardware rendering that could be used aswell on the apple watch?
At least until the CPU starts throttling.
Are you aware of / had you considered implementing Quake's famous Reaperbot:
https://www.quakewiki.net/quakesrc/56.html
- might make for good demos, I thought?
(Some of the links are old and broken - https://www.gamers.org/pub/idgames2/quakec/bots/ works)
I don't have an Apple Watch but it would be interesting to know what happens when you fire it up on one.
Also debugging would be pain.
And most importantly, performance would be IMHO terrible.
I haven't even though about using WASM, I prefer native code as much as possible. But WASM is actually cool technology in my book :-)
1 - https://twitter.com/d0m96/status/1356670213090066432
How things have changed over 25 years or so.
https://web.archive.org/web/20011212074611/https://www.insom...
For the second point on persistence, this guy must have a lot of patience. I've struggled on this actually. If the initial push is strong enough I sit through 3-4 days but at least for me I can't seem to come back and finish it if I put it away for more than a day.
Truly impressive considering all this.
How do people do that?
When you take small consistent steps, you can go very long distances at relatively short time.
Asking seriously. Those kind of feats are amazing :)
As you take small steps, you need to start with small targets.
In my second internship, my mentor shown me a PC, and said "This is yours". Then produced a Nokia 7110 and a serial cable for said phone. He continued: "We need this phone to send SMS messages, via an application on this PC". Catch: The PC had no OS, and the software he wanted was nonexistent.
I said OK, and he asked: You know Linux, right? I truthfully said "Installed a couple of times, spent time with it." He produced a Debian 3.0 CD from a drawer, and said "Let's see whether you can install this" (Debian was hard, then).
My first target was to get Debian run on that system, then make it connect to the network.
Then, I learnt how to install and manage packages on it via "dselect".
Next, I managed to found the user manual of the phone to find out that it has a serial modem on it. I also found the AT reference guide for the phone the same day IIRC.
Next day I managed to connect it via minicom, talk with it and send a couple of SMS messages to myself.
With the knowledge I had, I found how to talk with that phone over C (Thanks Beej, and his guides). In 6th day, I was sending messages. In 8th day, the tool was a daemon waiting for messages via a specified port in a specified format.
The IT department written file watching daemons and embedded to their systems, allowing them to create many many "wire traps" inside system to detect when something went wrong. That system worked for 6 years and saved enormous effort by notifying from the right place, at the right time.
This experience allowed me to discover Debian from top to bottom. I still use Debian, still do the research same way, and move step by step, because I built the confidence over that week.
The key is proverbially "not looking down", and just "thinking the current mile", like a marathon runner. You're a web developer? I don't care. If you start from the edge of your knowledge and just walk, you can go great distances. The target is incidental here. A Quake port, an SMS daemon, something bigger/smaller... Doesn't matter.
What matters is going somewhere new, learning something you don't know. Then you can build upon this. One day, you may find yourself beyond the people who inspired you, which happened to me without noticing, but it's a story for another time.
If you want to talk on this further, you can also reach me via my webpage (see my profile), or we can continue via here.
P.S.: I still have the AT Reference Guide, both digital and in printed and bounded form. :)
The first step of displaying a test pattern, sending test bytes between devices, etc. is the biggest one, and in my case usually involves finding an open-source program that is capable of doing the thing and butchering it until it only does the thing. Every step after that is incremental, just like any other development.
You start with a "What if", and it tends to nibble at the back of your brain. Then it evolves to "Why not?"
You hack it and see the light, or more specifically you fail to find a reason for the "not" part, and you make it.
And yes, there's an immense satisfaction for doing it. Not from "look at me" angle, but from "ach, it was possible, and I made it. It turned out I was capable enough to make it work. Let me get some tea" angle.
I like feats like this. Honestly kudos to them. Both impressive and fun. Delightful, more precisely.
Along the way, I learned that when "what if?" becomes "I have to", the drive in me just dies. So I've had to learn how to stay in "what if?" mindset even when I have a deliverable I have committed to.
Sometimes, this means picking at a totally unimportant part of a project, getting it working and then—while in the same mental groove—shift to delivering the core feature.
Also, thanks for the kind words!
Some people build hot rods or fix old tractors, some people collect all 7,341 achievements in some game, some people catch up on the complete available catalog of Doctor Who, some people go out and bag peaks or train for better times on their marathon, some people grind on their karaoke performance of Tainted Love, some people devote themselves to being close with and available to their kids.
This is a beautiful project, but what makes you feel like the motivation is somehow different here than it is for those?
I once ported Quake 1 to the Rockbox operating system for MP3 players, which enabled it to run on the Apple iPod: https://www.youtube.com/watch?v=r6V-4AZ7pkA
The whole world of software ports basically boils down to "anything is possible, given enough memory, pixels, and time". The actual process of porting anything is sometimes incredibly tedious (e.g. "scour the entire source code for unaligned memory accesses, and manually rewrite all of them"), but also gives a chance to do some very clever things (like, "use the piezo speaker to beep out the address of a fault, because nothing else works on the device after a crash").
What made me do it was 1) the satisfaction I got from seeing my work produce something which, at first glance, shouldn't exist (Quake... on an MP3 player?), all while 2) learning deeply about software close to the bare metal, which is fairly hard to do early in one's career. There's of course also the factor of having lots of free time - I did my port when I was still a student with not very many responsibilities, so I could afford to spend entire evenings and weekends poring through mountains of C code. Nowadays, not so much...