Friday, August 1, 2014

Been Busy...

I've been busy on things recently, although any time in front of the computer has been spent on programming project(s)/paying contract work rather than writing blog posts, so I'm a bit behind in getting things documented here.

I've done quite a bit of hardware-ey projects in the past few months... every Tuesday night for me is my "hardware hacking" night at Interlock, but by the time I get home I'm too tired to write up what I worked on... so I've gotten horribly behind!

I've got a bunch of what I think are really neat things I've worked on that I'll get up online here soon...  One cool retro-programming-hardware project, a few item repairs (monitor, Kindle, etc), and a couple of Lego-based electronic projects..

Monday, June 16, 2014

Lego Series 1: Benny's Spaceship

This is the first post of a new series of Lego-related posts.  I have a few things I've been designing that I think are neat, or in this case, are fixes for existing sets.

The Lego Movie came out last year, and it was AWESOME.  I bought 70816 "Benny's Spaceship, Spaceship, SPACESHIP", and had a great time building it.

After re-watching the film, I noticed a couple of differences between the model in the movie and the real-life one.  Let's start off this series by showing two of these differences in Benny's spaceship, as well as a very simple modification to fix one if them.

Behold, the completed spaceship, and it is awesome:


First, I'll point out something that cannot be fixed.  Here's a shot of the ship from the movie:


1.  The side intake

 

Right in the center of the above images, you can see a 61409 1x2 slope with 4 slots. I should note here that there are a few different versions/names of grays, including light blue-gray, dark gray etc, but for the sake of simplicity, I'll just use "light gray" and "dark gray" in this series.  The model in the movie (first image) shows this part in light gray, while the constructed model is dark gray.  This part is not available, nor has it ever been, in light gray.  So, sadly, we can't fix this one.

2.  Astro Kitty's bracket





If you look carefully in the above image of Benny's ship, you will notice that the area that holds Astro Kitty in place is different than the model.  I have fixed this and you can see the results in the above images.  The first one shows the version from the model, whereas the second one is film-accurate.

The parts for the storebought model: (left to right)
- 30375 dark gray robot torso
- 11476 light gray 1.2 with clip on horizontal side
- 11477 dark gray 2x1 curved slope (x2)

The parts for the film-accurate model: (left to right)
- 2555 light gray 1x1 with clip
- 30375 dark gray robot torso
- 30377 light gray robot arm (x2)
- 2540 dark gray 1x2 with handle on side
- 11477 blue 2x1 curved slope (x2)

Thursday, April 24, 2014

Fixing Pac-Man - Attract mode with less burn-in


One of the problems with Pac-Man, especially for home use, is that once a coin is dropped in, or you have it in Free Play mode, it will sit on the "Press Start" button screen forever, until all of the credits are depleated... which can take a long time, especially in Free Play mode. ;)

After being inspired by the ET bugfix project (a great read, btw), I decided to attempt to fix this myself. I should note that there are other versions of this fix on the net, and I have no idea if any of those are better or worse than mine.  Mine is a total of 30 bytes changed in the ROM.


My first thought is that it switches into the "Press Start" screen after it has some credits in it.  So the first thing to look for in the Ms. Pac-Man documented disassembly is the RAM location for number of credits in the machine.


At the top of the disassembly, are a bunch of RAM locations that have been decoded by contributors. As you can see, 0x4e6e contains the number of credits in the system.  Next thing to do is to search for "4e6e" in the file, and sooner or later, I figured I'd find the right location.  There's got to be a section of code that reads a value in from this, and compares it with 0 to determine if it should stay in attract mode or show the "Press Start" screen.  Sure enough...


Here we see a snippet of code.  This is in the main attract sequence.  This block of code above draws the number of credits on the screen (at 03fe), then checks the number of credits against zero (0401-0405).  If it's still 0, it goes to 0x0413, where it continues through the attract sequences.  Otherwise, it falls through, to some code (0407-0412) that advances the game mode to the dreaded "Press Start" screen that we want to eliminate.  Jackpot!

All that I need to do now, is to patch off of this code to my own routine.  The basic thought (which did work out) is that the only way that it will switch to the "Press Start" screen is if the user is pressing start.  Once it changes to that screen, the start button will still be pressed, and the game will just start.

