tomek's blog now I'll lie

Macintosh System 6 and 7 images for IOmega ZIP

As described in the previous post, I’m using SCSI IOmega ZIP (Z100S) drive as a mass storage for my Macintosh Plus. I prepared zip floppies with a few versions of the Macintosh System installed - if you’re into retro computing it’s fun to compare the performance and the features between different OSes.

I dumped the zip floppies into disk images, so they can be easily restored. All you need is an USB zip drive (Z100U) connected to your modern computer (Macbook Pro in my case). Images can be downloaded below:

Besides from the system, images contain a fair amount of abandonware tools and games (MacWrite, MacPaint, MS Excel & Word, StuffIt, ZTerm, Civilization, Lemmings, etc.)

If you use OS X / Linux, the images can be written to the zip floppies using the dd command:

gzip -c system608-zip.image.gz | dd of=/dev/diskX

where /dev/diskX is the appropriate device. On the OS X it’s a good idea to disable the automount feature, as the OS may corrupt the old HFS filesystem once it’s written. The Disk Arbitrator can be used for this purpose.

The images can be also used with emulators (like vMac or Basilisk II). It’s only required to extract the HFS filesystem (as the image also contains the IOmega drive, partition table which confuses the emulator):

gzip -c system608-zip.image.gz | dd bs=512 count=196106 skip=491 of=system608-hfs.image

The resulting system608-hfs.image is an emulator-bootable image:

System 7.5.5 on Mac Plus

Resurrecting my Macintosh Plus

I wanted to extend my vintage computer collection with a classic, all-in-one Macintosh for a long time. Unfortunately, they are not so common in Europe as in the US and the costs of the shipment are often higher than the computer itself. Sometimes you may find something on the local auction portal, but usually it costs a lot.

My Mac Plus

That’s why I was really happy to find a Macintosh Plus in an attractive price. However, the low cost was justified — according to the description, the screen was dead, it also lacked of the mouse and the keyboard. Who cares, I’ve got it anyway. The worst case scenario — I’ll get a modern art sculpture.

Fixing the screen

So, the first thing to fix was the screen. I hoped that it’ll be enough to turn the brightness knob, but it wasn’t the case. Internet forums and the amazing book about fixing classic Macs — Macintosh Repair and Upgrade Secrets — suggested that the black screen is often a symptom of the cold joints in J4 connector. I get all of my engineering skills and touched the offending pins with the solderning iron:

Cold joints photo

After switching the Mac on, it presented a beautiful icon of floppy disk with blinking question mark:

I’d never been happier in my life and danced around the room seeing this icon :) An interesting thing that I also found in the Mac was this box of old batteries:

Old batteries

Apparently the previous user tried hard to keep the internal clock powered, without the original battery.


You can’t do much on a Mac without a mouse. The Mac Plus uses a different kind of mouse than PCs or even later Macs. Some people were able to convert an old, ball mouse so it’s compatible with Mac Plus. However, it seems that it’s much easier to use Amiga or Atari ST mouse - it have the same internals, the only difference is pinout. Two DB9 male connectors and a bunch of cables did the trick:

Amiga mouse connected to Mac

I guess that you can also connect an USB mouse, using the USB-to-Amiga mouse converter (eg. Jerry and the custom DB9 pinout as above).


At this point I was able to move the mouse pointer on an empty screen with a blinking floppy icon. In order to move things forward, I needed a system. One option is the Rescue My Classic Mac webpage offering a complete set of floppy disks, containing system, games and disk utilities.

I took a different path and asked on a Polish Facebook group dedicated to the old computers and game consoles. In a few hours I was contacted by a few people offering their help. Eventually, I’ve got the system disk (and the Lemmings game) from Paweł - thanks!


Mac Plus memory can be easily upgraded from 1 to 4 MB. All you need is a bunch of old 1MB SIMM modules (preferably with 8 or 9 chips). I’ve bought 4 such modules ($1 per module), installed it in the Mac and cut the resistor leg:

Installing memory

The last part was a bit scary (what if the RAM doesn’t work?), but everything went fine and now I can enjoy 4 times bigger RAM:

4MB RAM screenshot


In case of computers like Macintosh Plus, with its innovative GUI, the mouse is much more important than keyboard. Still, sometimes it’s good to type something and my Mac lacked of the keyboard. As you may guess, it’s not a standard PS2/USB/ADB keyboard, but a device specific to Mac 128k/512k/Plus models. It also has a strange connector - the same as for old phone sets.

