More from Old Vintage Computing Research
prior articles for more of the history, but MacLynx is a throwback port of the venerable Lynx 2.7.1 to the classic Mac OS last updated in 1997 which I picked up again in 2020. Rather than try to replicate its patches against a more current Lynx which may not even build, I've been improving its interface and Mac integration along with the browser core, incorporating later code and patching the old stuff. However, beta 6 is not a fat binary — the two builds are intentionally separate. One reason is so I can use a later CodeWarrior for better code that didn't have to support 68K, but the main one is to consider different code on Power Macs which may be expensive or infeasible on 68K Macs. The primary use case for this — which may occur as soon as the next beta — is adding a built-in vendored copy of Crypto Ancienne for onboard TLS without a proxy. On all but upper-tier 68040s, setting up the TLS connection takes longer than many servers will wait, but even the lowliest Performa 6100 with a barrel-bottom 60MHz 601 can do so reasonably quickly. The port did not go altogether smoothly. While Olivier Gutknecht's original fat binary worked fine on Power Macs, it took quite a while to get all the pieces reassembled on a later CodeWarrior with a later version of GUSI, the Mac POSIX glue layer which is a critical component (the Power Mac version uses 2.2.3, the 68K version uses 1.8.0). Some functions had changed and others were missing and had to be rewritten with later alternatives. One particularly obnoxious glitch was due to a conflict between the later GUSI's time.h and Apple Universal Interfaces' Time.h (remember, HFS+ is case-insensitive) which could not be solved by changing the search order in the project due to other conflicting headers. The simplest solution was to copy Time.h into the project and name it something else! Even after that, though, basic Mac GUI operations like popping open the URL dialogue would cause it to crash. Can you figure out why? Here's a hint: application: your application itself was almost certainly fully native. However, a certain amount of the Toolbox and the Mac OS retained 68K code, even in the days of Classic under Mac OS X, and your PowerPC application would invariably hit one of these routines eventually. The component responsible for switching between ISAs is the Mixed Mode Manager, which is tightly integrated with the 68K emulator and bridges the two architectures' different calling conventions, marshalling their parameters (PowerPC in registers, 68K on the stack) and managing return addresses. I'm serious when I say the normal state is to run 68K code: 68K code is necessarily the first-class citizen in Mac OS, even in PowerPC-only versions, because to run 68K apps seamlessly they must be able to call any 68K routine directly. All the traps that 68K apps use must also look like 68K code to them — and PowerPC apps often use those traps, too, because they're fundamental to the operating system. 68K apps can and do call code fragments in either ISA using the Code Fragment Manager (and PowerPC apps are obliged to), but the system must still be able to run non-CFM apps that are unaware of its existence. To jump to native execution thus requires an additional step. Say a 68K app running in emulation calls a function in the Toolbox which used to be 68K, but is now PowerPC. On a 68K MacOS, this is just 68K code. In later versions, this is replaced by a routine descriptor with a special trap meaningful only to the 68K emulator. This descriptor contains the destination calling convention and a pointer to the PowerPC function's transition vector, which has both the starting address of the code fragment and the initial value for the TOC environment register. The MMM converts the parameters to a PowerOpen ABI call according to the specified convention and moves the return address into the PowerPC link register, and upon conclusion converts the result back and unwinds the stack. The same basic idea works for 68K code calling a PowerPC routine. Unfortunately, we forgot to make a descriptor for this and other routines the Toolbox modal dialogue routine expected to call, so the nanokernel remains in 68K mode trying to execute them and makes a big mess. (It's really hard to debug it when this happens, too; the backtrace is usually totally thrashed.) the last time that my idea with MacLynx is to surround the text core with the Mac interface. Lynx keys should still work and it should still act like Lynx, but once you move to a GUI task you should stay in the GUI until that task is completed. In beta 5, I added support for the Standard File package so you get a requester instead of entering a filename, but once you do this you still need to manually select "Save to disk" inside Lynx. That changes in beta 6: :: which in MacOS is treated as the parent folder. Resizing, scrolling and repainting are also improved. The position of the thumb in MacLynx's scrollbar is now implemented using a more complex but yet more dynamic algorithm which should also more properly respond to resize events. A similar change fixes scroll wheels with USB Overdrive. When MacLynx's default window opens, a scrollbar control is artificially added to it. USB Overdrive implements its scrollwheel support by finding the current window's scrollbar, if any, and emulating clicks on its up and down (or left and right) buttons as the wheel is moved. This works fine in MacLynx, at least initially. When the window is resized, however, USB Overdrive seems to lose track of the scrollbar, which causes its scrollwheel functionality to stop working. The solution was to destroy and rebuild the scrollbar after the window takes its new dimensions, like what happens on start up when the window first opens. This little song and dance may also fix other scrollwheel extensions. Always keep in mind that the scrollbar is actually used as a means to send commands to Lynx to change its window on the document; it isn't scrolling, say, a pre-rendered GWorld. This causes the screen to be redrawn quite frequently, and big window sizes tend to chug. You can also outright crash the browser with large window widths: this is difficult to do on a 68K Mac with on-board video where the maximum screen size isn't that large, but on my 1920x1080 G4 I can do so reliably. lynx.cfg a no-op. However, if you are intentionally using another character set and this will break you, please feel free to plead your use case to me and I will consider it. Another bug fixed was an infinite loop that could trigger during UTF-8 conversion of certain text strings. These sorts of bugs are also a big pain to puzzle out because all you can do from CodeWarrior is force a trap with an NMI, leaving the debugger's view of the program counter likely near but probably not at the scene of the foul. Eventually I single-stepped from a point near the actual bug and was able to see what was happening, and it turned out to be a very stupid bug on my part, and that's all I'm going to say about that. SameSite and HttpOnly (irrelevant on Lynx but supported for completeness) attributes are, the next problem was that any cookie with an expiration value — which nowadays is nearly any login cookie — wouldn't stick. The problem turned out to be the difference in how the classic MacOS handles time values. In 32-bit Un*xy things, including Mac OS X, time_t is a signed 32-bit integer with an epoch starting on Thursday, January 1, 1970. In the classic MacOS, time_t is an unsigned 32-bit integer with an epoch starting on Friday, January 1, 1904. (This is also true for timestamps in HFS+ filesystems, even in Mac OS X and modern macOS, but not APFS.) Lynx has a utility function that can convert a ASCII date string into a seconds-past-the-epoch count, but in case you haven't guessed, this function defaults to the Unix epoch. In fact, the version previously in MacLynx only supports the Unix epoch. That means when converted into seconds after the epoch, the cookie expiration value would always appear to be in the past compared to the MacOS time value which, being based on a much earlier epoch, will always be much larger — and thus MacLynx would conclude the cookie was actually expired and politely clear it. I reimplemented this function based on the MacOS epoch, and now login cookies actually let you log in! Unfortunately other cookies like trackers can be set too, and this is why we can't have nice things. Sorry. At least they don't persist between runs of the browser. Even then, though, there's still some additional time fudging because time(NULL) on my Quadra 800 running 8.1 and time(NULL) on my G4 MDD running 9.2.2, despite their clocks being synchronized to the same NTP source down to the second, yielded substantially different values. Both of these calls should go to the operating system and use the standard Mac epoch, and not through GUSI, so GUSI can't be why. For the time being I use a second fudge factor if we get an outlandish result before giving up. I'm still trying to figure out why this is necessary. ogle). This didn't work for PNG images before because it was using the wrong internal MIME type, which is now fixed. (Ignore the MIME types in the debug window because that's actually a problem I noticed with my Internet Config settings, not MacLynx. Fortunately Picture Viewer will content-sniff, so it figures it out.) Finally, there is also miscellaneous better status code and redirect handling (again not a problem with mainline Lynx, just our older fork here), which makes login and browsing sites more streamlined, and you can finally press Shift-Tab to cycle backwards through forms and links. If you want to build MacLynx from source, building beta 6 is largely the same on 68K with the same compiler and prerequisites except that builds are now segregated to their own folders and you will need to put a copy of lynx.cfg in with them (the StuffIt source archive does not have aliases predone for you). For the PowerPC version, you'll need the same set up but substituting CodeWarrior Pro 7.1, and, like CWGUSI, GUSI 2.2.3 should be in the same folder or volume that contains the MacLynx source tree. There are debug and optimized builds for each architecture. Pre-built binaries and source are available from the main MacLynx page. MacLynx, like Lynx, is released under the GNU General Public License v2.
Everyone should pull one great practical joke in their lifetimes. This one was mine, and I think it's past the statute of limitations. The story is true. Only the names are redacted to protect the guilty. My first job out of college was a database programmer, even though my undergraduate degree had nothing to do with computers and my current profession still mostly doesn't. The reason was that the University I worked for couldn't afford competitive wages, but they did offer various fringe benefits, and they were willing to train someone who at least had decent working knowledge. I, as a newly minted graduate of the august University of California system, had decent working knowledge at least of BSD/386 and SunOS, but more importantly also had the glowing recommendation of my predecessor who was being promoted into a new position. I was hired, which was their first mistake. The system I was hired to work on was an HP 9000 K250, one of Hewlett-Packard's big PA-RISC servers. I wish I had a photograph of it, but all I have are a couple bad scans of some bad Polaroids of my office and none of the server room. The server room was downstairs from my office back in the days when server rooms were on-premises, complete with a swipe card lock and a halon system that would give you a few seconds of grace before it flooded everything. The K250 hulked in there where it had recently replaced what I think was an Encore mini of some sort (probably a Multimax, since it was a few years old and the 88K Encores would have been too new for the University), along with the AIX RS/6000s that provided student and faculty shell accounts and E-mail, the bonded T1 lines, some of the terminal servers, the massive Cabletron routers and a lot of the telco stuff. One of the tape reels from the Encore hangs on my wall today as a memento. The K250 and the Encore it replaced (as well as the L-Class that later replaced the K250 when I was a consultant) ran an all-singing, all-dancing student information system called CARS. CARS is still around, renamed Jenzabar, though I suspect that many of its underpinnings remain if you look under the table. In those days CARS was a massive overlay that was loaded atop the operating system and database, which when I started were, respectively, HP/UX 10.20 and Informix. (I'm old.) It used Informix tables, screens and stored procedures plus its own text UI libraries to run code written variously as Perform screens, SQL, C-shell scripts and plain old C or ESQL/C. Everything was tracked in RCS using overgrown Makefiles. I had the admin side (resource management, financials, attendance trackers, etc.) and my office partner had the academic side (mostly grades and faculty tracking). My job was to write and maintain this code and shortly after to help the University create custom applications in CARS' brand-spanking new web module, which chose the new hotness in scripting languages, i.e., Perl. Fortuitously I had learned Perl in, appropriately enough, a computational linguistics course. CARS also managed most of the printers on campus except for the few that the RS/6000s controlled directly. Most of the campus admin printers were HP LaserJet 4 units of some derivation equipped with JetDirect cards for networking. These are great warhorse printers, some of the best laser printers HP ever made. I suspect there were line printers other places, but those printers were largely what existed in the University's offices. It turns out that the READY message these printers show on their VFD panels is changeable. I don't remember where I read this, probably idly paging through the manual over a lunch break, but initially the only fun things I could think of to do was to have the printer say hi to my boss when she sent jobs to it, stuff like that (whereupon she would tell me to get back to work). Then it dawned on me: because I had access to the printer spools on the K250, and the spool directories were conveniently named the same as their hostnames, I knew where each and every networked LaserJet on campus was. I was young, rash and motivated. This was a hack I just couldn't resist. It would be even better than what had been my favourite joke at my alma mater, where campus services, notable for posting various service suspension notices, posted one April Fools' Day that gravity itself would be suspended to various buildings. I felt sure this hack would eclipse that too. The plan on April Fools' Day was to get into work at OMG early o'clock and iterate over every entry in the spool, sending it a sequence that would change the READY message to INSERT 5 CENTS. This would cause every networked LaserJet on campus to appear to ask for a nickel before you printed anything. The script was very simple (this is the actual script, I saved it): The ^[ was a literal ASCII 27 ESCape character, and netto was a simple netcat-like script I had written in these days before netcat was widely used. That's it. Now, let me be clear: the printer was still ready! The effect was merely cosmetic! It would still print if you sent jobs to it! Nevertheless, to complete the effect, this message was sent out on the campus-wide administration mailing list (which I also saved): At the end of the day I would reset everything back to READY, smile smugly, and continue with my menial existence. That was the plan. Having sent this out, I fielded a few anxious calls, who laughed uproariously when they realized, and I reset their printers manually afterwards. The people who knew me, knew I was a practical joker, took note of the date, and sent approving replies. One of the best was sent to me later in the day by intercampus mail, printed on their laser printer, with a nickel taped to it. Unfortunately, not everybody on campus knew me, and those who did not not only did not call me, but instead called university administration directly. By 8:30am it was chaos in the main office and this filtered up to the head of HR, who most definitely did know me, and told me I'd better send a retraction before the CFO got in or I was in big trouble. That went wrong also, because my retraction said that campus administration was not considering charging per-page fees when in fact they actually were, so I had to retract it and send a new retraction that didn't call attention to that fact. I also ran the script to reset everything early. Eventually the hubbub finally settled down around noon. Everybody in the office thought it was very funny. Even my boss, who officially disapproved, thought it was somewhat funny. The other thing that went wrong, as if all that weren't enough, was that the director of IT — which is to say, my boss's boss — was away on vacation when all this took place. (Read E-mail remotely? Who does that?) I compounded this situation with the tactical error of going skiing over the coming weekend and part of the next week, most of which I spent snowplowing down the bunny slopes face first, so that he discovered all the angry E-mail in his box without me around to explain myself. (My office partner remembers him coming in wide-eyed asking, "what did he do??") When I returned, it was icier in the office than it had been on the mountain. The assistant director, who thought it was funny, was in trouble for not putting a lid on it, and I was in really big trouble for doing it in the first place. I was appropriately contrite and made various apologies and was an uncharacteristically model employee for an unnaturally long period of time. The Ice Age eventually thawed and the incident was officially dropped except for a "poor judgment" on my next performance review and the satisfaction of what was then considered the best practical joke ever pulled on campus. Indeed, everyone agreed it was much more technically accomplished than the previous award winner, where someone had supposedly gotten it around the grounds that the security guards at the entrance would be charging a nominal admission fee per head. Years later they still said it was legendary. I like to think they still do.
Rockwell famously used 6502-based cores in modems for many years, but that doesn't mean other 6502s couldn't be used. If only there were a way to connect a Commodore 64's audio output directly to an RJ-11 plug ... Convergent WorkSlate stuff I've got to catalogue. Officially the WorkSlate's only means of telecommunications is its 300 baud internal modem. While we have a 9600bps way of wiring up a Workslate to a modern computer, it's always nice to have a simpler alternative, and I figured this would be a great challenge to see if John's old program could let my Commodore SX-64 talk to my WorkSlate. Spoiler alert: it works! I don't know precisely what happened to John; regrettably I know little of his personal history. For a period of time he was a very prolific poster on comp.sys.cbm, but his last post there was July 19, 2000, in which he replied to someone's question about the relationship between sound frequencies and SID register values. (We'll actually talk about this in a bit.) His last post I can find in any Commodore newsgroup of the era is dated the next day, July 20, though he posted through CompuServe and it's possible may have made later posts there. Among his many contributions, including this one, are the Spyne self-extracting file archive utility, a .d64 downloader patch for Common Sense, an in-place PETSCII to ASCII text file converter, a user port-based audio A/D converter and player, and a custom track-by-track floppy disk formatting tool. He issued them all freely for anyone to use for any purpose. While he and I briefly corresponded over snail mail, I can't find the letter he sent me and I don't remember his exact location, and I never heard from him again. Sadly, although I hope I'm wrong, from his handwriting I knew he wasn't a young man and I'm all but certain he has since passed away. Rootsweb lists a John J. Iannetta who died in April 2001 at the age of 82. (If you know for sure, post in the comments, or E-mail me privately at ckaiser at floodgap dawt com.) The "35-cent modem" was first posted on October 27, 1998. John estimated the 35 cent cost based on the then-purchase price of an RCA jack ("listed in my Jameco catalog at 35 cents each"), though this didn't include the phone cable, or about 68 cents in 2025 dollars. Looking in their online catalogue now, you could even go cheaper, since Jameco (not affiliated, not sponsored, just using for comparison) now sells a through-hole right-angle RCA jack for $0.29 — in 1998 dollars, that would have been a mere 15 cents. If you don't have a landline phone cable anymore, the lowest Jameco price for a compatible connector I could find was a 6P6C modular cable for $1.49. Such a cable is technically a RJ-25, but it or an RJ-14 (6P4C) will do just fine. This project is a very easy build job, so let's do it. how T1 lines work. On old exchanges like this one (used in rural New South Wales, Australia), phone lines were carried by literal tip-and-ring connectors plugged into the switchboard to connect calls, which is where the name comes from. Telco guys call a combination of tip and ring a "pair." Each phone line uses one pair. Although it likely makes little difference for this application, there is a polarity to the connection which should be observed, i.e., tip is positive and ring is negative. The cable I used is a real USOC RJ-11C with a 6P2C connector and thus has only two wires for a single pair. The tip wire for this first pair on typical North American RJ-11 installations can be green, or white with a blue stripe (in other countries it may be any number of other colours); the ring wire can be red, blue, or blue with a white stripe. Thus, after stripping back the wires — sometimes easier said than done on a sticky old cable — connect ring to the phono jack's ground/sheath and tip to the phono jack's centre. Make it pretty and you're done. An important warning before we continue: from the telephone company side the line pair carries voltage used to power the phone and ringer, so never plug this cable into a wall jack — doing so could potentially send up to 48 volts to the computer, with likely undesirable and even fiery results. A cable like this should only ever be directly connected to another modem. The software part has to do with how data from the Commodore 64 is modulated to send to the other system's modem. For that, we turn to John's program, as he posted it (in separate versions for NTSC and PAL Commodores for reasons I'll explain as we analyse the disassembly). It was presented as a type-in program in BASIC, short enough to type in by hand, with an embedded machine language section loaded from DATA statements. Here's a couple videos showing what it looked like in practice. The modulated audio is played through the speaker, so don't have it up too high. so the KIM-1 could speak through a DECtalk, that the transmission of a byte or character of data is divided into more or less distinct phases. The default state is mark (one). At the beginning of transmission comes a start bit (always space, or zero), followed by the data (seven or eight bits). After the data comes an optional parity bit, then back to the stop bit for at least one and sometimes two or more bit times. The most common transmission type is 8N1, which is eight data bits, no parity bit, and one stop bit (i.e., characters must be separated by no less than one stop bit, though it can be more). Praat, we see a sine wave of varying wavelength. In the spectrogram at the bottom we can pick out two distinct frequencies being used to encode a character, as shown on the dark black band. This is the hallmark of audio frequency-shift keying (AFSK), or often just called FSK. For this spectrogram I've typed the letter "U" which in binary is 01010101. That's the "wiggle" in the middle. John's program sends 8-N-1, so since we know the byte is framed by stop bits, which are marks/ones, we can deduce the initial frequency is used to transmit a one. Serial communications send the bits in little endian order, i.e., from least significant to most significant, meaning the wiggle is actually the start bit (space/zero), followed by 10, 10, 10, 10, then a stop bit (mark/one) and finally the normal mark state between bytes, which in this plot is indistinguishable from the stop bit. Dr. Strangelove. It remained in operation well into the 1980s; even as just a giant coincidence there are many suspicious similarities between the concept and WarGames' WOPR. The 101 ran at 110 baud over regular telephone lines and became available for commercial sale in 1959. On the wire it uses separate sets of frequencies for each side of the conversation: 1070Hz and 1270Hz (space, mark) for the modem originating the call, and 2025Hz and 2225Hz (space, mark) for the modem answering the call. In 1962 AT&T introduced the Bell 103, which used the same frequencies but ran over twice as fast at 300 baud. It quickly became very popular and almost completely replaced the 101 in commercial use. Even after the 1976 Bell 202 introduced 1200 baud operation (with different frequencies and duplex modes), it remained compatible with the 103 in 300 baud mode, and virtually every third-party 300 baud modem was compatible as well (many were also compatible with ITU-T V.21, which uses the same basic communication scheme but different frequency sets). The Originate-Answer switch on 300 baud modems like the Commodore 1600 VICMODEM and Commodore 1660 "Modem/300" selects which two frequencies the modem will send bits with, using the other two frequencies for receiving. Since any 300bps modem can speak Bell 103, that's why John chose it, and since we're "responding" to the other side that "initiated" the "call" this code uses answerer frequencies. The software came in both NTSC and PAL versions because obviously something like this is highly timing-dependent, and PAL Commodore 64s run slightly slower (0.985250MHz) than NTSC systems (1.022730MHz). The variance is because each video standard uses a different master crystal from which all other clocks are obtained by dividing down, including the colourburst frequency needed for correct display, and also the clock speed of the CPU. This speed additionally affects the 6581 SID sound chip, since each of its three oscillators are incremented by the given audio value (0-65535) every clock cycle, so we need different values for the mark and space frequencies on PAL and NTSC systems. John's last known post in comp.sys.cbm, using slightly different processor speeds, explains the math (shown as written): Using this relationship, we can then solve for "word" to get the proper value for the SID frequency register based on the detected video standard. SID's three voices are thus able to generate tones up to ~3848Hz on PAL machines and ~3995Hz on NTSC machines, well in excess of the necessary range. Because SID generates audio asynchronously, we can just tell it to use infinite sustain (to infinitely prolong the note until we gate it off), play the mark frequency, and then leave the note playing while we go do something else, keeping the line open. Since the specification requires a sinusoidal wave, the code uses the SID's triangle waveform which is the closest approximation. The result is, in fact, the very tone you hear at the beginning of the videos. However, there's one other reason we need separate NTSC and PAL versions, and that's because of how John set up the baudrate. Here's how the BASIC loader starts (from the NTSC version): After reading the hex-encoded DATA statements into memory, at line 110 John's code starts initializing both the SID and the two CIA chips, though he primarily uses CIA #2. To determine bit times, rather than having the CPU manually count off a specific number of clock cycles, this code has the CIA do it. A critical point is that while the CIA chips can be set to issue IRQs or not, their interrupt control registers will still indicate when they would have fired one, even if that individual interrupt condition is technically disabled. John turns off all interrupts on both CIAs so they won't fire and upset system timing, including the usual Timer A IRQ on CIA #1 used for keyscan, then sets Timer A on CIA #2 to repeatedly count down $0d50 (3408) clock cycles. If we divide 1022730 by 3408, we get ... 300.09, almost exactly our baud rate. (It's okay to be a bit faster as long as you're never slower.) A smaller value is used for PAL systems. With the CIAs (and audio) set up, we then go into the mini-terminal, which is loaded into memory and started from the usual location for such routines at 49152 ($c000). We disassemble that next. John chose to call direct into the Kernal for these routines to short-circuit code he didn't need. With thousands of cycles available to send each single bit, the full-fat routines would have been fine, but why bother with work you don't need to do? After initializing the screen editor, the code waits for the next Timer A interval to fire and scans the keyboard manually (since the IRQ isn't running anymore), then fetches the next key, if there is one. Assuming it's not F1 (send a file) or F7 (quit the terminal), the code then goes on to send a character using this subroutine at $c027: Each access on the interrupt control register clears any conditions that were set. This apparent "double-wait" on entering the routine isn't an error: it ensures not only that everything's in a known state, but that also at least one stop bit's interval has elapsed between the prior character and this one. Once that has occurred, we clock out the start bit, then eight data bits least significant first, and finally leave back at the stop bit frequency. Each time, except for the very end, we wait for another trigger on CIA #2's ICR before we proceed. When F1 or F7 is pressed, the mini-terminal sets location $2 to non-zero or zero respectively (above, after the call at $c00f) and returns to BASIC. BASIC then turns back on the Timer A IRQ on CIA #1, and if $2 is non-zero, it proceeds to ask for a device number and filename. This is a fun routine on its own, but you've seen enough of the code to understand the basics of how it works, so let's get out the WorkSlate now and try it with a real device. For the Commodore side, we're going to use one of my portable SX-64 systems. A warning about the SX-64 specifically: never plug in a video cable — more specifically, never connect the audio output — with the computer's power on. Doing so runs you a decent chance of frying the SID, something I actually did many years ago and is a well-known problem. This goes likewise for connecting our mutant phone cable to the SX-64, since we necessarily have to use the computer's video port for the audio signal. The WorkSlate has a built-in terminal desk accessory which can be activated from the Phone menu and selecting Terminal. However, simply selecting the Terminal is not enough. The trick with the WorkSlate is to have the speakerphone line open (Phone, SpkPhone) first, and then try to answer with the Terminal. This is supported by the device; it assumes in this case that you've manually dialed a number somehow (say, from an attached phone handset) and the computer on the other end has answered. We already have the answer stop bit tone playing, so the WorkSlate's modem immediately hears it and tries to go on-line. ATX1D sets up a "blind dial" so that the 64's answer signal is also immediately recognized. The interesting part is comparing how the speakerphone operated between the three WorkSlates I now have. On the most recent one I acquired and on my "tester" unit that I soldered jumper probes to (both with serial numbers starting with CCA8415), I could hear the "call" and what the SX-64 was sending when the WorkSlate was in speakerphone mode, as expected. However, on my regular unit (a later machine with a CCA8417 serial number), I could hear both ends of the conversation through the SX-64's speaker, including the Workslate's dial tones and originate frequencies — and nothing on the WorkSlate's speaker. I'm not sure if this is due to different internal wiring, changes in the tape gate array or both. Again, this is a good reminder that the SID in the SX-64 is unusually vulnerable to stray voltages: if there were proper isolation I shouldn't have been able to hear incoming audio through the speaker output. In fairness, Commodore probably didn't think people would be wiring phone lines to SID audio either. But let's embroider the situation a little more. Some modems may listen for a dial tone first before they attempt to do anything, especially if you need to actually dial a phony (narf narf narf) telephone number, since they reasonably expect there's a real POTS "plain old telephone service" line on the other side. computer did. Programs like Common Sense could be provided a phone number and dial it by playing tones like music. (Interestingly, the VIC-20 does not seem to be capable of precise enough frequency control to generate DTMF; Commodore even warns against it in the Modem/300 manual.) Dialtones and other call-progress tones are often multi-frequency tones similar to DTMF, but they're specified separately by each region's telephone system. In the North American Bell System's Precise Tone Plan, dialtone is a combination of 350Hz and 440Hz at -13dBm, also played using a sine wave. If we use the formulas above and solve for the SID register values using those frequencies, these statements in BASIC will make a sufficient approximation of a dialtone on SID voices 1 and 2 (NTSC): smaller system, so let's make it a little friendlier. I removed the BASIC portion and wrote up a new menu system in pure assembly, incorporating and converting John's original code, and merging the PAL and NTSC versions together. It LOADs and RUNs like a BASIC program but is fully machine language. Ward Christensen, uses a fixed 128 data bytes per block and a simple checksum with known deficiencies, so John opted for the more complex version with a cyclic redundancy check to ensure errors could be promptly detected. Most terminal programs support this mode. We previously encountered a variant of Xmodem-CRC when we were figuring out how The Newsroom's Wire Service operated. From that article, the CRC-16-CCITT used in Xmodem-CRC is transmitted using this algorithm, rendered in K&R C: = 0) { crc = crc ^ (int)*ptr++ << 8; for (i = 0; i < 8; ++i) if (crc & 0x8000) crc = crc << 1 ^ 0x1021; else crc = crc << 1; } return (crc & 0xFFFF); } lda #$01 sta $96 ; number of current packet ; start sending the current Xmodem packet lc08a lda #$00 sta $02 lda #$01 jsr lc027 ; send Xmodem SOH $01 lda $96 jsr lc027 ; send packet number eor #$ff jsr lc027 ; send inverse of packet number ldy #$03 jsr $ffa5 ; Kernal acptr, read next byte from file sta $8b ; store in high byte of CRC jsr lc027 ; transmit it inc $02 ldx $90 ; EOF? beq lc0b3 lc0ad lda #$1a ; yes, handle final packet, store a ^Z sta $8c bne lc115 lc0b3 jsr $ffa5 ; read again sta $8c ; store in low byte of CRC jsr lc027 ; transmit again ldx $90 bne lc115 ; check EOF again lc0bf inc $02 big-endian, unlike the usual 6502 little-endian convention, and exploits the fact that most transmitted blocks will have at least two data bytes. The routine starts each block by clearing the count, then with the modulation routine at $c027 above it sends the standard Xmodem start-of-header (^A) character, the packet number and inverse of packet number, then (checking for EOF each time) reads two characters into the high byte and low byte of the running CRC-16 and transmits them. If the status word at $90 shows an EOF, this condition remains until the file is closed. For each byte after that to complete the block, another one is read and stored into $8d, then shifted into $8b and $8c: When a high bit is rolled out of the rolling CRC-16, this is detected as carry being set (no need for a bitmask) and the rolling CRC-16 bytes are exclusive-ORed with the required polynomial value ($1021, 4129). This is a very efficient translation of the algorithm. The code then continues to run to complete the block of 128 bytes. After the last byte is read from the file and shifted in, we need to incorporate three zero bytes into the CRC-16 to represent the header we sent. We then send that value and "wait" to pretend it worked, then go back for the next block. The weird delay routine allowed John to fit the entire loop into the maximum 7-bit displacement of a relative branch instruction. In fact, when I added code to flash the border on each block, I had to insert an absolute jump instead since those three extra bytes upset the apple cart. At the very end of the file, any block in progress is padded with EOT (^Z), and then Xmodem EOF (^D) is sent to terminate the transmission: Note that the branch at $c11b will always be taken since we just loaded a non-zero immediate into the accumulator. Again, another nice way of increasing code density and reducing type-in size. Should the file have ended in the first two bytes used to prime the CRC-16, John's code just stuffs ^Zs into it manually. John's original post containing the type-in versions (you can cut and paste these into VICE, if you like), plus the assembly source for this unified version and a pre-built binary, on Github. As John never asserted copyright to his programs and explicitly intended them to be freely distributable so that others could use and learn from them, I've placed this version into the public domain (to the extent available in your jurisdiction). You can assemble it using xa65. John was a good guy with a clever programming style and it was nice to see his code running again (and working, though that was a given). Plus, this is a great use for a Commodore to support your other systems, and a roadmap for doing something similar on other machines with sufficiently capable sound hardware. In future articles I think we'll explore a few other things he wrote, including that audio digitizer. I think he would have enjoyed it.
Ask any Atari Stacy owner how to open an Atari Stacy and the answer is always "never, if you can avoid it." So I'll just lead with this spoiler image after the refurb to prove this particular escapade didn't completely end in tragedy: see the much lighter and streamlined STBook in the flesh, let alone own one. If you really want a portable all-in-one Atari ST system, the Stacy is likely the best you're gonna do. And we're going to make it worse, because this is the lowest-binned Stacy with the base 1MB of memory. I want to put the full 4MB the hardware supports in it to expand its operating system choices. It turns out that's much harder to do than I ever expected, making repairing its bad left mouse button while we're in there almost incidental — let's just say the process eventually involved cutting sheet metal. I'm not entirely happy with the end result but it's got 4MB, it's back together and it boots. Grit your teeth while we do a post-mortem on this really rough Refurb Weekend. it lacks a blitter, but does have an expansion slot electrically compatible with the Mega), it sports a backlit monochrome LCD, keyboard, trackball in lieu of the standard ST mouse, and a full assortment of ST ports including built-in MIDI. A floppy drive came standard; a second floppy or a 20 or 40MB internal SCSI hard disk was optional. This was Jack Tramiel-era Atari and the promises of a portable ST system were nearly as old as the ST itself. For a couple years those promises largely came to naught until Atari management noticed how popular the on-board MIDI was with musicians and music studios, who started to make requests for a transportable system that could be used on the road. These requests became voluminous enough for Tramiel's son and Atari president Sam Tramiel to greenlight work on a portable ST. In late 1988 Atari demonstrated a foam mockup of a concept design by Ira Velinsky to a small group of insiders and journalists, where it was well-received. By keeping its internals and chipset roughly the same as shipping ST machines, the concept design was able to quickly grow into a functional prototype for Atari World and COMDEX in March 1989. Atari announced the baseline 1MB Stacy with floppy disk would start at $1495 (about $3800 in 2024 dollars), once again beating its other 68000-based competitors to the punch as Apple hadn't themselves made a portable Macintosh yet, and Commodore never delivered a portable Amiga. Sam Tramiel was buoyed by the response, saying people went "crazy" for the Stacy prototype, and vowed that up to 35,000 a month could be made to sate demand. any configuration. FCC Part 15 certification for the hard disk-equipped 2MB Stacy2 and 4MB Stacy4 was delayed until December 1989 and at first only as Class A, officially limiting it to commercial use, while the lowest-end 1MB floppy-only Stacy didn't obtain clearance until the following year. We'll see at least one internal consequence of this shortly (I did mention sheet metal). The delays also stalled out the system's introduction in Europe and despite Tramiel's avowed industrial capacity relatively few Stacys were ultimately sold. Based on extant serial numbers, the total number is likely no more than a few thousand before Atari cancelled it in 1991, though that's greater than the successor ST Book which probably existed in just a thousand or so units tops. The Stacy's failure to meet its technical goals (particularly with respect to size and power use) was what likely led to the ST Book's development. Unfortunately, although a significant improvement on the Stacy, the ST's decline in the market made sustaining the ST Book infeasible for Atari, and it was cancelled along with the entirety of Atari's personal computer line in 1993. third party upgrade provided an installable internal battery option which could last up to two hours. ACSI ("Atari Computer Systems Interface") predates SCSI-1's standardization in 1986 but is still quite similar, using a smaller 19-pin port, a related but incompatible protocol, and a fixed bus relationship where the computer is always in control. It is nevertheless enough like SCSI that many SCSI devices can be interfaced to it — we'll come back to this too. The rear ports should be covered by a door, but it's missing from this system. is present that the expansion slot never got used by its prior owner(s), and I don't have anything to connect to it either. carefully through their hole in the bottom case so you can lift up the top case completely. peripherals for the Convergent WorkSlate (the WorkSlate itself uses a Hitachi 6303). This serves as the keyboard, mouse/trackball and joystick controller with its own 4K internal ROM and 128 bytes of internal RAM. Counting the RAM, though, we don't have 4MB on this side. Where's the rest of it? other side, covered by tape. Why is it taped? So it doesn't short against anything! Remember, this is exactly how Atari shipped it! The keyboard connector is here as well. This board is quite critical. Without it, the system has no RAM, no ROM and, almost trivially by comparison, no keyboard, trackball, mouse or joysticks. If it's not connected firmly, you'll get a blank screen. requiring desoldering of the 68HC000. This would have been a rather complex upgrade to install. not. What's depicted here is in fact a consolidation of multiple false starts and a whole lot of screaming. The first part was to put the metal shield back on and bend the tabs back to hold it in position. While doing so, be careful with the display wires to get them back into their little canal because they can literally short and spark. I don't know how this is possible but they do! You can also get the display cabling messed up enough that the Stacy will continuously beep at you when you turn it on. The only good way I found to avoid this was to pull as much play in the display wiring into the top case as possible so that the wires don't bunch up in the bottom case. also affect its connection with the logic board. The middle one seems to be the most involved. All of this suggests Atari never meant a 1MB Stacy to be upgraded with this particular card. Hall SC-VGA-2 scan converter to turn the ST's 71.2Hz high resolution display into the 60Hz my VGA box can capture. This stack doesn't get a pixel-perfect grab but the budget isn't there for the super duper OSSC right now, so you'll just have to deal. HDDRIVER that was already on the SD card. extensible control panel, much like Macs use CDEVs, uses CPXes (Control Panel Extensions). Show System. This was what I was using to display the memory configuration before. And, now adjusted, we still have 4MB of memory to my great relief with the computer back in one uneasy piece. I'm not 100% happy with the end result but the trackball button works better and our memory has quadrupled, at least when Stacy is in a good mood. Like I say, I can only conclude that the 1MB Stacy was never meant to be upgraded in this fashion. One of the third-party RAM cards might have worked, but I have no idea where I can find one. Regardless, based on the amount of apoplexy and late-night screaming that Stacy caused over the past couple months' weekends, my wife has told me in no uncertain terms that if I'm ever going to crack this laptop open again, I need to have a good long talk with her about it first. I've decided I'm okay with that.
More in technology
China-based purveyors of SMS phishing kits are enjoying remarkable success converting phished payment card data into mobile wallets from Apple and Google. Until recently, the so-called “Smishing Triad” mainly impersonated toll road operators and shipping companies. But experts say these groups are now directly targeting customers of international financial institutions, while dramatically expanding their cybercrime infrastructure and support staff.
My friend and podcast co-host Chris Lawley just posted a video about how his relationship with the iPad has changed over time. I linked to this on social media and got a few replies from folks who said something to the effect of, "we told you so," which
Modern civilization relies on electric power for almost everything, and even small disruptions to electric service are incredibly disruptive.
Another day, another little app on Quick Stuff: Markdown Converter. This one also solves a personal need I have, which is that I write the show notes for my podcast in Markdown, but I need to put them in my podcast host as HTML and my co-host Chris needs them
Woodwinds and brass are so 19th century. We’re living in the future and now it is synthesizers all the way down. There are many to choose from and the Bleep Labs Nebulophone is a neat example that was sold from 2012 to 2016, with the design files now available on GitHub for DIYers. Marcus Dunn […] The post Solar upgrades the Nebulophone synthesizer to enhance playability appeared first on Arduino Blog.