This means that the only way that the code from 0407-0412 will get run here is if there is not zero credits AND a start button is being pressed.  On top of this, we don't want to run that code when the user is pressing 2P start unless there's at least 2 credits.



And that is the entire patch.  30 bytes of code.

The original code will check if there's credits in the machine.  If there are, it falls through to 0407, which is where my code takes over.

It simply jumps to some unused space in the ROM, starting at 0f3c.  "attStTest" checks to see if the user is pressing P1 or P2 start.  If they're not, we jump on over to 0413, as before, to continue with the attract sequence.  If they are pressing P2 start, it does the extra check in "credChk2" to make sure that there's at least 2 credits in the machine.  If there's not, it again will jump over to 0413.  Finally, we know that we can switch the game mode to the "Press Start" screen, where our button press will promptly get gobbled up, and the game will start.

The code in "startIt" should look a little familiar.  The first two opcodes are the opcodes we overwrote in 0407 where we jumped over here to this mess.  Then we jump back to "startItR" return location, and the original code resumes at 040b, performing the game mode switch.  For clarity, I could have dropped the remaining 4 opcodes which start at 040b in here, but I decided to save space and do it this way.

30 bytes different, and the game is the way it should be... especially if your friends come over to your basement arcade, and press the credit button 12 times, or you have it set on Free Play. ;)

Saturday, April 19, 2014

The Otto Project


I've been trying to figure out the angle I should take on this post, and I've decided to focus on my effort here, rather than a history lesson more than a brief overview about who "Crazy Otto" was... but here's the quick recap...

In 1980, General Computer Corp (GenComp/GCC) was making mod kits for games, including one for Missile Command, and one for Pac-Man. Their Pac-Man add-on was quite innovative.  It brought four new mazes to the game, a new lead character with legs and feet, a new intro sequence, and monsters with antennae instead of ghosts.  If this sounds somewhat familiar, it should.  This mod kit became "Ms. Pac-Man", but before it was Ms, it was "Crazy Otto".  It went through a few steps in the progression, all of which I will cover below.

If you want a more comprehensive history of Ms. Pac-Man, you should watch the video of Steve Golson's presentation "From Crazy Otto to Ms. Pac-Man".  It covers many of the details that I used to create these.  Links to the PAX-2012 and MIT-2014 presentations of this are available at the bottom of this post, and are well worth your time to watch.  All of the sets I present here are directly based on sets that he described, demoed, or showed screenshots of, in an attempt to recapture the history of this iconic video game.

The tools I used to create this are:
  • ASZ80 - assembler (ASM to IHX)
  • genroms - converts IHX to binary rom files, capable of patching over source images
  • Turaco - arcade game graphics editor for MS-DOS
  • Boxer/Dos Box - MS-DOS emulator so that I could run Turaco on my Mac. ;)
  • mspacman.asm - Our well documented Ms Pac disassembly
All of these are available either through online repositories.  Links for all are at the bottom of this post.

None of this is to be used or repackaged for profit.  This is all for educational and historical reasons.  It's okay to drop it into a free-play machine as a museum piece... It is NOT okay to include it with a multigame that you're selling, etc.  Don't be a jerk.

Okay... All of that is out of the way. Let's get into the differences between the romsets, and the patches necessary to make them happen.  I'm going to use the names I came up with for the sets to differentiate them here.  Details of differences and dates were gleaned from Steve Golson's presentations.

Information gleaned from his pre-PAX-2012 talk: (Time magazine photo and rumors)
  • Approximate image of Otto, one frame of 16, no animations
  • Approximate image of monster sprites, one frame of two
  • The fact that this existed at all
Information gleaned from the PAX-2012 talk:
  • Dates of ROM releases
  • Attract sequence differences (Pac-Man, Ms. Pac Marquee, Pac-Woman additional movement)
  • Ghost name differences
  • Crazy Otto exact graphics romset (shown as two screenshots, recreated using Turaco)
  • Monster exact graphics
  • Pac-Woman exact character graphics (recreated using Turaco)
  • Character coloring (for the "alternate" character in intermissions)
  • Intermission structure (short bits of original asm code were displayed, providing a rosetta stone)
  • Lack of monster "eyes" after monster death
  • Death animations for all 
The following ROMsets were released by me (version 05) on April 19th, 2014.  They were playable on a 13" JAMMA test rig (on a Yenox bootleg mspac board) in the lobby of BarCamp Rochester on this day as well.  I switched the ROMs back and forth between the "PZ" set, and the "Pac-Woman" set.

