PrintStar's Blog
Ramblings of a Fortran Nut
October 26, 2016 by Jeff

Troubleshooting Some Hardware Issues

Today I wanted to set up my Rainbow 100 server, but I ran into some unforeseen issues.  After spending far too long trying to find the “perfect” combination of serial cables, null modem adapters, and gender changers, I decided I better actually turn on the Rainbow I’ll be configuring as a floppy-driven web server.  That’s when I ran into problems.

My web server is a Rainbow 100A variant, meaning it:

  • can’t boot directly from a hard disk (a.k.a. a Winchester disk)
  • supports less RAM
  • has an older BIOS

All these things really don’t matter for this application except, perhaps, the RAM.

After connecting the monitor and powering it up, I was presented with a blank screen and 8 illuminated diagnostic LEDs on the back panel.  It appeared dead.  Pulling the motherboard and removing the memory expansion did not alleviate the symptoms.  Swapping the floppy controller also didn’t help matters.

When Rainbow motherboards aren’t working, I usually move on quickly.  I still have some spares, and trying to diagnose why it isn’t working can be tedious.  I had exactly one spare Rainbow 100A motherboard, and I swapped it into the machine.  The system posted, but the RX50 floppy drive was dead (and one of the “B” drive door pins was missing).  Swapping the floppy drive and exercising it a bit yielded a working system.

Time for some pictures!  The server internals:

The delightfully large amount of space DEC left for cabling the drives to the controllers and power supply to the motherboard can be extremely frustrating:

A closeup of the labeling of a relatively rare Suitable Solutions IDrive, which provides a double-sided double-density IBM-compatible floppy drive on a Rainbow:

After checking out this machine, I’ve slid it back into its tower stand in preparation for its service as a web server.

As a side task, I need to back up the floppy that came with this box.  I’m not sure that the IDrive drivers are generally available anywhere anymore.

  •   •   •   •   •
October 25, 2016 by Jeff

Figuring Out Some Networking

In order to bring this Retrochallenge static blog online, I first need to figure out the specifics of networking.  Obviously the Rainbow will be located in my house as opposed to a data center, so I had to devise a way to make it accessible to the world at large.  In the past I had used Dyn’s old dynamic DNS solutions, but I really dislike configuring those setups.  In addition, it reveals my home IP, which I suppose could be dangerous.

Clearly the Rainbow has to connect to a modern-ish machine to act as its gateway.  There is no generally available ethernet card for the Rainbow (although a Univation device is rumored to exist in at least a prototype form), so the Rainbow has to speak serially with a machine with a true network connection.  For this challenge, it will be a brand new Raspberry Pi 3:

The Raspberry Pi will connect to the Rainbow eventually using a USB-to-Serial adapter.  While the Raspberry Pi does have a “serial port” built in, there are a lot of caveats that come along with it (3.3v, no hardware flow control, etc.).  The USB-to-Serial adapters are definitely preferable, in my opinion.

To access the Raspberry Pi, I’ve configured a VPN between it and a Digital Ocean droplet that is able to use nginx to reverse-proxy certain URL patterns over the VPN back to the Raspberry Pi.  The Raspberry Pi will then, in turn, forward these requests to the Rainbow’s address once the SLIP address is established.

While there appears to be many layers, there should be no confusion: the Rainbow will ultimately be serving web pages itself with its own, true HTTP server, albeit through a pair of reverse proxies.

  •   •   •   •   •
October 22, 2016 by Jeff

Finishing Touches

The static blog generator, believe it or not, is actually working!  I have a few sample test files that I’ve been working with, and the code seems to be in working order now.  I ran into some difficulties with how the Textile parser was handling exclamation points (every single one triggered the code to generate an image tag), but I’ve more-or-less corrected it now.  The parser, again, is a subset of the Textile markup language, making some pretty reasonable assumptions to keep the code clean.

I did add a few notable items to the code since I last updated this blog:

  • Static files, stored in the project’s STATIC folder, are now copied to the deployment folder
  • A page listing all posts is now generated
  • An INDEX.HTM file is created by copying the latest post to be the default landing page

The very last addition I’d like to add is possibly some parsing of the dates.  In this static site generator, blog post filenames are formatted as YYYYMMDD.TXT as a rule.  I still need to parse the filenames and generate a more friendly date for each post.

I also need to upload a sample project for the site generator.  Once I have the sample site, I’ll be moving on to actually setting up the Rainbow as the web server and beginning my blogging on floppy disks!

  •   •   •   •   •
October 18, 2016 by Jeff

Forgetting How BASIC Works

I finally had enough code earlier today to actually launch the site generator today!  There were plenty of bugs, of course, but I didn’t forsee the bugs related to my handling of arrays.

