<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="3.9.0">Jekyll</generator><link href="https://dialup.world/blog/feed.xml" rel="self" type="application/atom+xml" /><link href="https://dialup.world/blog/" rel="alternate" type="text/html" /><updated>2026-03-18T02:38:30+00:00</updated><id>https://dialup.world/blog/feed.xml</id><title type="html">dialup.world/blog</title><subtitle>modem stuff and things</subtitle><entry><title type="html">Reviving the AT&amp;amp;T Sceptre</title><link href="https://dialup.world/blog/att-sceptre-revival.html" rel="alternate" type="text/html" title="Reviving the AT&amp;amp;T Sceptre" /><published>2025-07-25T00:00:00+00:00</published><updated>2025-07-25T00:00:00+00:00</updated><id>https://dialup.world/blog/att-sceptre-revival</id><content type="html" xml:base="https://dialup.world/blog/att-sceptre-revival.html">&lt;p&gt;I don’t know when I first became aware of the AT&amp;amp;T Sceptre. It was several years ago; I think someone posted a photo of one somewhere and I became instantly mesmerized by the weird little beige box. I always liked the design language of the basic set-top-box with black bezel and an iconic “AT&amp;amp;T” logo. It reminded me of AT&amp;amp;T’s much older Dataphone line of modems (the Dataphone II, or Dataphone 300 specifically, and apparently the Sceptre shares some of the same DNA with the older models), but in larger footprint and a touch more approachability. This is something that could sit in the family room, not just the home office.&lt;/p&gt;

&lt;figure style=&quot;text-align: center; margin: 0;&quot;&gt;
  &lt;a href=&quot;/blog/assets/images/2025-07-25-att-sceptre-revival/sceptre-01.jpeg&quot;&gt;
    &lt;img style=&quot;display: block; margin: 0 auto; border 0;&quot; src=&quot;/blog/assets/images/2025-07-25-att-sceptre-revival/sceptre-01-sm-d.png&quot; loading=&quot;lazy&quot; alt=&quot;An AT&amp;amp;T Sceptre posing with Comdial 3500S phone.&quot; onmouseover=&quot;this.src=&apos;./assets/images/2025-07-25-att-sceptre-revival/sceptre-01-sm.jpg&apos;;&quot; onmouseout=&quot;this.src=&apos;./assets/images/2025-07-25-att-sceptre-revival/sceptre-01-sm-d.png&apos;;&quot; /&gt;
  &lt;/a&gt;
  &lt;figcaption&gt;An AT&amp;amp;T Sceptre posing with Comdial 3500S phone.&lt;/figcaption&gt;
 &lt;/figure&gt;

&lt;p&gt;At the time, all I really knew about it was that it was some device that you’d connect to a television set. “WebTV but in the ’80s” was how I had seen it described, and looking back this is a pretty appropriate description.&lt;/p&gt;

&lt;p&gt;I had an eBay saved-search set for years trying to get one, but the few that were listed always sold for too high of a price. I never really understood why, or who was buying them. The original services were long offline and from some minimal searching there wasn’t any project of hobbyists building a new one. Maybe the people purchasing them were enamored just as I was, and wanted one simply to look at or a fill a hole in some weird telephone ephemera collection.&lt;/p&gt;

&lt;p&gt;Eventually the planets aligned and I was able to get one for about $100. Of course, I needed to learn more about it and made myself a promise that it wouldn’t sit on a shelf. If I got it, it would need to do &lt;em&gt;something&lt;/em&gt;, even if that was just some proof-of-concept project.&lt;/p&gt;

&lt;h2 id=&quot;some-history&quot;&gt;Some History&lt;/h2&gt;

&lt;p&gt;The Sceptre was a graphical “videotex” (interactive content displayed on a video monitor) terminal, a piece of expensive, long-shot technology birthed from a collaboration between AT&amp;amp;T and several news outlets as a way of getting more information into more people’s households. This was the World Wide Web a decade before the World Wide Web would be born. And as you may guess, there are reasons why you likely haven’t heard of it.&lt;/p&gt;

&lt;p&gt;This wasn’t created on a whim. In 1978 the Canadian Communications Research Center (CRC) launched &lt;a href=&quot;https://en.wikipedia.org/wiki/Telidon&quot;&gt;Telidon&lt;/a&gt;, an interactive videotex platform featuring 2D color graphics. Compared to text-based systems of the time, Telidon was groundbreaking and quickly became a standout in computer technology, allowing users to interact with services like news, banking, travel booking, and more from the comfort of their own homes.&lt;/p&gt;

&lt;p&gt;AT&amp;amp;T followed suit in 1983, partnering with 16 other organizations to turn Telidon into the &lt;a href=&quot;https://en.wikipedia.org/wiki/NAPLPS&quot;&gt;NAPLPS&lt;/a&gt; (North American Presentation Layer Protocol Syntax) standard that could be adopted by terminal manufacturers and content service providers alike. In the US, the Sceptre would be used in at least 4 different services:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Knight Ridder’s &lt;a href=&quot;https://en.wikipedia.org/wiki/Viewtron&quot;&gt;Viewtron&lt;/a&gt; service in Florida (a joint venture with AT&amp;amp;T)&lt;/li&gt;
  &lt;li&gt;The Los Angeles Times’ Gateway service in Southern California (a joint venture of Times Mirror and InfoMart of Canada)&lt;/li&gt;
  &lt;li&gt;Covidea in New York (a joint venture by AT&amp;amp;T and Chemical Bank, with Time Inc. and Bank of America)&lt;/li&gt;
  &lt;li&gt;Aviotex’s TABS service in California&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Aside from those, Keyfax was operating in Chicago as a joint venture by Field Enterprises and Centel (though they used Honeywell terminals) and another venture ran by AT&amp;amp;T and CBS operated under a trial in Ridgewood, NJ before the two companies parted ways with CBS going on to partner with IBM and Sears to form Trintex which would later turn into the widely-popular &lt;a href=&quot;https://en.wikipedia.org/wiki/Prodigy_(online_service)&quot;&gt;Prodigy&lt;/a&gt; online service.&lt;/p&gt;

&lt;p&gt;Soon though, the bubble would burst. Telidon and Keyfax were discontinued in 1985, Viewtron and Gateway in 1986, and Covidea (and most others) in 1989. While the US systems lacked the government backing that allowed Telidon to thrive as long as it did, the main failures of these systems were the associated operating costs and poor user adoption, again caused by high upfront costs for a terminal and monthly subscription fees. NAPLPS would live on in Prodigy (as previously mentioned), the &lt;a href=&quot;https://en.wikipedia.org/wiki/NABTS&quot;&gt;NABTS&lt;/a&gt; protocol (for one-way, North American teletext), WebTV for Windows, and a few other niche areas, but is mostly forgotten today.&lt;/p&gt;

&lt;h2 id=&quot;technical-specs&quot;&gt;Technical Specs&lt;/h2&gt;

&lt;p&gt;The Sceptre seemingly has a lot of horsepower for a terminal. The basic specs are as follows:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Intel 8088 processor (the same as used in the original IBM PC)&lt;/li&gt;
  &lt;li&gt;127K ROM&lt;/li&gt;
  &lt;li&gt;48K RAM&lt;/li&gt;
  &lt;li&gt;Motorola 6845 display controller&lt;/li&gt;
  &lt;li&gt;16-color display with a palette of 256 colors&lt;/li&gt;
  &lt;li&gt;Full IR wireless keyboard, powered by 9V battery&lt;/li&gt;
  &lt;li&gt;1200/75 baud 7-bit modem&lt;/li&gt;
&lt;/ul&gt;