And now I'll list off details about what makes each particular release distinct, as well as some info about recreating it, backwards, from a standard "mspacmab" bootleg ROMset.

OttoP1 - 1981-Oct-12




Character and sprite roms for OttoP1.  These are pixel-for-pixel copies of the original.
The character graphics (top) are based on Pac-Man (Notice the score graphics)

  • Pixel perfect Crazy Otto graphics rom (characters moved around)
  • Pac-Man intro sequence (stationary ghosts) showing their names
  • GENCOMP logo, rather than Midway logo/copyright
  • Remap movement animation frames (characters, stork, baby, etc)
  • Remap of characters and colors for intermissions

This one was one of the more interesting hacks to work on.  A lot of what makes this one unique was to be eventually obliterated by Ms Pac patches.  At first I tried reversing the one patch in Pac-Man that jumps to Ms Pac romspace, where the new "marquee" intro happens, and just let it fall back on original code.  This kind-of worked.  The problem is that it used quite a few of the text slots, which were re-used for the new marquee introduction.  To fix this, I reverted many of the text strings to their modified Pac-Man versions, eg Mad Dog, Killer, etc instead of Inky, Blinky, etc.

The GENCOMP logo was already in the character set, so i just needed to remove the jump to the Midway logo and copyrights, and replaced one of the copyright strings with the characters necessary to draw out "GENCOMP" ("pqrstuv").  I also used a feature of the text render routine that I'm fairly certain no one else uses anywhere else, and that lets you draw the text out in multiple colors, rather than just one color for the entire text string.

Remapping the movement frames was fairly straightforward once I replaced the original math-based routine with my table-based routine.  This is discussed in the section below "Player Sprite Picker".

Remapping the colors, characters, and sprite frames was fairly easy once I was able to use the rosetta from Golson's talk to figure out some of the animation format.  Past that, It was a bunch of experimenting to determine what parameters did what (color, speed, location, etc)  The 'female' character from the intermissions required more attention, since it now uses a different palette color (red), so all occurrences of the color (12 of them) are replaced from 0x09 (yellow) to 0x01 (red).


In Golson's talk, as you can see in the above image, he had a couple of pages of code snippets.  The one above is showing the animation format.  Thanks to him publishing his presentation materials, we can see that up close:

With a little bit of sleuthing, I was able to use this as a kind of rosetta stone, to figure out the animation format.  These animation scripts are used for the intermissions, as well as the introduction attract "marquee" screen.  This becomes more important with the P5 (Pac-Woman) hack below.

For the record, here's the above code chunk, but in the mspac.asm disassembly project, showing that we have a better grasp on how these scripts work.

OttoP2 - 1981-Oct-20




The graphics roms for P2 are similar to P1.  The sprite rom (second) is identical.  The character rom (first) is upgraded to the MsPac version. Notice the marquee graphic instead of the scores in the character rom.

  • Everything from P1 except for:
  • Marquee intro sequence, with "Bonnie" instead of "Sue"
  • "MIDWAY MFG. CO" with Midway Logo
Replacing "Sue" with "Bonnie" was a simple text replacement.  Same with the Midway logo.  The year line was removed from the final product, and the other line was just moved down, and changed to the text seen above.  Nothing really major.  All of the guts of this was accomplished in the P1 variant.

OttoP3 - 1981-Oct-29


  • Everything from P2 exept for:
  • "(c) MIDWAY MFG CO"
  • "1980"
Again, this was just further text changes and tweaks. Nothing major here.

SuperP4M, SuperP4G - 1981-Oct-29

   

This one signifies two different graphics rom sets with the same code underneath it. "P4M" specifies the version with Crazy Otto Monsters, while "P4G" specifies the standard ghosts.




For this version, the character ROM is basically the same as P2 above.
I switched the layout for Super Pac0Man to be closer to the Pac-Man layout.

  • Graphics Rom is closer to Pac-Man than Ms. Pac, to retain the Pac-Man death animation
  • Many similarities with P1-P3
  • Copyright string from P3
  • Game and character names on marquee introduction changed to "Super Pac-Man"
  • Character sprite table for movement and animations changed to Pac-Man
  • Stork and baby sprites in the table were also remapped