Using resources available in the internet, like this blog post and Mac Plus technical information I was able to create an Arduino-based converted that allows to use a PS/2 keyboard with Mac Plus. I think it’s pretty neat:

Arduino - PS/2

The project can be found on my Github.

Hard drive

Macintosh Plus, unlike the later models, comes without a built-in hard drive. Floppy disk drive is the default storage device and it isn’t great at all — unreliable, slow and offering little space.

The computer has a SCSI port, so we can connect an external storage. External SCSI hard drives (even the old and small ones) are a bit pricey, but there’s an interesting alternative: IOmega ZIP drive. It’s often used as the main storage for the classic Macs and 100 MB of the disk space it offers on a single floppy is more than enough.

After reading a ton of blog posts and forum discussions, I decided to use the IOMega ZIP Init 4.2 driver to format the drive. Another collegue from the retro group offered his help. Using his Powebook 150 I created the floppies containing System 6.0.8 and the driver. Now I was able to install the system on ZIP. It booted happily!

The aforementioned Rescue My Classic Mac also offers the floppies containing System installation and IOMega driver, in 800k format. It may help if you don’t have any classic Mac equipped in the HD drive nearby.

Serial port connection

Macintosh Plus is unable to read PC-formatted floppies (even 720k), so I had to find another way to exchange data with my MacBook Pro. I decided to use the serial port connection. Mac uses Mini Din-8 RS-422 standard, but it can be easily connected to the DB9 serial port. For some reason the X/Y/ZModem file transfer didn’t worked, so I was forced to transmit files as binhex-encoded text. It’s very slow, but works and allows to communicate with Mac.


So, from a blank-screened, mouse- and keyboard-less Mac Plus I’ve got this machine:

The final specs are as follows:

  • Macintosh Plus,
  • System 7.0.1,
  • 4 MB RAM,
  • Amiga mouse connected via adapter,
  • PS2 keyboard connected via Arduino,
  • IOmega 100 MB ZIP used as a hard drive.

It’s an amazing machine and I feel that amount of the work and time I have to spent to get to this state makes it even greater. Probably if I’d bought a slightly newer Macintosh SE/Classic, containing an internal hard drive and the standard ADB ports I wouldn’t have to deal with all of these issues myself. But I don’t regret any second working on it :) I’m just glad that I was able to put one of these little computers back to life.


Bay Area

Travelling alone has its bright and dark sides. You can neither share the excitement when you notice a sea lion swimming next to the boat nor look all the 227 meters down the Golden Gate Bridge. But you are free to do whatever you like, without discussing your options with anyone. For instance, you can exchange one more day in San Francisco for visiting the Computer History Museum in Mountain View, which probably isn’t the way of spending your holidays that many would choose.

In the museum you will find a former ballistic missile that after its retirement started an academia career as an univeristy, general-purpose computer.


Renting a car

The lady at the Avis counter tried really hard to give me this Camaro.

— Mustang is an entry-level sport car. But Camaro (Camaro!) is really luxurious.

She also told me that they have a red Camaro, but Mustang (which I originally booked online) is only available in black. What could I do? I chose the luxury and agreed to get the Camaro. When it came to signing the deal, lady Avis told me that Camaro is only $30 more expensive than Mustang - per day. Given this unexpected piece of information, I decided to stick to the original choice. However, she wasn’t accepting “no” as an answer:

— OK, there’s one more thing. Please tell me which airlines did you use to get here.
— Lufthansa - I said, adding that I don’t have the ticket anymore.
— No worries, it’s important that you are Lufthansa customer. For such special clients we have a discount: only $10 extra fee for Camaro.

Really, I didn’t have a chance.


Pacific Coast Highway

If you’re going from San Francisco to Los Angeles, you can either take one of the standard highways and see the Hollywood sign in about 5 hours or choose the Pacific Coast Highway, part of the State Route 1 (and admire the views for 8+ hours). It was the best 8 hours during the whole trip. The road is simply beautiful, with Pacific Ocean on one side and a steep wall of mountains on the other. It really deserves to be contemplated. A lot of people did - you’ll find multiple viewpoints there. Seriously, you should see it, at least in the street view:

I was listening to the latest Iggy Pop album. There’s this song, Paraguay, about escaping from the civilization, from all of these information and knowledge, that really resonated with me then, at the western edge of the North American continent.

Tar pits