The first, simple bug I ran into was the “Duplicate Definition” error.  Without really thinking, I never accounted for multiple calls to subroutines that contained BASIC’s DIM instruction for sizing an array.  One cannot simply call DIM for the same variable multiple times.  I do recall a REDIM instruction that existed in PowerBASIC, but it doesn’t exist in ol’ GW.  To fix the issue, I basically “check” if I’ve called the subroutine before by seeing if a variable is set to 1.  If so, I use the ERASE statement to clear the arrays that I’m about to dimension.  It’s dirty but functional.

Once that simple bug was fixed, I noticed most of my arrays were empty later on in the program.  After some digging, I realized that my naive use of assignment of arrays to another variable simply doesn’t work.  I had to squeeze in some additional dimensioning and assignment loops to copy arrays, as one can see in this diff of the blog generator master routine. I feel silly for making such a mistake.

There are still a number of bugs, and it doesn’t “just work” yet, but it did actually generate two HTML files the last time I ran it.  The files themselves, though, are a mess, meaning I’ll need to look at how the Textile processor is wokring again.  Additionally, I did run a test that I thought had shown I could just issue a new line character, but that test was clearly incorrect.

  •   •   •   •   •
October 17, 2016 by Jeff

Moving Slowly Ahead

I’ve recently added another file to the repository, GWBLOG.BAS, that represents the beginnings of the actual static site generator.  As I mentioned before, I thought I’d use the GW-BASIC MERGE statement to keep all the modules separate.  It turns out that MERGE doesn’t exactly work as I had expected.  When called programatically, it actually halts execution after the first MERGE statement.  My attempt at some coding cleanliness failed.

I could just continue by copy/pasting everything into a single BASIC source file, but that could have some downsides just from trying to locate things.  On the other hand, every other GW-BASIC program I’ve ever attempted was a single file, including one game that I once printed out on paper, measuring 11 pages of tractor-fed spagetti code.  I’m already feeling some of the stress of having separate files since I have to call subroutines by line number, and I keep forgetting what the damn subroutine line numbers are!

I’ve decided instead to use a batch file to combine all the files into a single BASIC file and launch the subsequent BASIC file.  I actually tried it for the first time today, and I ran into a bug that I had feared: The list of files returned by the directory listing don’t contain a path, whereas TSORT.BAS expects a full, valid path.  It’s a minor speed bump that I should have some time to correct tomorrow.

  •   •   •   •   •
October 12, 2016 by Jeff

Finally, Some Code!

I’ve been working on my GW-BASIC blog generator quite a bit, and I’ve finally gotten around to posting the code:

https://bitbucket.org/ArmstrongJ/gwblog/overview

The code is currently a set of GW-BASIC source files that each contain a single general purpose.  The goal is to combine all these into a single, functioning static site generator using GW-BASIC’s MERGE command in a programmatic manner.  MERGE will function a bit like the C preprocessor’s #include functionality, but, due to line numbers, you need to plan ahead so that any given file will not overwrite another file.

Below I’ll provide some basic (haha) explanations of each module of the static site generator as it stands today:

FILES.BAS

This file contains a subroutine for listing files in a given subdirectory.  The task of getting a directory listing as an array is actually pretty infuriating.  In summary, the subroutine actually executes “DIR” using BASIC’s SHELL statement, piping the output to a temporary file.  This file is, in turn, read in and parsed line-by-line in the most naive manner.  Later versions of MS-DOS provided ways to retrieve directory listings without all the other nonsense like file sizes and dates, but MS-DOS 3.10 on a Rainbow 100 does not.

LINK.BAS

This rather short pair of subroutines create links and lists of links given labels and URLs.

POST.BAS

This file contains two subroutines for actually generating complete HTML pages from Textile  markup that are meant to be either a dated post or a static page.  Most of the heavy lifting (e.g. the actual Textile parsing) is handled elsewhere.

TMPLATE.BAS

This source file contains an extremely simple templating engine (if you could even call it that).  Basically, it’s just a straightforward text replacement engine.  A template filename is provided along with arrays of keys and values, and replaced text is returned.  It can’t do fancy things like loop through lists or perform conditional replacements.  It’s enough, though, to throw a title or link on a page.

TSORT.BAS

This BASIC source code is designed to sort a list of files by either title or date depending on the file’s name.  The idea for blog posts is that each will be named based on the date written: YYYYMMDD.txt In contrast, a page would just be something generic.  If the filename is a date, we need to sort the files based on this date.  If not, the files should probably be sorted based on the page’s title, assumed to be the first occurrence of an h1. tag in the Textile.  This subroutine both sorts the pages appropriately and loads their titles.

TXTDIR.BAS

This poorly-thought-out file was meant to process a whole directory of Textile into HTML, but it doesn’t have the necessary templates and header/footer code needed that POST.BAS provides.

TXTILE.BAS