All of the changes here were explained in previous sections.  The character movement table was used to tweak the frames of animation to the Pac-Man standard.  The death animation frames were remapped to what Pac originally had.  Also the color of the "female" for the intermissions was retained as red as in the above, but is now a red Pac-Man puck, rather than an Otto with legs (AKA "Anna").

WomanP5 - 1981-Nov-12






The Pac-Woman set is based on Ms. Pac-Man.  The orientations for the death animation are the same as in the final MsPac.  I've included this in yellow so you can see the woman graphics appropriately.  The red/blue/white version is included for comparison with the above examples.

This one got a bit interesting. Golson didn't have any demonstration of this other than a screenshot of "Pac-Woman" in the graphics ROM, and the intro screen animation.  I interpolated this up from what I had for P3, as well as putting her in place of Ms. Pac-Man in her romset.  He even said that there wasn't a playable version of the ROMs that existed... which makes my P5 set even more interesting, since we can now actually try it out.
  • Ms Pac graphics rom with "woman" in place of Ms. pac
  • other character in animations was Pac-Man, like in the final version
  • Animation frame indexing changed from Ms. Pac to use the tables, as explained above
  • Additional animation added to the intro sequence
Since I now knew most of the animation format, as explained earlier, I was able to tweak the animation segment table to point to a new section for Pac-Woman's introduction.  It does the same thing as before, where she walks in from the right side, and stops in the middle of the screen.  But from there, she turns and moves down a little bit.  I did a bunch of tweaking to the speed, distance, and ending frame to try to make this look as much like the demonstration video as possible.

He stated that this version was abandoned due to the fact that when she's moving away from you, it's easy to confuse her with the red ghost.  And he's absolutely right.

From this stage, they generated a slightly different character, again with a bow on her, and she became the Ms. Pac-Man that we all know and love.

OttoPZ




The PZ variant brought forward a bunch of problems.  The main screen needed to have the monster graphics, as well as both logos and the marquee for the Pac-Man and Ms. Pac-Man introduction screen.  The sprite rom is basically the same as the above P2 version

This one is a multigame version of P1-P3, plus an additional fictitious mode not based on any single romset.  It also has additional patches for playability.  You select at startup time which variant (P1, P2, P3, PZ) you want to play as well as whether you want the fast or regular variant of it.  Once you pick that, it behaves like any game above.

While it's running, holding P1 and P2 start and pressing the joystick up "drops a quarter".  Holding those and pressing the joystick down resets the machine, so you can pick a different variant.

This one is perfect for your home arcade, MAME machine or other emulator.
  • Switchable Pac-Man intro and Ms Pac-Man marquee intro
  • General playability of P1-P3 above
  • Fast mode selectable at bootup time too
  • PZ mode also selectable - Ms Pac marquee intro, with GENCOMP logo.
This one got a little complicated.  In P1 above, I was able to just swap out the Ms Pac text table and restore the Pac-Man one.  I didn't have that luxury this time, since we needed the Ms Pac text table to be intact for the P2, P3 and PZ versions of the game.  I implemented this by hooking in to the actual text rendering routine.   It skips out and goes to my own routine which checks to see if the current game is P1.  If it is, it uses a reproduction of the Pac-Man table, but out in my memory space, and with a few strings restored to the OttoP1 versions.  This one has the original P1 strings, rather than the re-used/remapped strings that are used for the Marquee introduction.

One other modification done in this patch is the check for if the game is trying to render string 0x13 (copyright) or 0x35 (copyright year).  Since each variant has different versions of these, the routine uses the variant number as an index into its own string table, and draws the appropriate-looking text to the screen.

This does get into something though.  How do we know which game and variant we're playing. We need to store it in RAM somewhere nonvolatile.  We can pick someplace unused, but it might get used and we haven't figured out the documentation yet.  Or we can use a trick that I figured out while working on a multigame Ms. Pac a few years ago.  The stack pointer always starts at 0x4fc0, and works down from there.  Nothing ever  goes above it other than sprite registers.  So, if we just patch the game code to start the stack pointer down a little bit, we have a few bytes that we can use for our own storage.  

The test for the coin drop and reset hack was hooked in to the routine that checks the coin slot switches.  This gets called often while the game is running, so it seemed like the most comprehensive place to insert our routine.  Before it checks the coin slot switch, it will check to see if P1 and P2 are being pressed.  If the joystick is also being pressed up also, we "drop a coin", and if it's pressed down, we reset the machine, so that the player can pick a different variant to play.