The main museum in Los Angeles is LACMA. It isn’t unusual for the museum to have a small park in front of it, so you can enjoy trees and fresh air before or after enjoying the work of art. However, in case of LACMA, the fresh air part is not entirely true. You can smell some oil or petrol scent here and there in the park, but it isn’t caused by the vehicles. There’s a few small lakes across the park (and one quite big) filled with a thick, black oil. They are fenced (as they probably would be fatal for a potential swimmer) and bubbles from time to time in the way, that only a thick, black oil pool can bubble.

It’s really strange to see such lake in the middle of a huge metropoly.

Mulholland highway

A really good way to feel the Americans’ love for their cars is going to the Mulholland highway in the Sunday morning. The road is very curvy, scenic and runs through the mountains. Every week you can spot multiple sport cars there, from old BMW to new Ferraris and from Corvettes to Fiskers.




Last day I hailed an Uber to get to the airport. A black lady was driving and listening to some really nice music. She wasn’t really talkative (unlike the other Uber drivers), but that was fine. I used Shazam to find out what song is that. A minute later the whole album was downloaded to my phone. We exchanged a few words about crazy taxi prices and she wished me a good flight. Later, I submitted an Uber comment to the ride: “great music, thanks!”. Now it’s time to go home.

Radio AdBlock 2

In the previous post I described the process of creating an ad-blocker for the polish radio station “Trójka”. It uses cross-correlation and fast Fourier transform to detect the ad jingles in the internet radio stream, silences the commercials and outputs the result. In other words: it plays the internet radio stream without ads. Creating the app wasn’t my final goal, though. I wanted to bring the same feature to my home amplituner (Yamaha R-N301), which receives “Trójka” in a traditional way via the FM broadcast.

Yamaha R-N301

missing parts

So, I already have the algorithm, but I’m missing 3 elements required to run it in the real world of my flat:

  1. a device on which I can run the analysis,
  2. the broadcast, which will be used as a source for the analyzer,
  3. a way to turn the volume up and down on the amplituner.

the device

That’s the easy one. I already have Raspberry Pi 2, which works great as a home media center. It should be able to run the Java analyzer.

the broadcast source

The internet broadcast is delayed by about 30 seconds, so I can’t use it to analyze the signal and silence the FM tuner. No, I should analyze the real-time FM broadcast. How to receive it on a Raspberry Pi? Well, it will cost about $20. There’s a lot of cheap DVB-T USB sticks on the market and apparently (because of the RTL-SDR library) they can be used to receive all kinds of signals, FM radio stations included.

After plugging-in the stick, following command will receive the broadcast on 89.5Mhz:

rtl_fm -f 89.5M -M wbfm

The stream will be redirected to the standard output as a 16-bit, little-endian, 32k, 1-channel PCM data, perfect for the Java analyzer.

controlling the amplituner

Yamaha calls R-N301 a “Network HiFi Receiver”, which means (among other things) it can be controlled from an iPhone app. Apparently, Yamaha network-enabled devices exposes a RESTful interface, which can be called with curl. Following command will set the volume level to 55:

curl -d '<?xml version="1.0" encoding="utf-8"?><YAMAHA_AV cmd="PUT"><Main_Zone><Volume><Lvl><Val>55</Val><Exp>0</Exp><Unit></Unit></Lvl></Volume></Main_Zone></YAMAHA_AV>'

What’s more, it’s possible to get the current amplituner state, so we can launch the analyzer only if the tuner is enabled and plays the appropriate station.

all together

I’ve used a few bash scripts to detect the current amplituner state, run the analyzer and turn down the volume during commercial blocks. Scripts can be found on my github.


This is how the adblocker works in practice. The terminal tails the analyzer log file:

Radio AdBlock

Polish Radio Three (so-called Trójka) is famous for broadcasting good music and having non-offensive speakers. On the other hand it suffers from the number of commercial blocks between auditions. The ads, usually related to drugs or electronics are loud and irritating. Trójka accompanies me in home and at work for most of the time, so I wondered if there’s something than can be done about the ads. It seems there is.

digital signal processing

My aim is to create an app that mutes the ads. The commercial block starts and finishes with a jingle, so the potential software should recognize these specific sounds and turn off the volume between them.

I know that the area of maths/computer science dealing with these kinds of problems is called digital signal processing, but it always seems like a magic for me - so this is a great opportunity to learn something new. I spend a day or two trying to find out what mechanism can be used to analyze an audio stream looking for a jingle. And I found it, eventually - it’s called cross-corellation.