&lt;figure style=&quot;text-align: center; margin: 0;&quot;&gt;
  &lt;a href=&quot;/blog/assets/images/2025-07-25-att-sceptre-revival/sceptre-02.jpeg&quot;&gt;
    &lt;img style=&quot;display: block; margin: 0 auto; border 0;&quot; src=&quot;/blog/assets/images/2025-07-25-att-sceptre-revival/sceptre-02-sm-d.png&quot; loading=&quot;lazy&quot; alt=&quot;An AT&amp;amp;T Sceptre from the front.&quot; onmouseover=&quot;this.src=&apos;./assets/images/2025-07-25-att-sceptre-revival/sceptre-02-sm.jpg&apos;;&quot; onmouseout=&quot;this.src=&apos;./assets/images/2025-07-25-att-sceptre-revival/sceptre-02-sm-d.png&apos;;&quot; /&gt;
  &lt;/a&gt;
  &lt;figcaption&gt;An AT&amp;amp;T Sceptre from the front.&lt;/figcaption&gt;
 &lt;/figure&gt;

&lt;p&gt;The terminal has a hard-wired power supply, with large external transformer (&lt;a href=&quot;https://github.com/dialup-world/att-sceptre/tree/main/photos/integrated-psu&quot;&gt;there is a later revision with a detachable cord as well&lt;/a&gt;, and it looks like it also has two boards in the same housing to accommodate an integrated power supply!), composite and RF video output, two RJ11 jacks for line and phone, and a DB25 port for printer support (though apparently this only supported very specific models, if at all).&lt;/p&gt;

&lt;figure style=&quot;text-align: center; margin: 0;&quot;&gt;
  &lt;a href=&quot;/blog/assets/images/2025-07-25-att-sceptre-revival/sceptre-03.jpeg&quot;&gt;
    &lt;img style=&quot;display: block; margin: 0 auto; border 0;&quot; src=&quot;/blog/assets/images/2025-07-25-att-sceptre-revival/sceptre-03-sm-d.png&quot; loading=&quot;lazy&quot; alt=&quot;An AT&amp;amp;T Sceptre rear ports.&quot; onmouseover=&quot;this.src=&apos;./assets/images/2025-07-25-att-sceptre-revival/sceptre-03-sm.jpg&apos;;&quot; onmouseout=&quot;this.src=&apos;./assets/images/2025-07-25-att-sceptre-revival/sceptre-03-sm-d.png&apos;;&quot; /&gt;
  &lt;/a&gt;
  &lt;figcaption&gt;An AT&amp;amp;T Sceptre rear ports.&lt;/figcaption&gt;
 &lt;/figure&gt;

&lt;p&gt;The transformer is rated to take an input of 120VAC, 60Hz, 0.41A. The output is 26VAC, 40VA.&lt;/p&gt;

&lt;figure style=&quot;text-align: center; margin: 0;&quot;&gt;
  &lt;a href=&quot;/blog/assets/images/2025-07-25-att-sceptre-revival/sceptre-06.jpeg&quot;&gt;
    &lt;img style=&quot;display: block; margin: 0 auto; border 0;&quot; src=&quot;/blog/assets/images/2025-07-25-att-sceptre-revival/sceptre-06-sm-d.png&quot; loading=&quot;lazy&quot; alt=&quot;An AT&amp;amp;T Sceptre&apos;s transformer.&quot; onmouseover=&quot;this.src=&apos;./assets/images/2025-07-25-att-sceptre-revival/sceptre-06-sm.jpg&apos;;&quot; onmouseout=&quot;this.src=&apos;./assets/images/2025-07-25-att-sceptre-revival/sceptre-06-sm-d.png&apos;;&quot; /&gt;
  &lt;/a&gt;
  &lt;figcaption&gt;An AT&amp;amp;T Sceptre&apos;s transformer.&lt;/figcaption&gt;
 &lt;/figure&gt;

&lt;p&gt;The system is passively cooled and has vents in the plastic housing. Only 4 captive flat-head (very AT&amp;amp;T of them) screws keep the case together.&lt;/p&gt;

&lt;p&gt;My unit has an AT&amp;amp;T sticker stating that this is a modem CS1200B01 control unit with serial number &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;547000989&lt;/code&gt;. There is also a stamp on this sticker reading &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;84321&lt;/code&gt;, possibly a date code meaning the 21st day of the third month of 1984 or the first day of the 32nd week of 1984. There is also a sticker stating that this Sceptre is the properly of Gateway, with a code &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;520864&lt;/code&gt;, likely an asset tag. This is an indicator that this Sceptre was used for the Times Mirror Gateway service.&lt;/p&gt;

&lt;figure style=&quot;text-align: center; margin: 0;&quot;&gt;
  &lt;a href=&quot;/blog/assets/images/2025-07-25-att-sceptre-revival/sceptre-04.jpeg&quot;&gt;
    &lt;img style=&quot;display: block; margin: 0 auto; border 0;&quot; src=&quot;/blog/assets/images/2025-07-25-att-sceptre-revival/sceptre-04-sm-d.png&quot; loading=&quot;lazy&quot; alt=&quot;An AT&amp;amp;T Sceptre&apos;s motherboard.&quot; onmouseover=&quot;this.src=&apos;./assets/images/2025-07-25-att-sceptre-revival/sceptre-04-sm.jpg&apos;;&quot; onmouseout=&quot;this.src=&apos;./assets/images/2025-07-25-att-sceptre-revival/sceptre-04-sm-d.png&apos;;&quot; /&gt;
  &lt;/a&gt;
  &lt;figcaption&gt;An AT&amp;amp;T Sceptre&apos;s motherboard.&lt;/figcaption&gt;
 &lt;/figure&gt;

&lt;p&gt;Inside are a slew of ICs:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;1x UA78S40PC - universal switching regulator subsystem&lt;/li&gt;
  &lt;li&gt;1x LM339N - analog comparator&lt;/li&gt;
  &lt;li&gt;1x SN74LS373N - 8-bit latch&lt;/li&gt;
  &lt;li&gt;1x SN74LS245N - tri-state octal bus transceiver&lt;/li&gt;
  &lt;li&gt;1x 74F139N - decoder/demultiplexer&lt;/li&gt;
  &lt;li&gt;1x SN74LS75N - 4-bit latch&lt;/li&gt;
  &lt;li&gt;1x LM348N - operational amplifier&lt;/li&gt;
  &lt;li&gt;1x 555CN - timer&lt;/li&gt;
  &lt;li&gt;1x WE 882A*2&lt;/li&gt;
  &lt;li&gt;1x AT&amp;amp;T CN83763N&lt;/li&gt;
  &lt;li&gt;1x AT&amp;amp;T CN83764N&lt;/li&gt;
  &lt;li&gt;1x AT&amp;amp;T CN83765N&lt;/li&gt;
  &lt;li&gt;1x AT&amp;amp;T CN83766N&lt;/li&gt;
  &lt;li&gt;1x MC68A45P - character display controller&lt;/li&gt;
  &lt;li&gt;1x P8088-2 - 8088 microprocessor, 8-bit 8MHz&lt;/li&gt;
  &lt;li&gt;1x TMM2364P - 64K mask ROM&lt;/li&gt;
  &lt;li&gt;1x TC5517AP - 8-bit static RAM&lt;/li&gt;
  &lt;li&gt;1x SN74LS08N - 4-channel logic gate&lt;/li&gt;
  &lt;li&gt;1x MC1498P - quad line EIA-232D receiver&lt;/li&gt;
  &lt;li&gt;1x MC1488P - quad line EIA-232D driver&lt;/li&gt;
  &lt;li&gt;1x MC1377P - RGB to PAL/NTSC encoder&lt;/li&gt;
  &lt;li&gt;1x TCM5089N - tone encoder&lt;/li&gt;
  &lt;li&gt;1x WE 408A*1&lt;/li&gt;
  &lt;li&gt;1x WE 416G&lt;/li&gt;
  &lt;li&gt;1x WE 416C&lt;/li&gt;
  &lt;li&gt;2x SN74LS453NS - multiplexer&lt;/li&gt;
  &lt;li&gt;6x TMS4416-15NL - 4-bit static RAM, 50ns&lt;/li&gt;
  &lt;li&gt;1x D8284A - clock driver&lt;/li&gt;
  &lt;li&gt;1x SN74LS74AN - flip flop&lt;/li&gt;
  &lt;li&gt;2x SN74LS04N - 6-channel inverter&lt;/li&gt;
  &lt;li&gt;1x 74F32 - quad 2-input OR gate&lt;/li&gt;
  &lt;li&gt;1x SN74LS139AN - dual 2-line to 4-line decoders/multiplexers&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The Western Electric and AT&amp;amp;T chips have unknown purposes.&lt;/p&gt;

&lt;p&gt;The board also seems to have a rechargeable 3V battery soldered on, which should probably be replaced. Something I always find interesting are the bodges done on the board after manufacturing. There are quite a few here.&lt;/p&gt;

&lt;figure style=&quot;text-align: center; margin: 0;&quot;&gt;
  &lt;a href=&quot;/blog/assets/images/2025-07-25-att-sceptre-revival/sceptre-05.jpeg&quot;&gt;
    &lt;img style=&quot;display: block; margin: 0 auto; border 0;&quot; src=&quot;/blog/assets/images/2025-07-25-att-sceptre-revival/sceptre-05-sm-d.png&quot; loading=&quot;lazy&quot; alt=&quot;An AT&amp;amp;T Sceptre&apos;s transformer.&quot; onmouseover=&quot;this.src=&apos;./assets/images/2025-07-25-att-sceptre-revival/sceptre-05-sm.jpg&apos;;&quot; onmouseout=&quot;this.src=&apos;./assets/images/2025-07-25-att-sceptre-revival/sceptre-05-sm-d.png&apos;;&quot; /&gt;
  &lt;/a&gt;
  &lt;figcaption&gt;An AT&amp;amp;T Sceptre&apos;s transformer.&lt;/figcaption&gt;
 &lt;/figure&gt;

&lt;p&gt;The keyboard is powered by 9-volt battery and communicates with the terminal via infrared. It has 67 keys, utilizing a membrane, including a set of function keys that seem to have an overlay sticker for the service the terminal was to be used for. My keyboard is branded “AT&amp;amp;T Sceptre” though others seem to be branded “&lt;a href=&quot;https://github.com/dialup-world/att-sceptre/tree/main/photos/american-bell-viewtron-keyboard&quot;&gt;American Bell&lt;/a&gt;.”&lt;/p&gt;

&lt;figure style=&quot;text-align: center; margin: 0;&quot;&gt;
  &lt;a href=&quot;/blog/assets/images/2025-07-25-att-sceptre-revival/sceptre-07.jpeg&quot;&gt;
    &lt;img style=&quot;display: block; margin: 0 auto; border 0;&quot; src=&quot;/blog/assets/images/2025-07-25-att-sceptre-revival/sceptre-07-sm-d.png&quot; loading=&quot;lazy&quot; alt=&quot;An AT&amp;amp;T Sceptre&apos;s keyboard.&quot; onmouseover=&quot;this.src=&apos;./assets/images/2025-07-25-att-sceptre-revival/sceptre-07-sm.jpg&apos;;&quot; onmouseout=&quot;this.src=&apos;./assets/images/2025-07-25-att-sceptre-revival/sceptre-07-sm-d.png&apos;;&quot; /&gt;
  &lt;/a&gt;
  &lt;figcaption&gt;An AT&amp;amp;T Sceptre&apos;s keyboard.&lt;/figcaption&gt;
 &lt;/figure&gt;

&lt;p&gt;This keyboard has a Western Electric sticker marking this as a model CS1000A01 keyboard with serial number &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;066007322&lt;/code&gt;. There is a second sticker with the Times Mirror company logo and the number &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;086868&lt;/code&gt;, likely an asset tag. In red ink stamped on the back is the numeric string &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;08084&lt;/code&gt;, likely a manufacturing date code corresponding to something like the eighth week of 1984.&lt;/p&gt;

&lt;figure style=&quot;text-align: center; margin: 0;&quot;&gt;
  &lt;a href=&quot;/blog/assets/images/2025-07-25-att-sceptre-revival/sceptre-08.jpeg&quot;&gt;
    &lt;img style=&quot;display: block; margin: 0 auto; border 0;&quot; src=&quot;/blog/assets/images/2025-07-25-att-sceptre-revival/sceptre-08-sm-d.png&quot; loading=&quot;lazy&quot; alt=&quot;The back of an AT&amp;amp;T Sceptre&apos;s keyboard.&quot; onmouseover=&quot;this.src=&apos;./assets/images/2025-07-25-att-sceptre-revival/sceptre-08-sm.jpg&apos;;&quot; onmouseout=&quot;this.src=&apos;./assets/images/2025-07-25-att-sceptre-revival/sceptre-08-sm-d.png&apos;;&quot; /&gt;
  &lt;/a&gt;
  &lt;figcaption&gt;The back of an AT&amp;amp;T Sceptre&apos;s keyboard.&lt;/figcaption&gt;
 &lt;/figure&gt;

&lt;p&gt;Three Phillips head screws hold the keyboard together. Two screws are visible on the back of the unit while the third is under a pad in the battery compartment.&lt;/p&gt;

&lt;p&gt;The ICs in the keyboard are:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;1x SAA 1250 - infrared remote-control transmitter&lt;/li&gt;
  &lt;li&gt;1x CD4011BE - quad 2-input NAND gate&lt;/li&gt;
&lt;/ul&gt;

&lt;figure style=&quot;text-align: center; margin: 0;&quot;&gt;
  &lt;a href=&quot;/blog/assets/images/2025-07-25-att-sceptre-revival/sceptre-09.jpeg&quot;&gt;
    &lt;img style=&quot;display: block; margin: 0 auto; border 0;&quot; src=&quot;/blog/assets/images/2025-07-25-att-sceptre-revival/sceptre-09-sm-d.png&quot; loading=&quot;lazy&quot; alt=&quot;The PCB in an AT&amp;amp;T Sceptre&apos;s keyboard.&quot; onmouseover=&quot;this.src=&apos;./assets/images/2025-07-25-att-sceptre-revival/sceptre-09-sm.jpg&apos;;&quot; onmouseout=&quot;this.src=&apos;./assets/images/2025-07-25-att-sceptre-revival/sceptre-09-sm-d.png&apos;;&quot; /&gt;
  &lt;/a&gt;
  &lt;figcaption&gt;The PCB in an AT&amp;amp;T Sceptre&apos;s keyboard.&lt;/figcaption&gt;
 &lt;/figure&gt;

&lt;p&gt;All button-press signals, including permutations via the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Shift&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Ctrl&lt;/code&gt; modifier keys were captured via Flipper Zero and are available &lt;a href=&quot;https://github.com/dialup-world/att-sceptre/tree/main/infrared&quot;&gt;here&lt;/a&gt;. With these signals captured, the original keyboard is not needed for operation provided the user has some other way to send these signals.&lt;/p&gt;

&lt;p&gt;A copy of the Sceptre manual (with bonus instructions for connecting to Aviotex) can be found &lt;a href=&quot;https://github.com/dialup-world/att-sceptre/tree/main/manual&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id=&quot;gathering-naplps&quot;&gt;Gathering NAPLPS&lt;/h2&gt;

&lt;p&gt;As previously mentioned, the Sceptre is a NAPLPS-compatible terminal intended for use with a NAPLPS service. From what I have heard, the Sceptre is capable of handing standard ASCII connections over something like Bell 101/103, but I didn’t pursue this route as I wanted to actually display NAPLPS as originally intended.&lt;/p&gt;

&lt;p&gt;NAPLPS is can be thought of in terms of “pages” that are rendered on the screen in real time. The more complex the page, the longer it takes to render. Some artwork can take 10s of minutes to fully load, even in ideal conditions. I haven’t read &lt;a href=&quot;https://archive.org/details/federalinformati121nati&quot;&gt;the NAPLPS specification&lt;/a&gt;, but from my messing around it seems that pages are stored in a binary format consisting of ASCII text and commands to draw the vector imagery that are processed by the terminal. Some features like form input or palette swapping are black boxes to me, but ultimately tangential to my primary goal of simply &lt;em&gt;displaying&lt;/em&gt; NAPLPS.&lt;/p&gt;

&lt;p&gt;I didn’t want to make my own NAPLPS images, as I was initially under the assumption that no tools that could be used to draw it were still available (which I later learned was false after finding &lt;a href=&quot;http://cd.textfiles.com/simtel/simtel20/MSDOS/NAPLPS/.index.html&quot;&gt;a directory on textfiles.com containing Microstar Graphics Editor&lt;/a&gt;) and I certainly didn’t want to roll my own software. Luckily I became aware of the work of &lt;a href=&quot;https://www.durno.ca/&quot;&gt;John Durno&lt;/a&gt;, specifically &lt;a href=&quot;https://remembertomorrow.ca/en-ca/archive&quot;&gt;remembertomorrow.ca&lt;/a&gt;, who has spent over a decade restoring Telidon artwork, preserving its culture, and publishing resources on both NAPLPS and Telidon.&lt;/p&gt;

&lt;p&gt;It cannot be overstated how much of the artwork and knowledge around NAPLPS would be lost if it wasn’t for the efforts spearheaded by John.&lt;/p&gt;

&lt;p&gt;It didn’t really occur to me previously that artists would use NAPLPS as a medium for their work, but I grew to understand how it could be fun to work with and how portable it was. Luckily, a lot of these works live on as &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.nap&lt;/code&gt; files and can be found all over the Internet. A few places I found files includes:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;http://cd.textfiles.com/simtel/simtel20/MSDOS/NAPLPS/.index.html&quot;&gt;http://cd.textfiles.com/simtel/simtel20/MSDOS/NAPLPS/.index.html&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/n1ckfg/Telidon&quot;&gt;https://github.com/n1ckfg/Telidon&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;John Durno’s own &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;boom.nap&lt;/code&gt; via &lt;a href=&quot;https://dspace.library.uvic.ca/items/599ee778-0bac-452e-9624-b5c04832a0d7&quot;&gt;https://dspace.library.uvic.ca/items/599ee778-0bac-452e-9624-b5c04832a0d7&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;figure style=&quot;text-align: center; margin: 0;&quot;&gt;
  &lt;a href=&quot;/blog/assets/images/2025-07-25-att-sceptre-revival/sceptre-17.jpeg&quot;&gt;
    &lt;img style=&quot;display: block; margin: 0 auto; border 0;&quot; src=&quot;/blog/assets/images/2025-07-25-att-sceptre-revival/sceptre-17-sm-d.png&quot; loading=&quot;lazy&quot; alt=&quot;The `boom.nap` graphic rendered to the screen.&quot; onmouseover=&quot;this.src=&apos;./assets/images/2025-07-25-att-sceptre-revival/sceptre-17-sm.jpg&apos;;&quot; onmouseout=&quot;this.src=&apos;./assets/images/2025-07-25-att-sceptre-revival/sceptre-17-sm-d.png&apos;;&quot; /&gt;
  &lt;/a&gt;
  &lt;figcaption&gt;The `boom.nap` graphic rendered to the screen.&lt;/figcaption&gt;
 &lt;/figure&gt;

&lt;h2 id=&quot;making-a-connection&quot;&gt;Making a Connection&lt;/h2&gt;

&lt;p&gt;The next step was to find a way to connect the Sceptre up to a computer so NAPLPS could be sent and rendered client-side. Unfortunately, I wasn’t able to find any existing software purpose-built for sending NAPLPS like this. It seems there are &lt;a href=&quot;https://github.com/n1ckfg/Telidon&quot;&gt;a few solutions to rendering NAPLPS graphics in a modern way on modern hardware&lt;/a&gt;, but not as much love for keeping the older machines alive.&lt;/p&gt;

&lt;p&gt;Luckily, I found a video of a &lt;em&gt;different&lt;/em&gt; NAPLPS-compatible terminal being sent files and rendering them! The video, &lt;a href=&quot;https://www.youtube.com/watch?v=0BKRfM5HHSM&amp;amp;t=653s&quot;&gt;Vintage Bell Alextel computer terminal can display graphics! by vintagecomputer.ca&lt;/a&gt;, showcases a &lt;a href=&quot;https://en.wikipedia.org/wiki/Alex_(videotex_service)&quot;&gt;Bell Alextel&lt;/a&gt;, a monochrome clamshell-style terminal that I hope to get my hands on someday.&lt;/p&gt;

&lt;p&gt;To connect the terminal to a host computer, the video shows a telephone line simulator to emulate a telephone network as well as some sort of modem running on the computer side to act as the counterpart to the modem in the Sceptre. I decided to use a &lt;a href=&quot;https://vikingelectronics.com/products/dle-200b/&quot;&gt;Viking DLE-200B&lt;/a&gt; as my line simulator since I had one already and thought it would be more reliable than using VoIP or a PBX for testing purposes.&lt;/p&gt;

&lt;figure style=&quot;text-align: center; margin: 0;&quot;&gt;
  &lt;a href=&quot;/blog/assets/images/2025-07-25-att-sceptre-revival/sceptre-109.jpeg&quot;&gt;
    &lt;img style=&quot;display: block; margin: 0 auto; border 0;&quot; src=&quot;/blog/assets/images/2025-07-25-att-sceptre-revival/sceptre-19-sm-d.png&quot; loading=&quot;lazy&quot; alt=&quot;A Viking DLE-200B.&quot; onmouseover=&quot;this.src=&apos;./assets/images/2025-07-25-att-sceptre-revival/sceptre-19-sm.jpg&apos;;&quot; onmouseout=&quot;this.src=&apos;./assets/images/2025-07-25-att-sceptre-revival/sceptre-19-sm-d.png&apos;;&quot; /&gt;
  &lt;/a&gt;
  &lt;figcaption&gt;A Viking DLE-200B.&lt;/figcaption&gt;
 &lt;/figure&gt;

&lt;p&gt;For the modem, I used a cheap Conexant RD02-D400 USB modem and wired everything up with standard 2-wire telephone cabling.&lt;/p&gt;

&lt;figure style=&quot;text-align: center; margin: 0;&quot;&gt;
  &lt;a href=&quot;/blog/assets/images/2025-07-25-att-sceptre-revival/sceptre-20.jpeg&quot;&gt;
    &lt;img style=&quot;display: block; margin: 0 auto; border 0;&quot; src=&quot;/blog/assets/images/2025-07-25-att-sceptre-revival/sceptre-20-sm-d.png&quot; loading=&quot;lazy&quot; alt=&quot;A Conexant RD02-D400 USB modem.&quot; onmouseover=&quot;this.src=&apos;./assets/images/2025-07-25-att-sceptre-revival/sceptre-20-sm.jpg&apos;;&quot; onmouseout=&quot;this.src=&apos;./assets/images/2025-07-25-att-sceptre-revival/sceptre-20-sm-d.png&apos;;&quot; /&gt;
  &lt;/a&gt;
  &lt;figcaption&gt;A Conexant RD02-D400 USB modem.&lt;/figcaption&gt;
 &lt;/figure&gt;

&lt;p&gt;To recreate the setup of the host computer, I used a machine running Windows 10 with the open-source &lt;a href=&quot;https://teratermproject.github.io/index-en.html&quot;&gt;Tera Term&lt;/a&gt; software.&lt;/p&gt;

&lt;p&gt;I set the serial port configuration as follows:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Port: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;COM1&lt;/code&gt; (may be different on your system, check Device Manager)&lt;/li&gt;
  &lt;li&gt;Speed: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;9600&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;Data: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;8 bit&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;Parity: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;none&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;Stop bits: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;1 bit&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;Flow control: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;RTS/CTS&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;Transmit delay: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;20&lt;/code&gt; msec/char&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The transmit delay proved to be essential and the terminal can’t generally keep up with the data is receives.&lt;/p&gt;

&lt;p&gt;The Sceptre also needs to be configured with connection settings that match our Tera Term session, after powering it on we can set one of the connection slots from the landing screen (also referred to as the &lt;em&gt;Data Base Access&lt;/em&gt; screen) by pressing &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;MODE&lt;/code&gt; on the keyboard for the &lt;em&gt;Mode Select&lt;/em&gt; screen and then &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;2&lt;/code&gt; for &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Directory&lt;/code&gt;. Then press a number &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;1&lt;/code&gt;-&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;5&lt;/code&gt; to create an entry with the following:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Name: any&lt;/li&gt;
  &lt;li&gt;Contents: &lt;em&gt;SHIFT+PHONE&lt;/em&gt; &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;5555555&lt;/code&gt; &lt;em&gt;SHIFT+DATA&lt;/em&gt;&lt;/li&gt;
  &lt;li&gt;Setup Parameters: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;yes&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;Parity: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;None&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;Duplex: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Full&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;All Caps: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Off&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;Protocol: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;NAPLPS 8&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;Sync/Async: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Async-1200&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;Flow Ctrl: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;On/On&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;EOL Char: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CR&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Note that the phone number &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;5555555&lt;/code&gt; can really be anything with this setup. By default, the Viking line simulator acts as a “ringdown line” meaning if either party goes off-hook it instantly calls the other, regardless of the number dialed.&lt;/p&gt;

&lt;figure style=&quot;text-align: center; margin: 0;&quot;&gt;
  &lt;a href=&quot;/blog/assets/images/2025-07-25-att-sceptre-revival/sceptre-10.jpeg&quot;&gt;
    &lt;img style=&quot;display: block; margin: 0 auto; border 0;&quot; src=&quot;/blog/assets/images/2025-07-25-att-sceptre-revival/sceptre-10-sm-d.png&quot; loading=&quot;lazy&quot; alt=&quot;Any existing connection set up for the Gateway service.&quot; onmouseover=&quot;this.src=&apos;./assets/images/2025-07-25-att-sceptre-revival/sceptre-10-sm.jpg&apos;;&quot; onmouseout=&quot;this.src=&apos;./assets/images/2025-07-25-att-sceptre-revival/sceptre-10-sm-d.png&apos;;&quot; /&gt;
  &lt;/a&gt;
  &lt;figcaption&gt;Any existing connection set up for the Gateway service.&lt;/figcaption&gt;
 &lt;/figure&gt;

&lt;p&gt;Then press &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;RETURN&lt;/code&gt; to save. Press &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;MODE&lt;/code&gt; to return to the &lt;em&gt;Mode Select&lt;/em&gt; screen and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;1&lt;/code&gt; to go back to the &lt;em&gt;Data Base Access&lt;/em&gt; screen. From here you can press the digit of the entry you made to start the call.&lt;/p&gt;

&lt;p&gt;After starting the call, we go back to the Tera Term session and wait to see &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;RING&lt;/code&gt; coming from the modem, indicating an incoming call. We then enter in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ATA&lt;/code&gt; to answer and we are now connected to the Sceptre.&lt;/p&gt;

&lt;p&gt;Now we can start sending files. If we drag-and-drop a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.nap&lt;/code&gt; file into the open terminal, a dialog box will appear for settings to send the file. Here, we need to make sure that the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Binary&lt;/code&gt; option is set under &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Send File&lt;/code&gt; before pressing the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;OK&lt;/code&gt; button.&lt;/p&gt;

&lt;p&gt;Just like that, the Sceptre will start receiving and drawing NAPLPS graphics!&lt;/p&gt;

&lt;p&gt;Well, sort of.&lt;/p&gt;

&lt;p&gt;For me, I had some drawing but a lot of parity error messages being printed to the screen as I initially had parity set on the Sceptre side (the configuration above is corrected if you’re playing around at home).&lt;/p&gt;

&lt;figure style=&quot;text-align: center; margin: 0;&quot;&gt;
  &lt;a href=&quot;/blog/assets/images/2025-07-25-att-sceptre-revival/sceptre-13.jpeg&quot;&gt;
    &lt;img style=&quot;display: block; margin: 0 auto; border 0;&quot; src=&quot;/blog/assets/images/2025-07-25-att-sceptre-revival/sceptre-13-sm-d.png&quot; loading=&quot;lazy&quot; alt=&quot;A shark NAPLPS file rendering with errors.&quot; onmouseover=&quot;this.src=&apos;./assets/images/2025-07-25-att-sceptre-revival/sceptre-13-sm.jpg&apos;;&quot; onmouseout=&quot;this.src=&apos;./assets/images/2025-07-25-att-sceptre-revival/sceptre-13-sm-d.png&apos;;&quot; /&gt;
  &lt;/a&gt;
  &lt;figcaption&gt;A shark NAPLPS file rendering with errors.&lt;/figcaption&gt;
 &lt;/figure&gt;

&lt;p&gt;After fixing that, I had graphics rendering just fine any time I drag-dropped a file!&lt;/p&gt;

&lt;figure style=&quot;text-align: center; margin: 0;&quot;&gt;
  &lt;a href=&quot;/blog/assets/images/2025-07-25-att-sceptre-revival/sceptre-15.jpeg&quot;&gt;
    &lt;img style=&quot;display: block; margin: 0 auto; border 0;&quot; src=&quot;/blog/assets/images/2025-07-25-att-sceptre-revival/sceptre-15-sm-d.png&quot; loading=&quot;lazy&quot; alt=&quot;A shark NAPLPS file rendering as expected.&quot; onmouseover=&quot;this.src=&apos;./assets/images/2025-07-25-att-sceptre-revival/sceptre-15-sm.jpg&apos;;&quot; onmouseout=&quot;this.src=&apos;./assets/images/2025-07-25-att-sceptre-revival/sceptre-15-sm-d.png&apos;;&quot; /&gt;
  &lt;/a&gt;
  &lt;figcaption&gt;A shark NAPLPS file rendering as expected.&lt;/figcaption&gt;
 &lt;/figure&gt;

&lt;h2 id=&quot;writing-a-server&quot;&gt;Writing a Server&lt;/h2&gt;

&lt;p&gt;I didn’t want to drag and drop files manually every time I wanted to see some graphics, so it was time to figure out how to do this myself.&lt;/p&gt;

&lt;p&gt;As an aside, around the time I was starting to write something I actually managed to connect with John Durno to chat about NAPLPS and learned that &lt;a href=&quot;https://dspace.library.uvic.ca/items/599ee778-0bac-452e-9624-b5c04832a0d7&quot;&gt;he had built something, coincidentally in Python, that would send a NAPLPS file to a device over the serial port&lt;/a&gt;. After I learned that he had built this I refused to look at the code until after my implementation as I didn’t want anything in there to influence me.&lt;/p&gt;

&lt;p&gt;The server was written in python, which I figured would be a powerful enough language that I could leverage to prototype something pretty quickly, but wouldn’t become unmaintainable as I grew it out.&lt;/p&gt;

&lt;p&gt;The final product of this effort is the dully named &lt;a href=&quot;https://github.com/dialup-world/naplps-server/?tab=readme-ov-file&quot;&gt;naplps-server&lt;/a&gt; which I have released as open-source software. It comes ready-to-go for those wanting to recreate my setup.&lt;/p&gt;

&lt;p&gt;If you want the deep-dive for how the code works, read on, but I won’t blame you if you want to skip to the next section.&lt;/p&gt;

&lt;p&gt;First, let’s import some libraries and get some variables set up:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;import serial
import time
import logging
import os
import signal
import sys
import random

DEFAULT_SERIAL_PORT = &apos;/dev/ttyUSB0&apos;
SCRIPT_DIR = os.path.dirname(os.path.realpath(__file__))
NAPLPS_DIR = os.path.join(SCRIPT_DIR, &apos;images&apos;)
LOOP_DELAY = 10  # seconds


logging.basicConfig(level=logging.INFO, format=&apos;%(asctime)s %(message)s&apos;)

running = True
last_file = None
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The library imports aren’t worth describing in-depth, but you can see we set up a default serial device (the path of our USB modem), a script directory and NAPLPS directory (so the script knows where it lives and then uses that to derive where the image files are), and a loop delay for how long we should wait before rendering a new image.&lt;/p&gt;

&lt;p&gt;Then we set up some logging configuration so all of our log messages will have a timestamp, and set a variable so we know the loop is running, and a variable so we know what the last NAPLPS file we rendered was (so we don’t render it again when we pick another randomly).&lt;/p&gt;

&lt;p&gt;A little more boilerplate, we have this function and logic for shutting down the application:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;def handle_shutdown(signum, frame):
    global running
    if running:
        running = False
        logging.info(&quot;Shutting down...&quot;)
    else:
        sys.exit(1)

signal.signal(signal.SIGINT, handle_shutdown)
signal.signal(signal.SIGTERM, handle_shutdown)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This will cleanly exit if the application is killed or otherwise needs to close.&lt;/p&gt;

&lt;p&gt;Next, we have a series of three related functions for handling the serial device and our connection:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;def open_serial(port):
    return serial.Serial(
        port=port,
        baudrate=1200,
        bytesize=serial.EIGHTBITS,
        parity=serial.PARITY_NONE,  # no parity
        stopbits=serial.STOPBITS_ONE,
        xonxoff=False,
        rtscts=False,
        dsrdtr=False,
        timeout=0,
        write_timeout=600
    )

def wait_for_ring(ser):
    logging.info(&quot;Waiting for RING...&quot;)
    buffer = &quot;&quot;
    while running:
        if ser.in_waiting:
            char = ser.read().decode(errors=&apos;ignore&apos;)
            buffer += char
            if &quot;RING&quot; in buffer:
                logging.info(&quot;RING detected.&quot;)
                return
        time.sleep(0.1)

def wait_for_connect(ser):
    logging.info(&quot;Sending ATA...&quot;)
    ser.write(b&apos;ATA\r&apos;)
    buffer = &quot;&quot;
    while running:
        if ser.in_waiting:
            char = ser.read().decode(errors=&apos;ignore&apos;)
            buffer += char
            if &quot;CONNECT&quot; in buffer:
                logging.info(&quot;Connection established.&quot;)
                return True
            elif &quot;NO CARRIER&quot; in buffer:
                logging.info(&quot;Call dropped.&quot;)
                return False
        time.sleep(0.1)
    return False
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;open_serial&lt;/code&gt; does exactly what you would expect and configures the serial device for use with our program, mimicking the settings we used previously for Tera Term.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;wait_for_ring&lt;/code&gt; simply reads from the serial device until we detect the string &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;RING&lt;/code&gt; which is reported by the modem if a call is coming in.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;wait_for_connect&lt;/code&gt; will be used after we detect a ring. We send the string &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ATA&lt;/code&gt; to answer the call and wait for either a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CONNECT&lt;/code&gt; string meaning the modem has negotiated a connection, or a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;NO CARRIER&lt;/code&gt; string signaling a disconnection or some other error that caused the call to drop.&lt;/p&gt;

&lt;p&gt;Next, we have a function that sleeps between sending NAPLPS files:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;def interruptible_sleep_with_monitor(ser, seconds):
    &quot;&quot;&quot;Sleep and monitor remote input, logging per-character during wait.&quot;&quot;&quot;
    buffer = &quot;&quot;
    elapsed = 0.0
    step = 0.1
    while running and elapsed &amp;lt; seconds:
        time.sleep(step)
        elapsed += step

        if ser.in_waiting:
            try:
                char = ser.read().decode(errors=&apos;ignore&apos;)
                buffer += char

                # Display to console
                sys.stdout.write(char)
                sys.stdout.flush()

                # Log each visible char separately
                if char.strip():
                    logging.info(f&quot;[REMOTE CHAR] {repr(char)}&quot;)

                # Check for disconnects
                if &quot;NO CARRIER&quot; in buffer or &quot;BUSY&quot; in buffer:
                    logging.info(&quot;Modem disconnected.&quot;)
                    return False

            except Exception as e:
                logging.warning(f&quot;Error reading serial: {e}&quot;)
                return False
    return True
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Here, we have a loop to wait for a given number of seconds, but we use this to also monitor for any data sent from the remote connection (the Sceptre) or the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;NO CARRIER&lt;/code&gt; string to determine that the call was ended. We don’t do anything with the data we get from the Sceptre, but this is essentially a stub that could be expanded in the future to use it. Any key-press from the Sceptre is sent to us in an encoded string, so we could potentially make some branching logic for navigation or something.&lt;/p&gt;

&lt;p&gt;Next, a function to get a NAPLPS file:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;def get_random_nap_file():
    global last_file

    if not os.path.isdir(NAPLPS_DIR):
        logging.error(f&quot;NAPLPS directory does not exist: {NAPLPS_DIR}&quot;)
        return None

    files = [f for f in os.listdir(NAPLPS_DIR)
             if os.path.isfile(os.path.join(NAPLPS_DIR, f)) and f.lower().endswith(&apos;.nap&apos;)]

    if not files:
        logging.error(f&quot;No .nap files found in directory: {NAPLPS_DIR}&quot;)
        return None

    if last_file and len(files) &amp;gt; 1:
        files = [f for f in files if f != last_file]

    chosen = random.choice(files)
    last_file = chosen
    return os.path.join(NAPLPS_DIR, chosen)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;As I mentioned, we know the directory where the NAPLPS files live so this function picks one at random and makes sure we didn’t just send it.&lt;/p&gt;

&lt;p&gt;Next is our sending loop:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;def send_naplps_loop(ser):
    logging.info(&quot;Starting NAPLPS send loop with 20ms/char delay.&quot;)
    while running:
        nap_file = get_random_nap_file()
        if not nap_file:
            logging.error(&quot;No NAPLPS file to send.&quot;)
            return

        logging.info(f&quot;Sending file: {nap_file}&quot;)
        try:
            with open(nap_file, &apos;rb&apos;) as f:
                data = f.read()

            for byte in data:
                if not running:
                    return
                ser.write(bytes([byte]))
                time.sleep(0.02)  # 20ms per byte

            logging.info(f&quot;NAPLPS file sent. Sleeping for {LOOP_DELAY} seconds and monitoring for input...&quot;)

            if not interruptible_sleep_with_monitor(ser, LOOP_DELAY):
                break

        except (serial.SerialException, OSError) as e:
            logging.warning(f&quot;Connection lost during send: {e}&quot;)
            break
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Here, we open that random NAPLPS file and read the whole thing into memory. Then we send it byte-by-byte to the Sceptre with a 20ms delay between each byte. This delay was mostly selected by trial and error for the fastest speed without getting errors. After we have sent all the bytes we start our sleep process.&lt;/p&gt;

&lt;p&gt;Lastly, we have our main loop:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;def main():
    port = sys.argv[1] if len(sys.argv) &amp;gt; 1 else DEFAULT_SERIAL_PORT
    logging.info(f&quot;Using serial port: {port}&quot;)
    logging.info(f&quot;Loading images from: {NAPLPS_DIR}&quot;)

    while running:
        try:
            with open_serial(port) as ser:
                ser.write(b&apos;ATZ\r&apos;)
                time.sleep(1)
                ser.write(b&apos;ATS0=0\r&apos;)
                time.sleep(1)

                wait_for_ring(ser)
                if wait_for_connect(ser):
                    send_naplps_loop(ser)
                    logging.info(&quot;Connection ended. Returning to idle...&quot;)
                else:
                    logging.info(&quot;No connection made. Returning to idle...&quot;)
        except serial.SerialException as e:
            logging.error(f&quot;Serial error: {e}&quot;)
            time.sleep(5)

if __name__ == &quot;__main__&quot;:
    main()
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;We allow the serial device to be passed in as an argument, so we make sure we use that device if it is supplied. Then we initialize the modem with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ATZ&lt;/code&gt; (which resets the modem) and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ATS0=0&lt;/code&gt; (which instructs the modem not to automatically answer and just supply us with a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;RING&lt;/code&gt; string). Then we wait for a ring, wait for a connection, and if successful start our loop for sending NAPLPS files. If a disconnect happens somewhere downstream we return to idle state where we wait for another call.&lt;/p&gt;

&lt;p&gt;That’s all there is to it. Connecting to a server running this from the Sceptre will result in images being rendered in a loop indefinitely. There will still be an occasional hiccup resulting in the image not rendering properly but it seems fairly stable.&lt;/p&gt;

&lt;figure style=&quot;text-align: center; margin: 0;&quot;&gt;
  &lt;a href=&quot;/blog/assets/images/2025-07-25-att-sceptre-revival/sceptre-16.jpeg&quot;&gt;
    &lt;img style=&quot;display: block; margin: 0 auto; border 0;&quot; src=&quot;/blog/assets/images/2025-07-25-att-sceptre-revival/sceptre-16-sm-d.png&quot; loading=&quot;lazy&quot; alt=&quot;A &apos;Beers &amp;amp; Beermaking&apos; graphic.&quot; onmouseover=&quot;this.src=&apos;./assets/images/2025-07-25-att-sceptre-revival/sceptre-16-sm.jpg&apos;;&quot; onmouseout=&quot;this.src=&apos;./assets/images/2025-07-25-att-sceptre-revival/sceptre-16-sm-d.png&apos;;&quot; /&gt;
  &lt;/a&gt;
  &lt;figcaption&gt;A &apos;Beers &amp;amp; Beermaking&apos; graphic.&lt;/figcaption&gt;
 &lt;/figure&gt;

&lt;h2 id=&quot;demo-line--exhibition&quot;&gt;Demo Line &amp;amp; Exhibition&lt;/h2&gt;

&lt;p&gt;The next step was to allow others to connect to this service. I configured one of my PBXs to allow connection from a few different ways:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;PSTN (US/Canada only) - 267-921-1337&lt;/li&gt;
  &lt;li&gt;PhreakNet - 263-0502&lt;/li&gt;
  &lt;li&gt;Direct SIP
    &lt;ul&gt;
      &lt;li&gt;Server: sip.dialup.world&lt;/li&gt;
      &lt;li&gt;Port: 16556&lt;/li&gt;
      &lt;li&gt;User: naplps&lt;/li&gt;
      &lt;li&gt;Password: naplps&lt;/li&gt;
      &lt;li&gt;Codecs: G.711/ulaw ONLY&lt;/li&gt;
      &lt;li&gt;Number: any&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;One of the benefits of NAPLPS being a standard is that this &lt;em&gt;should&lt;/em&gt; work for other terminals aside from just the Sceptre. I haven’t had anyone confirm, but I would love to see if Telidon, Keyfax, or Alextel terminals can make a connection.&lt;/p&gt;

&lt;p&gt;In October of 2025 the setup was taken to JawnCon and put on display at the PhilTel booth. For two days it was running for about eight hours a day, happily displaying graphics.&lt;/p&gt;

&lt;figure style=&quot;text-align: center; margin: 0;&quot;&gt;
  &lt;a href=&quot;/blog/assets/images/2025-07-25-att-sceptre-revival/sceptre-18.jpeg&quot;&gt;
    &lt;img style=&quot;display: block; margin: 0 auto; border 0;&quot; src=&quot;/blog/assets/images/2025-07-25-att-sceptre-revival/sceptre-18-sm-d.png&quot; loading=&quot;lazy&quot; alt=&quot;The Sceptre at JawnCon among other devices at the booth.&quot; onmouseover=&quot;this.src=&apos;./assets/images/2025-07-25-att-sceptre-revival/sceptre-18-sm.jpg&apos;;&quot; onmouseout=&quot;this.src=&apos;./assets/images/2025-07-25-att-sceptre-revival/sceptre-18-sm-d.png&apos;;&quot; /&gt;
  &lt;/a&gt;
  &lt;figcaption&gt;The Sceptre at JawnCon among other devices at the booth.&lt;/figcaption&gt;
 &lt;/figure&gt;

&lt;p&gt;I ultimately made a video about the Sceptre and server software I wrote which went up on my YouTube channel in late December 2025.&lt;/p&gt;

&lt;iframe style=&quot; width: 100%; aspect-ratio: 16 / 9;&quot; src=&quot;https://www.youtube.com/embed/a2dxuqol0c0?si=GSzibq-diZp4i8wB&quot; title=&quot;YouTube video player&quot; frameborder=&quot;0&quot; allow=&quot;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share&quot; referrerpolicy=&quot;strict-origin-when-cross-origin&quot; allowfullscreen=&quot;&quot;&gt;&lt;/iframe&gt;

&lt;h2 id=&quot;next-steps&quot;&gt;Next Steps&lt;/h2&gt;

&lt;p&gt;There are a few more things I could see myself doing with the Sceptre and the NAPLPS server software in the future.&lt;/p&gt;

&lt;p&gt;I would like to dump the ROM to share online. The 2364 mask ROM is not the most straight-forward when it comes to dumping, but it looks like there are several solutions available. The chip being socketed makes it even easier to remove from the board for dumping.&lt;/p&gt;

&lt;p&gt;The Sceptre will occasionally have an error when interpreting data and display a parity error on the screen. Implementing parity should be easy as the Sceptre supports it in connection settings and it would be trivial to implement in the server software. I don’t know exactly how the routine would work but I imagine the Sceptre would transmit some sort of message back to the server on parity error at which point the same byte could be resent.&lt;/p&gt;

&lt;p&gt;As previously mentioned, implementing some type of two-way communication would be really interesting.&lt;/p&gt;

&lt;p&gt;I’ve been told that as part of the &lt;a href=&quot;https://www.prodigyreloaded.com/&quot;&gt;Prodigy Reloaded&lt;/a&gt; project, a NAPLPS editor that works on modern computers is being built. When that becomes available it would be great to leverage that for menuing or just to have people create and submit art to be included.&lt;/p&gt;

&lt;p&gt;As previously mentioned, the Sceptre should support ASCII connections as well, meaning I would likely be able to connect to a traditional BBS or remotely log in to one of my servers.&lt;/p&gt;

&lt;p&gt;That RS-232 port on the back seems like a lot of fun, even if it could only be leveraged for printing.&lt;/p&gt;

&lt;h2 id=&quot;sources&quot;&gt;Sources&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/Telidon&quot;&gt;https://en.wikipedia.org/wiki/Telidon&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/Videotex&quot;&gt;https://en.wikipedia.org/wiki/Videotex&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/NAPLPS&quot;&gt;https://en.wikipedia.org/wiki/NAPLPS&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/Viewtron&quot;&gt;https://en.wikipedia.org/wiki/Viewtron&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/AT%26T_Sceptre&quot;&gt;https://en.wikipedia.org/wiki/AT%26T_Sceptre&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/Chemical_Bank&quot;&gt;https://en.wikipedia.org/wiki/Chemical_Bank&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/Prodigy_(online_service)&quot;&gt;https://en.wikipedia.org/wiki/Prodigy_(online_service)&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/NABTS&quot;&gt;https://en.wikipedia.org/wiki/NABTS&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/Alex_(videotex_service)&quot;&gt;https://en.wikipedia.org/wiki/Alex_(videotex_service)&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://scruss.com/blog/2023/09/18/the-glorious-futility-of-generating-naplps-in-2023/&quot;&gt;https://scruss.com/blog/2023/09/18/the-glorious-futility-of-generating-naplps-in-2023/&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=0BKRfM5HHSM&quot;&gt;https://www.youtube.com/watch?v=0BKRfM5HHSM&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.remembertomorrow.ca/en-ca&quot;&gt;https://www.remembertomorrow.ca/en-ca&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content><author><name></name></author><category term="projects" /><summary type="html">I don’t know when I first became aware of the AT&amp;amp;T Sceptre. It was several years ago; I think someone posted a photo of one somewhere and I became instantly mesmerized by the weird little beige box. I always liked the design language of the basic set-top-box with black bezel and an iconic “AT&amp;amp;T” logo. It reminded me of AT&amp;amp;T’s much older Dataphone line of modems (the Dataphone II, or Dataphone 300 specifically, and apparently the Sceptre shares some of the same DNA with the older models), but in larger footprint and a touch more approachability. This is something that could sit in the family room, not just the home office.</summary></entry><entry><title type="html">Portmaster Password Recovery Wasm</title><link href="https://dialup.world/blog/portmaster-password-recovery-wasm.html" rel="alternate" type="text/html" title="Portmaster Password Recovery Wasm" /><published>2025-07-16T00:00:00+00:00</published><updated>2025-07-16T00:00:00+00:00</updated><id>https://dialup.world/blog/portmaster-password-recovery-wasm</id><content type="html" xml:base="https://dialup.world/blog/portmaster-password-recovery-wasm.html">&lt;p&gt;After buying a Livinston/Lucent Portmaster 2 a while back and being locked out of the machine due to not knowing the password, I eventually stumbled upon the wonderful &lt;a href=&quot;http://home.eversberg.eu/public/portmaster.php&quot;&gt;PortMaster password recovery tool&lt;/a&gt; by &lt;a href=&quot;http://eversberg.eu/contact/&quot;&gt;jolly&lt;/a&gt; and used it to instantly gain access to my Portmaster.&lt;/p&gt;

&lt;figure style=&quot;text-align: center; margin: 0;&quot;&gt;
  &lt;a href=&quot;/blog/assets/images/2025-07-16-portmaster-password-recovery-wasm/portmaster-01.jpeg&quot;&gt;
    &lt;img style=&quot;display: block; margin: 0 auto; border 0;&quot; src=&quot;/blog/assets/images/2025-07-16-portmaster-password-recovery-wasm/portmaster-01-sm-d.png&quot; loading=&quot;lazy&quot; alt=&quot;A Portmaster 2e and a Portmaster 3.&quot; onmouseover=&quot;this.src=&apos;./assets/images/2025-07-16-portmaster-password-recovery-wasm/portmaster-01-sm.jpg&apos;;&quot; onmouseout=&quot;this.src=&apos;./assets/images/2025-07-16-portmaster-password-recovery-wasm/portmaster-01-sm-d.png&apos;;&quot; /&gt;
  &lt;/a&gt;
  &lt;figcaption&gt;A Portmaster 2e and a Portmaster 3.&lt;/figcaption&gt;
 &lt;/figure&gt;

&lt;p&gt;From what I can gather, the Portmaster has no local reset procedure, even if you have physical access to the machine, but will give you a &lt;em&gt;challenge code&lt;/em&gt; in the event that you no longer have the password. Back in the ’90s you could provide this code to customer support who would then return to you a &lt;em&gt;response code&lt;/em&gt; (essentially just an MD5 digest composed of the CHALLENGE code and some extra bytes) that could be used to get into the machine. At that point you could change your password and carry on with your day.&lt;/p&gt;

&lt;p&gt;Now though, customer support is long-gone, and this recovery tool emulates the whole interaction &lt;em&gt;in software&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;I don’t know the whole story behind the tool, but it seems like the original C implementation was written by &lt;a href=&quot;mailto:pmsac@toxyn.org&quot;&gt;pmsac@toxyn.org&lt;/a&gt;, implementing an MD5 message-digest algorithm from Ron Rivest, written by Colin Plumb, with contributions by Ian Jackson and Stephen Early. The PHP tool, to my best guess, calls the original C code to get a response. If it doesn’t do this, that means there is a PHP implementation that hasn’t been made publicly available.&lt;/p&gt;

&lt;h2 id=&quot;wasm-to-the-wescue&quot;&gt;Wasm to the Wescue&lt;/h2&gt;

&lt;p&gt;This didn’t site well with me, and I thought there should be a way to use this tool without needing to build/run a C program and/or host a PHP application if the original ever disappears.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://webassembly.org/&quot;&gt;Wasm (WebAssembly)&lt;/a&gt; seemed like the logical way to use the existing C code without a massive rewrite, and have the resulting tool available as a highly-portable application that can be copied into &lt;em&gt;any&lt;/em&gt; webserver directory and &lt;em&gt;just work&lt;/em&gt; was really enticing.&lt;/p&gt;

&lt;p&gt;The original &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;mz.c&lt;/code&gt; file was modified into a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;mz_web.c&lt;/code&gt; file with changes for Wasm. Notably, we cannot call a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;main&lt;/code&gt; function via Wasm, so this had to be modified.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://emscripten.org/&quot;&gt;Emscripten&lt;/a&gt; was used to build &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;mz_web&lt;/code&gt;. If you have Emscripten installed yourself, you can replicate the compilation of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;mz_web.c&lt;/code&gt; via:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;emcc mz_web.c -o mz_web.js \
  -sEXPORTED_FUNCTIONS=&apos;[&quot;_get_response&quot;, &quot;_malloc&quot;, &quot;_free&quot;]&apos; \
  -sEXPORTED_RUNTIME_METHODS=&apos;[&quot;cwrap&quot;, &quot;UTF8ToString&quot;]&apos; \
  -sMODULARIZE -sENVIRONMENT=web
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This generates &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;mz_web.js&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;mz_web.wasm&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Full code for this can be found in the &lt;a href=&quot;https://github.com/dialup-world/portmaster-password-recovery-wasm&quot;&gt;portmaster-password-recovery-wasm&lt;/a&gt; repository.&lt;/p&gt;

&lt;h2 id=&quot;live-demo--usage&quot;&gt;Live Demo &amp;amp; Usage&lt;/h2&gt;

&lt;p&gt;A live demo is available at &lt;a href=&quot;https://dialup.world/portmaster-password/&quot;&gt;https://dialup.world/portmaster-password/&lt;/a&gt;. It seems to work in FireFox, Chrome, and Safari.&lt;/p&gt;

&lt;p&gt;Anyone is free to run and host this themselves, it’s as easy as cloning the repository and dropping the directory on a web server.&lt;/p&gt;

&lt;p&gt;Upon loading the page you can follow these instructions on your Portmaster:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;At login prompt enter: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;!root&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;At password prompt enter: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;override&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;Copy the 16 character &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;CHALLENGE_STRING&amp;gt;&lt;/code&gt; and enter it into the webpage to receive a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;RESPONSE_STRING&amp;gt;&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;At login prompt enter again: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;!root&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;At password prompt enter: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;RESPONSE_STRING&amp;gt;&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;Be sure to change password set password &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;pw&amp;gt;&lt;/code&gt; and save it via &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;save all&lt;/code&gt;&lt;/li&gt;
&lt;/ol&gt;</content><author><name></name></author><category term="projects" /><summary type="html">After buying a Livinston/Lucent Portmaster 2 a while back and being locked out of the machine due to not knowing the password, I eventually stumbled upon the wonderful PortMaster password recovery tool by jolly and used it to instantly gain access to my Portmaster.</summary></entry></feed>