This set also drops the "jumble of characters" standard MsPac startup tests. 

All of the patched romsets mentioned in this post are available through links at the bottom of this post.

Common patches applied

There are a few patches that got applied to just about all of the sets in one way or another.  I didn't want to change any of the gameplay behaviors, so I didn't fix the killscreen at level 240ish.  I also didn't apply the "Fast" hack to any of these sets, since I wanted to reproduce the original gameplay, not a "comfortable playable set". If you want that, use the "OttoPZ" multigame, which is tweaked for general "daily" use.

Memory Mirror Fix

First of all, due to nothing being mapped in memory space above 0xAFFF, writes to those locations map down to lower memory.  That is to say that writes to 0xB000 will acutally occur at 0x4000.  The emulators do something weird with this, and the writes disappear into unreferenced 'ram' space.  This is a problem because the text rendering routine (at 0x2c5e) does something weird with it.  You call this routine with a number, an index into a list of pointers to text structures.  The first item in the text structure is the offset into video memory that the text should start.  The upper two and lower two lines use a different arrangement of bytes, so they need to behave differently.  This behavior is signified by setting the high bit (0x8000) on the offset.  Well, if we now have text that was supposed to be at offset 0x00FF, but it is in that region so the high bit is set (0x80ff).  This offset added to memory space at 0x4000 produces 0xC0FF as the starting location.  In real hardware, this is fine, since the high bit is not connected, so the write actually happens to (0x4000 + 0x00ff), but in emulators, it actually happens at 0xC0FF.  There's a patch that fixes this -- it masks off that high bit when adding in the offset to the video base pointer.

Player Sprite Picker

Another patch standard on all of these is replacing the original function that determines what sprite to display for Pac/Ms.Pac/Otto.  The original did some sort of weird math to determine the sprite number.  I replaced all of that with four hooks into my code that loads the appropriate four-entry table (four hooks; one for North, South, East, and West.)  This code actually fits over the original code, without needing any extra space... in fact, it's smaller and more efficient than the original at 58 bytes instead of 81 bytes... plus, and more importantly, it's MUCH easier to hack in different sprite characters for different graphics sets, which I needed to do.  I'm actually kinda surprised that Otto/Msp didn't use a table for this.

Splash Intro Page

One obvious modification is that all romsets have a splash screen on startup. I didn't want my reproduction sets to be mistaken for the real thing, should it ever be released.  At the end of the startup tests, just after the test grid is drawn, it is cleared, and then my own routine occurs.  This one has its own text string table for the standard text routine at 0x2c5e, so as to not need entries in the standard string table.  It will draw out info about the romset, my email address, and after a moment, it prompts the user to press a button (or move the joystick.) (The "clear screen" routine was also re-added as a patch, since the original wasn't easily callable.

Links


NOTE:  I pursued this project on my own, using only publicly available information.  No direct contact was made during development by anyone involved with GENCOMP nor Midway nor Namco.  This is meant to be a historical/educational project, not for profit.  The use of copyrighted materials is covered by fair use, as this is for educational use.  It is fine to use this for museum-type displays, but not included in a multigame that you're selling.  Don't be a jerk.

NONE OF THESE WORKS ARE TO EVER BE DISTRIBUTED FOR PROFIT, EITHER ALONE, OR REPACKAGED. 

JAMMA test rig box (Part 2)


I decided to package up my JAMMA test rig so that I could demo Crazy Otto at Rochester BarCamp for today.  My design was basically a box that would house the entire thing, with a nice control panel for player 1.  As you can see in the above image, I have the A/V cable going to an external monitor.  Broken out on the box are player 1 and 2 start, coin 1, and player 1 controls - joystick and 3 buttons.  On the right side of the box are the three "coin box" controls -- Test, Tilt, and Service, for testing those functions of the board.  Also on that side is a nice handle to help it be portable.

This is a continuation of part 1, where I updated the AV connections of the rig.

This is about the extent of blueprints I have for this.  I knew I needed 14" depth for the monitor, and that it needed about a 2" rise from the back to the front to put it at a good angle.  I wanted it to be 18" wide, and 24" deep.  That would give enough room for a game board inside of it, as well as for a decent sized control panel.