People usually describes the cross-corellation referring to the MATLAB implementation. MATLAB is an expensive application that makes it easy to perform complex mathematical operations, including DSP operations. Fortunatelly, there’s a free alternative to MATLAB, called Octave. It seems it’s quite easy to run cross-corellation on two audio files using Octave. All you have to do is to run following commands:

pkg load signal
jingle = wavread('jingle.wav')(:,1);
audio = wavread ('audio.wav')(:,1);
[R, lag] = xcorr(jingle, audio);

it’ll result in following plot:

octave plot

As you can see, there’s a peek describing the position of the jingle.wav within the audio.wav. What suprised me is the simplicity of the method - the xcorr() makes all the work, the rest of the Octave code is just for reading the files and displaying the result.

I wanted to reimplement the same algorithm in Java, so I’ll have a tool that:

  1. reads the audio stream from standard input (eg. provided by ffmpeg),
  2. analyses it looking for the jingles,
  3. outputs the same stream on stdout and/or muting it.

Using stdin and stdout will allow to connect the new analyzer with other apps, responsible for providing audio stream and playing the result.

reading sound files

The first step of the Java implementation is to read the jingle (saved as a .wav file) into an array. .wav file contains some extra info, like headers, metadata, etc. while we need the raw data. The format I was looking for is PCM - it simply contains the list of numbers representing sounds. Converting a wav to PCM can be done using ffmpeg:

ffmpeg -i input.wav -f s16le -acodec pcm_s16le output.raw

In this case each sample will be saved as 16-bit number, little endian. In Java such number is called short and the ByteBuffer class may be used to automatically transform the input stream into a list of short values:

ByteBuffer buf = ByteBuffer.allocate(4);
short leftChannel = buf.readShort(); // stereo stream
short rightChannel = buf.readShort();

xcorr reverse-engineering

In order to implement the xcorr() function in Java, I looked into the Octave’s source code. Without changing the final result, I was able to replace the xcorr() invocation with the following lines - they need to be rewritten to Java:

N    = length(audio);
M    = 2 ^ nextpow2(2 * N - 1);
pre  = fft(postpad(prepad(jingle(:), length(jingle) + N - 1), M));
post = fft(postpad(audio(:), M));
cor  = ifft(pre .* conj(post));
R    = real(cor(1:2 * N));

It looks quite scary, but most of the functions are trivial array operations. The heart of the cross-corellation is applying the fast Fourier transform on the sound sample.

fast Fourier transform

As someone who didn’t have earlier experience with DSP, I’ve simply treated the FFT as a function that takes the array describing the sound sample and returns an array containing complex numbers representing the frequencies. This minimalistic approach worked well - I was able to run the FFT implementation from the JTransforms package and got the same results as in Octave. I guess there’s a bit of cargo cult here, but hey - it works!

running xcorr on a stream

As you may see, the algorithm above assumes that the audio is an array, in which we are looking for the jingle. That’s not exactly the case for the radio broadcast, where we have a continous stream of sound. In order to run the analysis, I created a round-robin buffer, slightly longer than the jingle I’m looking for. The incoming stream fills the buffer and once it’s full, I run the cross-corellation test. If there’s nothing found, I discard the oldest part of the buffer and then wait until it’s full again.

I experimented a bit with the buffer length and got the best results with buffer 1.5 times bigger than the jingle size.

putting it all together

Getting the stream in PCM format is easy and can be done using aforementioned ffmpeg - the command below redirects the stream into the java standard input and then plays the result:

ffmpeg -loglevel -8 \
       -i\;stream \
       -f s16le -acodec pcm_s16le - \
  | java -cp analyzer-1.0.0-SNAPSHOT.jar \
             eu.rekawek.radioblock.MuteableMain RATE_44_1 \
  | play -r 44100 -b 16 -c 2 -e signed -t raw -

Apparently, it works :)

standalone version

I also prepared a simple standalone version of the analyzer, that connects to the Trójka stream on its own (without an external ffmpeg) and plays the result using javax.sound. The whole thing is a single JAR file and contains a basic start/stop UI. It can be downloaded here: radioblock.jar. If you feel uneasy about running a foreign JAR on your machine (like you should do), all the sources can be found on my GitHub.


further work

The final goal is to mute ads on a hardware amplituner, receiving a “real” FM signal rather than some internet streams. This will be covered in the next blog post.