Apple PowerBook Duo 230
This little beast arrived last week and I've finally cleared the workspace to work on it. I've been on a bit of a buying-frenzy since christmas, so there should be some random things appearing on here in the next few weeks.
Anyway, it was cheap because it's damaged. It's reported to have a non-responsive keyboard, a broken screen latch and a poor install of System 7.6. The poor install is described as "every app, when double-clicking, just throws error -39".
Keyboard
So, turns out people have fixed these before. That's a cute story.. but I have never thought of using an eraser on any of those goddamn-awful rubber buttons. Does it work?
Got the required utensil... next...
Ok, getting the keyboard out was easy enough... just don't follow these instructions. The author says to remove the bottom two screws... this is WRONG!. Remove the top three instead! Actually, I just checked the link... he's responded saying he'll fix it. I left a comment under the image where he points to the screws to remove. Anyway, where were we... Under the keyboard, you'll see how the keys are held in. I initially wanted to remove the backplane, but it's plastic-welded in place via the lugs.
Above, in the dark holes, you can see that the keys are held with two opposing clips. Turns out that, if from the top-side you just apply gentle pressure to the top-half of each key, it'll gently prise out!
Once the keys are off, you have direct access to the rubber sheet. This actually has the graphite contact rings under it, so don't be too rough!
As you can see, each key has a black ring directly under it that is pressed down onto the membranes. There are actually two membranes, but they act different to the regular press-them-together. Usually there's a third sheet in-between the two membranes that keeps them separate... instead we have two membranes that form opposing semi-circles that the rings under the keys connect.
So, from here, GENTLY rub the areas that receive contact from the rubber rings. There's a caps-lock LED to the left that you need to watch out for... what did I say? Watch out!
Too late... my eraser was too large, my force too strong. I recommend using a pencil with an eraser on the end... or just anything with a finer tip! I'll fix that LED at a later date. Let's assemble and see the difference.
Yessss! It works beautifully. Meanwhile, there's weird red dead pixels... but they don't line up with pixels... maybe there's something in the screen layers... fun for when I replace the latch later.
It's alive! Time to network it. And reformat once the MiniDock arrives.
Replacing the ear microphones on a Sony Aibo ERS-7
He'd arrived a few weeks back and gets energised a few hours per week... but he's a bad dog! He says "Good bye" in repsonse to me saying "Hello Aibo" and I'm going to blame him first... it can't be my mumbling? Can it? Just to be certain, I browsed around and found a DIY Repair Guide on Aibo Doctor. I quickly ordered a selection of microphones from element14 and got to work. Canine surgery is daunting!
The Microphones
As I always manage to get my orders wrong, I went ahead and ordered a selection of Microphones.
Note that an ERS-7 Aibo needs 6mm microphones, so you can see that one set is already incorrect. Next, there's directional and omni-directional. The microphones in Aibo are omni*, so I settled with the KECG2742TBL-A units.
Disassembling Aibo's Visor
Following the instructions here, one can disassemble Aibo's head to get to his ears. First step, remove the rubber earlobes by stretching them over the silver joint. Next, open his mouth and remove the two screws.
With these two removed, you can un-hook the rear of the bottom half of his head. This shell is not directly connected to his bottom jaw, so open his mouth fully and then push the whole lower-half back. With it unhooked, you can then bring it forward again and bring it over his jaw. With this piece out of the way, it's back to the front of his head where we need to remove the two outside screws on the metal plate inside his nose.
With those two out, you then need a longer screwdriver to get to the two screws deeper inside his skull. They're on either side of where his jaw would attach near his ears. See the image below, one screw on one side is in focus.
Finally, there's a clip on each side just in front of his ears, holding the visor on.
Very gently pry this open and the visor should lift up. You now have the option to disconnect all the cabling, but instead I just let it rest forward. Make sure it doesn't put undue pressure on the ribbon cables inside.
You now have access to the ear joints.
Disassembling Aibo's Ear Joints
Ok, this isn't the actual ear/microphone yet... before we get to that, there's a bit of fidgeting required to get the ear joints disassembled. When following the next steps, at no time will you need to apply excessive force! Doing so will most-probably damage poor Aibo. The ear joints are a two-part component and are built to be assembled/disassembled with ease. If you look at either side of Aibo's ears, you'll see that one side has a fixed arm and the other has an arm that slides backwards. The fixed arm is at the front and also has a little actuator (metal bar with notch) that is the mechanism that flaps Aibo's ears around when he's playing.
So, back to the joints: two pieces, first is removed by sliding the rear arm further to the rear. From there, you can grab the whole circular joint and unhook it from both front lugs. There's a lug in the actual main arm and a lug in the little black actuator arm.
The image above doesn't really help to explain how to undo it. The movement is one-shot and you can see in the photo above that the black actuator is on the left. This means that you're looking at Aibo's right ear and that you'd grab the top silver circle and slide it gently to the right (rear of his head) until both lugs are clear on the left. Once done, you can then slide off the rear shield.
From here, it's a single screw and the microphone + housing is free. Make sure you also unhook the cable!
Replacing Aibo's Inner-Ear
With the microphone unhooked and unscrewed, the silver shell can be lifted off (gently) by applying pressure to the joints that hold it on. With this off, you can really see what condition Aibo's ears are in!
From here, you can slide the microphone out, just enough, to be able to de-solder and solder a new component.
As you can see, I cheated and used the phone the new microphones came in to hold them in-place whilst soldering. I used the datasheet to make sure I got the polarity the correct way around, assuming that red was positive.
With everything wired up, the microphone was pushed back into the housing and re-assembled. Make sure that you have the wires in the correct groove according to the side the ear has been removed from!
Finally, as per above, there is absolutely no need for excessive force on any part of this assembly. I found that, once trying to re-fit the visor, it wouldn't sit flat! Turns out that I'd assembled the rear part of the ear-joint incorrectly and only one side of the guides was actually in the right spot!
If you look above, you can see that the left guide is sitting above the plastic strip that it was meant to slide onto! This meant totally dismantling that ear again to pull that part back and slide it back on again! Painful, but required.
Can Aibo hear me now?
Nope, same as before! Turns out you can just use Clinic Mode to determine if his microphones actually really need replacing! I should've done this first, but I also sorta wanted to play doctor and see what his insides looked like!
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!