I started by cutting a sheet of plywood I've had in our garage for a while.  I also built the control panel using spare parts I had.


Some standard microswitch buttons, and a nice ball-top leaf-switch joystick.
The basic construction is that I glued some cleats on the inside of each side. Then the back, bottom, front and control panel will be screwed to it.  After that, it looked like this:

I also cut and drilled a small metal bracket to hold the power supply in place, which you can see in the above.  The coin 1 button on the front has a 12v light in it.  The old P2 controller is still attached to the JAMMA rig, in case I want to test/play 2 player games.  You can also see the 1 1/4" fine thread drywall screws holding it together here.  From here, the only change is that I painted it, stinking up our garage in the process. heh.  The top lid hooks under the control panel, and has a cleat in the back to keep it from sliding off the back.  There's a single screw to hold it in place, and to let it be carried withot the contents falling out.
The great thing about this thing is that it's easy to tote this thing around to play/demo games and such.  It takes two trips since the monitor is cumbersome, and the box itself is pretty heavy, but it's SIGNIFICANTLY easier than toting around a full arcade cabinet.

For reference, here's the JAMMA pinout standard:  (Most games since the late 1980s use this or a variant of it -- for example, Neo Geo adds additional buttons on unused pins, Rampart uses a trackball on the joystick pins, and Mortal Kombat has additional buttons on another interface harness.)
The power and ground at the top portion are wired directly to the old PC power supply.  Coin counters and lockout coils are not wired to anything.  The speaker wires are broken out to a RCA plug, and the Video (RGB,Sync) are out to a DIN connector, as seen in the previous post.  Service, Tilt, and Test are wired to the three switches on the side of the box.  Coin switch 1, and the two start buttons are on the control panel, as are all of the 1P controls (on the right).

Friday, April 4, 2014

Sparkfun Arduino Day / SD-Arduino device

Sparkfun had their "Arduino Day 2014 Sale" this past weekend.  Thanks to their sale, as well as an additional $20 off thanks to Reddit Gold ($4 for one month), I was able to get a whole lot of stuff at a really good price.


So here's what I got:

  • Arduino Uno R3 - I wanted a modern board with the 32u4 on it, for doing USB device enumeration type of stuff. My first thought is to put it on my C=64 keyboard, replacing the old Arduino Serial i've got on there, and turning it into a real HID keyboard.  That could be really neat.
  • Two Arduino Pro Mini 3.3v - For future projects, including a super small SD interface (below) And for $3, it's a no-brainer.
  • Two Arduino Pro Mini 5v - For future projects. Again. $3? No questions there...
  • Two soft-power switches - I need one for my Lego RCX/Arduino project, and I figured it'd be nice to have a spare for another project.
  • 5v-3.3v level converter - I've modified my old Sparkfun SD shield, which did not have level conversion, using resistor networks, and that was always a variable.  For the next time I need 3v-5v conversion, I have this thing to use, in my toolbox.
  • Pack of LEDs - because why not. I needed to pad my order to $50 to be able to use the $20 off reddit coupon.
  • Bunch of male and female headers, since I always seem to depleat my supply of these.  Useful thingies.

One of the things I wanted to do with the 3.3v Pro Mini was to try to make a serial-sd device as small and as inexpensive as possible, for a serial-based storage device and SD management shell project.  I did the trick of wiring up an SD-MicroSD adapter to the Arduino.  Since they're both 3.3v, i didn't need to do any conversion, so it's directly hooked up.


It was pretty straightforward wiring here. +3.3v to one pin, ground to two pins, then four data lines. Easy stuff.  The only nonconventional thing I needed to do was to wire up the FTDI connector to the RAW power input, rather than directly to VCC on the board.  My FTDI interface boards are all 5v, so that would kinda fry things.  The short red wire jumper over to the RAW input on the board means that it all gets regulated down to 3.3v, and everybody is happy.

Here's the wiring diagram:


The fun thing is, that it all fits inside of a SD Card storage case pretty neatly. (Well, not including the FTDI interface.) 


I figure that I can eventually work this in with a 2032 Lithium cell holder, RS232 adapter, and shove it into a DB-25 shell, for it to be a tiny "plug into serial port" storage device for my Tandy 102, Amiga 1000 or some other classic machine.