The madness contained in this file is actually a crude, fragile Textile markup processor.  It unbelievably does work.  Currently, it understands:

  • Headers
  • Paragraphs
  • Ordered and Unordered Lists
  • Links
  • Images
  • Block quotes (because they’re easy)
  • Preformatted text
  • Text styling (bold and italics)

The fact that any of it works is quite baffling to me.  It’s handling of lists, for example, is atrocious.  However, it does actually work, so I can’t complain that much.

The next step is to build an example site to start integrating and testing.  Once that seems to be working, I’ll get an actual blog post or two written in it and attempt to configure the actual Rainbow as a host!

 

  •   •   •   •   •
October 3, 2016 by Jeff

About My Software

I haven’t had much of a chance to update the ol’ blog this weekend because I’ve had some delightful plumbing problems and I couldn’t miss watching the NWSL playoffs!  I’ll add a quick post tonight, though.

Generally, most work during this Retrochalleng will focus on writing the static blog generator.  To do so, I thought I’d mention some of the software I’d be using since I’m doing everything on the Rainbow itself:

MS-DOS 3.10b

Version 3.10b was the last version of MS-DOS released for the Rainbow.  In fact, Digital Equipment Corp. didn’t even release it.  A separate company, Suitable Solutions, purchased the nearly finished port after DEC killed the Rainbow line and released it to the public.  MS-DOS 3 always felt like a sweet spot to me, although it didn’t come with its own screen editor, which brings me to…

SEDT 4

SEDT, or Screen EDiTor, is a fantastic text editor written by Anker Berg-Sonne for an enormous variety of computers.  The MS-DOS version, though, actually recognizes Rainbow 100 hardware, making it somewhat unique amongst DOS text editors.  On DEC machines with an LK-series keyboard, the hotkeys are wonderful to use, relying on the “Gold” key (Num Lock on IBM compatibles) for tons of functionality.  It’s the only text editor on which I really learned all the hotkeys.

GW-BASIC 2

GW-BASIC on the Rainbow stopped at version 2, while the IBM PC saw plenty of future releases.  The Rainbow version probably froze because it was almost certainly being ported by DEC itself rather than Microsoft.  That said, GW-BASIC 2 is plenty complete for my purposes.  It’s where I learned to program!

Turbo C 2

Borland’s Turbo C version 2 does “work” on the Rainbow, but only after patching.  For whatever reason, Borland decided with version 2 to employ an interrupt internally that the IBM personal computer didn’t use, but the Rainbow used to access serial ports (I think? It’s been a while since I patched my copy…).  This development was particularly infuriating because version 1 worked just fine.  A little MS-DOS DEBUG action can fix the Turbo C executables, though.

I’m using Turbo C to compile the uIP/FOSSIL TCP/IP stack.  I believe originally I compiled uIP/FOSSIL with Open Watcom on a modern machine, but Turbo C on a Rainbow is way more fun.  The most annoying part, however, is that Turbo C 2 doesn’t understand UNIX line endings, so I have to make sure that MS-DOS line endings are maintain in the source repo.

The above is a little rundown on what’s being used.  I’ll get a bit more specific as I discuss the specific tasks on which I’m working.

  •   •   •   •   •
October 1, 2016 by Jeff

A Peek at My Hardware

I’ll be doing almost all my Retrochallenge programming on one of my Digital Rainbow 100 personal computers.  The one I currently have set up is particularly exciting because:

  • It’s mounted in an E.T. stand
  • It’s using an MFM Emulator for its hard disk

The E.T. stand mounting is pictured below:

An E.T. Stand

The E.T. stand had been featured on this blog before, I believe.  It’s a ridiculous piece of hardware that feautres a pedal-driving monitor arm.  Good times!

The disk emulator is currently set up to simulate a 40MB MFM hard disk; using a higher capacity disk on the Rainbow can be troublesome due to DEC’s terrible cable connecting the disk to the controller.  However, the machine is delightfully silent now that some ancient Seagate monstrosity doesn’t have to spin up.  Furthermore, the emulator is a bit faster than an actual hard disk (though not appreciably so).  I had previously taken some pictures of the emulator, so I’ll skip that for now.

Just two days ago, I decided to “modify” the LK201 keyboard attached to my ‘bow.  Some years ago I acquired a clear plastic cover to replace the tan plastic on the keyboard.  The alternate casing was apparently created by DEC as a way to show off the keyboard’s internals at promotional events.  It’s clearly built by them since a mold that fits perfectly would have been expensive to produce.

