OpenTTD 0.1.4 on TurboLinux 1.1 for Power PC
So, TurboLinux 1.1 is up and running on my Power Computing PowerCenter 180. It took a lot of effort and what is the result? A cobbled-together version of RedHat 2.0 for PPC! Ancient. I should probably stick to tuxracer, but that may even be 'too new'. I want to get OTTD running on this, so I've chosen a really early version that will hopefully mean I don't need to uplift the entire kernel/OS to get running.
Automake and Autoconf
To build OpenTTD, we'll need an appropriate version of SDL. I chose 1.2.1 and, upon trying to build this, found out that it then needs newer versions of Automake and Autoconf. Actually, it requires Autoconf 2.13 and, perfectly, we only had 2.12 from the CD-ROM! One point makes a difference, eh? Linux from scratch has a great tutorial here for autoconf, so I just followed the instructions and installed very easily.
tar -xzvf autoconf-2.13.tar.gz cd autoconf-2.13 ./configure --prefix=/usr make make install
automake 1.4-p6 was then built and installed (same process as above, but with a different archive and folder name)... and now SDL would behave.
SDL 1.2.1
SDL was actually very straight-forward, once I knew what I was doing. I actually initially started down a path of upgrading the compiler and libc, but then quickly decided that it was a dependency-can-of-worms and just left everything as 'stock' as possible. So, back to SDL, downloaded 1.2.1 from here, extract it and try to configure it. Actually, you can't, you need to call autogen.sh first...
./autogen.sh
With the above auto* tools installed, autogen will sit quietly for a few minutes and then tell you that you're ready to run configure...
./configure
This completed cleaning, so now we just make...
make
This then took hours... and eventually failed! There was a very obvious error: the installed version of RedHat 2.0 (I mean, TurboLinux 1.1) does not have a linux/joystick.h header file! What to do/guess?
./configure --disable-joystick
It didn't complain, and rebuilt the Makefiles... including those in the src/joystick folder... bad sign? Let's quickly build that and see what happens...
cd src/joystick make
It compiled fine! Seems that it still needs to create a 'don't make anything' Makefile in there. Also, you could see a new GCC arg of -DDISABLE_JOYSTICK, so my fluke worked perfectly. Anyway, let's go back and re-build.
cd .. make
The build continued... And finished! What next?
make install
This also succeeded, with a few warning through it, and a bit of doco which zoomed past, not allowing me to scroll back up! Regardless, the following is used when configuring:
which sdl-config /usr/local/bin/sdl-config
Nice! But actually, it wasn't... I'd later find out that half of the source was still expecting joysticks and that I should've performed a make clean when I re-configure'd! Also, the SDL bits and bobs landed in the /usr/local folder... not optimal on this system, so at the very start, if you're playing at home, use this configure line instead:
./configure --disable-joystick --prefix=/usr
And then OTTD will build! Or so we hope...
OpenTTD 0.1.4
The source was extracted and I started by trying to configure:
# ./configure error: permission denied # chmod a+x configure # ./configure : bad option
Actually inspecting the configure script just shows it replacing the SDL variables in a JamFile? Uh oh... not a Makefile... we don't have Jam on here! There's also a Makefile, does that work?
# make ... Makefile:113: window.d: No such file or directory ...
Eh? Started building OTTD and it was quickly apparent that it hated the Makefile. I started creating a new version, and things were working, so I looked at the old one again and realised the line-endings were incorrect! Make sure your Makefile has just \n and not windows endings! Kicking it off again, all was working fine, until it got to minilzo.c/.h.
minilzo.c:249: Invalid token in expression
This file is sprinkled with multi-line \'d source and gcc simply hates it all... so it had to all be collapsed.
#define LZO_CHECK_MPOS_DET(m_pos,m_off,in,ip,max_offset) \ (m_pos == NULL || (m_off = (lzo_moff_t) (ip - m_pos)) > max_offset) #define LZO_CHECK_MPOS_NON_DET(m_pos,m_off,in,ip,max_offset) \ (BOUNDS_CHECKING_OFF_IN_EXPR( \ (PTR_LT(m_pos,in) || \ (m_off = (lzo_moff_t) PTR_DIFF(ip,m_pos)) <= 0 || \ m_off > max_offset) ))
All those slashes weren't allowed... so a quick find/replace in Notepad++ of '\\n' to '' worked a treat. lzoconf.h also had a few... but, with these all collapsed...
unix.c:10: sys/statvfs.h: No such file or directory
Indeed, the file didn't exist! But, statfs.h did, so I did a quick rename! And well, it built! And failed when I ran it as english.lng was missing. Usually you'd build the strings, but I stole the file plus the other required GRFs from my standard TTDX Data Archive.. that was always kept near for emergencies such as this!
And it loaded! Slow, chuggy and crashy with lots of frameskip warning shown in the console. Actually, the whole thing would segfault when I tried to move the window on the screen. From here, I'm happy to have achieved this much, but I'm not going to polish it. Instead, it's time to test a newer version of Linux.
TurboLinux 1.1 on a PowerCenter 180
I've been meaning to try this for a long time, after getting BeOS to work on the PowerCenter. Actually, I now realise I haven't even posted about that... I promise to do that later. Anyway, I'd recently been scouring the vintage column on eBay and trundled across a beautiful jewel-cased 2-CD version of TurboLinux 1.1 for PowerPC (original site). There was absolutely no one bidding on it, so I took that and a camera for a Raspberry Pi, of which I'll tinker with later.
For those who want a copy of the ISOs, I've dumped them via the instructions here. Of course, if you're inside TurboLinux (Inception?) then you can't use isoinfo as it doesn't exist. Instead, I loaded into Mac OS 9 and loaded up Adaptec Toast to get the data. Actually, I loaded up Toast to make a toast-formatted ISO. But instead, toast just 'stopped' when I asked it to save a disc image. Either way, dd worked with the parameters that Toast provided and I even managed to use a burnt copy to run the final install... how else to test?
A note on the images above, they were built with dd on ppc linux (TurboLinux 1.1 at that!) and they failed to burn with PowerISO. Somehow ImgBurn succeeded.
To get this up-and-running, I needed to put my PowerCenter 180 back together. I'd recently scavenged a few parts to get the AV Power Mac 6400 running (oh crap, that's another post that never happened) and so slapped RAM back in this machine and a second spare 50-pin SCSI drive.
Note that there's already some great tutorials online. This LinuxPPC Installation Guide by Jérôme Cornet helped me tremendously.
Preparing the SCSI drive
I could've/should've changed the order of this post... but for those playing at home who just want to get this installed and working, you'll want to set up your drive correctly first! When I was first tinkering, I happened to do it in the reverse order: slap the drive in and start the Linux install... I don't recommend this as the partitioning tool doesn't really like 'weird' disks. I had issues when trying to re-write the partition tables on PC formatted drives, to the point where some would prevent the machine from even booting.
To get started, you'll need a totally separate SCSI HDD from your Macintosh install (if you have one) to get TurboLinux going in a PowerCenter. On my specific machine, the OpenFirmware boot screen stays black, so I actually don't know if there are options there, or if the quik bootloader (installed at the end of the process) actually work. If they do, then you may be able to get away with one HDD, if the bootloader let's you back into Mac OS. Or maybe Boot-X will work, I'll test that at the end of the article.
Anyway, I grabbed a spare Seagate 2.1gb drive and installed it as SCSI ID 0. I then downloaded FWB Hard Disk Toolkit 4.5.2 and formatted it. Finally, the drive was partitioned with one 2gb root partition and one swap partition. I found that there are errors if the root partition is over 2gb, so please make it no larger. Note that you cannot use the LinuxPPC partition type. I tried this first and TurboLinux will just tell you that your drive isn't prepared. Instead, you have to choose custom and then type in Apple_UNIX_SVR2 as the partition type, for your swap partition also! The installer then distinguishes the partition by name, so make sure, as above, you call them root and swap!
Note that I didn't low-level format the drive the first time and managed to muck up the whole drive when attempting my first install. This was because I'd created a 4gb root partition and the system reported that it was out of space!? I then used pdisk in the installer and somehow whacked the drive to the point where it started reporting that it was only 1gb in size. Because of all this, I can only recommend that you simply start fresh with a low-level-formatted clean disk.
Grab your Linux CD
TurboLinux requires a 1.44mb floppy to boot the installer. Make sure you have a clean Macintosh-formatted floppy available. Note that during the install, it managed to fail when copying installer.coff file over to the floppy. I Ok'd out of the error and just copied the file manually. In hindsight, you should eject the floppy now! I then re-ran the installer, skipping the copy-to-floppy, and it turns out the final step afterwards is 'double-clicking' on the Install Linux icon that it's put on the desktop...
So, that Install Linux icon just loads up a preset into the Boot Variables control panel. This was installed by the TurboLinux installer and is just a GUI to manipulate OpenFirmware's settings. The preset it loads is to boot installer.coff file from the floppy drive. Double-click the link on the desktop and then choose Write & Reboot. It'll ask if you're ready to reboot. Eject the floppy now (if you haven't followed the above advice) and hit Yes. As soon as you press the button, slap that floppy disk back in. I took my time to do this the first time and got nothing but a black screen! Turns out my machine was sitting at the OpenFirmware prompt, but I couldn't see it and had no idea what was going on. At this point, as that I hadn't ejected the floppy, it got ejected as part of the reboot process (without me noticing), and OpenFirmware just baulked at a command to boot from a floppy disk when there was nothing in the drive.
What to do? Either reboot again with the disk in the drive, or just slap the disk back in, blindly type boot and hit enter.
Nostalgique RedHat 2.0 (I mean TurboLinux) Installation Process!
If you've made it this far, then you're doing well! My gosh... I remember sitting on the floor of a friend's house (Hi Nathan!) back in maybe 1997 installing RedHat 5.x and running through these screens. Back then the IP configuration confused the crap outta me... doesn't this come with a DHCP client? Anyway, this time around it was entirely painless... just follow the usual prompts...
Next up, partitioning! Make sure to highlight the correct SCSI device in the top list... use the tab key to get up there and select with up/down arrows.
If you skipped the partitioning step above, then you'll need to hit Edit and follow the next block. If you have already partitioned your disk, then hit Done and skip it with gleeeeeee...!
Partitioning with pdisk
Yeah, not fdisk, pdisk! Note that fdisk is also on the distro, but pdisk is a wrapper for PowerPC-style partitioning which knows how to create Apple Partition Maps.
If you've really keen to do it this way, then I'll assume that the installer has listed your drive and you've tabbed over and chosen Edit. From here, you're thrown to a console prompt at the bottom of the screen and you'll need to navigate pdisk carefully. Please make sure to chose the correct partition first, before hitting Edit!
Disregard that it tells you you've chosen one device in the /dev folder and that its actually loaded the same device from the /tmp folder. This is just the way it seems to work and you'll need to find the device in /tmp later if you want to switch to another console and hack behind-the-scenes.
Anyway, pdisk accepts most of the fdisk commands, such as p to list the partition table. If you want to mangle it yourself, then use d # to delete individual partitions or i to completely re-write the partition map and start fresh.
Once you've got space to create your root and swap partitions, you'll want to use the command c to create them. If you're feeling professional, then split everything up into usr/home/root into partitions (this stops one of them from stealing all of the disk space from another and causing system failure). But, if you're lazy like me, then you only need to create a 64mb swap partition and then another partition for root, filling up the rest of the drive.
The basic structure to create a partition is as follows:
c 2p 64m swap
The command above will create a 64mb partition with the name swap at position 2. You can then type p and hit enter to see the new listing. Specifically you can see how much space is left on the disk. I had 1.9g available, so I then created root:
c 3p 1900m root
As opposed to fdisk, you don't need to specify the partition types here. You just need to name them accordingly: swap for swap, root for root. After creating the root partition, I went ahead and checked out the table via the command: p.I was happy with it and wrote the changes to disk via w. Finally, q took me back to the installer and tabbing in a loop back to OK allowed me to proceed to the formatting stage.
Formatting and Package Selection
From here, if you haven't low-level formatted your drive, then I'd recommend bad-block checking on both formatting runs.
You'll then be asked the packages you want to install. Choose what you feel is relevant. You can always mount the CD-ROM at a later stage and individually install RPMS at a later date.
If you've chosen a miriad of groups, then there might be dependencies that need to be installed... please consider and then accept... otherwise your packages will fail to install.
The install will then make the filesystem on the root partition and install the selected packages. If you selected Everything, then expect the following errors during installaion! The packages seem to be corrupt on both the original CD and my copy!
Aww... no Mahjongg!? Note that the packages aren't really important... the machine still worked fine afterwards.
Finally it'll ask a few questions about mice, networking, printers and boot parameters. You really should take a photo of the final window to record the boot-device and boot-file settings required for OpenFirmware!
Once all is done, the machine will reboot, ejecting the floppy. I'd installed TurboLinux around 6 times by the time I'd gotten to this part of writing this article and every-so-often one wouldn't boot at this point... the machine would restart, chime and hang at a black screen. I had to use the magic 4-finger-salute: Option+Command+P+R to get back to Mac OS and then re-enter the boot params from the final step of the installation process back into the Boot Variables control panel and Write & Reboot. It would then boot without fail!
TurboLinux is starting for the first time...
Shit, it booted! But I got a lot of crappy errors in the boot log.. which zoomed past and landed me at the boot prompt.
I logged in as root (as the installer didn't let me create any other users) and checked dmesg...
Not good.. seems that anything network-related just crashed?
Let's check X-Windows: startx got me to a very mustard-flavoured OpenStep desktop, but the Netscape icon from the launcher did nothing... I then tried netscape from xterm and got a segfault! Why is all network-related code throwing exceptions? Oh wait, I have two PCI cards installed in this system doing nothing. One is a 'bootable' Sonnet IDE card and another is a Kingston KNE100TX LAN card. Maybe TurboLinux can't work out if it should be using the onboard LAN or PCI LAN? Let's remove both cards...
A clean boot! I can even ping!
Netscape then even wanted to load... but got sad when it couldn't phone home. Poor thing... a few decades too late!
Screen Resolution
TurboLinux will use the resolution that you had Mac OS configured to. That value is store as a mode-number in PRAM and, unless you've reset it recently, should therefore display how you expect. If you want to override this, then choose a value from the list below...
# 1 512 x 386 60Hz (interlaced, NTSC) # 2 512 x 386 60Hz # 3 640 x 480 50Hz (interlaced, PAL) # 4 640 x 480 60Hz (interlaced, NTSC) # 5 640 x 480 60Hz # 6 640 x 480 67Hz # 7 640 x 870 75Hz (portrait) # 8 768 x 576 50Hz (interlaced, PAL) # 9 800 x 600 56Hz # 10 800 x 600 60Hz # 11 800 x 600 72Hz # 12 800 x 600 75Hz # 13 832 x 624 75Hz # 14 1024 x 768 60Hz # 15 1024 x 768 72Hz # 16 1024 x 768 75Hz # 17 1024 x 768 75Hz # 18 1152 x 870 75Hz # 19 1280 x 960 75Hz # 20 1280 x 1024 75Hz
And replace the value '20' in the command below...
startx -- -mode 20
You'll then get the resolution you desire... as long as you have a monitor that supports what get's output. And maybe as long as you have the VRAM? This unit is decked out, so mode 20 worked fine. You can also pass -DEPTH with the value 8, 16 or 24.
Mounting HFS Extended Partitions
No-can-do out of the box! hfsutils can't mound HFS Extended partitions. Instead you'll just get the HFS shim with the Where_have_all_my_files_gone? file explaining that your data is still on the drive, but your current software is perfectly rubbish. I haven't found a solution to this yet... it seems that hfsprogs is open-source from Apple, but this OS may be way too old to compile it.
Getting back into Mac OS
There's a Linux tool called nvsetenv that will allow you to set the OpenFirmware boot-device setting inside Linux so that you can get back to MacOS on the next reboot:
nvsetenv boot-device "/AAPL,ROM"
Using BootX?
BootX (download it here) got installed whilst I was mucking around with Linux 1999 (mentioned below, and I'll write up a HOWTO on that also) during failed installs of TurboLinux. Just like BeOS, it throws a system extension in Mac OS with a symbol as the first character of its name to make it get loaded first. It then pops up a cute boot dialog to let you choose Mac OS or Linux with a configurable default. This is much nicer than the OpenFirmware prompt as it actually displays!
Unfortunately, there's an issue when you want to try and use it for TurboLinux. We'd need a vmlinux bootstrap kernel available for it to boot that matches the 2.1.x kernel in TurboLinux 1.1, otherwise there'll be a version mismatch. I tried all vmlinux files I could find on the CD; I even copied the exact file from the root partition... but BootX would just display a black screen each time I tried to boot it! Just for fun, I then used the 'Standard LinuxPPC' kernel with /dev/sda4 as the root and the bloody thing booted! But there was no sound and I had no idea what other damage might occur with a mismatched body vs. head.
So this is a really old version of Linux....
I went a'googlin and tried to find something newer, but there doesn't seem to be one! That site also doesn't have these ISOs, so I'll contribute those in due course. PowerISO on Win10 just threw a CRC error reading them? I might try Toast on the actual Mac. And then? Let's try LinuxPPC 1999 or LinuxPPC 2000.
But does it run OpenTTD?
There's no un-emulated version of A-Train to get running on here, so let's aim for OpenTTD. I've actually made this topic a new post as I nearly tripled the draft of this one with my moaning as to how hard it is to find a correct collection of libraries to build anything!
Smushing JSON into submission!
I don't even know how to describe this operation on JSON. The basic idea is that we want to deserialise a stream into something legible, without creating a class for each item in an array. json2csharp believes that each item should be an array since it sees them all as individually named classes. Let me prove it! Here's a chunk'o'data:
{ "trainCount":122, "requestTimestamp":1601124556789, "responseTimestamp":1601128156789, "nextUrl":"https://junatkartalla-cal-prod.herokuapp.com/trains/1601128156789", "trains":{ "8":{ "id":"8", "from":"LR", "to":"HKI", "title":"IC8", "latitude":60.172097, "longitude":24.941249, "speed":0, "direction":0, "category":"IC", "status":"1", "delta":60, "trainType":"LONGDISTANCE", "updated":1601127783841, "action":"deleted" }, "9":{ "id":"9", "from":"HKI", "to":"LR", "title":"S9", "latitude":60.571148, "longitude":25.199523, "speed":0, "direction":0, "category":"S", "status":"1", "delta":60, "trainType":"LONGDISTANCE", "updated":1601128143878, "action":"modified" } } }
So, if you slam that JSON into json2csharp, you'll get the following:
public class 8 { public string id { get; set; } public string from { get; set; } public string to { get; set; } public string title { get; set; } public double latitude { get; set; } public double longitude { get; set; } public int speed { get; set; } public int direction { get; set; } public string category { get; set; } public string status { get; set; } public int delta { get; set; } public string trainType { get; set; } public long updated { get; set; } public string action { get; set; } } public class 9 { public string id { get; set; } public string from { get; set; } public string to { get; set; } public string title { get; set; } public double latitude { get; set; } public double longitude { get; set; } public int speed { get; set; } public int direction { get; set; } public string category { get; set; } public string status { get; set; } public int delta { get; set; } public string trainType { get; set; } public long updated { get; set; } public string action { get; set; } } public class Trains { public 8 8 { get; set; } public 9 9 { get; set; } } public class Root { public int trainCount { get; set; } public long requestTimestamp { get; set; } public long responseTimestamp { get; set; } public string nextUrl { get; set; } public Trains trains { get; set; } }
So, that's actually uncompilable code. Is uncompilable a word? Dunno... this is actually the first time that json2csharp has failed me! No matter the options selected on the site, the output was always bad code... json2csharp doesn't work with ALL json! So, what to do? Well, we actually need to mangle this JSON into submission. The best bet would be to move that train id/number into the array object as a parameter, rather than having it as the dictionary key. We have two methods to do this...
Using jQuery MAP Function
If you are pulling JSON from a hosted browser, then you can run JS in the browsers console and produce cleaner JSON. In this case, you want to use jQuery's MAP function to rewrite each array object:
json_data.trains = $.map(json_data.trains, function (data, idx) { return data; });
If you feed the JSON at the top of this post into that function, you'll get the following:
{ "trainCount": 122, "requestTimestamp": 1601124556789, "responseTimestamp": 1601128156789, "nextUrl": "https://junatkartalla-cal-prod.herokuapp.com/trains/1601128156789", "trains": [{ "id": "8", "from": "LR", "to": "HKI", "title": "IC8", "latitude": 60.172097, "longitude": 24.941249, "speed": 0, "direction": 0, "category": "IC", "status": "1", "delta": 60, "trainType": "LONGDISTANCE", "updated": 1601127783841, "action": "deleted" }, { "id": "9", "from": "HKI", "to": "LR", "title": "S9", "latitude": 60.571148, "longitude": 25.199523, "speed": 0, "direction": 0, "category": "S", "status": "1", "delta": 60, "trainType": "LONGDISTANCE", "updated": 1601128143878, "action": "modified" }] }
Very nice.
Using C# Regex
I've never thoroughly learnt Regex and it still makes me sad. One day I'll sit down and go through a course. For now, googlin' works nicely to find an example for this scenario. Effectively we want to remove the "NUM": and just leave the curly braces. We then also need to remove a curly brace at the end.
var data = (new System.Net.WebClient()).DownloadString(nextUrl); data = new Regex("\"([0-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9])\":").Replace(data, ""); data = data.Replace("\"trains\":{", "\"trains\":["); data = data.Replace("}}}", "}]}");
So, the first line downloads the data. The second uses Regex to find anything in double-quotes that's a number from 0-9. I actually wanted 0-9999, but it seems you need to match each character 1-by-1, so I gave it options with | (pipe) up to 99999. From there, the third line turns the trains object into an array and the final line closes that array with a square bracket instead of the existing curly brace.
Final C# Class Output
With either of the methods above, you end up with cleaned JSON. From here, slapping that back in json2csharp gets you the following:
public class Train { public string id { get; set; } public string from { get; set; } public string to { get; set; } public string title { get; set; } public double latitude { get; set; } public double longitude { get; set; } public int speed { get; set; } public int direction { get; set; } public string category { get; set; } public string status { get; set; } public int delta { get; set; } public string trainType { get; set; } public object updated { get; set; } public string action { get; set; } } public class Root { public int trainCount { get; set; } public long requestTimestamp { get; set; } public long responseTimestamp { get; set; } public string nextUrl { get; set; } public List<Train> trains { get; set; } }
Thank you json2charp, that's exactly the reusability that I was looking for!
Repairing Atari 2600 Original Wireless Controllers
So, I've recently been repairing a large selection of Atari paraphenalia and, included in the container-load, was an official Atari-branded CX-42 wireless controller kit! The setup is pretty awesome; the base unit has a power input and then an output to go to the console. This means it doesn't need a separate power adapter as it chains into the power for your Atari. It then has the two controller plugs which you simply insert into the left and right controller ports on your console. Finally, the joysticks are more-or-less standard one-button Atari joysticks with extra 4cm bases to contain a 9v battery and radio circuitry.
Of course, this came to me due to being unhealthy. One of the controllers wouldn't go left! I'd usually associate this to cable failure, but... well... they don't really get much abuse in this scenario! They needed a good clean anyway, so the tear-down and diagnosis begun.
Is it the controller? (Hard way!)
So, just because I'd previously torn 100s of these apart, I went straight to the controller to check the internal switches. The construction of these is relatively simple, until you try to separate the joystick circuit board from the actual joystick... so many screws and springs fly everywhere. Regardless, once the unit was open, all switches were tested and found to be functional. I didn't think of taking a photo at the time, so you'll just have to imagine.
Is it the controller? (Easy way!)
After a little googlin', I stumbled across this hint stating that you could 'hear' the controllers using an FM radio. Hah, of course you can... It seems that they use frequencies down around ~40mhz, but somehow you can hear this at ~100mhz on your FM radio. So, what to do? Find an FM radio first. Fortunately I had some on the shelf thanks to wanting to listen to tapes a few months back.
On Windows 10, you'll find there's no more sndrec32. Instead you need to browse over here and Voice Recorder. Yey for anti-monopolistic effort! Anyway, I managed to record the following:
What you'll hear above is: Static -> radio station -> static -> radio station -> static -> weak carrier signal! -> misc. tuning -> STRONG CARRIER SIGNAL! -> 5 presses of the fire button -> ~7 full rotations of the joystick -> 6 presses of the fire button (the last one is longer) -> static. Totally random! But it's a great way to test.
As you can hear above, I started just above ~102mhz FM and scrolled down until I found the carrier signal. Note that I had difficulty originally finding the signal as it's not that strong. Make sure you hold the joystick against whatever FM receiver you're using.
Once the carrier signal was found, I then fine-tuned it until the signal was the strongest and began mashing buttons. Of course, just because LEFT is transmitting something, doesn't mean it's transmitting the correct signal! But hey, we can now check the base to see if there's any obvious issue.
Is it the base unit?
The circuitry inside this unit is, thankfully, quite easy to trace and diagnose. The unit consists of two individual circuits, decoding each controller independently. This is actually a life-saver, thanks to one of the joysticks being 100% functional! With my multimeter in-hand, I went ahead reviewing the circuit and measuring signals along the way. Doing this for both joysticks and both circuits meant that it was straight-forward to determine where the signal started going funny!
Starting from the output, there are two hex-inverter chips on each side. All 6 inverters (2chips x 3inverters) on each side are used and these flip the signal before sending it out to the controller port. The left button was seeing a twitch in the voltage, but not enough to flip the inverter to full +5v. The input was meant to drag to ground, sending the full signal out, but it wasn't happening.
Tracing the signal back, there is an OKI MSM4015RS IC and, for the life of me, I still can't find a datasheet online. I thought this would be a show-stopper, but after testing the signals on this IC for both joysticks when the fire button was pressed, it turns out they're both reporting the same values.
I therefore traced the value back up towards the output and found that the output after the first inverter wasn't being dragged low enough. It was 0.6v on the working joystick and 0.7v on the failing joystick. The output of the inverter is tied to ground with a green-cap and tied high with a 4.7k resistor.
The resistor checked out, but I had no way to test the capacitor with my multimeter. Instead, I swapped the capacitor from joystick one's side to joystick two's. Surprisingly, this now saw joystick one's LEFT button working and joystick two's was now faulty. Nice!
Replacing all green-caps
You'll find three different-valued sets of green-caps on this board: 10x 183k100v (18nf), 10x 223k100v (or 2A223K) (22nf) and 6x 104k100v (100nf). I went ahead and purchased a full set of them from Jaycar with the goal to replace every one of them.
Who knows how close another is to frying?
The aftermath... (did I say only the green-caps? Ooops.. I didn't discriminate and took out the electros as well.)
Removing and replacing was easy enough. I really recommend Goot-Wick desoldering braid for cleaning up the PCB whilst you're doing things like this.
Now up doesn't work?
Hah, seems that enough plugging-and-un-plugging of the controller output cables from the main board caused one pin to fail. Thanks to standard technology, there were plenty of these plugs in my junk box, although not with the same pin count...
So I borrowed an internal connector from a three-pin plug and soldered it in. Worked perfectly!
A minor note on the usage of these wireless controllers
With the wireless base unit powered-on and fully-connected to your Atari, it'll send spurious/erratic/totally-crazy signals to the console on the joystick cable of any joystick that is turned off! There is therefore a correct sequence for powering everything up... Turn the joysticks on first and then the base unit. Note that the base unit doesn't have a power switch, so I'd recommend always turning it off at the wall. I suppose you could then leave the Atari power switch on, as you'll be using the wall switch as the power cable is chained through the wireless controller receiver. Just make sure that both controllers are powered on BEFORE you turn on the wall switch!
When I was first diagnosing this kit, I thought all was pointless after seeing the random signals coming out of the base unit. I was very happy to see the signals settle once the joysticks were powered up!
Testing
This unit worked splendidly with 2600-series consoles and games.
Even 2600 games in a 7800 console. What didn't work was the built-in asteroids for/on the 7800.
For some reason, the down and fire buttons won't work. Of course, a standard 1-button Atari 2600 joystick works fine on 7800-Asteroids, but this unit doesn't. I did a little digging and found that the pins aren't brought straight to ground... instead they hover around 150-250 ohms... I wonder if that's enough to not send through a proper button press? Also, they seem to 'repeat'... the multimeter actually goes pretty damn crazy when a button is pressed, beeping on and off as the resistance floats near-zero. As mentioned above, each output is tied high by a 4.7k resistor and low by a 22nf green-cap capacitor. I assume the cap is there to de-bounce the incoming signal, but maybe it's not big enough to trigger a single press for the 7800? I don't want to modify this unit as it's very original, so I'll just suggest that if anyone else wants to use this on a 7800 then they should tinker with the pull-down capacitors on the output lines.
Again, they worked 100% perfectly with all 2600-series equipment I tested.
Battery Cover
One was missing, so I used my Creality CR6-SE to bring a replacement. It didn't turn out toooooo bad. Works well when there's a battery inside... falls out when there's no battery!
I’m not original…
In fact, my new best friend is over 16 years old!
I ... thiiiiink ... he's half deaf... might be time to replace his ears.
EZIO + OS9 + Hypercard (Or Just Windows)
The EZIO Board is a serial-based I/O module that can connect to both Windows and Macintosh machines. Actually, it can connect to anything that speaks RS-232. One of these came up on eBay recently and I couldn't resist. I saw the Macintosh serial port and decided to give it a go. It's really similar to an Arduino, but from a few decades before the Arduino was even a dream. If I'd known about these back in the early 2000s then I would've definitely had a very nice automated model railway. But alas, I only happen to find one now thanks to eBay!
The unit has 10 digital output lines, 10 digital input lines, 8 analog-to-digital lines and two PWM lines. You then get 4 +5v terminals and 4 GND terminals. There's a PIC microcontroller in the middle running the show and a MAX232 for the RS-232 comms. The unit has a DC-rectifier, so you can feed it 5-15v either AC or DC. The 5-15v is literally the operating recommendations of the 7805 voltage regulator on-board.
There's a whole lot of code on the old site (yeah, you have to use web archive to get to it), but it's mainly for Director!? and Macintosh. Hilariously, the Macintosh example uses Hypercard! Before booting up the Power Mac, I instead wrote a quick bit of C# to test out the unit.
The shot above uses dotnet-ncurses, allowing the console to act like a canvas. It's really nice to be able to draw text to specific areas, rather than scrolling the screen. Anyway, the basic idea is that you can control the digital out and then everything else is read in. Interestingly, floating pins show some very random values... so if you're using this device, make sure you tie everything to ground or use pull-up resistors where appropriate.
Of course, the whole reason I bought this was due to the Macintosh serial port. I wasn't overly-energetic, so I tried a virtual Macintosh first...
After installing Hypercard, the app came up, but the performance once it started trying to interact with the serial port was terrible. It also just didn't work, so I gave up and booted up the Power Mac.
Yup, works a charm. Hypercard is pretty clunky, but I'm sure you could do a lot with it. I'll have to dig out the railway track and control a train!
Philips CDI 450 – Laser Replacement
The Philips CD-i (Compact Disc-Interactive) brand/tech was released back in 1990 to add a level of interactivity to CD-ROM based entertainment. Philips, from 1990 through to 1998, produced and released multiple devices for both the home and educational markets based on this technology. One of those models was the CDI 450 and I just happened to stumble across one a long time back at a Belgian flea market. It's been in a box for quite a while and I've only just gotten around to looking at it... The driving factors were: #1 COVID lockdown is driving me crazy and #2 there's a version of The 7th Guest for this unit!
The unit came with the power supply, a controller with it's face missing and, randomly, a game CD in the drive.
The controller was obviously useless, so I went to GAME OVER? in Amsterdam and picked up the cheapest controller I could find.
There's the standard rule of 'sunk cost' where you don't spend large amounts of money on something that could be dead. I then returned to Australia and the unit has been in the box since. Only recently did I turn it on...
Cool! It works! My French is rusty, so I wanted to try and get other games working. No matter what I tried, the unit would not read CDRs. Every google search I tried lead me to believe that the laser was gone, or going, so I scoured eBay for a replacement. It turns out that searching for VAM-1201 will give you shops in China that have the exact 'new old stock' component that I needed! I ordered one, expecting it to take years, instead having it arrive in just under two weeks!
Popping open the CDI was easy enough. There are four screws in the unit. Two are in the CD bay and two are in the 'optional module area' to the left. Open the CD lid and then remove the plastic shell to the left. It has two clips that need to be pushed in. Woah, what's this? My unit has the Digital Video Cartridge!
With the screws out, you'll now find the RF shield in the way... remove this evenly, prying it up from each corner and making sure there are no wires in the way.
Mine had a lovely amount of discolouration... maybe from the rain that was falling in the flea market in Belgium? Fortunately the motherboard looked pristine.
The Laser aparatus consists of the laser unit and drive motor in a plastic housing, attached to a metal plate via rubber suspension joints. This whole component is held in place by the two screws from the main case and two plastic lugs along the top frame. Gently lift the whole lot, evenly pulling it up. The top two lugs are quite tight, to make sure to ease the unit vertically away from them until it's free. Once done, don't lift too high as you'll first need to disconnect the data ribbon cable and power cables underneath.
Once done, you then need to remove the laser unit from the metal plate. It's held there by four rubber spacers. Note that these are old now, so be very gentle when sliding them out laterally from the slots in the laser housing. I managed to break one when doing so, but fortunately this didn't impact the ability of the unit.
Once you've slotted the new laser on the housing, place it back into the main unit. This is as simple as lining up the lugs at the top, holding the unit at 45-degrees whilst doing so. Note that the wired cable might be longer than the original... just place the wires somewhere in the spacing to the bottom-right. Also make sure the wires don't get pinched when you place the RF shielding back in!
From here? We test...
And the icing on the cake:
A perfect game to test out the DVC! It worked very very nicely.
Atari 2600 Jr – Reset/Select Switch Repairs
I'd recently come across an Atari 2600 Jr with faulty select and reset buttons. Turns out that the mylar strip that conducts the button presses to the motherboard is toast. It doesn't conduct anything at all and I can't work out exactly where the break is.
To test if the button area even works, you can insert wires as above and check for continuity. In this case, they did, so I considered the following options to repair them.
Silver Conductive Pen
This nearly worked, but I couldn't get the paste to set correctly. The pen is from Jaycar and the basic idea is to draw a line where you want the circuit and let it set. I drew some pretty bad lines on the plastic film, but my first attempt seems to have failed as I drew the tracks too thickly. The 'ink' only becomes conductive once it's totally dry and I'm blaming winter and the fact that I don't have an incandescent bulb in the house anymore.
The next attempts were seemingly too thin. It also seems that you can't 'restart' a trace... the joint isn't conductive? Finally, the resistance seen down the track is totally erratic... but that may also be due to wet ink.
Threaded Wire
I punched a few holes in the mylar and threaded copper wire through. It was a little too stiff but, once in-place, seemed to work quite well! The main issue with this method is that, at either end of the plastic strip, adhering the wire to the conductive trace is difficult. Of course, at the motherboard end you can just jam the wires in the socket!
At the button end, you need to slip it in under the top-layer of plastic. I didn't feel confident that I could keep a valid joint and therefore didn't pursue this technique.
Microswitches
Prior to opening and testing the methods above, I was always intending on just replacing whole plastic strip with microswitches. There's a nice plastic base behind the push buttons and one could easily drill in some switches. This would also give a nice tactile experience to what is (from the factory) a really awful and mushy button press.
I went ahead and drilled holes slightly smaller than the switches. From here, I gouged out the rest of the required space as I wanted a tight fit. Of course, I was imagining things thinking that I tight fit would be enough to hold the switches in place... a hard button-press would probably send them into the case.
Therefore I glued a strip of plastic (yeah, it's a cable-tie) along the back of the holes as a backing plate for the switches. This worked perfectly! I probably should've soldered the wiring first, but it was easy enough once the switches were in position!
Once it was all back together, it turns out that the buttons were pressed in 100% of the time. To fix this, I had to drill out a section of the plastic where the button meets the switch. This worked nicely. I then decided to remove the rubber as the press was being overly-softened by it. I'd recommend you test it both ways to see which feels the best... you can also try mounting the rubber on the actual case to make sure the alignment is correct.
From here, I just soldered the wiring up to a standard pin-header which fit snugly into the socket on the motherboard.
Testing began and the switches performed perfectly!
Fluke Multimeter Repair – Elastometric Strips
What what? I'd had this Fluke Multimeter sitting broken in my box'o'junk for literal decades. It used to work great, but failed at some point a long time ago and was never fixed. Recently, I snapped the cable off a shitty AUD$10 multimeter that I'd been using and so, in my infinite wisdom, thought I'd resurrect the Fluke!
It turned on, but the buttons didn't work.. so it wasn't much good except for the default setting of DC voltage. Testing voltages takes up 50% of my time, but I still need resistance and continuity! Let's rip it open...
So, not shown above (since I'd already fixed it and this post is months old) is that the strips of weird rubber weren't both there. The top strip was, but it turns out there's a lower strip needed. I had probably replaced the battery back in the day and somehow managed to discard the strip that conducts the button presses.
That's where it was meant to go. You can sorta see there's 5-ish segments on the PCB down in the channel, but there's a beautiful air-gap between that PCB and the mainboard. What's meant to go in the middle? I popped out the strip at the top and I, telling the truth, had no idea what the material was. A little bit of googlin' allowed me to realise that it was elastometric strip! Andy's Surplus came to the rescue and quickly delivered two cuttable strips of elastometricity!
Cut.. cut again...
And cut once more and ... TADA!
It works. And whilst the beast is open, replace the battery and solder that battery terminal!
Damn this thing is beautiful.
Burning 16-bit EPROMs with a Willem Programmer
This wasn't fun! I wanted to get Kickstart 1.3 on my Amiga 500 and so I purchased some M27C400 EPROMs from eBay with the thought that I could host two ROMs on them and make it switchable. The ROMs arrived and, to my stupidity, didn't fit in a standard Willem EPROM Programmer! Of course, a quick google prior to purchasing anything would've made this very apparent. Fortunately, there's a fix! You can buy a DIP42 16-bit EPROM Adapter for the Willem, and so I did.
Thanks to COVID, it took an extra-specially long time to arrive and, once it did, got thrown into the box'o'Amiga'junk as I'd put the whole lot on the backburner whilst working on the Ataris of late. This weekend I'd finally managed to wrangle some time together and sat down with my trusty XP laptop to program these chips.... It wasn't easy!
Input Voltages
I jumped head-first into the programming and failed a LOT with errors such as 0x00 and 0x11. Any search online will tell you that, when getting lots of 0x00 and 0x11 errors, it mainly indicates that you aren't supplying the correct programming voltage for your target chip. Check out the PDF Datasheet for the chip you want to burn, it'll specify a programming voltage that it requires to successfully understand and store the bits that you're about to throw at it.
For the M27C400, we need to provide 12.5v +/- 0.25v. The Willem has a blue trimmable capacitor (or is that a resistor) on the top-right of the board that you can adjust to get this voltage. I always recommend to use an external power supply with these programmers and so I have a plug-pack which happily provides 12v @ 2amps. To make sure we'll have a chance of programming this chip, switch to the Test H/W tab of the software and tick VPP. This is pin 1 of the E32 socket. If this has worked, then you'll have a red LED illuminated on the board. Now, check the voltage between pin 16 (GND) and pin 1 (VPP) of the socket.
Mine was reporting a value lower than 12v to start with and hence I had a few issues burning. With a multimeter in place, I tuned the trimmer on the top-right and got the value to 12.5v. Actually, it was probably 12.6... but 12.4 would also work as you just need to be in the range of 12.25 - 12.75.
Another test burn saw a new error... no more 0x00 and 0x11, it was now further into the chip, usually around 0x100?
Willem Software vs. Programmer Settings
Next up, we need to make sure that you can correctly control ALL address lines with your Willem Programmer. After fixing the initial errors above, I started getting new errors at random intervals into the burning process. The errors all seemed to indicate that there was an issue writing data after address 0x100. I'd only been using empty chips, so it couldn't be because they already had data on them. You can also check if the chips are empty prior to burning and I totally recommend doing this. Either way, after this new error was received, I chose to then read the chips and view the data:
What you're seeing above is the data read back from the chip. I wrote the rom (loaded from file) to the chip, got the error and then chose to read the data from the chip back into the application. 75% of the data on that screen is correct, but you'll notice that the data repeats itself from 0x100! It turns out that this was all due to the fact that my Willem was only controlling the first 8 address lines and leaving the rest low. I recommend you rig up an LED test harness as per below and control the address pins via the Test H/W tab on the Willem Software.
After swapping chips around, checking continuity between the 4051s and reseating everything else, I came to the conclusion that there's incorrect information in the Standard Willem Programming Guide. If you scroll to page 5, you'll find information on the version of the software to use. It suggests that, based on jumper settings on the board, you can select if the board emulates a PCB3B or PCB3.5. If you've chosen PCB3B, then you'll need to use software version 0.97ja, as per my post from a long time ago, when I was failing with the same issue! Alternatively, if you've chosen PCB3.5, you need to use 0.98d6 or higher.
I looked at my board and checked out the jumpers that set the board emulation. Mine were actually individually set to 1-2 and 2-3 instead of both 1-2 or both 2-3. Hah... how did this thing ever work?! With these jumpers now set to 2-3 (aka PCB3B), I went back to version 0.97ja of the software and tried to get the full suite of address lines to light up via the Test H/W tab. No dice! If you browse to page 6 of the above PDF, you'll find that the jumpers should be set to 1-2 for PCB35 and 2-3 for PCB3B. Just for fun, I switched the jumpers to 1-2 and tested out version 0.98d6 of the burning software... still no dice! No permutation of checkboxes on the Test H/W tab would get a high signal on any of the address lines higher than A7! Up until this point in time, I'd only programmed 8-bit EPROMs, so I'd never noticed this.
I went ahead and played musical-chips. There's a chain of CD4015BE ICs that shift out the address lines, 3 of them with 1 each controlling 8 bits. It seemed plausible that there might have been a faulty connection between the first and second, but no amount of tinkering brought the address pins to life. I took a break as the frustration (or was that sadness) levels were elevating and sat down to a bit of TV. With a fresh mindset, I came back to the device, forgetting which settings were applied. Opening up version 0.97ja and testing address lines now worked!? Wait, the jumpers are set for PCB35... what the hell, it's backwards!? I opened 0.98d6 and it didn't work, so I set the jumpers back to 2-3 (for PCB3B) and it now 0.98d6 worked!? Urgh... so much time lost. So, TLDR; The PCB3B/PCB35 jumper settings are backwards on my Willem Programmer. Set them to 1-2 for PCB3B and 2-3 for PCB35!
Using the adapter
First up, there's two jumpers on the adapter to configure. The right-most controls the VPP/A21 line and needs to be set to 1-2 for M27C400 or M27C800 EPROMs. The other, in the middle of the board, I left at 1-2 as I don't know what it does.
Next up, there's a ribbon cable used to obtain more address pins from the main programming board. For the M27C400, the base E32 socket of the Willem actually produces enough address lines, so this ribbon cable isn't actually needed. Check out the diagram below to work out how the adapter is constructed. I've coloured the lines that are used on the M27C400 and 800, where you can see that the 400 doesn't use any of the wires from the header on the right.
If you're going to program an M27C800 or larger, you'll need to connect this. Simply make sure that pin A23 (bottom-most) lines up with A23 on the Willem board.
Finally, when inserting ANY chip into to the socket, make sure that the pins are all straight and that none will foul. For any of the chips, always make sure that the bottom pins are at the bottom end of the socket. The EPROMs are designed so that the Address lines extend 'north', so the silhouette on the board is actually for an M27C800. An M27C400 will be one pin lower than the silhouette, aligned at the bottom of the socket.
Conclusion
All the errors I made above would've been avoided if I'd known what I was doing from the start. Usually the old RTFM instruction makes sense, but when the jumper settings work in reverse to the manual, it's a little frustrating. On another note, I'd just trusted that this piece of hardware worked, as I've managed to burn other chips in the past. Assuming that cheap hardware just-works(tm) is a flaw in itself. Always make sure you know the hardware you're working with back-to-front, which was totally possible this time around thanks to open-source schematics being available!