More from Old Vintage Computing Research
Prior Art Department and today we'll consider a forgotten yet still extant sidebar of the early 1990s Internet. If you had Internet access at home back then, it was almost certainly dialup modem (like I did); only the filthy rich had T1 lines or ISDN. Moreover, from a user perspective, the hosts you connected to were their own universe. You got your shell account or certain interactive services over Telnet (and, for many people including yours truly, E-mail), you got your news postings from the spool either locally or NNTP, and you got your files over FTP. It may have originated elsewhere, but everything on the host you connected to was a local copy: the mail you received, the files you could access, the posts you could read. Exceptional circumstances like NFS notwithstanding, what you could see and access was local — it didn't point somewhere else. Around this time, however, was when sites started referencing other sites, much like the expulsion from Eden. In 1990 both HYTELNET and Archie appeared, which were early search engines for Telnet and FTP resources. Since they relied on accurate information about sites they didn't control, both of them had to regularly update their databases. Gopher, when it emerged in 1991, consciously tried to be a friendlier FTP by presenting files and resources hung from a hierarchy of menus, which could even point to menus on other hosts. That meant you didn't have to locally mirror a service to point people at it, but if the referenced menu was relocated or removed, the link to it was broken and the reference's one-way nature meant there was no automated way to trace back and fix it. And then there was that new World Wide Web thing introduced to the public in 1993: a powerful soup of media and hypertext with links that could point to nearly anything, but they were unidirectional as well, and the sheer number even in modest documents could quickly overwhelm users in a rapidly expanding environment. Not for nothing was the term "linkrot" first attested around 1996, as well as how disoriented a user might get following even perfectly valid links down a seemingly infinite rabbithole. "memex" idea, imagining not only literature but photographs, sketches and notes all interconnected with various "trails." The concept was exceedingly speculative and never implemented (nor was Ted Nelson's Xanadu "docuverse" in 1965) but Douglas Engelbart's oN-Line System "NLS" at the Stanford Research Institute was heavily inspired by it, leading to the development of the mouse and the 1968 Mother of All Demos. The notion wasn't new on computers, either, such as 1967's Hypertext Editing System on an IBM System/360 Model 50, and early microcomputer implementations like OWL Guide appeared in the mid-1980s on workstations and the Macintosh. Hermann Maurer, then a professor at the Graz University of Technology in Austria, had been interested in early computer-based information systems for some time, pioneering work on early graphic terminals instead of the pure text ones commonly in use. One of these was the MUPID series, a range of Z80-based systems first introduced in 1981 ostensibly for the West German videotex service Bildschirmtext but also standalone home computers in their own right. This and other work happened at what was the Institutes for Information Processing Graz, or IIG, later the Institute for Information Processing and Computer-Supported New Media (IICM). Subsequently the IIG started researching new methods of computer-aided instruction by developing an early frame-based hypermedia system called COSTOC (originally "COmputer Supported Teaching Of Computer-Science" and later "COmputer Supported Teaching? Of Course!") in 1985, which by 1989 had been commercialized, was in use at about twenty institutions on both sides of the Atlantic, and contained hundreds of one-hour lessons. COSTOC's successful growth also started to make it unwieldy, and a planned upgrade in 1989 called HyperCOSTOC proposed various extensions to improve authoring, delivery, navigation and user annotation. Meanwhile, it was only natural that Maurer's interest would shift to the growing early Internet, at that time under the U.S. National Science Foundation and by late that year numbering over 150,000 hosts. Maurer's group decided to consolidate their experiences with COSTOC and HyperCOSTOC into what they termed "the optimal large-scale hypermedia system," code-named Hyper-G (the G, natürlich, for Graz). It would be networked and searchable, preserve user orientation, and maintain correct and up-to-date linkages between the resources it managed. In January 1990, the Austrian Ministry of Science agreed to fund a prototype for which Maurer's grad student Frank Kappe formally wrote the architectural design as his PhD dissertation. Other new information technologies like Gopher and the Web were emerging at the same time, at the University of Minnesota and CERN respectively, and the Hyper-G team worked with the Gopher and W3 teams so that the Hyper-G server could also speak to those servers and clients. The prototype emerged in January 1992 as the University's new information system TUGinfo. Because Hyper-G servers could also speak Gopher and HTTP, TUGinfo was fully accessible by the clients of the day, but it could also be used with various Hyper-G line-mode clients. One of these was a bespoke tool named UniInfo which doesn't appear to have been distributed outside the University and is likely lost. The other is called the Hyper-G Terminal Viewer, or hgtv (not to be confused with the vapid cable channel), which became a standard part of the server for administration tasks. The success of TUGinfo convinced the European Space Agency to adopt Hyper-G for its Guide and Directory in the fall, after which came a beta native Windows client called Amadeus in 1993 and a beta Unix client called Harmony in 1994. Yours truly remembers accessing some of these servers through a web browser around this time, which is how this whole entry got started trying to figure out where Hyper-G ended up. a partial copy of these files, it lacks, for example, any of the executables for the Harmony client. Fortunately there were also at least two books on Hyper-G, one by Hermann Maurer himself, and a second by Wolfgang Dalitz and Gernot Heyer, two partnering researchers then at the Konrad-Zuse-Zentrum für Informationstechnik Berlin (ZIB). Happily these two books have CDs with full software kits, and the later CD from Dalitz and Heyer's book is what we'll use here. I've already uploaded its contents to the Floodgap Gopher server to serve as a supreme case of historical irony. collections. A resource must belong to at least one collection, but it may belong to multiple collections, and a collection can span more than one server. A special type of collection is the cluster, where semantically related materials are grouped together such as multiple translations, alternate document formats, or multimedia aggregates (e.g., text and various related images or video clips). We'll look at how this appears practically when we fire the system up. Any resource may link to another resource. Like HTML, these links are called anchors, but unlike HTML, anchors are bidirectional and can occur in any media type like PostScript documents, images, or even audio/video. Because they can be followed backwards, clients can walk the chains to construct a link map, like so: man page for grep(1), showing what it connects to, and what those pages connect to. Hyper-G clients could construct such maps on demand and all of the resources it shows can of course be jumped to directly. This was an obvious aid to navigation because you always could find out where you were in relation to anything else. Under the hood, anchors aren't part of the document, or even hidden within it; they're part of the metadata. Here's a real section of a serialized Hyper-G database: This textual export format (HIF, the Hyper-G Interchange Format) is how a database could be serialized and backed up or transmitted to another server, including internal resources. Everything is an object and has an ID, with resources existing at a specified path (either a global ID based on its IPv4 address or a filesystem path), and the parent indicating the name of the collection the resource belongs to. These fields are all searchable, as are text resources via full-text search, all of which is indexed immediately. You don't need to do anything to set up a site search facility — it comes built-in. Anchors are connected at either byte ranges or spatial/time coordinates within their resource. This excerpt defines three source anchors, i.e., a link that goes out to another resource. uudecodeing the text fragment and dumping it, the byte offsets in the anchor sections mean the text ranges for hg_comm.h, hg_comm.c and hg_who.c will be linked to those respective entries as destination anchors in the database. For example, here is the HIF header for hg_comm.h: These fields are indexed, so the server can walk them backwards or forwards, and the operation is very fast. The title and its contents and even its location can change; the link will always be valid as long as the object exists, and if it's later deleted, the server can automatically find and remove all anchors to it. Analogous to an HTML text fragment, destination anchors can provide a target covering a specific position and/or portion within a text resource. As the process requires creating and maintaining various unique IDs, Hyper-G clients have authoring capability as well, allowing a user to authenticate and then insert or update resources and anchors as permitted. We're going to do exactly that. Since resources don't have to be modified to create an anchor, even read-only resources such as those residing on a mounted CD-ROM could be linked and have anchors of their own. Instead of having their content embedded in the database, however, they can also appear as external entities pointed to by conventional filesystem paths. This would have been extremely useful for multimedia in particular considering the typical hard disk size of the early 1990s. Similarly, Internet resources on external servers could also be part of the collection: While resources that are not Hyper-G will break the link chain, the connection can still be expressed, and at least the object itself can be tracked by the database. The protocol could be Hyper-G, Gopher, HTTP, WAIS, Telnet or FTP. It was also possible to create SQL queries this way, which would be performed live. Later versions of the server even had a CGI-compatible scripting ability. I mentioned that the user can authenticate to the server, as well as being anonymous. When logged in, authenticated access allows not only authoring and editing but also commenting through annotations (and annotating the annotations). This feature is obviously useful for things like document review, but could also have served as a means for a blog with comments, well before the concept existed formally, or a message board or BBS. Authenticated access is also required for resources with limited permissions, or those that can only be viewed for a limited time or require payment (yes, all this was built-in). In the text file you can also see markup tags that resemble and in some cases are the same as, but in fact are not, HTML. These markup tags are part of HTF, or the Hyper-G Text Format, Hyper-G's native text document format. HTF is dynamically converted for Gopher or Web clients; there is a corresponding HTML tag for most HTF tags, eventually supporting much of HTML 3.0 except for tables and forms, and most HTML entities are the same in HTF. Anchor tags in an HTF document are handled specially: upon upload the server strips them off and turns them into database entries, which the server then maintains. In turn, anchor tags are automatically re-inserted according to their specified positions with current values when the HTF resource is fetched or translated. dbserver) that handles the database and the full-text index server (ftserver) used for document search. The document cache server (dcserver), however, has several functions: it serves and stores local documents on request, it runs CGI scripts (using the same Common Gateway Interface standard as a webserver of the era would have), and to request and cache resources from remote servers referenced on this one, indicated by the upper 32 bits of the global ID. In earlier versions of the server, clients were responsible for other protocols. A Hyper-G client, if presented with a Gopher or HTTP URL, would have to go fetch it. hgserver (no relation to Mercurial). This talks directly to other Hyper-G servers (using TCP port 418), and also directly to clients with port 418 as a control connection and a dynamically assigned port number for document transfer (not unlike FTP). Since links are bidirectional, Hyper-G servers contact other Hyper-G servers to let them know a link has been made (or, possibly, removed), and then those servers will send them updates. There are hazards with this approach. One is that it introduces an inevitable race condition between the change occurring on the upstream and any downstream(s) knowing about it, so earlier implementations would wait until all the downstream(s) acknowledged the change before actually making it effective. Unfortunately this ran into a second problem: particularly for major Hyper-G sites like IIG/IICM itself, an upstream server could end up sending thousands of update notifications after making any change at all, and some downstreams might not respond in a timely fashion for any number of reasons. Later servers use a probablistic version of the "flood" algorithm from the Harvest resource discovery system (perhaps a future Prior Art entry) where downstreams pass the update along to a smaller subset of hosts, who in turn do the same to another subset, until the message has propagated throughout the network (p-flood). Any temporary inconsistency is simply tolerated until the message makes the rounds. This process was facilitated because all downstreams knew about all other Hyper-G servers, and updates to this master list were sent in the same manner. A new server could get this list from IICM after installation to bootstrap itself, becoming part of a worldwide collection called the Hyper Root. requiring license fees for commercial use of their Gopher server implementation. Subsequent posts were made to clarify this only applied to UMN gopherd, and then only to commercial users, nor is it clear exactly how much that license fee was or whether anybody actually paid, but the damage was done and the Web — freely available from the beginning — continued unimpeded on its meteoric rise. (UMN eventually relicensed 2.3.1 under the GNU Public License in 2000.) Hyper-G's principals would have no doubt known of this precautionary tale. On the other hand, they also clearly believed that they possessed a fundamentally superior product to existing servers that people would be willing to pay good money for. Indeed, just like they did with COSTOC, the intention of spinning Hyper-G/HyperWave off as a commercial enterprise had been planned from the very beginning. Hyper-G, now renamed HyperWave, officially became a commercial product in June 1996. This shift was facilitated by the fact that no publicly available version had ever been open-source. Early server versions of Hyper-G had no limit on users, but once HyperWave was productized, its free unregistered tier imposed document restrictions and a single-digit login cap (anonymous users could of course still view HyperWave sites without logging in, but they couldn't post anything either). Non-commercial entities could apply for a free license key, something that is obviously no longer possible, but commercial use required a full paid license starting at US$3600 for a 30-user license (in 2025 dollars about $6900) or $30,000 for an unlimited one ($57,600). An early 1997 version of this commercial release appears to be what's available from the partial mirror at the Internet Archive, which comes with a license key limiting you to four users and 500 documents — that expired on July 31, 1997. This license is signed with a 128-bit checksum that might be brute-forceable on a modern machine but you get to do that yourself. Fortunately, the CD from our HyperWave book, although also published in 1996, predates the commercial shift; it is a offline and complete copy of the Hyper-G FTP server as it existed on April 13, 1996 with all the clients and server software then available. We'll start with the Hyper-G server portion, which on disc offers official builds for SunOS 4.1.3, Solaris 2.2 (SPARC only), HP-UX 9.01 (PA-RISC only), Ultrix 4.2 (MIPS DECstation "PMAX" only), IRIX 3.0 (SGI MIPS), Linux/x86 1.2, OSF/1 3.2 (on Alpha) and a beta build for IBM AIX 4.1. Apple Network Server 500 would have been perfect: it has oodles of disk space (like, whole gigabytes, man), a full 200MHz PowerPC 604e upgrade, zippy 20MB/s SCSI-2 and a luxurious 512MB of parity RAM. I'll just stop here and say that it ended in failure because both the available AIX versions on disc completely lack the Gopher and Web gateways, without which the server will fail to start. I even tried the Internet Archive pay-per-u-ser beta version and it still lacked the Gopher gateway, without which it also failed to start, and the new Web gateway in that release seemed to have glitches of its own (though the expired license key may have been a factor). Although there are ways to hack around the startup problems, doing so only made it into a pure Hyper-G system with no other protocols which doesn't make a very good demo for our purposes, and I ended up spending the rest of the afternoon manually uninstalling it. In fairness it doesn't appear AIX was ever officially supported. Otherwise, I don't have a PA-RISC HP-UX server up and running right now (just a 68K one running HP-UX 8.0), and while the SunOS 4 version should be binary compatible with my Solbourne S3000 running OS/MP 4.1C, I wasn't sure if the 56MB of RAM it has was enough if I really wanted to stress-test it. and it has 256MB of RAM. It runs IRIX 6.5.22 but that should still start these binaries. That settled the server part. For the client hardware, however, I wanted something particularly special. My original Power Macintosh 7300 (now with a G4/800) sitting on top will play a supporting role running Windows 98 in emulation for Amadeus, and also testing our Hyper-G's Gopher gateway with UMN TurboGopher, which is appropriate because when it ran NetBSD it was gopher.floodgap.com. Today, though, it runs Mac OS 9.1, and the planned native Mac OS client for Hyper-G was never finished nor released. Our other choices for Harmony are the same as for the server, sans AIX 4.1, which doesn't seem to have been supported as a client at all. Unfortunately the S3000 is only 36MHz, so it wouldn't be particularly fast at the hypermedia features, and I was concerned about the Indy running as client and server at the same time. But while we don't have any PA-RISC servers running, we do have a couple choices in PA-RISC workstations, and one of them is a especially rare bird. Let's meet ... ruby, named for HP chief architect Ruby B. Lee, who was a key designer of the PA-RISC architecture and its first single-chip implementation. This is an RDI PrecisionBook 160 laptop with a 160MHz PA-7300LC CPU, one of the relatively few PA-RISC chips with support for a categorical L2 cache (1MB, in this case), and the last and most powerful family of 32-bit PA-RISC 1.1 chips. Visualize B160L, even appearing as the same exact model number to HP-UX, it came in the same case as its better-known SPARC UltraBook siblings (I have an UltraBook IIi here as well) and was released in 1998, just prior to RDI's buyout by Tadpole. This unit has plenty of free disk space, 512MB of RAM and runs HP-UX 11.00, all of which should run Harmony splendidly, and its battery incredibly still holds some charge. Although the on-board HP Visualize-EG graphics don't have 3D acceleration, neither does the XL24 in our Indy, and its PA-7300LC will be better at software rendering than the Indy's R4400. Fortunately, the Visualize-EG has very good 2D performance for the time. With our hardware selected, it's time to set up the server side. We'll do this by the literal book, and the book in this case recommends creating a regular user hgsystem belonging to a new group hyperg under which the server processes should run. IRIX makes this very easy. hyperg as the user's sole group membership, ... tcsh, which is fine by me because other shells are for people who don't know any better. Logging in and checking our prerequisites: This is the Perl that came with 6.5.22. Hyper-G uses Perl scripts for installation, but they will work under 4.036 and later (Perl 5 isn't required), and pre-built Perl distributions are also included on the CD. Ordinarily, and this is heavily encouraged in the book and existing documentation, you would run one of these scripts to download, unpack and install the server. At the time you had to first manually request permission from an E-mail address at IICM to download it, including the IPv4 address you were going to connect from, the operating system and of course the local contact. Fortunately some forethought was applied and an alternative offline method was also made available if you already had the tarchive in your possession, or else this entire article might not have been possible. Since the CD is a precise copy of the FTP site, even including the READMEs, we'll just pretend to be the FTP site for dramatic purposes. The description files you see here are exactly what you would have seen accessing TU Graz's FTP site in 1996. quote PASV 227 Entering Passive Mode (XXX). ftp> cd /run/media/spectre/Hyper-G/unix/Hyper-G 250-You have entered the Hyper-G archive (ftp://ftp.iicm.tu-graz.ac.at/pub/Hyper-G). 250-================================================================================ 250- 250-What's where: 250- 250- Server Hyper-G Server Installation Script 250- UnixClient the vt100 client for UNIX - Installation Script 250- Harmony Harmony (the UNIX/X11 client) 250- Amadeus Amadeus (the PC/Windows client) 250- VRweb VRweb (free VRML browser for Hyper-G, Mosaic & Gopher) 250- papers documentation on Hyper-G (mainly PostScript) 250- talk slides & illustrations we use for Hyper-G talks 250- 250-Note: this directory is mirrored daily (nightly) to: 250- 250- Australia ftp://ftp.cinemedia.com.au/pub/Hyper-G 250- ftp://gatekeeper.digital.com.au/pub/Hyper-G 250- Austria ftp://ftp.tu-graz.ac.at/pub/Hyper-G 250- Czech Rep. ftp://sunsite.mff.cuni.cz/Net/Infosystems/Hyper-G 250- Germany ftp://elib.zib-berlin.de/pub/InfoSystems/Hyper-G 250- ftp://ftp.ask.uni-karlsruhe.de/pub/infosystems/Hyper-G 250- Italy ftp://ftp.esrin.esa.it/pub/Hyper-G 250- Poland ftp://sunsite.icm.edu.pl/pub/Hyper-G 250- Portugal ftp://ftp.ua.pt/pub/infosystems/www/Hyper-G 250- Spain ftp://ftp.etsimo.uniovi.es/pub/Hyper-G 250- Sweden ftp://ftp.sunet.se/pub/Networked.Information.Retrieval/Hyper-G 250- UK ftp://unix.hensa.ac.uk/mirrors/Hyper-G 250- USA ftp://ftp.ncsa.uiuc.edu/Hyper-G 250- ftp://mirror1.utdallas.edu/pub/Hyper-G 250 Directory successfully changed. ftp> cd Server 250 Directory successfully changed. ftp> get Hyper-G_Server_21.03.96.SGI.tar.gz local: Hyper-G_Server_21.03.96.SGI.tar.gz remote: Hyper-G_Server_21.03.96.SGI.tar.gz 200 PORT command successful. Consider using PASV. 150 Opening BINARY mode data connection for Hyper-G_Server_21.03.96.SGI.tar.gz (2582212 bytes). 226 Transfer complete. 2582212 bytes received in 3.12 seconds (808.12 Kbytes/s) ftp> get Hyper-G_Tools_21.03.96.SGI.tar.gz local: Hyper-G_Tools_21.03.96.SGI.tar.gz remote: Hyper-G_Tools_21.03.96.SGI.tar.gz 200 PORT command successful. Consider using PASV. 150 Opening BINARY mode data connection for Hyper-G_Tools_21.03.96.SGI.tar.gz (3337367 bytes). 226 Transfer complete. 3337367 bytes received in 3.95 seconds (825.82 Kbytes/s) ftp> ^D221 Goodbye. ~hgsystem, a central directory (by default /usr/local/Hyper-G) holds links to it as a repository. We'll create that and sign it over to hgsystem as well. Next, we unpack the server (first) package and start the offline installation script. This package includes the server binaries, server documentation and HTML templates. Text in italics was my response to prompts, which the script stores in configuration files and also in your environment variables, and patches the startup scripts for hgsystem to instantiate them on login. Floodgap Hyper-G Full internet host name of this machine:indy.floodgap.com installed bin/scripts/hginstserver installed bin/SGI/dbcontrol [...] installed HTML/ge/options.html installed HTML/ge/result_head.html installed HTML/ge/search.html installed HTML/ge/search_simple.html installed HTML/ge/status.html did make this piece open-source so a paranoid sysadmin could see what they were running as root (in this case setuid). Now for the tools. This includes adminstration utilities but also the hgtv client and additional documentation. The install script is basically the same for the tools as for the server. Last but not least, we will log out and log back in to ensure that our environment is properly setup, and then set the password on the internal hgsystem user (which is not the same as hgsystem, the Unix login). This account is setup by default in the database and to modify it we'll use the hgadmin tool. This tool is always accessible from the hgsystem login in case the database gets horribly munged. That should be all that was necessary (NARRATOR: It wasn't.), but starting up the server still failed. It's possible the tar offline install utility wasn't updated as often as the usual one. Nevertheless, it seemed out-of-sync with what the startup script was actually looking for. Riffling the Perl and shell-script code to figure out the missing piece, it turns out I had to manually create ~hgsystem/HTF and ~hgsystem/server, then add two more environment variables to ~hgsystem/.hgrc (nothing to do with Mercurial): Logging out and logging back in to refresh the environment, ... we're up! Immediately I decided to see if the webserver would answer. It did, buuuuut ... uname identifies this PrecisionBook 160 as a 9000/778, which is the same model number as the Visualize B160L workstation.) Netscape Navigator Gold 3.01 is installed on this machine, and we're going to use it later, but I figured you'd enjoy a crazier choice. Yes, you read that right ... on those platforms as well as Tru64, but no version for them ever emerged. After releasing 5.0 SP1 in 2001, Microsoft cited low uptake of the browser and ended all support for IE Unix the following year. As for Mainsoft, they became notorious for the 2004 Microsoft source code leak when a Linux core in the file dump fingered them as the source; Microsoft withdrew WISE completely, eliminating MainWin's viability as a commercial product, though Mainsoft remains in business today as Harmon.ie since 2010. IE Unix was a completely different codebase from what became Internet Explorer 5 on Mac OS X (and a completely different layout engine, Tasman) and of course is not at all related to modern Microsoft Edge either. because there are Y2K issues, the server fails to calculate its own uptime, but everything else basically works. ruby:/pro/harmony/% uname -a HP-UX ruby B.11.00 A 9000/778 2000295180 two-user license ruby:/pro/harmony/% model 9000/778/B160L ruby:/pro/harmony/% grep -i b160l /usr/sam/lib/mo/sched.models B160L 1.1e PA7300 ruby:/pro/harmony/% su Password: # echo itick_per_usec/D | adb -k /stand/vmunix /dev/mem itick_per_usec: itick_per_usec: 160 # ^D ruby:/pro/harmony/% cat /var/opt/ignite/local/hw.info disk: 8/16/5.0.0 0 sdisk 188 31 0 ADTX_AXSITS2532R_014C 4003776 /dev/rdsk/c0t0d0 /dev/dsk/c0t0d0 -1 -1 5 1 9 disk: 8/16/5.1.0 1 sdisk 188 31 1000 ADTX_AXSITS2532R_014C 6342840 /dev/rdsk/c0t1d0 /dev/dsk/c0t1d0 -1 -1 4 1 9 cdrom: 8/16/5.4.0 2 sdisk 188 31 4000 TOSHIBA_CD-ROM_XM-5701TA 0 /dev/rdsk/c0t4d0 /dev/dsk/c0t4d0 -1 -1 0 1 0 lan: 8/16/6 0 lan0 lan2 0060B0C00809 Built-in_LAN 0 graphics: 8/24 0 graph3 /dev/crt0 INTERNAL_EG_DX1024 1024 768 16 755548327 ext_bus: 8/16/0 1 CentIf n/a Built-in_Parallel_Interface ext_bus: 8/16/5 0 c720 n/a Built-in_SCSI ps2: 8/16/7 0 ps2 /dev/ps2_0 Built-in_Keyboard/Mouse processor: 62 0 processor n/a Processor an old version ready to run. Otherwise images and most other media types are handled by Harmony itself, so let's grab and setup the client now. We'll want both Harmony proper and, later when we play a bit with the VRML tools, VRweb. Notionally these both come in Mesa and IRIX GL or OpenGL versions, but this laptop has no 3D acceleration, so we'll use the Mesa builds which are software-rendered and require no additional 3D support. cd /run/media/spectre/Hyper-G/unix/Hyper-G/Harmony 250- 250-You have entered the Harmony archive. 250- 250-The current version is Release 1.1 250-and there are a few patched binaries in the 250-patched-bins directory. 250- 250-Please read INSTALLATION for full installation instructions. 250- 250-Mirrors can be found at: 250- 250- Australia ftp://ftp.cinemedia.com.au/pub/Hyper-G 250- Austria ftp://ftp.tu-graz.ac.at/pub/Hyper-G/ 250- Germany ftp://elib.zib-berlin.de/pub/InfoSystems/Hyper-G/ 250- ftp://ftp.ask.uni-karlsruhe.de/pub/infosystems/Hyper-G 250- Italy ftp://ftp.esrin.esa.it/pub/Hyper-G 250- Spain ftp://ftp.etsimo.uniovi.es/pub/Hyper-G 250- Sweden ftp://ftp.sunet.se/pub/Networked.Information.Retrieval/Hyper-G 250- New Zealand ftp://ftp.cs.auckland.ac.nz/pub/HMU/Hyper-G 250- UK ftp://unix.hensa.ac.uk/mirrors/Hyper-G 250- USA ftp://ftp.utdallas.edu/pub/Hyper-G 250- ftp://ftp.ncsa.uiuc.edu/Hyper-G 250- ftp://ftp.ua.pt/pub/infosystems/www/Hyper-G 250- 250-and a distributing WWW server: 250- 250- http://ftp.ua.pt/infosystems/www/Hyper-G 250- 250 Directory successfully changed. ftp> get harmony-1.1-HP-UX-A.09.01-mesa.tar.gz get harmony-1.1-HP-UX-A.09.01-mesa.tar.gz 200 PORT command successful. Consider using PASV. 150 Opening BINARY mode data connection for harmony-1.1-HP-UX-A.09.01-mesa.tar.gz (11700275 bytes). 226 Transfer complete. 11700275 bytes received in 11.95 seconds (956.02 Kbytes/s) ftp> cd ../VRweb 250- 250-ftp://ftp.iicm.tu-graz.ac.at/pub/Hyper-G/VRweb/ 250-... here you find the VRweb (VRML 3D Viewer) distribution. 250- 250-The current release is 1.1.2 of Mar 13 1996. 250- 250-Note: this directory is mirrored daily (nightly) to: 250- 250- Australia ftp://ftp.cinemedia.com.au/pub/Hyper-G/VRweb 250- ftp://gatekeeper.digital.com.au/pub/Hyper-G/VRweb 250- Austria ftp://ftp.tu-graz.ac.at/pub/Hyper-G/VRweb 250- Czech Rep. ftp://sunsite.mff.cuni.cz/Net/Infosystems/Hyper-G/VRweb 250- Germany ftp://elib.zib-berlin.de/pub/InfoSystems/Hyper-G/VRweb 250- ftp://ftp.ask.uni-karlsruhe.de/pub/infosystems/Hyper-G/VRweb 250- Italy ftp://ftp.esrin.esa.it/pub/Hyper-G/VRweb 250- Poland ftp://sunsite.icm.edu.pl/pub/Hyper-G/VRweb 250- Portugal ftp://ftp.ua.pt/pub/infosystems/www/Hyper-G/VRweb 250- Spain ftp://ftp.etsimo.uniovi.es/pub/Hyper-G/VRweb 250- Sweden ftp://ftp.sunet.se/pub/Networked.Information.Retrieval/Hyper-G/VRweb 250- UK ftp://unix.hensa.ac.uk/mirrors/Hyper-G/VRweb 250- USA ftp://ftp.ncsa.uiuc.edu/Hyper-G/VRweb 250- ftp://mirror1.utdallas.edu/pub/Hyper-G/VRweb 250 Directory successfully changed. ftp> cd UNIX 250-This directory contains the VRweb 1.1.2e distribution for UNIX/X11 250- 250- 250-vrweb-1.1.2e-[GraphicLibrary]-[Architecture]: 250- VRweb scene viewer for viewing VRML files 250- as external viewer for your WWW client. 250- 250-harscened-[GraphicLibrary]-[Architecture]: 250- VRweb for Harmony. Only usable with Harmony, the Hyper-G 250- client for UNIX/X11. 250- 250-[GraphicLibry]: ogl ... OpenGL (available for SGI, DEC Alpha) 250- mesa ... Mesa (via X protocol; for all platforms) 250- 250-help.tar.gz 250- on-line Help, includes installation guide 250- 250-vrweb.src-1.1.2e.tar.gz 250- VRweb source code 250- 250 Directory successfully changed. ftp> get vrweb-1.1.2e-mesa-HPUX9.05.gz 200 PORT command successful. Consider using PASV. 150 Opening BINARY mode data connection for vrweb-1.1.2e-mesa-HPUX9.05.gz (1000818 bytes). 226 Transfer complete. 1000818 bytes received in 1.23 seconds (794.05 Kbytes/s) ftp> ^D221 Goodbye. /pro logical volume which has ample space. Because this is for an earlier version of HP-UX, although it should run, we'd want to make sure it wasn't using outdated libraries or paths. Unfortunately, checking for this in advance is made difficult by the fact that ldd in HP-UX 11.00 will only show dependencies for 64-bit binaries and this is a 32-bit binary on a 32-bit CPU: So we have to do it the hard way. For some reason symlinks for the shared libraries below didn't exist on this machine, though I had to discover that one by one. /usr/lib/X11R5/libX11.1 lrwxr-xr-x 1 root sys 23 Jan 17 2001 /usr/lib/libX11.2 -> /usr/lib/X11R6/libX11.2 lrwxr-xr-x 1 root sys 23 Jan 17 2001 /usr/lib/libX11.3 -> /usr/lib/X11R6/libX11.3 ruby:/pro/% su Password: # cd /usr/lib # ln -s libX11.1 libX11.sl # ^D ruby:/pro/% harmony/bin/harmony /usr/lib/dld.sl: Can't open shared library: /usr/lib/libXext.sl /usr/lib/dld.sl: No such file or directory Abort ruby:/pro/% ls -l /usr/lib/libXext* lrwxr-xr-x 1 root sys 24 Jan 17 2001 /usr/lib/libXext.1 -> /usr/lib/X11R5/libXext.1 lrwxr-xr-x 1 root sys 24 Jan 17 2001 /usr/lib/libXext.2 -> /usr/lib/X11R6/libXext.2 lrwxr-xr-x 1 root sys 24 Jan 17 2001 /usr/lib/libXext.3 -> /usr/lib/X11R6/libXext.3 ruby:/pro/% su Password: # cd /usr/lib # ln -s libXext.1 libXext.sl # ^D ruby:/pro/% harmony/bin/harmony --- Harmony Version 1.1 (MESA) of Fri 15 Dec 1995 --- Enviroment variable HARMONY_HOME not set ruby:/pro/harmony/% gunzip vrweb-1.1.2e-mesa-HPUX9.05.gz ruby:/pro/harmony/% file vrweb-1.1.2e-mesa-HPUX9.05 vrweb-1.1.2e-mesa-HPUX9.05: PA-RISC1.1 shared executable dynamically linked ruby:/pro/harmony/% chmod +x vrweb-1.1.2e-mesa-HPUX9.05 ruby:/pro/harmony/% ./vrweb-1.1.2e-mesa-HPUX9.05 can't open DISPLAY ruby:/pro/harmony/% mv vrweb-1.1.2e-mesa-HPUX9.05 bin/vrweb -hghost option passed to Harmony or it will connect to the IICM by default. starmony #!/bin/csh setenv HARMONY_HOME /pro/harmony set path=($HARMONY_HOME/bin $path) setenv XAPPLRESDIR $HARMONY_HOME/misc/ $HARMONY_HOME/bin/harmony -hghost indy & ^D ruby:/pro/harmony/% ps -fu spectre UID PID PPID C STIME TTY TIME COMMAND spectre 2172 2170 0 14:55:25 pts/0 0:00 /usr/bin/tcsh spectre 1514 1 0 12:34:19 ? 0:00 /usr/dt/bin/ttsession -s spectre 1535 1534 0 13:18:41 pts/ta 0:01 -tcsh spectre 1523 1515 0 12:34:20 ? 0:04 dtwm spectre 1515 1510 0 12:34:19 ? 0:00 /usr/dt/bin/dtsession spectre 2210 1535 3 15:28:44 pts/ta 0:00 ps -fu spectre spectre 1483 1459 0 12:34:13 ? 0:00 /usr/dt/bin/Xsession /usr/dt/bin/Xsession spectre 1510 1483 0 12:34:15 ? 0:00 /usr/bin/tcsh -c unsetenv _ PWD; spectre 2169 1523 0 14:55:24 ? 0:00 /usr/dt/bin/dtexec -open 0 -ttprocid 1.1eAEIw 01 1514 134217 spectre 2170 2169 0 14:55:24 ? 0:00 /usr/dt/bin/dtterm spectre 2194 2193 0 15:01:47 pts/0 0:01 hartextd -c 49285 spectre 2193 1 0 15:01:42 pts/0 0:06 /pro/harmony/bin/harmony -hghost indy hgsystem anyway, but in a larger deployment you'd of course have multiple users with appropriate permissions. Hyper-G users are specific to the server; they do not have a Unix uid. Users may be in groups and may have multiple simultaneously valid passwords (this is to facilitate automatic login from known hosts, where the password can be unique to each host). Each user gets their own "home collection" that they may maintain, like a home directory. Each user also has a credit account which is automatically billed when pay resources are accessed, though the Hyper-G server is agnostic about how account value is added. We can certainly whip out hgadmin again and do it from the command line, but we can also create users from a graphical administration tool that comes as part of Harmony. This tool is haradmin, or the Harmony Administrator. DocumentType is what we'd consider the "actual" object type. By default, all users, including anonymous ones, can view objects, but cannot write or delete ("unlink") anything; only the owner of the object and the system administrators can do those. In practical terms this unprivileged user with no group memberships we created has the same permissions as an anonymous drive-by right now. However, becase this user is authenticated, we can add permissions to it later. I've censored the most significant word in this and other screenshots with global IDs for this machine because it contains the Indy's IPv4 address and you naughty little people out there don't need to know the details of my test network. % hifimport rootcollection cleaned-tech.hif Username:hgsystem Password: hifimport: HIF 1.0 hifimport: # hifimport: # hifimport: Collection en:Technical Documentation on Hyper-G hifimport: Text en:Hyper-G Anchor Specification Version 1.0 [...] hifimport: # END COLLECTION obj.rights hifimport: # END COLLECTION hg_server hifimport: Collection en:Software User Manuals (man-pages) hifimport: Text en:dbserver.control (1) hifimport: # already visited: 0x000003b7 (en:dcserver (1)) hifimport: # already visited: 0x000003bf (en:ftmkmirror (1)) hifimport: # already visited: 0x000003c2 (en:ftquery (1)) hifimport: # already visited: 0x000003c1 (en:ftserver (1)) hifimport: # already visited: 0x000003be (en:ftunzipmirror (1)) hifimport: # already visited: 0x000003bd (en:ftzipmirror (1)) hifimport: Text en:gophgate (1) hifimport: Text en:hgadmin (1) [...] hifimport: Text en:Clark J.: SGMLS hifimport: * Object already exists. Not replaced. hifimport: Text en:Goldfarb C. F.: The SGML Handbook hifimport: Text en:ISO: Information Processing - 8-bit single-byte coded graphic character sets - Part 1: Latin alphabet No. 1, ISO IS 8859-1 [...] hifimport: # END COLLECTION HTFdoc hifimport: Text en:Hyper-G Interchange Format (HIF) hifimport: # END COLLECTION hyperg/tech PASS 2: Additional Collection Memberships C 0x00000005 hyperglinks(0xa1403d02) hifimport. Error: No Collection hyperglinks(0xa1403d02) C 0x00000005 technik-speziell(0x83f65901) hifimport. Error: No Collection technik-speziell(0x83f65901) C 0x0000015c ~bolle(0x83ea6001) hifimport. Error: No Collection ~bolle(0x83ea6001) C 0x00000193 ~smitter hifimport. Error: No Collection ~smitter [...] PASS 3: Source Anchors SRC Doc=0x00000007 GDest=0x811b9908 0x00187b01 SRC Doc=0x00000008 GDest=0x811b9908 0x00064f74 [...] hifimport: Warning: Link Destination outside HIF file: 0x00000323 hifimport: ... linking to remote object. hifimport. Error: Could not make src anchor: remote server not responding [...] SRC Doc=0x000002e1 GDest=0x811b9908 0x000b5c5b SRC Doc=0x000002e1 GDest=0x811b9908 0x000b5c5a hifimport: Inserted 75 collections. hifimport: Inserted 528 documents. hifimport: Inserted 596 anchors. rootcollection). The import then proceeds in three passes. The first part just loads the objects and the second one sets up additional collections. This dump included everything, including user collections that did not exist, so those additional collections were (in this case desirably) not created. For the final third pass, all new anchors added to the database are processed for validity. Notice that one of them referred to an outside Hyper-G server that the import process duly attempted to contact, as it was intended to. In the end, the import process successfully added 75 new collections and 528 documents with 596 anchors. Instant content! hgtv, the line-mode Hyper-G client, on the Indy. This client, or at least this version of the client, does not start at the Hyper Root and we are immediately within our own root collection. The number is the total number of documents and subdocuments within it. hgtv understands HTF, so we can view the documents directly. Looks like it all worked. Let's jump back into Harmony and see how it looks there too. hgsystem. emacs, but this house is Team vi, and we will brook no deviations. For CDE, though, dtpad would be better. You can change the X resource for Harmony.Text.editcommand accordingly. Here I've written a very basic HTF file that will suffice for the purpose. the Floodgap machine room page (which hasn't been updated since 2019, but I'll get around to it soon enough). As a point of contrast I've elected to do this as a cluster rather than a collection so that you can see the difference. Recall from the introduction that a cluster is a special kind of collection intended for use where the contents are semantically equivalent or related, like alternative translations of text or alternative formats of an image. This is a rather specific case so for most instances, admittedly including this one, you'd want a collection. In practice, however, Hyper-G doesn't really impose this distinction rigidly and as you're about to see, a cluster mostly acts like a collection by a different term — except where it doesn't. <map> for imagemaps. alex, our beige-box Am5x86 DOS games machine, as the destination. can be open at the same time — I guess for people who might do text descriptions for the visually impaired, or something. Clusters appear differently in two other respects we'll get to a little later on. Markup Language), was nearly a first-class citizen. Most modern browsers don't support VRML and its technological niche is now mostly occupied by X3D, which is largely backwards-compatible with it. Like older browsers, Hyper-G needs an external viewer (in this case VRweb, which we loaded onto the system as part of the Harmony client install), but once installed VRML becomes just as smoothly integrated into the client as PostScript documents. Let's create a new collection with the sample VRML documents that came with VRweb. fsn), as most famously seen in 1993's Jurassic Park. Jurassic Park is a candy store for vintage technology sightings, notably the SGI Crimson, Macintosh Quadra 700 and what is likely an early version of the Motorola Envoy, all probably due to Michael Crichton's influence. online resources, made possible by the fact that edges could be walked in both directions and retrieved rapidly from the database. GopherVR, which came out in 1995 and post-dates both FSN and earlier versions of Harmony, but it now renders a lot better with some content. (I do need to get around to updating GopherVR for 64-bit.) hgtv did. This problem likely never got fixed because the beta versions on the Internet Archive unfortunately appear to have removed Gopher support entirely. Rodney Anonymous. C:\ ... \Program Files as \PROGRA~1. This version of Amadeus is distributed in multiple floppy-sized archives. That was a nice thing at the time but today it's also really obnoxious. Here are all the points at which you'll need to "switch disks" (e.g., by unzipping them to the installation folder): Simpsons music). hgtv than it does to Harmony, which to be sure was getting the majority of development resources. In particular, there isn't a tree view, just going from collection to collection like individual menus. blofeld and spectre) into the lusers group. W:g lusers which keeps the default read and unlink permissions, but specifically allows users in group lusers to create and modify documents here. blofeld, because you can never say never again, I will now annotate that "thread." (Oddly, this version of Harmony appears to lack an option to directly annotate from the text view. I suspect this oversight was corrected later.) spectre can post too. blofeld and spectre have the same permissions and the default is to allow anyone in the group to write, without taking some explicit steps they can then edit each other's posts with impunity. To wit, we'll deface blofeld's comment. now? That concludes our demonstration, so on the Indy we'll type dbstop to bring down the database and finish our story. offices in Germany and Austria, later expanding to the US and UK. Gopher no longer had any large-scale relevance and the Web had clearly become dominant, causing Hyperwave to also gradually de-emphasize its own native client in lieu of uploading and managing content with more typical tools like WebDAV, Windows Explorer and Microsoft Word, and administering and accessing it with a regular web browser (offline operation was still supported), as depicted in this screenshot from the same year. Along the way the capital W got dropped, becoming merely Hyperwave. In all of these later incarnations, however, the bidirectional linkages and strict hierarchy remained intact as foundational features in some form, even though the massive Hyper Root concept contemplated by earlier versions ultimately fell by the wayside. Hyperwave continues to be sold as a commercial product today, with the company revived after a 2005 reorganization, and the underlying technology of Hyper-G still seems to be a part of the most current release. As proof, at the IICM — now after several name changes called Institute of Human-Centred Computing, with professor Frank Kappe its first deputy — there's still a HyperWave [sic] IS/7 server. It has a home collection just like ours with exactly one item, Herman Maurer's home page, who as of this writing still remains on Hyperwave's advisory board. Although later products have attempted to do similar sorts of large-scale document and resource management, Hyper-G pioneered the field by years, and even smaller such tools owe it a debt either directly or by independent convergent evolution. That makes it more than appropriate to appear in the Prior Art Department, especially since some of its more innovative solutions to hypermedia's intrinsic navigational issues have largely been forgotten — or badly reinvented. That said, unlike many such examples of prior art, it has managed to quietly evolve and survive to the present, even if by doing so it lost much of its unique nature and some of its wildest ideas. Of course, without those wild ideas, this article would have been a great deal less interesting. You can access the partial mirror on the Internet Archive, or our copy of the CD with everything I've demonstrated here and more on the Floodgap gopher server.
(Hat tip to the late Bill Strauss and The Capitol Steps' Lirty Dies.) take my Palm OS Fossil Wrist PDA smartwatch mobile. It has no on-board networking libraries but can be coerced into doing PPP over its serial port (via USB) by using the libraries from my Palm m505. Of course, that then requires it be constantly connected to a USB port, which is rather inconvenient for a wristwatch. But what if the USB connection could be made wirelessly? For a few years, real honest-to-goodness wireless USB devices were actually a thing. Competing standards led to market fracture and the technologies fizzled out relatively quickly in the marketplace, but like the parallel universe of FireWire hubs there was another parallel world of wireless USB devices, at least for a few years. As it happens, we now have a couple of them here, so it's worth exploring what wireless USB was and what happened to it, how the competing standards worked (and how well), and if it would have helped. for the iBook G3 in 1999 people really started to believe a completely wireless future was possible — for any device. This was nevertheless another type of network, just one involving only one computer and one user over a short range, which was grandiosely dubbed the "personal area network," or PAN, or WPAN, depending on executive and blood alcohol level. Although initial forms of Bluetooth were the first to arrive in this space, Bluetooth was never intended to handle the very high data rates that some wireless peripherals might require, and even modern high-speed Bluetooth isn't specced beyond 50 megabits/sec (though hold that thought for a later digression). The key basis technology instead was the concept of ultra wide-band, or UWB, which in modern parlance collectively refers to technologies allowing very weak, very wide-spectrum (in excess of 500MHz) signals to become a short range yet high bandwidth communications channel. Wideband, in this case, is contrasted against the more typical narrowband. In general radio transmission works by modulating a carrier wave of a specified frequency, changing its amplitude (AM), phase, and/or the frequency itself (FM), to encode a signal to be communicated. For terrestrial analogue broadcasting, a good example of narrowband radio, this might be an audio signal carrying some specified frequency range; for FM radio in the United States this audio signal ranges from 30Hz to 15kHz, enough to capture much of the human-audible range, plus various higher frequencies not intended for listening. This collective signal effectively becomes encoded into sidebands on one or both sides of the carrier frequency (even with AM), and per Carson's rule the higher the maximum modulated frequency of the encoded signal then the larger the sidebands (ergo, its bandwidth) must be. As a result, commercial radio stations in particular are often heavily filtered for coexistence to allow many stations to share the band: in the United States, within ITU Region 2, the Federal Communications Commission (FCC) divides the FM band from 88.0MHz to 108.0MHz into 100 "channels" of 200kHz each, putting the nominal carrier frequency in the middle of the channel to provide sufficient sideband width for modulation, and strictly regulates any spillover outside those channel boundaries. In practice, most adjacent U.S. FM stations are no closer than 400kHz, a balance between spectrum capacity and signal strength. This typically permits a maximum FM stereo modulated frequency of about 53kHz; frequencies in the aggregate range being transmitted that are unused or unnecessary can be repurposed as subcarriers to emit additional information, such as FM stereo's 19kHz pilot tone subcarrier used to signal receivers, or Microsoft's brief flirtation with one-way transmissions to SPOT smartwatches. Doing so is "free" because the subcarrier frequency is already part of the frequency range. By contrast, signals like 802.11 Wi-Fi are wideband radio, or at least comparatively wid-er band, because they pass much higher bandwidths. Although 802.11 frequencies (except for the very highest 45/60GHz band) are generally divided into 5MHz channels, people typically only use channels 1, 6 and 11 with 2.4GHz Wi-Fi, for example (or, in later standards, 1, 5, 9 and maybe 13), which spaces them by 20MHz or more. Compare this with medium-wave AM radio, where channel spacing in the United States is just 10kHz and even 9kHz in some countries like Australia, or shortwave radio with only 5kHz spacing. impulse radar, which is a form of the more familiar pulsed radar (such as the traffic cop at the corner) using much briefer radio pulses. Radar also works on a carrier wave model, but instead of FM or AM, the radar carrier wave is merely pulsed on and off. This is necessary so that the detector during the "off" phase can pick up echoes of the radio pulse transmitted during the "on" phase, and for most applications of radar, the pulse-repetition frequency (PRF) is much less than the frequency of the carrier wave being pulsed. Shorter, more frequent pulses would have theoretically yielded greater precision at close range, but such capability was beyond the electronics available to early radar researchers who were more concerned with long-range detection anyway, where the off phase had to be of sufficient length to detect a distant reflection. By the 1970s, however, the technology had sufficiently advanced that the radar's PRF could approach its carrier frequency, making things like ground-penetrating radar possible. While higher frequencies couldn't travel through ground for great distances, they did yield much better resolution and therefore meaningful data. To a basic approximation UWB uses the same principle as impulse radar: a series of pulses, potentially as short as picoseconds long, of a particular carrier wave. As the carrier wave itself isn't changing, all of the information is necessarily being encoded in the pulses' timing. Being discontinuous waves, Carson's rule doesn't directly apply to most forms of UWB, but the analogous Shannon capacity limit indicates that rapid modulation from a high PRF would also require significant bandwidth — hence, ultra wide-band. To mitigate UWB transmissions from interfering with narrower-band transmissions on the same frequencies, the pulsed transmissions can be made at very low power, often below the typical noise floor for other transmissions. Naturally this also necessarily limits its range to perhaps a hundred or so metres at most but also makes battery-powered operation highly practical. Its utility in location-finding is because time-of-flight can be measured very quickly and exactly due to the short pulse lengths; when fully active, an Apple AirTag typically transmits a pulse about every other nanosecond. subsequent amendments. A standards group quickly emerged at the IEEE called the IEEE 802.15 Working Group for WPANs, addressing not only UWB but other WPAN-enabling technologies generally. The 802.15 WG had two arms, 802.15.4 for low bandwidth applications which we will not discuss further in this article (Zigbee is probably the most well-known in this category), and 802.15.3 for high bandwidth applications. Subsequently, the WiMedia Alliance was established that summer to capitalize on the new high-bandwidth technology, counting among other early members Eastman Kodak, Motorola, Hewlett-Packard, Intel, Philips, Samsung, Sharp and STMicroelectronics. 802.15.3 had obvious utility in determining precise location, but an extension called 802.15.3a in December 2002 sought to further enhance the standard for high-speed transmission of image and multimedia data. This team started with 23 proposals and whittled them down to two, DS-UWB (alternatively DS-CDMA) and MB-OFDM. DS-UWB stands for direct sequence ultra wide-band, where the data is simply sent as pulses (as in binary pulse AM) over the entire frequency range in use. However, although the low power of UWB prevents it from interfering with higher-power narrowband signals, an additional layer is needed to prevent UWB transmissions from interfering with each other (i.e., multiple access). DS-UWB uses a system similar to cellular CDMA (code-division multiple access) where each transmitter modulates the data signal with an even higher frequency pseudorandom code known to the receiver, hence its alternative name of DS-CDMA. An interfering transmitter without the same code will have its signals attenuated during the decoding (despreading) process and be ignored. Additionally, by making the transmitted signal require more bandwidth than the original one, the composite signal becomes spread over an even larger frequency range and thus more resistant to narrow-band interference (i.e., direct sequence spread spectrum). On the other hand, MB-OFDM (multiband orthogonal frequency-division multiplexing) instead employs a massive number of subcarriers to send its data. The basic principle of OFDM, which dates back to Bell Labs in 1966, is to divide up the desired digital signal into multiple bits transmitted in parallel on multiple simultaneous subcarriers. OFDM has many current applications, among others various standards for Wi-Fi and digital TV such as DVB-T and 802.11a/g/n/ac/ah. To avoid interference between the subcarriers yet maximize the channel's capacity, each subcarrier is separated by a minimum frequency distance usually computed as the reciprocal of the useful symbol duration, making each subcarrier orthogonal to the others surrounding it and easily discriminated. MB-OFDM as used here divides the approved range into fourteen 528MHz subbands of 128 subcarriers each, 100 of which are used for data transmission and the remainder for zeroes, guard tones and pilot signals. It solves the multiple access problem by hopping between transmission subfrequencies in a defined pattern (time-frequency coding), meaning each user ideally is on a different one at any given time while also avoiding narrowband intrusion on any one particular frequency. In practice the spec doesn't use all of the subbands simultaneously, bundling them into four bandgroups of three (with a fifth group of two, and a sixth group overlapping two others) and selecting a group as required by local regulation or to compensate for existing sources of interference. MultiBand OFDM Alliance in June 2003, founded by Texas Instruments and crucially joined by Intel, while the DS-UWB camp was largely led by Motorola and subsequently Freescale, its inheritor, who had significant investment in CDMA. Although MB-OFDM demanded obviously greater technical complexity, it also presented the prospect of much faster data rates, and as a result the MBOA continued to accrete members despite Motorola's protests. Motorola attempted to develop a compromise lower-speed Common Signaling Mode ("UWB CSM") so DS-UWB and MB-OFDM devices could coexist, but the process descended into squabble, and Motorola pulled out of the WiMedia Alliance to establish the competing UWB Forum in 2004 exclusively focused on DS-UWB with CSM. As the standards argument raged in the background, OEMs meanwhile started evaluating potential market applications. After all, just about any potential short-range interconnect could be built on it; proposals to replace or reimplement Bluetooth with UWB were considered, as well as transports for IPv4 networking and FireWire (IEEE 1394). The original wireless USB concept in particular came from Motorola's new spinoff Freescale, who was determined to win the war anyway by getting their chipset to retail first, but also from Intel, who through its heavy influence on the USB Implementers Forum (USB-IF) persuaded the organization to adopt WiMedia's version of MB-OFDM as their officially blessed USB solution for high-speed wireless devices. In February 2004 Intel announced the formation of the Wireless USB (W-USB) Promoter Group, composed of themselves, Agere (now part of Broadcom via the former LSI Logic), Hewlett-Packard, Microsoft, NEC, Philips and Samsung, with an aim for products within the next year. Because the W-USB name clashed with Freescale's initial branding, Intel and the USB-IF eventually settled on CW-USB ("Certified Wireless USB") and the MBOA was merged into the WiMedia Alliance in 2005. Now that the attempt to make an IEEE standard had clearly stalled for good, WiMedia submitted its own specification to Ecma instead, published as ECMA-368, and the 802.15.3a Task Group subsequently disbanded in January 2006. Both Freescale W-USB (later changed to Cord-Free USB and then Cable-Free USB, both of which we'll call CF-USB for short) and Intel CW-USB conceptually replicate the host-centric nature of USB 2.0, hewing more or less to the same basic topology but obviously without wires. Both systems supported up to 127 devices and necessarily the over-the-air connection was encrypted, both with AES-128. There were of course no compliant devices yet, nor compliant computers, so both competing standards required a dongle on the PC side and offered wireless USB hubs to connect existing peripherals. The main user-facing difference between Cable-Free and Certified Wireless USB was that CF-USB was intentionally, and in this case ironically, much closer to the wired USB spec. In particular, although CF-USB connections could only go point-to-point — just like a single cord — all USB features and transfer types were supported, even isochronous transfers for real-time data. CF-USB also had the compatibility edge in that the other end would look just like a regular USB hub to the computer, so no software update was necessary. CW-USB, on the other hand, although its virtual bus was much more flexible and devices could be hosts to other devices, wasn't fully backwards-compatible with all USB devices and needed new drivers and operating system support. non-UWB wireless USB system that I'll come back to later on. Freescale's team eventually suffered management departures and failed to release any future CF-USB hardware, after which the UWB Forum itself imploded in 2007. Using a USB PC dongle made by Taiwanese OEM Gemtek, exhibitors were shown a PC and a digital camera associating with each other and the PC downloading images from the camera to its desktop, which Intel claimed could run at up to USB 2.0's full 480Mb/s at three metres (110Mb/sec up to 10). One heavily anticipated application was as a docking station you could just walk up to: if you had been previously associated, then boom, you were connected. The bandwidth, Intel promised, would be real and it would be spectacular. A few months later, Belkin's reworked dongle-hub kit — initially still called "Cable-Free" until Freescale objected — finally emerged for retail sale in 2007. Unfortunately, the chipset switch eliminated Belkin's Mac compatibility and it only came with Windows drivers. Worse, Belkin's hub took it on the chin in various reviews, citing an eighty percent reduction in throughput if the devices were just a foot away, and another 30% on top of that at four feet, with a maximum range of somewhere around six (or one big wall). This probably made it more secure, but definitely not more convenient, and far short of the claimed 10 metre maximum range. It doesn't look like Belkin sold very many. Another vendor was D-Link, who produced both dongles and hubs along with a starter kit containing one of each. This NOS example, utterly unused in a sealed box, had an original MSRP of about $170 ($225 in 2025 dollars) but showed up on eBay for $12. I couldn't resist picking it up and a couple other cheap CW-USB products to play with, all of which carried the proud and official Certified Wireless USB logo. I made sure one of them was a docking station since that was intended to be the killer app. all of them come with an HWA, even though only one of them actually (or at least officially) has a DWA hub: the D-Link starter kit (model DUB-9240), consisting of a DUB-2240 4-port DWA USB 2.0 hub and a DUB-1210 HWA. The TRULink #29596 Wireless USB to VGA and Audio Kit has two downstream devices with on-board DWAs, one for a VGA monitor (up to 1600x1200 or 1680x1050) and one for analogue audio, plus its own HWA; the Atlona AT-PCLink Wireless USB DisplayDock offers DVI video, 3.5mm (1/8") audio and two USB ports, advertised for your mouse and keyboard (but really a lurking hub also). The dock base, interestingly enough, is not a CW-USB device itself: you have to plug a DWA into it (included) which can go in one of two ports depending on physical configuration. In the package Atlona also includes another HWA. However, since they're all allegedly CW-USB 1.0 compliant, you should be able to use any HWA you want. (Theoretically. That's called "foreshadowing.") The D-Link and TRULink HWAs only support Windows XP SP3 and Vista — there was a short-lived Linux implementation that Intel themselves wrote, but it was very incomplete and eventually removed — and the Atlona HWA does too, but it also claims support for Windows 7 and even Mac OS X (Leopard and Snow Leopard). So our test system will be ... Virus Alert by Weird Al. Get out your Intel if you want to try this.) That covers the HWA and the HWA-DWA link, but being "USB" (after a fashion) you also need a driver for the device it's connecting to. Fortunately the TRULink and Atlona video systems are both DisplayLink-based, supporting screen mirroring and spanning, for which (Intel) Mac drivers also exist. does later on.) association process, which is necessary because obviously you don't want malicious USB devices trying to talk to you, and you don't want your next-door neighbour possibly being able to use your printer or read tax returns on your thumb drive. (I didn't know that was deductable!) The process of association generates a new AES-128 session key and records both 128-bit host and device IDs for future recognition. This shared 384-bit association context remains in effect until explicitly disabled: the associated device now won't interact with HWAs it doesn't know, other than to potentially associate with them also, and the HWA will only talk to devices with which it has been associated. It is possible, and absolutely supported, for a device to be associated with multiple HWAs. Association in CW-USB can be done one of three ways, either by factory pre-association (the TRULink and Atlona devices come pre-associated with their HWAs, for example), numeric association where the device provides an on-screen code (like Bluetooth pairing) or the PIN on the underside of the device can be manually entered (an alpha-numeric code like D0NTH4CKM3), or, uniquely, by cable association. physically connect the CW-USB device to your PC or Mac via USB cable, let it be recognized by the HWA's driver, and then disconnect it. It then continues to act connected, just via the HWA. The D-Link DWA-hub is cable-associated as part of the installation process, or can be associated by PIN; it is the only one of these three that is not pre-associated. All devices support pre-association and some sort of numeric association, but a physical USB port is naturally required for cable association. It is nevertheless the most secure of the three methods, first because you have to have physical custody of both the device and the computer, second because it's a new and unique key, and third because key creation and distribution occurs entirely via the cable and never over the air. Unfortunately it's not possible to blacklist the other association methods, so you'd better not let your neighbour get your PIN. (You pay how much in mortgage interest??) Some devices like the TRUlinks mercifully do support changing it, but that ability didn't seem universal in the devices I looked at. In this case, all three devices support cable-association. The D-Link hub and the TRULink devices do so via their USB ports, but the Atlona dock does it by plugging the DWA into the computer instead of the docking base itself. The reverse process is also obviously possible to de-associate a device, and you can outright block devices as well, though this may require some fiddling if they were pre-associated. Similarly, most devices, including this one, have a reset button which will clear the association context(s) stored in them, removing any undesired linkages. Let's get the D-Link kit installed in the Vista VM. not big the wireless USB market ultimately got. A few pieces of WiQuest and their IP are now part of modern Staccato Communications. not to plug in either the dongle or the hub until installation is complete and the hub has been cable-associated. can see it. Although I found it initially surprising that VMware didn't ask me about the device when I connected it, upon reflection it's perfectly logical that wireless USB devices wouldn't be seen at all by the Mac because we've effectively constructed a new and separate USB bus completely outside of it. For all the devices I connected to the hub-DWA, VMware was absolutely unaware of all of them, including the hub itself; the only device the MacBook and therefore VMware saw was the HWA. This is probably good from a performance view though possibly bad from a device control view. COM3: we just installed (the others are provided by VMware). emulate a serial port but only appear on the USB bus when there is activity, such as kicking off a HotSync. Notice the only thing connected to the MacBook is the HWA (all ports are on the left side of this model), but with the watch connected to the hub-DWA the Vista VM sees the new USB device appear. does appear to work suggests this should work on, say, Windows XP. Let's see if the Atlona AT-PCLink natively in Snow Leopard can do any better. It's time to bring on the docking station. .dmg double the size it needed to be. A help alias points to a small HTML-based manual, but the Windows version has a full PDF available on the disc. and had a Universal payload, even though Atlona said explicitly it wasn't compatible with PowerPC. I grabbed my great big A1139 17" DLSD PowerBook G4 1.67GHz, the last and mightiest PowerBook which I use as a portable DVD player and Leopard 10.5.8 test system, to see if it would work. this way? pilot-xfer, but that doesn't give you the rest of the PIM, and Mark/Space's Missing Sync does not run on Mavericks or later.) Fortunately, this is Snow Leopard, so we have O.G. Rosetta. associate or pair a new device. (Remember what I said about foreshadowing?) This restriction appears to be entirely due to the software and isn't unique to the Mac version; the Atlona manual indicates that the Windows version can't associate new devices either, other than possibly another Atlona dock. Officially it can be re-paired with its original DWA and that's it. /System/Library/WUSB/CBA.app/Contents/Resources/DB.plist, which lists associated devices. (The very location of this .plist again suggests it wasn't intended for user modification.) Here is the relevant portion, with keys suppressed: You can identify the WiMedia bandgroup (1, 3.1GHz to 4.8GHz), the 128-bit host and device IDs, and the 384-bit association context (which includes both IDs) in the key-value pairs. Yes, I could insert another device entry easily enough, but I wouldn't know the AES key the other end is using, so I couldn't compute a valid context. Since this driver is running natively and we're not paying a VM tax, let's see how well video streaming worked since oodles of cableless bandwidth was just about the entire use case for wireless USB. Snow Leopard welcome video and prove it wrong. (The Snow Leopard welcome video has audio in a separate file, so this comparison movie has no sound.) 2.0 Extender, used a much more familiar wireless transport: 802.11g. Yup — it's USB over Wi-Fi. bulk transfers, and I tend to believe Icron because it's their hardware — but both are clear that high-bandwidth devices like UVC webcams are going to have a bad time: "Icron Technologies Corporation does not guarantee that all USB devices are compatible with the WiRanger and only recommends the product be used with keyboard, mouse, and some flash drives." some of my devices use. bus like CW-USB. I wanted to do some performance tests with it, but strangely macOS Sequoia will not recognize the sender when connected to my M1 MacBook Air, even though it worked fine connected to the Raptor POWER9 in Fedora 41 and was seen as a hub there too. So we'll do the tests on the MacBook as well, which also had no problem seeing and using the pair. Again, we'll just copy that same 1.09GB combo installer and see how long it takes. pilot-xfer from the command line instead of Palm Desktop. Slirp or usb2ppp. as before. It actually doesn't feel much different in terms of speed from a direct connect and I didn't find it particularly unstable. Of what we've explored here, the Gefen box seems the least complicated solution, though the receiver pulled a bit more battery power and of course you'd need a host around to connect through. As such I'm still using the "Raspberry Pi in a camera bag" notion for the time being, but it's nice to see it can work other ways. My experience with the Gefen/Icron extender was generally consistent with other reviews that found it adequate for undemanding tasks like printing. However, it doesn't look like either Icron or Gefen sold many of them, likely due to their unattractive price tag. Icron did announce plans for a much faster wireless USB solution on the 60GHz band using 802.11ad, which with its 7 Gbit/s capacity would easily handle USB 2.0 and even 5 Gbit/s 3.0, but it doesn't seem like the device was ever offered for sale. (A couple people have mentioned to me that there were other ≥802.11ad wireless USB products out there, including WiGig. Their bandwidth was reportedly more than sufficient for video but I don't have any of those devices here, and they are better understood as Wi-Fi routers that also do USB device sharing.) Although Icron still sells extenders, now as a division of Analog Devices, all of their current products are wired-only. As for CW-USB, by 2008 few laptops on the market offered the feature, and even for those that did like the Lenovo ThinkPad X200, it was always an extra option. That meant most computers that wanted to connect to a CW-USB device still needed a HWA-dongle, so they still took up a port, and HWAs never got produced in enough numbers to be cheap. On top of that, it further didn't help matters that anything close to the promised maximum bandwidth was hardly ever observed in real-world situations. Device makers, meanwhile, mostly chose to wait out greater availability of CW-USB capable computers, and since that never happened, neither a large number of computers with built-in CW-USB nor CW-USB devices were ever made before the standard was abandoned. The last stand of UWB as a device interconnect was ironically as a proposal for Bluetooth 3.0+HS, the 2009 optional high-data-rate specification. 3.0+HS introduced AMP (Alternative MAC/PHY) as a bolt-on method, in which low-speed Bluetooth would be used to set up a link and then the high-speed data exchange would occur over the second transport, originally MB-OFDM. With CW-USB fading from the market, however, the WiMedia Alliance closed its doors in 2009 and shed its existing work to the USB-IF, the W-USB Promoter Group and the Bluetooth SIG. This move was controversial with some WiMedia members, who consequently refused to grant access to their intellectual property to the new successor groups, and instead AMP ended up being based on 802.11 as well. The AMP extension was little used and eventually removed in Bluetooth 5.3. Is there a moral to this story? I'm not quite certain. As so often happens, the best technology didn't win; in my eyes CF-USB had the potential for being more widely adopted because of its simplicity and compatibility, but was ruined when Freescale got greedy and it never recovered. That said, the real question is whether wireless USB itself, with all of its broken promises, was the right approach for the WPAN concept. It's certainly not an indictment of ultra wideband, which is used today more than ever before: many chips are still produced that implement it, the best known undoubtedly being Apple's U1 and U2 chips in iOS and iOS-adjacent devices like the AirTag, and such chips continue to be widely used for things such as precise location fixing and local interactions. UWB has also been used for diverse tasks like tracking NFL players during games or parts during factory assembly, and for autonomous vehicles in particular it's extremely useful. without wireless USB — and we just never noticed. Maybe that's the moral.
Just a brief programming note. Before this blog there was Floodgap Retrobits, and I still maintain those pages. One of the earliest was my Tomy Tutor-specific page devoted to my very first computer which we got in 1983. Relatives of the Texas Instruments home computers and closely patterned after the unreleased TI 99/8, the history of the Japanese models is relatively well-known and there are a number of Japanese enthusiasts that specialize in the Pyuuta, the Tutor's ancestor system. On the other hand, hardly anybody knows anything about the British version. That system is the Grandstand Tutor: Your Computer October 1983, at that time one of the major home computer magazines in the UK. The original form of this machine was very similar to the Pyuuta, which emphasized its TMS9918A-based built-in paint program and due to its specialization on graphics only implements a very simplified animation-oriented dialect of BASIC called GBASIC. Adam Imports rebadged many Asian and some American toys and games for the UK (and, for some period of time, New Zealand) and had a particularly close relationship with Tomy. In fact, the relationship was close enough that Adam in fact rejected this initial version as uncompetitive with other home computers and sent it back to Tomy for a more upgraded BASIC. Tomy provided this by modifying TI Extended BASIC, calling it Tomy BASIC and implementing it as a second mode accessible from the system's menu-based interface. The absence of Tomy BASIC places the earliest Grandstand Tutor prior to the American Tomy Tutor, which also has the upgraded Tomy BASIC. Tomy subsequently sold this upgrade in at least two forms as an option for the Japanese machines as well. The interesting part is that while PAL Tutors have been documented to exist (the American Tutor is obviously NTSC), no one yet has reported finding a Grandstand. It wouldn't be hard to distinguish one — the photograph has obvious Grandstand branding on its silver badge. It's possible they were never released at all because even accounting for publishing delays, the second Grandstand would have emerged late in 1983, hitting in the wake of the video game crash and against heavier hitters like the Commodore VIC-20 and Commodore 64 as well as (in the UK) the ZX Spectrum. Adam may have simply concluded it wasn't a strong enough competitor even with the upgraded BASIC to sell. including SunView. Later their IDT workstations, though uniprocessor, competed directly with and even could squeak by contemporary SPARCstations, at least in the beginning. Solbourne eventually ran out of money when they hit engineering limits with their own CPU and could never reclaim the throughput crown, abandoning the computer hardware market in 1994. We might be adding more remembrances as other Solbourne engineers are contacted. You can see these updates at The Little Orphan Tomy Tutor as well as past Old VCR Tomy articles, and The Solbourne Solace as well as past Old VCR Solbourne-specific articles. Naturally, if you have anything to add, feel free to post in the comments or drop me E-mail at ckaiser at floodgap dawt com.
COMPUTE!'s Gazette was for many years the leading Commodore-specific managzine. I liked Ahoy! and RUN, and I subscribed to Loadstar too, but Gazette had the most interesting type-ins and the most extensive coverage. They were also the last of COMPUTE!'s machine-specific magazines and one of the longest lived Commodore publications, period: yours truly had some articles published in COMPUTE (no exclamation point by then) Gazette as a youthful freelancer in the 1990s until General Media eventually made Gazette disk-only and then halted entirely in 1995. I remember pitching Tom Netzel on a column idea and getting a cryptic E-mail back from him saying that "things were afoot." What was afoot was General Media divesting the entire publication to Ziff-Davis, who was only interested in the mailing list, and I got a wholly inadequate subscription to PC Magazine in exchange which I mostly didn't read and eventually didn't renew. This week I saw an announcement about a rebooted Gazette — even with a print edition, and restoring the classic ABC/Cap Cities trade dress — slated for release in July. I'm guessing that "president and founder [sic]" Edwin Nagle either bought or licensed the name from Ziff-Davis when forming the new COMPUTE! Media; the announcement also doesn't say if he only has rights to the name, or if he actually has access to the back catalogue, which I think could be more lucrative: since there appears to be print capacity, seems like there could be some money in low-run back issue reprints or even reissuing some of their disk products, assuming any residual or royalty arrangements could be dealt with. I should say for the record that I don't have anything to do with the company myself and I don't know Nagle personally. By and large I naturally think this is a good thing, and I'll probably try to get a copy, though the stated aim of the magazine is more COMPUTE! and less Gazette since it intends to cover the entire retro community. Doing so may be the only way to ensure an adequate amount of content at a monthly cadence, so I get the reasoning, but it necessarily won't be the Gazette you remember. Also, since most retro enthusiasts have some means to push downloaded data to their machines, the type-in features which were the predominant number of pages in the 1980s will almost certainly be diminished or absent. I suspect you'll see something more like the General Media incarnation, which was a few type-ins slotted between various regular columns, reviews and feature articles. The print rate strikes me as very reasonable at $9.95/mo for a low-volume rag and I hope they can keep that up, though they would need to be finishing the content for layout fairly soon and the only proferred sample articles seem to be on their blog. I'm at most cautiously optimistic right now, but the fact they're starting up at all is nice to see, and I hope it goes somewhere.
More in technology
Recently there’s been very exciting developments in the Godot game engine, that have allowed really easy and powerful integration into an existing normal iOS or Mac app. I couldn’t find a lot of documentation or discussion about this, so I wanted to shine some light on why this is so cool, and how easy it is to do! What’s Godot? For the uninitiated, Godot is an engine for building games, other common ones you might know of are Unity and Unreal Engine. It’s risen in popularity a lot over the last couple years due to its open nature: it’s completely open source, MIT licensed, and worked on in the open. But beyond that, it’s also a really well made tool for building games with (both 2D and 3D), with a great UI, beautiful iconography, a ton of tutorials and resources, and as a bonus, it’s very lightweight. I’ve had a lot of fun playing around with it (considering potentially integrating it into Pixel Pals), and while Unity and Unreal Engine are also phenomenal tools, Godot has felt lightweight and approachable in a really nice way. As an analogy, Godot feels closer to Sketch and Figma whereas Unity and Unreal feel more like Photoshop/Illustrator or other kinda bulky Adobe products. Even Apple has taken interest in it, contributing a substantial pull request for visionOS support in Godot. Why use it with iOS? You’ve always been able to build a game in Godot and export it to run on iOS, but recently thanks to advancements in the engine and work by amazing folks like Miguel de Icaza, you can now embed a Godot game in an existing normal SwiftUI or UIKit app just as you would an extra UITextView or ScrollView. Why is this important? Say you want to build a game or experience, but you don’t want it to feel just like another port, you want it to integrate nicely with iOS and feel at home there through use of some native frameworks and UI here and there to anchor the experience (share sheets, local notifications, a simple SwiftUI sheet for adding a friend, etc.). Historically your options have been very limited or difficult. You no longer have to have “a Godot game” or “an iOS app”, you can have the best of both worlds. A fun game built entirely in Godot, while having your share sheets, Settings screens, your paywall, home screen widgets, onboarding, iCloud sync, etc. all in native Swift code. Dynamically choosing which tool you want for the job. (Again, this was technically possible before and with other engines, but was much, much more complicated. Unity’s in particular seems to have been last updated during the first Obama presidency.) And truly, this doesn’t only benefit “game apps”. Heck, if the user is doing something that will take awhile to complete (uploading a video, etc.) you could give them a small game to play in the interim. Or just for some fun you could embed a little side scroller easter egg in one of your Settings screens to delight spelunking users. Be creative! SpriteKit? A quick aside. It wouldn’t be an article about game dev on iOS without mentioning SpriteKit, Apple’s native 2D game framework (Apple also has SceneKit for 3D). SpriteKit is well done, and actually what I built most of Pixel Pals in. But it has a lot of downsides versus a proper, dedicated game engine: Godot has a wealth of tutorials on YouTube and elsewhere, bustling Discord communities for help, where SpriteKit being a lot more niche can be quite hard to find details on The obvious one: SpriteKit only works on Apple platforms, so if you want to port your game to Android or Windows you’re probably not going to have a great time, where Godot is fully cross platform Godot being a full out game engine has a lot more tools for game development than can be handy, from animation tools, to sprite sheet editors, controls that make experimenting a lot easier, handy tools for creating shaders, and so much more than I could hope to go over in this article. If you ever watch a YouTube video of someone building a game in a full engine, the wealth of tools they have for speeding up development is bonkers. Godot is updated frequently by a large team of employees and volunteers, SpriteKit conversely isn’t exactly one of Apple’s most loved frameworks (I don’t think it’s been mentioned at WWDC in years) and kinda feels like something Apple ins’t interested in putting much more work into. Maybe that’s because it does everything Apple wants and is considered “finished” (if so I think that would be incorrect, see previous point for many things that it would be helpful for SpriteKit to have), but if you were to encounter a weird bug I’d feel much better about the likelihood of it getting fixed in Godot than SpriteKit I’m a big fan of using the right tool for the job. For iOS apps, most of the time that’s building something incredible in SwiftUI and UIKit. But for building a game, be it small or large, using something purpose built to be incredible at that seems like the play to me, and Godot feels like a great candidate there. Setup Simply add the SwiftGodotKit package to your Xcode project by selecting your project in the sidebar, ensuring your project is selected in the new sidebar, selecting the Package Dependencies tab, click the +, then paste the GitHub link. After adding it, you will also need to select the target that you added it to in the sidebar, select the Build Settings tab, then select “Other Linker Flags” and add -lc++. Lastly, with that same target, under the General tab add MetalFX.framework to Frameworks, Libraries, and Embedded Content. (Yeah you got me, I don’t know why we have to do that.) After that, you should be able to import SwiftGodotKit. Usage Now we’re ready to use Godot in our iOS app! What excites me most and I want to focus on is embedding an existing Godot game in your iOS app and communicating back and forth with it from your iOS app. This way, you can do the majority of the game development in Godot without even opening Xcode, and then sprinkle in delightful iOS integration by communicating between iOS and Godot where needed. To start, we’ll build a very simple game called IceCreamParlor, where we select from a list of ice cream options in SwiftUI, which then gets passed into Godot. Godot will have a button the user can tap to send a message back to SwiftUI with the total amount of ice cream. This will not be an impressive “game” by any stretch of the imagination, but should be easy to set up and understand the concepts so you can apply it to an actual game. To accomplish our communication, in essence we’ll be recreating iOS’ NotificationCenter to send messages back and forth between Godot and iOS, and like NotificationCenter, we’ll create a simple singleton to accomplish this. Those messages will be sent via Signals. This is Godot’s system for, well, signaling an event occurred, and can be used to signify everything from a button press, to a player taking damage, to a timer ending. Keeping with the NotificationCenter analogy, this would the be Notification that gets posted (except in Godot, it’s used for everything, where in iOS land you really wouldn’t use NotificationCenter for a button press.) And similar to Notification that has a userInfo field to provide more information about the notification, Godot signals can also take an argument that provides more information. (For example if the notification was “player took damage” the argument might be an integer that includes how much damage they took.) Like userInfo, this is optional however and you can also fire off a signal with no further information, something like “userUnlockedPro” for when they activate Pro after your SwiftUI paywall. For our simple example, we’re going to send a “selectedIceCream” signal from iOS to Godot, and a “updatedIceCreamCount” signal from Godot to iOS. The former will have a string argument for which ice cream was selected, and the latter will have an integer argument with the updated count. Setting up our Godot project Open Godot.app (available to download from their website) and create a new project, I’ll type in IceCreamParlor, choose the Mobile renderer, then click Create. Godot defaults to a 3D scene, so I’ll switch to 2D at the top, and then in the left sidebar click 2D Scene to create that as our root node. I’ll right-click the sidebar to add a child node, and select Label. We’ll set the text to the “Ice cream:”. In the right sidebar, we’ll go to Theme Overrides and increase the font size to 80 to make it more visible, and we’ll also rename it in the left sidebar from Label to IceCreamLabel. We’ll also do the same to add a Button to the scene, which we’ll call UpdateButton and sets its text to “Update Ice Cream Count”. If you click the Play button in the top right corner of Godot, it will run and you can click the button, but as of now it doesn’t do anything. We’ll select our root node (Node2D) in the sidebar, right click, and select “Attach Script”. Leave everything as default, and click Create. This will now present us with an area where we can actually code in GDScript, and we can refer to the objects in our scene by prefixing their name with a dollar sign. Inside our script, we’ll implement the _ready function, which is essentially Godot’s equivalent of viewDidLoad, and inside we’ll connect to our simple signal we discussed earlier. We’ll do this by grabbing a reference to our singleton, then reference the signal we want, then connect to it by passing a function we want to be called when the signal is received. And of course the function takes a String as a parameter because our signal includes what ice cream was selected. extends Node2D var ice_cream: Array[String] = [] func _ready() -> void: var singleton = Engine.get_singleton("GodotSwiftMessenger") singleton.ice_cream_selected.connect(_on_ice_cream_selected_signal_received) func _on_ice_cream_selected_signal_received(new_ice_cream: String) -> void: # We received a signal! Probably should do something… pass Note that we haven’t actually created the singleton yet, but we will shortly. Also note that normally in Godot, you have to declare custom signals like the ones we’re using, but we’re going to declare them in Swift. As long as they’re declared somewhere, Godot is happy! Let’s also hook up our button by going back to our scene, selecting our button in the canvas, selecting the “Node” tab in the right sidebar, and double-clicking the pressed() option. We can then select that same Node2D script and name the function _on_update_button_pressed to add a function that executes when the button is pressed (fun fact: the button being pressed event is also powered by signals). func _on_update_button_pressed() -> void: pass Setting up our iOS/Swift project Let’s jump over to Xcode and create a new SwiftUI project there as well, also calling it IceCreamParlor. We’ll start by adding the Swift package for SwiftGodotKit to Swift Package Manager, add -lc++ to our “Other Linker Flags” under “Build Settings”, add MetalFX, then go to ContentView.swift and add import SwiftGodotKit at the top. From here, let’s create a simple SwiftUI view so we can choose from some ice cream options. var body: some View { HStack { Button { } label: { Text("Chocolate") } Button { } label: { Text("Strawberry") } Button { } label: { Text("Vanilla") } } .buttonStyle(.bordered) } We’ll also create a new file in Xcode called GodotSwiftMessenger.swift. This will be where we implement our singleton that is akin to NotificationCenter. import SwiftGodot @Godot class GodotSwiftMessenger: Object { public static let shared = GodotSwiftMessenger() @Signal var iceCreamSelected: SignalWithArguments<String> @Signal var iceCreamCountUpdated: SignalWithArguments<Int> } We first import SwiftGodot (minus the Kit), essentially because this part is purely about interfacing with Godot through Godot, and doesn’t care about whether or not it’s embedded in an iOS app. For more details on SwiftGodot see its section below. Then, we annotate our class with the @Godot Swift Macro, which basically just says “Hey make Godot aware that this class exists”. The class is a subclass of Object as everything in Godot needs to inherit from Object, it’s essentially the parent class of everything. Following that is your bog standard Swift singleton initialization. Then, with another Swift Macro, we annotate a variable we want to be our signal which signifies that it’s a Signal to Godot. You can either specify its type as Signal or SignalWithArguments<T> depending on whether or not the specific signal also sends any data alongside it. We’ll use that “somethingHappened” signal we mentioned early, which includes a string for more details on what happened. Note that we used “ice_cream_selected” in Godot but “iceCreamSelected” in Swift, this is because the underscore convention is used in Godot, and SwiftGodotKit will automatically map the camelCase Swift convention to it. Now we need to tell Godot about this singleton we just made. We want Godot to know about it as soon as possible, otherwise if things aren’t hooked up, Godot might emit a signal that we wouldn’t receive in Swift, or vice-versa. So, we’ll hook it up very early in our app cycle. In SwiftUI, you might do this in the init of your main App struct as I’ll show below, and in UIKit in applicationDidFinishLaunching. @main struct IceCreamParlor: App { init() { initHookCb = { level in guard level == .scene else { return } register(type: GodotSwiftMessenger.self) Engine.registerSingleton(name: "GodotSwiftMessenger", instance: GodotSwiftMessenger.shared) } } var body: some Scene { WindowGroup { ContentView() } } } In addition to the boilerplate code Xcode gives us, we’ve added an extra step to the initializer, where we set a callback on initHookCb. This is just a callback that fires as Godot is setup, and it specifies what level of setup has occurred. We want to wait until the level setup is reached, which means the game is ready to go (you could set it up at an even earlier level if you see that as beneficial). Then, we just tell Godot about this type by calling register, and then we register the singleton itself with a name we want it to be accessible under. Again, we want to do this early, as if Godot was already setup in our app, and then we set initHookCb, its contents would never fire and thus we wouldn’t register anything. But don’t worry, this hook won’t fire until we first initialize our Godot game in iOS ourself, so as long as this code is called before then, we’re golden. Lastly, everything is registered in iOS land, but there’s still nothing that emits or receives signals. Let’s change that by going to ContentView.swift, and change our body to the following: import SwiftUI import SwiftGodotKit import SwiftGodot struct ContentView: View { @State var totalIceCream = 0 @State var godotApp: GodotApp = GodotApp(packFile: "main.pck") var body: some View { VStack { GodotAppView() .environment(\.godotApp, godotApp) Text("Total Ice Cream: \(totalIceCream)") HStack { Button { GodotSwiftMessenger.shared.iceCreamSelected.emit("chocolate") } label: { Text("Chocolate") } Button { GodotSwiftMessenger.shared.iceCreamSelected.emit("strawberry") } label: { Text("Strawberry") } Button { GodotSwiftMessenger.shared.iceCreamSelected.emit("vanilla") } label: { Text("Vanilla") } } .buttonStyle(.bordered) } .onAppear { GodotSwiftMessenger.shared.iceCreamCountUpdated.connect { newTotalIceCream in totalIceCream = newTotalIceCream } } } } There’s quite a bit going on here, but let’s break it down because it’s really quite simple. We have two new state variables, the first is to keep track of the new ice cream count. Could we just do this ourselves purely in SwiftUI? Totally, but for fun we’re going to be totally relying on Godot to keep us updated there, and we’ll just reflect that in SwiftUI to show the communication. Secondly and more importantly, we need to declare a variable for our actual game file so we can embed it. We do this embedding at the top of the VStack by creating a GodotAppView, a handy SwiftUI view we can now leverage, and we do so by just setting its environment variable to the game we just declared. Then, we change our buttons to actually emit the selections via signals, and when the view appears, we make sure we connect to the signal that keeps us updated on the count so we can reflect that in the UI. Note that we don’t also connect to the iceCreamSelected signal, because we don’t care to receive it in SwiftUI, we’re just firing that one off for Godot to handle. Communicating Let’s update our gdscript in Godot to take advantage of these changes. func _on_ice_cream_selected_signal_received(new_ice_cream: String) -> void: ice_cream.append(new_ice_cream) $IceCreamLabel.text = "Ice creams: " + ", ".join(ice_cream) func _on_update_button_pressed() -> void: var singleton = Engine.get_singleton("GodotSwiftMessenger") singleton.ice_cream_count_updated.emit(ice_cream.size()) Not too bad! We now receive the signal from SwiftUI and update our UI and internal state in Godot accordingly, as well as the UI by making our ice cream into a comma separated list. And then when the user taps the update button, we then send (emit) that signal back to SwiftUI with the updated count. Running To actually see this live, first make sure you have an actual iOS device plugged in. Unfortunately Godot doesn’t work with the iOS simulator. Secondly, in Godot, select the Project menu bar item, then Export, then click the Add button and select “iOS”. This will bring you to a screen with a bunch of options, but my understanding is that this is 99% if you’re building your app entirely in Godot, you can plug in all the things you’d otherwise plug into Xcode here instead, and Godot will handle them for you. That doesn’t apply to us, we’re going to do all that normally in Xcode anyway, we just want the game files, so ignore all that and select “Export PCK/ZIP…” at the bottom. It’ll ask you where you want to save it, and I just keep it in the Godot project directory, make sure “Godot Project Pack (*.pck)” is selected in the dropdown, and then save it as main.pck. That’s our “game” bundled up, as meager as it is! We’ll then drop that into Xcode, making sure to add it to our target, then we can run it on the device! Here we’ll see choosing the ice cream flavor at the bottom in SwiftUI beams it into the Godot game that’s just chilling like a SwiftUI view, and then we can tap the update button in Godot land to beam the new count right back to SwiftUI to be displayed. Not exactly a AAA game but enough to show the basics of communication 😄 Look at you go! Take this as a leaping off point for all the cool SwiftUI and Godot interoperability that you can accomplish, be it tappings a Settings icon in Godot to bring up a beautifully designed, native SwiftUI settings screen, or confirmation to you your game when the user updated to the Pro version of your game through your SwiftUI paywall. Bonus: SwiftGodot (minus the “Kit”) An additional fun option (that sits at the heart of SwiftGodotKit) is SwiftGodot, which allows you to actually build your entire Godot game with Swift as the programming language if you so choose. Swift for iOS apps, Swift on the server, Swift for game dev. Swift truly is everywhere. For me, I’m liking playing around in GDScript, which is Godot’s native programming language, but it’s a really cool option to know about. Embed size A fear might be that embedding Godot into your app might bloat the binary and result in an enormous app download size. Godot is very lightweight, adding it to your codebase adds a relatively meager (at least by 2025 standards) 30MB to your binary size. That’s a lot larger than SpriteKit’s 0MB, but for all the benefits Godot offers that’s a pretty compelling trade. (30MB was measured by handy blog sponsor, Emerge Tools.) Tips Logging If you log something in Godot/GDScript via print("something") that will also print to the Xcode console, handy! Quickly embedding the pck into iOS Exporting the pck file from Godot to Xcode is quite a few clicks, so if you’re doing it a lot it would be nice to speed that up. We can use the command line to make this a lot nicer. Godot.app also has a headless mode you can use by going inside the .app file, then Contents > MacOS > Godot. But typing the full path to that binary is no fun, so let’s symlink the binary to /usr/local/bin. sudo ln -s "/Applications/Godot.app/Contents/MacOS/Godot" /usr/local/bin/godot Now we can simply type godot anywhere in the Terminal to either open the Godot app, or we can use godot --headless for some command line goodness. My favorite way to do this, is to do something like the following within your Godot project directory: godot --headless --export-pack "iOS" /path/to/xcodeproject/target/main.pck This will handily export the pck and add it to our Xcode project, overwriting any existing pck file, from which point we can simply compile our iOS app. Wrapping it up I really think Godot’s new interoperability with iOS is an incredibly exciting avenue for building games on iOS, be it a full fledged game or a small little easter egg integrated into an existing iOS app, and hats off to all the folks who did the hard work getting it working. Hopefully this serves as an easy way to get things up and running! It might seem like a lot at first glance, but most of the code shown above is just boilerplate to get an example Godot and iOS project up and running, the actual work to embed a game and communicate across them is so delightfully simple! (Also big shout out to Chris Backas and Miguel de Icaza for help getting this tutorial off the ground.)
[Hardware] GPS synchronised, millisecond precision, automatic timezones and more!
When 3D printing matured from an industrial edge case to a mainstream commercial technology in the 2010s, it captured the imaginations of everyone from schoolteachers to fashion designers. But if there’s one group that really, really got excited about 3D printing, it was makers. When 3D printers became commercially available, they knew that everything was […] The post What can you do with Arduino and a new 3D printer? appeared first on Arduino Blog.
There are a handful of instruments that are staples of modern music, like guitars and pianos. And then there are hundreds of other instruments that were invented throughout history and then fell into obscurity without much notice. The Luminaphone, invented by Harry Grindell Matthews and unveiled in 1925, is a particularly bizarre example. Few people […] The post Recreating a bizarre century-old electronic instrument appeared first on Arduino Blog.