There’s a brief look at where I’ll be working!  I’ll have another post on the software I’m working with on the Rainbow itself next.

      •   •   •   •   •
    September 30, 2016 by Jeff

    Retrochallenge 2016/10

    I’ve decided to try another Retrochallenge!  This October, I plan to attempt migrating my blogging activities, however sparse, to a DEC Rainbow 100 permanently.  The blog will be generated by a static site generator written in GW-BASIC and served using uIP/FOSSIL, originally ported during the 2009 Retrochallenge Winter Warm Up.

    Using WordPress has become somewhat unpleasant.  Yes, I’m currently typing into a WordPress blog, but it isn’t a fun experience.  Lately, for work, I’ve transitioned a number of websites to static sites generated via Cactus.  I think moving to a static generator for my blog could be delightful.

    Over the past few weeks, I’ve been writing some GW-BASIC subroutines to support this endeavor.  A nice deadline, though, should really get things moving.

    I plan on providing some delightful details of the hardware involved of getting a DEC Rainbow 100 permanently serving pages. I also plan on completing the static blog generator in GW-BASIC, and hopefully someone else might actually find it useful or, at the very least, amusing.  With a DEC Rainbow serving a blog, I think I might perhaps become a bit more prolific.

      •   •   •   •   •
    July 23, 2014 by Jeff

    The Unfamiliar Land of 8088 Interrupts

    It’s been just less than two weeks since my last Retrochallenge update.  I started off strong with posting, but I fizzled fast once I hit the real work.  So have I dropped out?  Not exactly…

    After perusing the piles of Rainbow documentation I have available in a desperate search for how to interact with the Z80 CPU through hardware, I started writing some test code.  At first it was simply a naive attempt to trigger the Z80 to execute anything at all.  Without any context, I was signaling the Z80 to start running by pushing code 0×21 out through I/O port 0 on the 8088 CPU.  This exercise was entirely uninteresting because, after doing so, the 8088 continues on about its own business.  It doesn’t automatically stop and wait for its sister CPU to finish up.

    What should happen under these circumstances is that the Z80 should trigger an interrupt (0×47 to be exact) on the 8088 to notify its friend that it has completed the requested work.  In order to perform this work, I wrote a slightly more elaborate program.  Now it would load some Z80 machine code into the lower 64KB of Rainbow RAM (but above the 2KB mark), attempt to configure the Z80′s start address, and request that the Z80 execute the code.  The unclear part of the above is how exactly to specify the start address to the Z80.  To move things along, I decided to hand-type the MS-DOS BIOS’s execz80 routine.

    The above, once again, really didn’t do much at all since the code didn’t handle any Z80 interrupts yet.  I did send the code off to the Z80, request some work, and halt the 8088, which did work.  What this program showed was that some miscellaneous interrupt was triggering the 8088 to come back to life.  I hoped it would be interrupt 0×47 from the Z80, but I wasn’t sure.  It was time to start writing an appropriate interrupt handler.

    The problem with all these attempts, of course, is that I really don’t know how to work with interrupts.  Sure, in the past, I’ve triggered interrupts to access screen or disk I/O, but I’ve never responded to an interrupt.  The other problem with writing something “new” of this vintage is the documentation.  I have a complete Microsoft C and Macro Assembler documentation set, but nowhere in these binders do they explain exactly how one might author an interrupt handler.  Sure, they provide functions to hook your handlers into the OS, but there’s no implementation examples.  Online searches are generally useless as well because they either focus on modern 32-bit (or higher) machines or they don’t turn up in results.

    I did find a promising introductory paper that gave an example of an interrupt handler responding to system clock ticks.  I decided to work with that code, and I wrote a simple handler that would allow my main program to proceed if it were ever triggered.  I attached the handler to the Z80 interrupt, and, lo and behold, I received the dreaded Message 16 – Interrupts Off message on the Rainbow, returning me to the boot menu. Anyone familiar with the Rainbow know that this message generally means, “something went wrong, so here’s an error that doesn’t actually help you figure out where the problem is.”

    While it was an error, it was something, at least.  For a few more days, I toyed with this same program, trying to get it to do something.  After continual failure, I decided to see if I could write a simple program to trigger and catch a generic, unused interrupt.  This program was met with varying success.  It didn’t always trigger Message 16, though, but it didn’t proceed either.  Basically, the program would trigger an interrupt, then continually check a variable to see if it changed.  The interrupt handler would change that variable when the interrupt was caught, allowing the program to exit.  Almost always, it simply sat there locked up.

    Yesterday it occurred to me that perhaps the handler wasn’t changing the variable properly.  Looking at the code, I made one simple change.  I had declared my status variable that allowed my program to exit as a global:

    static int returned;

    I had been compiling my program as a “small” memory model (don’t you all love x86 chips!).  In this circumstance, though, the variable “returned” existed only in the data segment in which my program ran.  The interrupt handler, on the other hand, does not run in this same segment.  I made one simple change:

    static int far returned;

    Surprise!  My program suddenly worked!  x86 segmented memory strikes again!

    I stopped yesterday after that small victory.  I’ll try again today (hopefully) to catch Z80 interrupts.

     

      •   •   •   •   •