RIBB@TACKING Bruce Lee – a C64 game tribute and homage

Bruce Lee homage and art project: A 3D rendered picture from the C64 Game "Bruce Lee" in an Ikea Ribba frame with Arduino magic for a cookoo's clock effect.

One day end of 2015 I stumbled upon some pretty kewl voxel art by Metin Sevin. Amongst many others like Mario Bros, Pacman, or Donkey Kong, I was immediately fascinated by the 3D rendered Bruce Lee Commodore 64 game tribute picture. I contacted Metin and asked him if his work is for sale and he kindly pointed me to society6 where a lot of his art is available in various formats. If you are interested in Metin and his work you can find out more in this interview at the end of this blog post. Due to some other planned projects based on Ikea Ribba frames I had one 23x23cm frame on stock so the 8″x8″ Bruce Lee art print would fit just fine. Shipment from Illinois/USA took about two weeks and I was ready to go for my art project!

tl;dr Watch the video to see what this project is about. Making of with gory details below video.

Project Description

Take the 8″x8″ Bruce Lee art print and put it in a 23x23cm Ikea Ribba frame. Use an Arduino to play the C64 Bruce Lee game title music at 12am and 7pm. Announce every hour starting with the first 3secs of Carl Douglas’ Kung Fu Fighting song and indicate the current hour by an according number of Yamo’s calls (the green Sumo in the game). Announce a quarter past, half past, and a quarter to with the Ninja’s stick strike sound ringing out once, twice, or thrice, respectively. Finally, add a capacative touch sensor to cycle through all Bruce Lee game sounds by touching one corner of the Ribba frame.


1 x 8″x8″ Bruce Lee art print from society6.
1 x RIBBA frame from Ikea
1 x Visaton K28.40 8Ω, Price comparison idealo
1 x Arduino Nano e.g. from eBay
1 x LM386 Audio Amplifier Module e.g. from eBay
1 x DS3231 Real Time Clock (RTC) e.g. from eBay
1 x CR2032 battery for DS3231 RTC
1 x SD Card Module e.g. from eBay
1 x SD Card 1GB is sufficient
1 x 5V 1A power supply

Cables, solder and iron, hot-melt gun, screws, (cordless) screwdriver, drill, side cutter, etc.

A 1GB SD would have been sufficient since the WAVE files are very small. Unfortunately, I threw away old small capacity SD cards years ago “…when should I ever need a one or two GB SD card again?” Well, now I know the answer. Thus, I had to use an 8 GB SD card.

Audacity will be helpful to recode the Bruce Lee tunes to the required format.


Order the Bruce Lee voxel from society6. Wait approximately two weeks until it arrives; might heavily depend on where the item is shipped to. 😉 While waiting: a] Buy a 23x23cm RIBBA frame at your local Ikea. b] Prepare the necessary electronics and code to get the thing up and running.


For the hardware part: Glue the required components, i.e. Arduino Nano, amplifier, SD card module, DS3231 RTC w/ CR2032 battery to the back of the RIBBA frame. It might look like this.

RIBBA frame with electronics

NB: This was my first shot with the loudspeaker directly glued to the backside as can be seen in the photo. My assumption that the – sort of abyssal – RIBBA frame will act as a good resonator
WAS WRONG. When I hung up the picture on the wall for the first time you could barely hear anything. The loudspeaker radiating directly to the wall was nearly completely muted since the sound waves cannot escape the frame.

Bruce Lee project Visaton SpeakeNew solution: Drill a plethora of holes into the bottom part of the frame and attach a (smaller) loudspeaker so that its sound waves can go through the holes. There are roughly 3 cm space between the backside (with the components) and the wall-facing side of the frame. Thus, I needed a speaker with a radius of max(3cm). I found an fairly good sounding 2,8x4cm rectangular-shaped speaker from Visaton that would fit snuggly into the available space (cf. picture).

Speaker drilling templateI created a drill template with the speaker’s exact dimensions by laying a piece of paper on top of it and tracing its contours with a pencil. Old school but works! After that I drew a mesh pattern with a lot of drill holes. That could have been the maiden trip for my drill press…but I went with the cordless screwdriver that did a nice job on drilling the 90+ holes. The template was fixed with sticky tape to the frame before drilling. I covered the whole template with tape to avoid frayed drill holes. This worked pretty good on the template Speaker drill holes burring done side but not on the inside of the frame. The RIBBA frame is made of chipboard so I lost quiet some material while drilling. You can see in the picture that the inside is not flat anymore but sort of curved due to the lost material. Next time I would apply sticky tape to the inside too.

After drillingThe holes needed some afterwork, i.e., burring and removing frayed pieces. The pictures do not show the final stage of afterwork so you will have to trust me that the result was ok. Especially, since the holes are on the bottom side that will, most likely, hardly been seen or looked at when the frame is hanging on the wall. I was happy with the result and moved on to screw the Visaton speaker into the frame with four black and tiny flat-head screws that were giving me a hard screwing time.

This is how the final setup looks like.

Visaton speaker attached

Note the blue cable going to the upper left corner?

This is the capacitive touch sensor wire. Capacitive touch sensor wire It is basically a piece of zinc coated copper wire bent to a 90° angle and sticked exactly to the corner of the frame using super glue. It was then painted black and soldered to the blue cable to have it connected to the Arduino. With this switch I would later be able to play all Bruce Lee game tunes one after another by repeatedly touching the bottom left corner of the frame. Actually, the ADCTouch-Library used is doing such a great job that the Arduino can react to a finger (or a hand, or some other body part) just coming near to the wire. You can measure changes in the wire’s capacity without even touching it. Awesome!

What’s missing? Yes, details on the wiring. The correct wiring might be hard to find out by just looking at the pictures, not least since my wire color scheme is a bit, eh, inconsistent. So here’s a Fritzing breadboard view of the wiring.

Bruce Lee RIBBA frame hanging on wall

That should cover the most important aspects of the hardware. But all this hardware is nothing without software. Let’s move into the matrix.


Code is poetry

There are more lines of code in the Arduino sketch (GitHub) than needed to implement the behaviour as described in the Project Description. Nonetheless, some of the code is helpful for debugging purposes and some other for fiddling with the TMRpcm Library.

This library is used “for asynchronous playback of PCM/WAV files direct (sic!) from SD card”. The WAVE files must be in a specific format, i.e., 8-bit, 8-32khz Sample Rate, mono. Thus, do not expect Hifi quality! I wrote a separate article WAV-Dateien von SD-Karte mit Arduino abspiele where you will find the gory details about the required file format, how to convert, e.g., an mp3-file using Audacity into this specific WAV-format, how to format the SD card – if required, how the WAV-files have to be named on the SD card (8.3. SFN – short file name from the good ol’ MS-DOS times), and a short Arduino sketch to test the TMRpcm lib.

The ADCTouch library is required for utilizing capacitive touch sensors without any additional hardware.

Debugging with “Serial.print()” is not that funny so we’re using the Streaming library to provide a C++ like << operator that allows constructs like Serial << F( "Current volume is " ) << gVolume << "." << endl; which is very convenient. NB: With the macro F() you put strings in an Arduino's flash memory instead of the sparse static RAM (SRAM) leaving more space for variables and such. The ATmega328 chip found on the Uno has the following memory:

Flash  32k bytes (of which .5k is used for the bootloader)
SRAM   2k bytes
EEPROM 1k byte

Flash is plenty but SRAM isn't - so there is reason to always save SRAM!

Finally, we need the DS3232RTC and Time library to handle the real time clock. Europe will not let go of the daylight saving time (DST) idiocy. Summer time is switched on at the last Sunday in March where 2 o'clock becomes 3 o'clock. Vice versae at the last Sunday in October where 3 o'clock becomes 2 o'clock. We have to recognize the DST so the Bruce Lee cookoo works both in summer and winter. 😉 Thanks to user "jurs" from the German Arduino Forum we have a great European daylight savings time calculation function fIsSummertime() that returns "true" when we're in summer time and false if not.

The Arduino sketch

Sketch also available on GitHub in the RIBBAttacking-Bruce-Lee repository.

Interview with the artist

Metin and I had a nice e-mail-chat while the project was ongoing. There are quiet some analogies in our CVs like being born in the 1970s, growing up with 8-bit computers, adjusting the datassette's azimuth with a screwdriver, hanging out at arcade halls, and - of course - liking minimalistic pixel graphics. Here is short interview with Metin to get you in touch with him as a digital artist and his voxel creations.

Metin, who are you?
My name is Metin Seven, I was born in the 1970s, and grew up in the 1980s with the first 8-bit and 16-bit generations of game consoles and 'home computers', particularly the Atari 2600, CBS ColecoVision, Commodore 64 and Commodore Amiga.

What is your artistic spectrum, i.e., what kind of art do you make/prefer?
I'm a die-hard digital artist. I used to draw on paper as well, but I prefer the flexibility of the digital screen. I started creating pixel art for Amiga demos in the late 1980s. That soon evolved into creating pixel graphics for commercial games, television commercials and children's animation series in the 1990s, all done using software like Deluxe Paint and Personal Paint on an Amiga. Since the late 1990s I've shifted towards 3D graphics creation, but pixel art will always keep a special place in my heart.

Why retro games and what is your reference to this genre?
Ever since I was a little kid I was enchanted by the magic glow of the digital screen. I used to hang out at arcade halls, playing the first 8-bit games, such as Donkey Kong, Lady Bug, Pac-Man and Pengo. When I was not playing them myself, I could stare at people playing the games for hours. The first pixel graphics had this pure, iconic quality because of the low resolution restrictions for sprites and such. It's great to see that atmosphere return in the current wave of minimalistic pixel art games for mobile devices.

Did you have decent experiences with the C64?
Definitely. During my school days I spent just about every afternoon and evening playing Commodore 64 games, first loading them using the Datassette tape recorder, adjusting the azimuth when necessary. After a while I bought a floppy disk drive. LOAD "*",8,1 😀

How did you come to create voxel pictures? Where does the idea come from?
During the 2000s I created a lot of stylized 3D illustrations for printed magazines and newspapers. My use of shapes and colors reflected my game pixel art background, and gradually my illustration style became more elementary, until I arrived at a point that fully made sense — a blend between pixel art and 3D artwork: voxels. It was then that I decided to start paying tributes to my childhood love: 8-bit and 16-bit games.

Can you tell us something about the voxel creation process?
My first voxel images were created in 3ds Max in the mid-2000s, extruding blocks of quadrangular polygons. That was quite a hassle, and I was eager to find a dedicated voxel editor. I found that in the shape of Paint3D for Windows. I got in touch with the coder and suggested a number of features, which he kindly implemented.

When I switched to Mac OS X in 2014, I started using Qubicle, also a versatile voxel editor. I guess MagicaVoxel would be the tool of my choice today, but to be honest I've become a bit saturated when it comes to voxel creation, although there’s a good chance I'll return to it some day.

Where should we go if we'd be interested in more from you?
The best starting place is my portfolio site metinseven.com, there you will find links to my online shops, offering 3D prints, 2D art prints, stock 3D models and stock illustrations.

Many thanks for this interview, and my sincere compliments to you regarding your clock creation based on my voxel tribute to the classic 8-bit Bruce Lee game.

The pleasure was all mine! Keep on the good work!

Bruce Lee RIBBA frame hanging on wall



WAV-Dateien von SD-Karte mit Arduino abspielen

Musik und Geräusche mit einem Arduino abspielen? Kein Problem mit dem guten alten WAVE-Format, einem SD-Kartenleser und der TMRpcm Library.

Arduino WAV Musik SD-Karte Eins gleich vorweg: Hifi-Qualität darf man von der hier beschriebenen Lösung nicht erwarten. Aber als Low-Budget-Player für einfache Zwecke reicht es auf jeden Fall. Habe ich beispielsweise hier im Kunstprojekt RIBB@TACKING Bruce Lee – a C64 game tribute and homage verwendet.

Was man braucht

Natürlich einen Arduino; der hier beschriebene Aufbau wurde mit einem Uno getestet. Alle 328er basierten, also auch Nano, LilyPad, Pro etc. sollten gleichermaßen funktionieren.

Da die WAVE-Dateien irgendwo abgespeichert sein müssen, bietet sich ein SD Kartenleser an. Es gibt Breakout Boards mit Micro-SD-Karten Slot oder andere Shields, auf denen solch ein Slot bereits integriert ist, bspw. das Ethernet-Shield. Hier kommt ein sehr einfacher 1 EUR SD-Kartenleser von eBay zum Einsatz. Dazu eine (alte) SD Karte.

Damit man etwas hört, braucht es einen Verstärker. Bryan beschreibt in diesem Blog-Artikel, wie man mit einem einzigen Transistor nebst Widerstand (4,7 kOhm) einen simplen Verstärker zusammenschustert. Der BC548B hat nicht ausreichend verstärkt. Mit dem 2N3904 (eBay) macht es mehr Spaß.

Dazu natürlich ein Lautsprecher, da hatte ich noch einen mit 0,25 Watt 4 Ohm auf Halde liegen.

Verkabelung / Aufbau

Die Anbindung des SD-Kartenlesers erfolgt über die Hardware SPI Pins des Arduino. Welche Pins das genau sind, hängt vom Arduino-Typ ab. Die hier gezeigte Verkabelung sollte für alle 328er Typen (Nano, Uno, etc.) funktionieren. Chip Select ist frei wählbar; vgl. auch der weiter unten stehende Arduino Sketch. Die Schaltung auf dem Breadboard ist der erwähnte Ein-Transistor-Verstärker. Wenn man hier den Widerstand zwischen Arduino-Ausgang (Pin 9) und der Transistorbasis zu klein wählt, kann man nach kurzer Zeit auf dem Transistor Eier braten, da zu viel Strom durch die Collector-Emitter-Strecke fliesst.


Wagemutige können den Widerstand einfach mal ganz weglassen und sich an einer, dann, recht ordentlichen Beschallung nebst Transistorheizung erfreuen. Das sei hiermit also ausdrücklich nicht empfohlen.

Kartenleser PIN Arduino PIN Was ist das?
GND GND Ground
+5V 5V Volle Power! 🙂
MISO 12 MISO, Hardware MISO
CLK 13 CLK, SCL, Hardware SCK
CS 4 CS, Chip Select
GND GND Ground

In der Tabelle ist die PIN-Verkabelung noch einmal aufgeführt. Der verwendete SD-Kartenleser hat zwei GND-Anschlüsse und funktioniert auch nur zuverlässig, wenn tatsächlich beide mit Masse verbunden werden. Der Lautsprecherausgang ist, ebenso wie Chip Select, über den Arduino Sketch frei wählbar (hier PIN 9).

Zwei Blog Posts haben bei Verkabelung und Inbetriebnahme gut geholfen. Zum einen dieser Beitrag bei maxoffsky.com sowie insbesondere diese Anleitung auf instructables.com.

Format der SD Karte

Die verwendete SD-Library unterstützt prinzipiell die Dateisysteme FAT16 und FAT32. Es wird jedoch empfohlen, wenn möglich, FAT16 einzusetzen. Bei mir hat’s mit einer FAT32-formatierten SD-Karte nicht funktioniert, daher wollte ich sie “mal eben” auf FAT16 formatieren. Das geht auch mit MacOS Bordmitteln, ist aber etwas komplizierter, als erwartet. Dieser Post im Adafruit-Forum beschreibt den Weg in Englisch; hier in knappem Deutsch:

  1. SD-Karte in den Mac stecken.
  2. Terminal-Fenster öffnen. Bspw. mit CMD+Space, dort “terminal” tippen und Return.
  3. Geräte-ID finden. Dazu im Terminal df gefolgt von Return eingeben. Es erscheint eine Filesystem-Übersicht, die unter anderem die folgenden Informationen enthält. Ganz unten ist die SD-Karte “NO NAME” zu sehen. Wer auf Nummer sicher gehen will, gibt seiner Karte einen eindeutigen Namen. Dann kann man sie in dieser Übersicht schneller finden. Die in den folgenden Schritten benötigte Geräte-ID lautet /dev/disk3s1.
    Filesystem        Used Available Capacity   iused   ifree %iused  Mounted on
    /dev/disk1   909007896  65197032    94% 113689985 8149629   93%   /
    devfs              371         0   100%       642       0  100%   /dev
    map -hosts           0         0   100%         0       0  100%   /net
    map auto_home        0         0   100%         0       0  100%   /home
    /dev/disk3s1     20928   4172608     1%       512       0  100%   /Volumes/NO NAME
  4. SD-Karte unmounten (nicht auswerfen!). Im Terminal diskutil unmount /dev/disk3s1 gefolgt von Return eingeben. Dabei disk3s1 natürlich durch die eigene Geräte-ID ersetzen. Erfolgreiches unmounten wird bspw. mit Volume NO NAME on disk3s1 unmounted quittiert.
  5. FAT16 Filesystem auf SD-Karte schreiben. ACHTUNG! Der folgende Befehl löscht alle Daten auf dem Gerät. Wenn die Geräte-ID nicht die von der eingesteckten SD-Karte ist, sondern bspw. aus Versehen die der eingebauten Festplatte, dann wird diese gelöscht. U have been warned.
    Folgendes Kommando im Terminal eingeben und nicht vergessen die Geräte-ID anzupassen. newfs_msdos -F 16 /dev/disk3s1
    Ich habe alle Warnmeldungen, die der Befehl produziert hat, konsequent ignoriert und als Lohn der Mühe im Anschluß eine lauffähige FAT16-formatierte SD-Karte gehabt.

Format der WAVE Dateien

Die Library TMRpcm benötigt zum Abspielen die WAVE-Dateien im Format acht Bit, acht bis 32 kHz Sample Rate, mono. Im WIKI zur Library werden zwei Wege beschrieben, wie man iTunes oder Audacity verwenden kann, um aus dem musikalischen Quellmaterial das Zielformat zu generieren. Audacity ist prima, und so geht’s damit:

  1. Hauptmenü “Tracks”, dort “Stereo Track to Mono” wählen.
  2. Unten links die “Project Rate (Hz)” mit dem Popup auf 8000, 11025, 16000, 22050 oder 32000 setzen. Je niedriger die Sampling Rate, desto schlechter die Qualität.
  3. Hauptmenü “File”, dort “Export Audio…” und im File Selection Dialog unten als Format “Other uncompressed files” wählen. Dann “Options…” klicken und als Header “WAV (Microsoft)” sowie bei Encoding “Unsigned 8-bit PCM” wählen. OK.
  4. Datei mit “Save” speichern.


Dateinamen müssen zwingend dem – aus alten MS-DOS Zeiten bekannten – 8.3-Format folgen, also maximal acht Zeichen für den Dateinamen gefolgt von Punkt und einer Endung mit drei Zeichen beispielsweise “NAME0001.EXT”. Der Dateiname kann kürzer als acht Zeichen sein, in keinem Fall aber länger. Die Wikipedia widmet dem 8.3 short filename (SFN) tatsächlich einen eigenen Artikel.

Arduino Sketch

Der folgende Sketch bindet zunächst die benötigten Libraries ein, definiert Chip Select- und Lautsprecherausgangs-PIN, initialisiert die SD-Karte mit SD.begin() und spielt im Erfolgsfall die Wave-Datei snakec16.wav direkt von der SD-Karte ab. Im Fehlerfall wird eine kurze Meldung über den seriellen Monitor ausgegeben.

#define CHIP_SELECT_PIN  4
#define SPEAKER_PIN      9
TMRpcm tmrpcm;

void setup( ) {
  tmrpcm.speakerPin = SPEAKER_PIN;
  Serial.begin( 9600 );
  while ( !Serial ) /*mt*/ ;
  if ( !SD.begin( CHIP_SELECT_PIN ) )
    Serial.println( "SD fail" );
  else {
    tmrpcm.play( "snakec16.wav" );
    delay( 5 );

void loop( ) {

Wenn alles läuft…

…dann sollte das in etwa so aussehen, wie in dem Video.

Musik © Snake Charmer (Synapsis) / CC BY-ND 4.0

OLED 0,96″ Zoll Display an den Arduino anschließen

OLED Displays für den Arduino sind beliebt. Ein kurzer Wegweiser durch Anschluß-Pins, Protokolle und Libraries, damit das Mini-Display auch etwas anzeigt.

Bei eBay, Aliexpress & Co. gibt es zahnlose Mini-OLED-Displays, beispielsweise für den Betrieb an einem Arduino. Dabei sind die gängigen Größen 0,96 Zoll und 1,3 Zoll mit Auflösungen von 128 x 64 oder 128 x 32 Pixeln. Die Displays sind selbstleuchtend und werden in weiß, blau, gelb, Kombinationen davon oder auch “full color” angeboten. Die Full Color Displays stellen dann üblicherweise 65K Farben dar.

Es werden unterschiedliche Kommunikationsprotokolle unterstützt, in der Regel entweder I2C oder SPI oder beides. Dazu kommen unterschiedliche Driver Chips, für die die richtige Library benötigt wird, um das OLED ansteuern zu können. Gängig und gut unterstützt ist der Driver Chip SSD1306, der u.a. mit den folgenden beiden Libraries angesteuert werden kann: Adafruit_SSD1306 (github) oder U8glib (github). Wer ein OLED mit SS1106 Driver Chip erwischt hat, kann es mit der SH1106_SPI Library (github) versuchen.

Dieser Post zeigt den Anschluß und Betrieb eines einfachen, weißen 0,96″ Zoll OLED Displays (eBay) mit SSD1306 Driver Chip und sieben Anschluss-Pins an einen Arduino Uno. Nano, und alle weiteren Modelle mit ATmega328 Pinout, dürften auf dieselbe Weise angesteuert werden können. Im Zweifel das Datenblatt des Arduinos zu Rate ziehen.

Im folgenden Video ist das OLED im Einsatz zu sehen. Die Chord-Animation ist von Hari Wiguna, sein Kode steht auf GitHub bereit.

Um ein OLED erfolgreich ansteuern zu können, ist die richtige Verdrahtung zwischen Arduino und Display wichtig. Dabei wird es durch die Tatsache, dass die Displays mit unterschiedlicher Anzahl und Beschriftung der Pins geliefert werden nicht einfacher. Die Libraries erlauben üblicherweise die Verwendung von Software oder Hardware SPI, wobei letztere Variante deutlich schneller ist. Hardware SPI erfordert mehr Anschluss-Pins als Software SPI.

OLED Anschluss Arduino PIN Was ist das?
GND GND Ground
VCC 5V Volle Power! 🙂
D0 13 CLK, SCL, Hardware SCK
DC 6 Data/Command
DS 7 CS, Chip Select
RES 8 Reset

Das im Video gezeigte 0,96″ Display ist zur Ansteuerung durch Hardware SPI entsprechend der Tabelle mit dem Arduino zu verbinden. Bitte unbedingt prüfen, ob das eigene Display für 5V ausgelegt ist! Im Zweifel am 3,3V Pin anschließen und erst einmal damit versuchen. Die “Was ist das?”-Spalte in der Tabelle zeigt die ausgeschriebenen, gängigen oder alternativen Bezeichnungen der Anschlüsse; vielleicht hilft es dem einen oder anderen bei der Verkabelung. Ich fand diesen Beitrag von paulwb im Adafruit-Forum sehr hilfreich, um das Display nach einigen erfolglosen Versuchen endlich zum Laufen zu bringen.

Hier noch der Arduino-Sketch zur Darstellung der Animation wie im Video.


/* Wiring for Hardware SPI
    GND ------- ground
    VCC ------- 5V
    D0 -------- 13 hardware SCK
    D1 -------- 11 to hardware MOSI
    DC -------- 6 (user choice, defined below)
    DS -------- 7 (user choice, defined below)
    RST ------- 8 (user choice, defined below)
  Hardware MISO (12) unused */

#define OLED_DC     6
#define OLED_CS     7
#define OLED_RESET  8
Adafruit_SSD1306 display( OLED_DC, OLED_RESET, OLED_CS );

void setup( ) {
  display.begin( );
  display.clearDisplay( );
  display.display( );

int nFrames = 36;
void loop() {
  for ( int frame = 0; frame < nFrames; frame++ )
    HariChord( frame );
  for ( int frame = ( nFrames - 1 ); frame >= 0; frame-- )
    HariChord( frame );

void HariChord( int frame ) {
  display.clearDisplay( );
  int   n   = 7;
  int   r   = frame * 64 / nFrames;
  float rot = frame * 2 * PI / nFrames;
  for ( int i = 0; i < ( n - 1 ); i++ ) {
    float a  = rot + i * 2 * PI / n;
    int   x1 = 64 + cos( a ) * r;
    int   y1 = 32 + sin( a ) * r;
    for ( int j = i + 1; j < n; j++ ) {
      a  = rot + j * 2 * PI / n;
      int x2 = 64 + cos( a ) * r;
      int y2 = 32 + sin( a ) * r;
      display.drawLine( x1, y1, x2, y2, WHITE );
  display.display( );

Zugriff auf Photo Stream Bilder auf dem Mac ohne Photos App

Man kann auf dem Mac auf die Bilder des Photo Streams auch OHNE Photos App zugreifen. Hier wird der zugehörige Lösungsweg beschrieben.

Der Use Case: Mit dem iPhone, iPad oder iPod geknipste Bilder können über die sog. “My Photo Stream”-Funktionalität automatisch auf die jeweils anderen, verbundenen Geräte übertragen werden. Das ist praktisch. Es wäre aber noch praktischer, wenn diese Bilder ebenso automatisch auf den Mac synchronisiert würden. Das ist möglich, erfordert aber ein paar Handgriffe. Insbesondere, wenn man eine Lösung sucht, bei der man nicht die Photos App verwenden möchte und die Bilder in einem beliebigen Zielordner landen sollen. Hier das Vorgehen, inspiriert durch einen Artikel auf bockenhauer.com, den es dort allerdings nicht mehr gibt.

Wie funktioniert’s?

Wir schalten sowohl auf dem gewünschten mobilen Gerät, also iPhone, iPad oder iPod, als auch auf dem Mac die “My Photo Stream”-Funktion ein. Danach landen alle mit dem mobilen Gerät aufgenommenen Bilder sowohl (und wie bisher) im “Camera Roll”-Ordner und (neu) zusätzlich in einem Ordner mit dem Namen “My Photo Stream”. Zeitgleich werden die Bilder auf alle verbundenen Geräte in deren “My Photo Stream” Ordner gespiegelt. Beim Mac gibt es aber einen solchen Ordner nicht. Stattdessen werden die Photo Stream Bilder in einen Unterordner des Photos App Packages gelegt. Die hier beschriebene Lösung greift auf diesen Ordner zu und verschiebt die Bilder in einen Wunsch-Zielordner.

My Photo Stream auf dem Mac

Eine kurze Schritt-für-Schritt-Anleitung, um einen “My Photo Stream”-Ordner auf dem Mac zu emulieren.

  1. Photo Stream einschalten. Das ist an vielen anderen Stellen im Netz schon detailliert beschrieben, bspw. hier. Die Kurzversion für’s iPhone: Settings → iCloud → Photos → “My Photo Stream” einschalten. Und für den Mac: System Preferences → iCloud → dort rechts bei Photos den Options-Button klick → “My Photo Stream” einschalten. Kann man alternativ auch über die Settings der Photos App einschalten, aber viele Weg, Rom, etc. pp. NB: Weder “iCloud Photo Library” noch “iCloud Photo Sharing” müssen eingeschaltet sein, damitdie hier beschriebene Lösung funktioniert.
  2. exiv2 installieren, falls noch nicht vorhanden. Die Lösung setzt zum Umbenennen der jpeg-Dateien auf Basis der im jpeg-Header (hoffentlich) vorhandenen EXIF-Informationen auf exiv2. Das Tool lässt sich einfach via (home)homebrew installieren, und zwar so:
    $ brew install exiv2
    Wenn der Packet-Manager brew noch nicht vorhanden ist, dann natürlich erst einmal homebrew installieren…
  3. Shell Datei anlegen. Das folgende Shell-Skript den eigenen Bedürfnissen anpassen und dann in einem Verzeichnis bspw. als photostream.sh speichern.
    # Alle Photo Stream Bilder in den Ordner ~/Downloads/MyPhotoStream/_tmp kopieren
    find ~/Pictures/Photos\ Library.photoslibrary/Masters/ -type f -exec cp "{}" ~/Downloads/MyPhotoStream/_tmp/ \;
    # in das _tmp Verzeichnis wechseln
    cd ~/Downloads/MyPhotoStream/_tmp
    # Mit dem Programm exiv2 das Aufnahmedatum aus den EXIF-Daten jeder jpg-Datei auslesen.
    # Der Parameter -t setzt das modification date der Dateien auf ihr Aufnahmedatum.
    # Der Parameter -r benennt die Dateien um: Es wird dem Dateinamen das Aufnahmedatum im ISO8601-Format vorangestellt.
    /usr/local/bin/exiv2 -t -r'%Y%m%d_ :basename:' rename $(ls)
    # Die Bilder aus dem aktuellen _tmp Verzeichnis in das darüberliegende "MyPhotoStream" Verzeichnis verschieben
    find . -type f -exec mv "{}" .. \;
    # Abschließend die Bilder aus dem Photostream-Ordner löschen
    rm -r ~/Pictures/Photos\ Library.photoslibrary/Masters/*
    rm -r ~/Pictures/Photos\ Library.photoslibrary/Thumbnails/*
  4. photostream.sh Rechte setzen. Mit
    $ chmod 700 photostream.sh
    die Rechte der Shell-Datei auf “ausführbar” setzen.
  5. Automatisieren. Wir richten einen Daemon ein, der einmal pro Minute unser photostream.sh Skript aufruft. Auf diese Weise werden Bilder-Neuankömmlinge aus dem Photo Stream regelmässig und zeitnah aus dem Photos App Unterordner in unseren Zielordner überführt. Dazu wird eine Datei mit folgendem Inhalt an einem beliebigen Ort mit dem Namen com.NAME.photostream.plist angelegt. NAME kann frei gewählt werden.
           /Volumes/Macintosh HD/Users/USER/photostream.sh
    In der Datei ist NAME in <string>com.NAME.photostream</string> entsprechend des beim Anlegen der Datei gewählten Dateinamens zu ändern. Auch der Pfad /Volumes/Macintosh HD/Users/USER/photostream.sh muß so angepasst werden, dass er korrekt auf die photostream.sh Shell-Datei zeigt. Das StartInterval von 60 entspricht 60 Sekunden, d.h. das Skript wird einmal pro Minute aufgerufen. Wer weniger häufig nach neuen Bildern im Photo Stream nachschauen möchte, kann den Wert einfach nach oben setzen.
  6. Daemon aktivieren. Wir müssen dem Daemon/Agent manager launchd noch mitteilen, dass es einen neuen Daemon gibt, um den er sich kümmern soll. Das geschieht auf der Kommandozeile mit dem folgenden Befehl:
    $ launchctl load com.NAME.photostream.plist
    Auch hier ist NAME entsprechend zu ersetzen.

Fertig! Wenn’s erstmal läuft, läuft’s wie geschnitten Brot. Auch mit El Capitan und ohne AirDrop. 😉

Chrome Shortcut oder Tastenkombination um aktuelles Tab zu duplizieren

Zwei Lösungen, um ein Chrome-Tab per Tastenkombination zu Duplizieren. Schnell, sauber, effizient und ein Video gibt's auch noch.

Der übliche Weg, um ein Tab in Chrome zu duplizieren führt über einen Rechts-Klick auf das Tab und Auswahl des Popup-Menüpunktes “Duplicate”.

Wer als Tastatur-Universalhackspecht seine Finger aber lieber auf dem Keyboard belassen möchte, findet jeden Griff zur Maus nervig. Leider gibt es in Chrome keine eingebaute Tastenkombination, um das aktuelle Tab zu duplizieren.

Eine schnelle Variante, die allerdings kein 100%iges Duplikat erzeugt: CMD+L (aktiviert die URL-Zeile), dann CMD+Return. Zack! Schon wird das Tab geklont. Aber nur geklont, nicht echt dupliziert. Die Seite wird neu geladen, was beim Duplizieren nicht der Fall sein sollte. Weder die Position im Dokument noch die History (Back-Button) wird übertragen. Wer damit leben kann, ist mit dieser Lösung axellent bedient. Weitere Lösungsvorschläge im Geek TV Style liefert dieser Stackoverflow-Post.

Zweite Variante, ohne Hacken: Die Chrome Extension Duplicate Tab Shortcut Key installieren. So muß ‘ne Extension aussehen, dann klappt’s auch mit dem Nachbarn Duplizieren.

PHP: Mit Google Spreadsheet verbinden und Daten lesen oder schreiben

Eine Schritt für Schritt Anleitung, um mit PHP via OAuth2 auf Daten von Google Spreadsheets oder anderen Google Diensten zuzugreifen.

Man kann den Suchmaschinenmarktführer mögen oder auch nicht. Aber die Google Docs bieten etwas, das mit Excel, Word & Co. Stand heute nicht realisierbar ist: Mehrere Personen arbeiten gemeinsam an einem Dokument. In Echtzeit. Zu den gemeinsam verwaltbaren Dokumenten gehören aktuell:

  • Docs (Textdokumente)
  • Slides (Präsentationen)
  • Sheets (Tabellenkalkulationen)
  • Forms (Web-Formulare, bspw. für Befragungen)
  • Drawings (Konkurrenz für Microsofts Bitmap Programm, muahaha)
  • My Maps (Karten)

Natürlich ist der Funktionsumfang der einzelnen Tools nicht mit anderen Tools wie aus den Suiten von Open Office oder MS Office vergleichbar. Aber die echt kollaborative Zusammenarbeit ist ein Killer Feature und eröffnet interessante Use Cases.

Google Docs Daten automatisiert verarbeiten

Docs, Slides & Co. werden in der Regel im Browser bearbeitet. Das wird für viele Anwendungsfälle genügen. Was aber, wenn Daten sowohl im Browser gepflegt als aber auch durch Software automatisiert verarbeitet werden sollen?

Google stellt umfangreiche Schnittstellen-Dokumentationen für verschiedene APIs zur Verfügung, die den Zugriff per .net, Java oder PHP beschreiben. Durch eine unlängst erfolgte Umstellung auf oAuth2 ist jedoch die Authentisierung für den softwaregesteuerten Zugriff komplexer geworden. Deutlich komplexer.

Wie geht dem?

Die Umstellung auf oAuth2 hat es in sich, denn viele selbstgeschriebene Skripte laufen seitdem nicht mehr. Während die alte Authentisierung mit Username-/Password-Kombination vergleichsweise simpel war, erfordert der Zugriff via oAuth2 mehr Aufwand.

Viele Nutzer im Netz suchen nach entsprechenden Lösungen, wobei konkrete Schritt-für-Schritt-Anleitungen, die 100%ig erfolgreich sind, fehlen. Zusätzlich scheint es nur im englischsprachigen Raum überhaupt Hilfe zu geben. Wenn man aber erst einmal genug Quellen in einen Topf geworfen hat, kommt am Ende sogar eine Suppe Lösung raus. Hier Schritt für Schritt, wie es funktionieren kann. (Viele Wege, Rom, blabla)

So geht dem!

Wir legen zu Testzwecken ein Google (Spread)Sheet an.
Test Google Spreadsheet Reiter

Das Spreadsheet heißt “Test-O-Mat” und besteht aus den zwei Worksheets “Argl” und “Wargl”.

Der Weg zu den Daten mit PHP: Schritt für Schritt

  1. Verzeichnis anlegen. Wir legen irgendwo ein passendes Verzeichnis für unser Testprojekt an, bspw. im Home-Verzeichnis des eingeloggten Users und wechseln hinein.
    $ mkdir ~/oauth && cd ~/oauth
  2. Composer installieren. Wir brauchen den PHP Dependency Manager “Composer”. Dieser lässt sich am einfachsten mit dem folgenden Befehl auf der Kommandozeile installieren. Das setzt natürlich eine funktionsfähige lokale PHP-Installation voraus.
    $ curl -sS https://getcomposer.org/installer | php

    Wenn die Installation erfolgreich verläuft, sieht das in etwa so aus:

    #!/usr/bin/env php
    All settings correct for using Composer
    Composer successfully installed to: <Pfad>/oauth/composer.phar
    Use it: php composer.phar

    Es wurde eine composer.phar Datei erstellt – ein PHp ARchive, das nach dem nächsten Schritt zum Einsatz kommt.

  3. composer.json erstellen. Für die Arbeit mit den Google APIs werden bestimmte PHP-Libraries benötigt. Der im vorherigen Schritt installierte Dependency Manager entledigt uns der Bürde, diese Libraries manuell zu verwalten. Aber er muss wissen, welche Libraries wir genau benötigen. Das bekommt er über eine projektbezogene composer.json Datei mitgeteilt. Dafür im aktuellen Verzeichnis eine composer.json Datei mit folgendem Inhalt anlegen.
      "require": {
        "asimlqt/php-google-spreadsheet-client": "2.2.*",
        "google/apiclient": "1.0.*@beta"
  4. Libraries installieren. Mit dem folgenden Befehl wird der Composer gestartet. Er lädt alle benötigten Libraries von den zugehörigen Servern und installiert die Library-Dateien im aktuellen Verzeichnis.
    $ php composer.phar install

    Wenn’s gut läuft, sieht das wie folgt aus.

    Loading composer repositories with package information
    Installing dependencies (including require-dev)
      - Installing asimlqt/php-google-spreadsheet-client (2.2.4)
        Downloading: 100%
      - Installing google/apiclient (1.0.6-beta)
        Downloading: 100%
    Writing lock file
    Generating autoload files

    Verzeichnis und Dateien nach den ersten Schritten Nach der erfolgreichen Ausführung des Composers sollte sich ein neues Unterverzeichnis “vendor” im aktuellen Verzeichnis befinden. Zusätzlich die Dateien composer.phar (Composer Dependency Manager), composer.lock (Finger weg!) und composer.json.

  5. Credentials für oAuth2 Authentisierung erstellen. Wir benötigen Authentisierungs-Credentials, die mit der Google Developers Console generiert werden. Dies erfordert, wie alles bei Google, einen Google Account. Falls noch nicht vorhanden, Google Account anlegen und dann bei der Google Developers Console registrieren. Nach dem Login empfängt uns eine karge Benutzeroberfläche.
    Google Developers Console
    Zur Erstellung der Credentials für unser PHP-Skript wie folgt vorgehen.

    1. Im Hauptmenü “APIs & auth” wählen. Dort “Credentials”.
    2. Der Datenbereich zeigt ein Drop-Down-Menü. Dort “Service account” wählen.
      Credentials Service Account
    3. Es folgt eine Auswahl zum gewünschten Keytype. “P12” anklicken und den Button “Create” drücken. Der Browser speichert daraufhin ein Key-Datei “API Project-xxxxxxxxxx.p12”. Diese in’s Projektverzeichnis kopieren. Gleichzeitig wird ein Passwort im Browser angezeigt. Dieses notieren, wir brauchen es später noch.
    4. Im Datenbereich wird daraufhin eine Übersicht aller Credentials angezeigt. Gibt es mehrere Service Account Credentials, so steht unser neu angelegter ganz unten in der Liste. Die zugehörige E-Mail-Adresse anklicken und die auf dem folgenden Screen angezeigte lange, kryptische Client ID sowie die ebenso lange und ebenso kryptische E-Mail-Adresse notieren. Brauchen wir später noch.
      Credentials Service Account

    Mehr gibt es in der Developers Console nicht zu tun.

  6. Spreadsheet freigeben. Das Google Spreadsheet “Test-O-Mat” muss für den soeben angelegten Service Account freigegeben werden, damit über diesen auf das Spreadsheet zugegriffen werden kann. Dazu verwenden wir die zuvor notierte E-Mail-Adresse aus der Google Developers Console: Im Google Spreadsheet oben rechts auf den Share/Teilen Button klicken. Daraufhin öffnet sich ein Popup-Fenster mit Eingabefeld. Dort die E-Mail-Adresse hineinkopieren, die Option “Notify people via E-Mail” abwählen und “Send” drücken.
  7. PHP Code für den Spreadsheet Zugriff erstellen. Now for the fun part, falls das noch nicht genug Spaß war. Eine frische index.php im Projektverzeichnis anlegen und im Editor öffnen. Dort den folgenden Kode einfügen und G_CLIENT_ID, G_CLIENT_EMAIL sowie G_CLIENT_KEY_PATH durch die eigenen Credentials ersetzen. Ggfs. ist auch das Passwort durch das eigene zu ersetzen, aber ich glaube, dass beim P12-Keyfile stets “notasecret” gewählt wird.
    setApplicationName( 'Test-O-Mat' );
    $client->setClientId( G_CLIENT_ID );
    $client->setAssertionCredentials( new Google_Auth_AssertionCredentials(
        array( 'https://spreadsheets.google.com/feeds', 'https://docs.google.com/feeds' ),
        file_get_contents( G_CLIENT_KEY_PATH ),
    ) );
    $client->getAuth( )->refreshTokenWithAssertion( );
    $objToken = json_decode( $client->getAccessToken( ) );
    $accessToken = $objToken->access_token;
    $serviceRequest = new GoogleSpreadsheetDefaultServiceRequest( $accessToken );
    GoogleSpreadsheetServiceRequestFactory::setInstance( $serviceRequest );
    $spreadsheetService = new GoogleSpreadsheetSpreadsheetService( );
    $spreadsheetFeed = $spreadsheetService->getSpreadsheets( );
    echo "
    foreach( $spreadsheetFeed as $spreadsheet ) {
      echo $spreadsheet->getTitle( )."n";
      $worksheetFeed = $spreadsheet->getWorksheets( );
      foreach( $worksheetFeed as $worksheet ) {
        echo "|n+-" . $worksheet->getTitle( ) . "n";
    echo "</pre>";

    Das Skript authentisiert sich via OAuth2, startet dann einen Service Request ggü. Google Spreadsheets, holt sich eine Liste aller(!) Spreadsheets, die mit der (kryptischen) E-Mail-Adresse geteilt wurden, iteriert über diese Liste und gibt für jedes Spreadsheet die Namen aller enthaltenen Worksheets aus.

    Wir haben nur das Spreadsheet "Test-O-Mat" für die E-Mail-Adresse freigegeben. Daher sollte der Browser eine Ausgabe wie die Folgende produzieren.



Wenn die Ausgabe wie zuletzt gezeigt war, dann ist es Zeit für einen Glückwunsch-Schokohasen. Die Authentisierung läuft, der Zugriff auf beliebige Spreadsheets ist möglich. Lesen und Schreiben von Daten is left as an excercise to the reader.

MacOS: Neuen “Öffnen mit”-Service zum Dienste-Menü hinzufügen

Eine Datei oder einen Ordner per Rechtsklick im MacOS-Lieblingsprogramm öffnen? Das geht in wenigen Schritten mit dem Automator.

Der Rechtsklick auf eine Datei oder einen Ordner im Finder öffnet das Kontextmenü. Dortens, ganz unten, befindet sich das Dienste-Untermenü, in dem Applikationen zusätzliche Funktionalitäten unterbringen können. Der Viren-Scanner ClamXav, jahrelang kostenlos und nun leider kostenpflichtig, nistet sich bspw. dort ein und ermöglicht auf diese Weise das Scannen einzelner Dateien.

das Rechtsklick-Dienste-Menü

Dienst-Menü erweiterbar

Dieses Service-Menü kann mit eigenen Diensten erweitert werden. Hier ein Beispiel für die Erstellung eines Dienste, der das Öffnen von Dateien oder Ordnern in Sublime Text ermöglicht. Dazu verwenden wir den Automator, eine Applikation, die jeder MacOS-Installation von Haus aus beiliegt.

Schritt-für-Schritt zum neuen Dienst

  1. Automator starten. Entweder Finder öffnen, dann CMD+Shift+A und in der Dateiliste die Automator.app Doppelklicken. Oder Spotlight mit CMD+Space aufrufen, “auto” tippen und Return. (Unterstellt, dass Spotlight den automator vorschlägt.)
  2. Automator-Typ wählen. Im Popdown-Fenster “Service” auswählen, dann mit dem Choose-Button bestätigen.
    Service im Automator wählen
  3. Service receives und Action wählen. Im “Service receives selected”-Drop-Down “files or folders” wählen.
    Im Suchfeld oben links “run shell” eingeben. In der darunterliegenden Liste an Aktionen sollte nur noch “Run Shell Script” erscheinen. Diese Aktion per Drag’n’Drop in das Workflow-Feld rechts ziehen.
    Services receives und Run Shell Skript Aktion
  4. Pass input und Shell Skript. Die Datei- und Ordner-Namen sollen als Kommandozeilenargumente an das Shell Skript übergeben werden. Dafür im “Pass input”-Drop-Down den Wert “as arguments” wählen.
    Anschliessend noch in das Eingabefenster der “Run Shell Skript”-Aktion den Pfad zum Sublime Text-Executable gefolgt von -n "$@" eintragen.
    Argumente und auszuführende Datei
  5. Den neuen Service mit CMD+S unter einem beliebigen Namen speichern, z.B. “Open in Sublime3”.

Fertig! Wer alles richtig gemacht hat, sieht im Finder nach Rechtsklick auf eine Datei oder einen Ordner “Open in Sublime3” als neuen Eintrag im Services-Untermenü, like diz:

fertiger Dienst im Finder

PS für Neunmalkluge

Ich höre sie schon rufen: “Was soll das denn mit der ‘Run Shell Script’-Aktion? Das geht doch alles viel einfacher mit ‘Open Finder Items’!” Stimmt. Und stimmt nicht. Der Ansatz mit “Open Finder Items” ist in diesem Artikel beschrieben, allerdings werden die Dateien/der Ordner damit in den Projektbaum des aktuell geöffneten Projektes eingefügt. Die hier beschriebene Verwendung von “Run Shell Script” verhindert dies und öffnet Dateien und Ordner in einem neuen Workspace in Sublime. Besser ist das.

C64 Daten von Floppy (1541) mit OpenCBM auf Mac sichern

Daten von einer 1541-Floppy auf den Mac übertragen. Das geht! Hier eine Schritt-für-Schritt-Anleitung mit OpenCBM on Mac.

C64 – die Netzhautpeitsche

C64 mit Schachbrett-Tastatur Mein C64 ist seit Ewigkeiten in Rente und fristet seit mehr als 25 Jahren im Keller ein trauriges Dasein. Alle paar Jahre, oder eher Jahrzehnte, wurde er exhumiert und in Betrieb genommen, um mal wieder so richtig im Retro-Feeling zu schwelgen. Bis nach ein paar Runden Delta, Rambo oder Gianna Sisters der Charme ganz schnell verflogen ist. Die HD-Ultra-Mega-4k-gewöhnten Augen können stecknadelkopfgroße 8-Bit-Pixel nicht mehr lange ertragen.

Mach’ mir den SIDney!

Und nur für die – nach wie vor – grandiose SID-Musik muss man nicht das vergilbte Original-Equipment aus dem Keller schleppen. Das geht einfacher auf dem PC oder Mac bspw. mit der High Voltage SID Collection (HVSC), die unglaubliche 46.000+ C64 Songs bereitstellt. Da kann man sich ein schönes Mix-Tape für die nächste Autofahrt zusammenschneiden. Infos dazu übrigens im Artikel zu C64 Klingeltönen für’s iPhone.

Wahrer Altruismus aka “die nahende Trennung”

Bisher konnte ich mich nicht von der Brotkiste trennen, weil so viele gute Erinnerungen damit verbunden sind. Und ich eine, aus heutiger Sicht, absurde Menge Lebenszeit in die Maschine gesteckt habe. Aber die (Umzugs)Kiste, in der die (Brot)Kiste steckt, hat nun genug Keller gesehen. Es gibt Fans des Retro-Computings, die mit dem C64 vielleicht noch etwas sinnvolles anstellen können. Also weg damit!


Doch es gibt noch etwas zu tun. Auf den ebenfalls noch vorhandenen 5 1/4 Zoll Floppy Discs schlummern unzählige Demos, Programme und andere Grausamkeiten meiner damaligen Programmierkünste, die ich selbstverständlich der Nachwelt erhalten möchte. Die Wahrscheinlichkeit ist zwar hoch, dass das “die Nachwelt” wenig bis null, nicht, zero, gar nicht interessiert, aber da halte ich es wie Richard Feynman und frage: Kümmert Sie, was andere denken? (Gutes Buch, BTW.)

Wie Daten vom C64 auf den PC/Mac transferieren?

ZoomFloppy V1.0 Die Kernfrage für dieses Datensicherungsunterfangen: Wie kommen die Programme von den labbrigen Floppy Discs auf den PC oder Mac? Findige Retro-Tüftler haben da so einiges zusammengelötet und meine Wahl fiel auf die ZoomFloppy v1.0 Platine. Damit wird ein Floppy-Laufwerk, in meinem Fall eine 1541, über die Platine mit dem PC oder Mac verbunden.

Der C64 wird für den Datentransfer nicht benötigt, allerdings eine passende Software auf dem PC/Mac, um die ZoomFloppy anzusteuern. OpenCBM ist so eine Software, die auf dem PC leicht in Betrieb genommen werden kann, da es vorkompilierte Packages gibt. Wie sich zeigte, war die Datensicherungsgeschichte mit dem Mac eine größere Herausforderung. Insbesondere, da es exakt nur eine einzige Anleitung im Netz zu geben scheint, wie denn OpenCBM auf dem Mac zum Laufen gebracht werden kann. Ok, habe nicht wochenlang recherchiert, aber egal wie man sucht, landet man am Ende doch immer wieder bei Lallafas Blog Artikel OpenCBM on Mac. Eine gute Anleitung, die nur leider bei mir nicht funktioniert hat.

Aber Lallafas Artikel enthielt genug Hinweise und Erläuterungen, um die nötigen Schritte quasi “von Hand” auszuführen. Hier ist also meine Schritt-für-Schritt-Anleitung, für alle, die sich mal wieder so richtig schön auf der Kommandozeile austoben möchten. *gg*

OpenCBM on Mac: HowTo für echte Kommandozeilenmänner

  1. XCode Developer Tools installieren. Bei mir war’s Version 6.3.1.
    Am einfachsten lässt sich XCode über Apples App Store installieren.
  2. Command Line Developer Tools installieren. Setzt die Existenz von XCode (vorheriger Schritt) voraus. Viele der folgenden Schritte erfolgen im Terminal; das $-Zeichen steht für den Terminal-Prompt. Zur Installation der Command Line Developer Tools folgenden Befehl ausführen.
    $ xcode-select –install
  3. XCode Lizenzbestimmungen zustimmen. NB: sudo erfordert in der Regel die Eingabe des (Admin-)Passwortes.
    $ sudo xcodebuild -license
  4. MacPorts installieren. Hier wird von macports.org das Package für die eigene MacOS Version benötigt. In meinem Fall war das Yosemite.
    Download von der MacPorts-Seite https://distfiles.macports.org/MacPorts/MacPorts-2.3.3-10.10-Yosemite.pkg.
    Danach das Paket mit Doppel-Klick installieren.
  5. MacPorts aktualisieren.
    $ sudo port -v selfupdate
  6. cc65 Compiler installieren. Den brauchen wir später, um OpenCBM zu kompilieren.
    $ sudo port install cc65
  7. USB Legacy Treiber installieren. Für den späteren Betrieb von OpenCBM.
    $ sudo port install libusb-legacy
  8. Verzeichnis für OpenCBM anlegen und hineinwechseln. Hier im Beispiel als Unterverzeichnis im Home-Verzeichnis des angemeldeten Nutzers.
    $ mkdir ~/opencbm && ~/opencbm
  9. OpenCBM runterladen. Das geht auf der Kommandozeile bspw. mit curl. NB: Ich habe Version 0.4.0 vom 28.04.2006 verwendet obwohl die aktuelle Version 0.4.2a vom 22.12.2007 ist. Wahrscheinlich ist es “safe”, die aktuelleste Version zu verwenden, aber ich halte mich hier in der Anleitung an das, was funktioniert hat.
    $ curl -o opencbm-0.4.0.tar.gz http://sourceforge.net/projects/opencbm/files/opencbm/opencbm-0.4.0/opencbm-0.4.0.tar.gz/download
  10. OpenCBM Archiv entpacken.
    $ tar xzvf opencbm-20110130.tgz && rm opencbm-20110130.tgz
  11. Verzeichniswechsel in den richtigen Unterordner.
    $ cd opencbm-20110130 && cd opencbm
  12. OpenCBM kompilieren. Dafür hatten wir in Schritt 6 den cc65 Compiler installiert. Nach erfolgreicher Kompilierung von OpenCBM werden die ausführbaren Dateien nebst man(ual)-Dateien automatisch an die richtigen Stellen im File-System kopiert. Nach Eingabe des folgenden Befehls erstmal Käffchen kochen.
    $ sudo make -f LINUX/Makefile PREFIX=/opt/local MANDIR=/opt/local/share/man/man1 install-all
  13. OpenCBM konfigurieren. Da ist nur ein Buchstabe in einer Datei zu ergänzen. Im folgenden Befehl wird der Editor vi verwendet. Wer dessen kryptische Syntax nicht kennt, ist verloren. Dann lieber die Datei mit dem Finder aufspüren und einem beliebigen anderen Text-Editor bearbeiten.
    $ sudo vi /opt/local/etc/opencbm.conf
    Und dort im Abschnitt


    xu1541 durch xum1541 ersetzen. Datei speichern.

That’s it! Piece of cake! Easy-peasy! Let’s rock! Örchz.

Inbetriebnahme und Test

Das ZoomFloppy-Manual empfiehlt die folgende Reihenfolge, um die technischen Komponenten miteinander zu verbinden bzw. diese einzuschalten.

  1. Floppy Kabel mit der ZoomFloppy-Platine verbinden. Das gilt für den runden 8-poligen, also auch für ein ggf. vorhandenes Parallelkabel.
  2. Jetzt die ZoomFloppy über die Micro-USB-Buchse an den USB-Anschluß des Mac anschließen. Eine grüne LED zeigt die Betriebsbereitschaft an.
  3. Floppy einschalten.

Bei der Ausserbetriebnahme alles in umgekehrter Reihenfolge.

Jetzt wird sich zeigen, ob die Mühe belohnt wird. Terminal öffnen und den folgenden Befehl eingeben.

$ cbmctrl detect
8: SpeedDOS 1541 (XP1541)

Wenn als Antwort so eine oder eine ähnlich Meldung erscheint, dann heisst das ERFOLG!

Die Meldung wird variieren, je nach dem, um welchen Floppy-Typ es sich handelt, ob ein Beschleuniger o.ä. vorhanden ist und an welchem Bus (8 oder 9) das Laufwerk hängt. Bei mir werkelt ein in der 1541 fest verbautes “Quickdos”; eine Variante des damals beliebten SpeedDOS, bei der nicht nur der Lade- sondern auch der Speichervorgang beschleunigt wurde. (35 x schneller laden, 17 x schneller speichern. Der Hammer!)

Bei einer 1571 könnte das wie folgt aussehen.

$ cbmctrl detect
8: 1571 (XP1541)

Der Mac kann jetzt über die ZoomFloppy mit dem Floppy-Laufwerk kommunizieren. FTW!

Noch ein letzter Test; wir überprüfen den Status des Laufwerks (an Bus 8).

$ cbmctrl status 8
00, ok,00,00

Wer seinerzeit mit dem C64 gearbeitet hat, wird die beruhigende Antwort “00, ok,00,00” noch kennen. Damit sind alle Tests erfolgreich abgeschlossen. Die Datensicherung kann beginnen.

Datensicherung = Fleißarbeit

So geht die Datensicherung dann los: Floppy ins Laufwerk schieben und im Terminal des Mac mit dem Befehl cbmctrl dir das Inhaltsverzeichnis (Directory) der eingelegten Diskette auslesen.

$ cbmctrl dir 8
140  "m.g.part x  /xsi" prg<   
40   "estimate    /xsi" prg<  
42   "control d.  /tsr" prg<  
87   "barbara d.  /xsi" prg<  
79   "megawurzel  /tsr" prg<  
130  "m.g.part xi /xsi" prg<   
47   "miami vice  /xsi" prg<  
31   "the tube m. /xsi" prg<  
28   "saboteur ii /xsi" prg<  
29   "shadow sc.  /xsi" prg<  
0 blocks free.             
00, ok,00,00

Kann die Diskette gelesen werden, wird das Directory wie man es vom C64 mit dem Befehl LOAD "$",8,1 und anschließendem LIST her kannte, ausgegeben. Nun gibt es zwei Möglichkeiten, um die Dateien von der Floppy-Disc auf den Mac zu übertragen.

1. Disk-Image (d64)

Auslesen des gesamten Inhalts einer Diskette mit dem Befehl d64copy und Ablegen in einer *.d64-Image-Datei. Hier ein Beispiel für das vollständige Auslesen einer Floppy-Disc.

$ d64copy --no-warp -r 3 8 dateiname.d64
[Warning] growing image file to 683 blocks
 1: *********************                  
 2: *********************                  
 3: *********************                  
 4: *********************                  
 5: *********************                  
 6: *********************                  
 7: *********************                  
 8: *********************                  
 9: *********************                  
10: *********************                  
11: *********************                  
12: *********************                  
13: *********************                  
14: *********************                  
15: *********************                  
16: *********************                  
17: *********************                  
18: *******************                    
19: *******************                    
20: *******************                    
21: *******************                    
22: *******************                    
23: *******************                    
24: *******************                    
25: ******************                     
26: ******************                     
27: ******************                     
28: ******************                     
29: ******************                     
30: ******************                     
31: *****************                      
32: *****************                      
33: *****************                      
34: *****************                      
35: *****************       100%   683/683
683 blocks copied.

Der Befehl zeigt Block-für-Block den Fortschritt an. Können Blöcke nicht gelesen werden, so wird dies ebenfalls angezeigt. In diesem Beispiel gab es keine (nicht korrigierbaren) Fehler und die Diskette wurde vollständig in das Disk-Image geschrieben.

Die verwendeten Parameter --no-warp und -r 3 haben sich bei meinen Disketten als sinnvoll erwiesen: Warp-Modus aus, da es mit eingeschaltetem Warp-Modus zu viele Lesefehler gab. Und maximal drei Versuche, um Blöcke mit Lesefehlern doch noch erfolgreich lesen zu können.

2. Einzelne Files (prg)

Auslesen einzelner Files mit dem Befehl cbmread und Ablegen im *.prg-Format. Das könnte dann so aussehen.

$ cbmread 8 "control d.  /tsr"
[Info] reading CONTROL D.  /TSR -> control d.  _tsr.prg
[Info] identified a SpeedDOS 1541 drive
[Info] 00, OK,00,00

Sowohl *.d64- als auch *.prg Dateien werden von den einschlägigen C64-Emulatoren verarbeitet. Auf dem Mac präferiere ich VICE, the versatile Commodore Emulator.


Das Auslesen 25 Jahre alter Disketten mit ebensoalter Hardware lief teilweise, und wenig überraschend, ein wenig unrund.

Gealterte Datenträger

Einige Diskette zeigen Stockflecken auf der Magnetscheibe. Keine Ahnung, ob das der Langlebigkeit zuträglich ist, aber mit Anhauchen und anschliessendem kräftigem Reiben mit dem dicken Daumen lasst sich die Flecken vermindern. Interessant, wie sich Einstellungen ändern. Früher war die Magnetschicht ein Heiligtum, das um Gottes Willen mit Nichts in Berührung kommen durfte. Schon gar nicht mit einem Daumen. Aber Dinge ändern sich und wer heilt, hat recht! Einige der Disketten waren so tatsächlich wieder in einen lesbaren Zustand zu bekommen.

Gealterte Hardware

Auch die 1541 hat ihre 25+ Jahre auf dem Buckel und kam zwar mit vielen Disketten erstaunlich gut, mit einigen aber gar nicht zurecht. Manchmal wollte sie auch Disketten nicht mehr lesen, die sie nur Minuten zuvor problemlos lesen konnte. Dann half zumeist meine "Master-Diskette": Eine Diskette, die die 1541 erstaunlicherweise jederzeit ohne zu Murren lesen konnte. Nach wiederholtem Lesen des Inhaltsverzeichnisses meiner Master-Diskette war möglicherweise der Schreib-/Lesekopf wieder an der richtigen Position und es konnten in Folge wieder andere Disketten gelesen werden.

Irgendwann ging dann leider gar nichts mehr und ich sah mich gezwungen, den Schreib-/Lesekopf der 1541 zu reinigen. Da gibt es zahlreiche Videos und Anleitungen im Netz; ich habe mich an diese bebilderte Anleitung gehalten. Der Andruckfilz blieb unangetastet. Sicherlich wäre es noch sinnvoll gewesen, wie beschrieben, die Führungsschienen mit Haftschmieröl zu pflegen. Mangels Öl habe ich das aber gelassen. Da bin ich knallhart.

format c:

Gerade bei der 1541 hat das Formatieren immer besonders viel Spaß gemacht, wenn der Schreib-/Lesekopf mit lautem Rattern an das Ende der Führungsschienen knallte. Nach dem Exhumieren des C64 aus dem Keller, war eine "Leerformatierung", also das Formatieren ohne eingelegte Diskette, aber genau der richtige Tipp, um der 1541 wieder auf die Sprünge zu helfen.

Mit OpenCBM lässt sich auch eine Diskette formatieren, bspw. so

cbmctrl command 8 N0:NAME,2D

oder so

cbmctrl open 8 15 I0

Wenn nichts mehr geht, ist das auf jeden Fall einen Versuch wert.

Ente gut, alles gut

Nach so viel Vorarbeit, ist die Freude groß, dass alle alten Demos, Programme und andere 8-Bit-Grausamkeiten in ein neues digitales Grab Format überführt werden konnten. Ipse fecit und ich habe fertig.

Google Analytics datenschutzkonform einsetzen

Für den datenschutzkonformen Einsatz von Google Analytics auf mobilen Browsern bedarf es spezieller Massnahmen zur Sicherstellung des Widerspruchsrechts.

Google Analytics kann seit geraumer Zeit datenschutzkonform in Deutschland eingesetzt werden. Es gibt eine Vielzahl an Artikeln, bspw. Google Analytics datenschutzkonform einsetzen, die sich mit dem Thema auseinandersetzen und die Rahmenbedingungen für diesen konformen Einsatz ausführlich erläutern. Kurz gefasst, müssen die folgenden Bedingungen erfüllt sein:

  1. Abschluß einer Auftragsdatenvereinbarungserklärung mit Google. So ein Wortmonster können sich nur deutsche Behörden ausdenken, daher sprechen wir im folgenden von einer ADV.
  2. Datenschutzerklärung mit Passus zur Verwendung von Google Analytics.
  3. Anonymisierung der IP-Adressen, die von Google Analytics erfasst werden.
  4. Widerspruchsmöglichkeit (Opt-Out) für Besucher einer Website, um die Datenerfassung durch Google Analytics auszuschalten.

Dieser Artikel hier hat seinen Fokus auf dem Thema Widerspruchsrecht/Opt-Out, behandelt der Vollständigkeit halber aber auch die Punkte 1-3.

ad 1. Auftragsdatenvereinbarungserklärung (ADV)

Für den Abschluß der ADV stellt Google ein mit den deutschen Behörden abgestimmtes Dokument bereit. Hier runterladen. Zweimal ausdrucken. Beide Exemplare ausgefüllt und unterschrieben an Google Irland senden. Einige Wochen auf ein von Google unterzeichnetes Exemplar warten. Abheften. Fertig.

ad 2. Datenschutzerklärung

Der Passus zur Verwendung von Google Analytics in meiner Datenschutzerklärung ist umfassend und sollte den Konformitätsanforderungen genügen. Ich weise explizit darauf hin, dass ich keine Rechtsberatung geben kann und darf. Verwendung des Passus daher auf eigene Gefahr.

Datenschutzerklärung für die Nutzung von Google Analytics
Diese Website benutzt Google Analytics, einen Webanalysedienst der Google Inc. (“Google”). Google Analytics verwendet sog. “Cookies”, Textdateien, die auf Ihrem Computer gespeichert werden und die eine Analyse der Benutzung der Website durch Sie ermöglichen. Im Auftrag des Betreibers dieser Website wird Google diese Informationen benutzen, um Ihre Nutzung der Website auszuwerten, um Reports über die Websiteaktivitäten zusammenzustellen und um weitere mit der Website-Nutzung und der Internet-Nutzung verbundene Dienstleistungen gegenüber dem Websitebetreiber zu erbringen. Wir verwenden Google Analytics auch, um demographische Informationen und Informationen über Ihre Vorlieben zu sammeln (z.B. Alter, Geschlecht und Interessen), einschließlich Google Analytics Demographics und Interest Reporting. Mehr Informationen zu Demographics und Interest Reporting finden Sie hier.

Die durch den o.g. Cookie erzeugten Informationen über Ihre Benutzung dieser Website werden in der Regel an einen Server von Google in den USA übertragen und dort gespeichert. Auf dieser Website ist die sogenannte IP-Anonymisierung aktiv. Ihre IP-Adresse wird von Google dadurch innerhalb von Mitgliedstaaten der Europäischen Union oder in anderen Vertragsstaaten des Abkommens über den Europäischen Wirtschaftsraum vor der Übertragung an die Google-Server verkürzt. Nur in Ausnahmefällen wird die volle IP-Adresse erst an einen Server von Google in den USA übertragen und dann dort gekürzt. Die IP-Anonymisierung erfolgt mit dem Google Analytics Flag zum IP-Masking.

Browser-Plugin zur Deaktivierung der Datenerfassung von Google Analytics
Google hält zum Zwecke des Widerspruchs gegen die Erfassung von Nutzungsdaten ein Browser-Plugin (s.u.) zur Deaktivierung von Google Analytics bereit. Die im Rahmen von Google Analytics von Ihrem Browser übermittelte IP-Adresse wird nicht mit anderen Daten von Google zusammengeführt. Sie können die Speicherung der Cookies durch eine entsprechende Einstellung Ihrer Browser-Software verhindern; wir weisen Sie jedoch darauf hin, dass Sie in diesem Fall gegebenenfalls nicht sämtliche Funktionen dieser Website vollumfänglich werden nutzen können. Sie können darüber hinaus die Erfassung der durch das Cookie erzeugten und auf Ihre Nutzung der Website bezogenen Daten (inkl. Ihrer IP-Adresse) an Google sowie die Verarbeitung dieser Daten durch Google verhindern, indem sie dieses Browser-Plugin herunterladen und installieren.

Nähere Informationen zu Nutzungsbedingungen und Datenschutz bzgl. Google Analytics finden Sie in den Terms & Conditions bzw. in den Policies.

Der ganz am Anfang dieses Posts verlinkte Artikel von datenschutzbeauftragter-info.de stellt ebenfalls einen entsprechenden Passus bereit; dort gibt es auch eine englische Version sowie eine Ergänzung, falls AdWords und/oder Double-Click zum Einsatz kommen. Wer hierzu recherchiert wird meistens auf sich ähnelnde Formulierungen stossen, da die Blaupause von Google selber stammt.

ad 3. IP-Adressen anonymisieren

Google stellt aktuell zwei unterschiedliche Tracking Pixel für Google Analytics bereit: Zum einen das klassische Tracking Pixel, zum anderen Universal Analytics. Bei Letztgenanntem ist zur Anonymisierung der IP-Adresse die folgende Zeile im Tracking Kode hinzuzufügen.
ga('set', 'anonymizeIp', true);
Falls das klassische Tracking Pixel zum Einsatz kommt, wird die Anonymisierung mit der folgenden Ergänzung im Tracking Kode eingeschaltet.

ad 4. Widerspruch / Opt-Out

Beim Thema Opt-Out geht es im Kern um die Bereitstellung von Tools oder Mechanismen, um dem Widerspruchsrecht des Website-Besuchers gegen die Erfassung seiner Daten durch Google Analytics gerecht zu werden.

Verweis auf Browser-Plugin für Opt-Out auf Desktop-Browsern

Einige Zeit war man davon ausgegangen, dass die Verlinkung eines von Google bereitgestellten Browser-Plugins, mit dem die Erfassung von Daten durch Google Analytics nach Installation des Plugins im Browser ausgeschaltet werden kann, genügen würde. Zwar wird dieses Plugin für alle gängigen Browser angeboten, es funktioniert jedoch nur im Zusammenspiel mit Desktop-Browsern! Auf den Browsern mobiler Geräte lassen sich in der Regel keine Plugins installieren, so dass hierfür eine andere – und zwar zusätzliche – Opt-Out-Möglichkeit angeboten werden muss. NB: Der oben zitierte Passus zur Datenschutzerklärung enthält bereits die Verlinkung auf das Browser-Plugin.

Opt-Out Link per Javascript für mobile Browser

Die gängigste Lösung, um den Widerspruch auch auf mobilen Browsern zu ermöglichen, bedient sich einiger Zeilen Javascript-Kode. Der Mechanismus ist einfach: Dem Besucher einer Website wird ein Link angeboten, dessen Klick ein Cookie setzt, welches wiederum Google Analytics den Do-not-track Wunsch des Nutzers mitteilt.

Für die Implementierung bei Verwendung des klassischen Google Analytics Pixels kann folgender Kode verwendet werden. Er entspricht dem Kode, der sich auf den Seiten von Rechtsanwalt Schwenke findet (GA mobile Nutzung), mit zwei Änderungen:

  1. Statt jQuery wird klassisches Javascript in gaOptoutStatus() verwendet. Es wäre ein Overkill nur zum Ändern einer Property die jQuery-Library einzubinden. Wer ohnehin jQuery nutzt, kann natürlich nach Belieben auch jQuery einsetzen.
  2. In gaOptoutToggle() wird das Cookie beim Opt-In, also wenn ein Website-Besucher sich entscheidet das Tracking wieder einzuschalten, auf false gesetzt, statt das Cookie zu löschen. Das hat aus Sicht von Google Analytics denselben Effekt, hilft aber beim Debugging.

Die Variable gaProperty ist mit der eigenen Google Analytics Property zu belegen. Beim Einsatz des Universal Analytics Tracking Pixels muß der zugehörige Google Analytics Tracking Kode entsprechend geändert werden.

Nun fehlt nur noch ein Abschnitt in der Datenschutzerklärung, der dieses Verfahren beschreibt und natürlich den Opt-Out Link enthält.

Cookie Opt-out zur Deaktivierung der Datenerfassung von Google Analytics
Alternativ zum Browser-Plugin (Browser-Add-On) oder in Browsern auf mobilen Geräten, bei denen Browser-Plugins nicht funktionieren, verwenden Sie bitte den folgenden Link, um die Datenerfassung durch Google Analytics auf dieser Website zu (de)aktivieren. Wenn Sie Google Analytics deaktivieren wird ein Opt-Out-Cookie auf ihrem Gerät gesetzt, das die zukünftige Erfassung Ihrer Daten beim Besuch dieser Website verhindert: . Bitte beachten Sie, dass Sie nach dem Löschen von Cookies in ihrem Browser den Link erneut anklicken müssen.

Das Ganze sieht als HTML-Kode dann wie folgt aus:

Cookie Opt-out zur Deaktivierung der Datenerfassung von Google Analytics
Alternativ zum Browser-Plugin (Browser-Add-On) oder in Browsern auf mobilen Geräten, bei denen Browser-Plugins nicht funktionieren, verwenden Sie bitte den folgenden Link, um die Datenerfassung durch Google Analytics auf dieser Website zu (de)aktivieren. Wenn Sie Google Analytics deaktivieren wird ein Opt-Out-Cookie auf ihrem Gerät gesetzt, das die zukünftige Erfassung Ihrer Daten beim Besuch dieser Website verhindert: . Bitte beachten Sie, dass Sie nach dem Löschen von Cookies in ihrem Browser den Link erneut anklicken müssen.

Bei der hier vorgestellten Lösung wird als Linktext der aktuelle Opt-Out-Zustand angezeigt: Wenn das Tracking aktiv ist (=kein Cookie gesetzt) erscheint “Google Analytics ist aktiv.”, wenn das Tracking nicht aktiv ist (=Cookie gesetzt) “Google Analytics ist deaktiviert.”

Im Zweifel fragt man jemanden, der Ahnung hat. Das gilt sowohl für die technische Implementierung als natürlich auch für die formaljuristische Prüfung der Vollständigkeit und Korrektheit der eigenen Datenschutzerklärung.

Mac OS versteckte Dateien anzeigen (und wieder verstecken)

Der Mac OS Finder zeigt versteckte Dateien nicht an. Darum sind sie ja auch versteckt. Aber sie lassen sich leicht sichtbar machen. Und ebenso leicht wieder verstecken.

Hinter MacOS werkelt ein *nix-System. Auf diesen Systemen ist es üblich, dass Dateien, die mit einem Punkt beginnen, also beispielsweise .htaccess, vom Dateibetrachter nicht angezeigt werden. Manchmal möchte man die versteckten Dateien aber doch sehen.

Die Terminal Methode

  1. Terminal öffnen.
  2. Mit dem folgenden Befehl wird dem Finder mitgeteilt, dass er alle Dateien anzeigen soll.
    $ defaults write com.apple.finder AppleShowAllFiles TRUE
  3. Noch ein
    $ killall Finder
    hinterher. Damit wird der Finder neu gestartet.


Die sichtbar gemachten Dateien können genauso leicht wieder versteckt werden, indem am Ende des oben stehenden Befehls “TRUE” durch “FALSE” ersetzt wird. Danach wieder killall Finder und die Dateien sind versteckt.

Wer das häufiger braucht, möchte es aber vielleicht ein wenig komfortabler haben.

Die Profi-Methode mit Toggle-Button in der Finder-Toolbar

Wir bauen uns einen hübschen Toggle-Button für die Finder-Toolbar, der auf Knopfdruck zwischen “Dateien versteckt” und “Dateien sichtbar” wechselt. Dazu bedienen wir uns des geballten Wissens aus dem vorigen Artikel Aus Shell Skript eine MacOS App erstellen und App Icon ändern und bauen sogar noch funktional völlig unnötige bells’n’whistles ein: In Abhängigkeit des aktuellen Status “sichtbar” oder “versteckt” verändert sich das Aussehen des Icons in der Toolbar. Toll!

  1. Wir benötigen zunächst ein Skript, das den aktuellen Sichtbarkeitsstatus ermittelt, diesen dann wechselt und das Icon austauscht. Den folgenden Kode kopieren und als toggleHidden.sh im Home-Verzeichnis /Users/ speichern. NB: Alle folgenden Schritte gehen davon aus, dass die zugehörigen Dateien im Home-Verzeichnis liegen!
    # get current visibility status
    isVisible="$(defaults read com.apple.finder AppleShowAllFiles)"
    # toggle visibility and change app icon
    rm ~/$'toggleHidden.app/Iconr'
    sleep 1
    if [ "$isVisible" = FALSE ]; then
      defaults write com.apple.finder AppleShowAllFiles TRUE
      Rez -append ~/toggleHidden-on.rsrc -o ~/$'toggleHidden.app/Iconr'
      sleep .2
      Rez -append ~/toggleHidden-on.rsrc -o ~/$'toggleHidden.app/Iconr'
      defaults write com.apple.finder AppleShowAllFiles FALSE
      Rez -append ~/toggleHidden-off.rsrc -o ~/$'toggleHidden.app/Iconr'
      sleep .2
      Rez -append ~/toggleHidden-off.rsrc -o ~/$'toggleHidden.app/Iconr'
    # force changes by restarting Finder
    sleep .2 && killall Finder
  2. Mithilfe des appify-Skripts (Hinweise im verlinkten Artikel beachten!) zaubern wir aus toggleHidden.sh eine MacOS App toggleHidden.app. Dazu ein Terminal-Fenster öffnen und den Befehl
    $ appify toggleHidden.sh
    ausführen. Im selben Verzeichnis liegt nun die App toggleHidden.app.
  3. Wir brauchen zwei Icons für die beiden Status. Rechteckig, bspw. mit den Abmessungen 128 x 128 px.
    Icon für versteckte Dateien sichtbarversteckte Dateien sichtbar, Datei toggleHidden-128x128-on.png
    Icon für versteckte Dateien sichtbarversteckte Dateien unsichtbar, Datei toggleHidden-128x128-off.png
    Die sind doch ganz hübsch. Örchz.
  4. Aus den Icon-Grafiken müssen zur späteren Verwendung Ressourcen produziert werden. Dafür werden ein paar Werkzeuge benötigt, die zu den XCode Command Line Tools gehören. Beim ersten Aufruf des folgenden Tools sips im Terminal sollte MacOS von sich aus fragen, ob die Command Line Tools installiert werden. Sobald die Tools verfügbar sind im Terminal folgende Befehle eingeben, um den ersten Schritt zu den Grafik-Ressourcen zu absolvieren.
    $ sips -i toggleHidden-128x128-on.png
    $ sips -i toggleHidden-128x128-off.png
  5. Jetzt die Ressourcen extrahieren.
    $ DeRez -only icns toggleHidden-128x128-on.png > toggleHidden-on.rsrc
    $ DeRez -only icns toggleHidden-128x128-off.png > toggleHidden-off.rsrc
  6. Initiale Bindung des Off-Icons an unsere App.
    $ Rez -append toggleHidden-off.rsrc -o $'toggleHidden.app/Iconr'
  7. Und MacOS mitteilen, dass diese App jetzt ein Icon hat.
    $ SetFile -a C toggleHidden.app
  8. Letzter Schritt! Im Finder in das Home-Verzeichnis wechseln, bspw. über das Finder-Menü “Go” und dann “Home”. Per CMD + Drag’n’Drop unsere App toggleHidden.app in die Finder Toolbar ziehen. Wichtig: Erst CMD drücken und gedrückt halten. Dann Datei packen und in die Finder Toolbar ziehen. MacOS ist da sehr “picky” was den Ablauf dieser Drag’n’Drop-Operation anbelangt.

Nun sollte unser wunderschönes Icon in der Toolbar prangen und in etwa so aussehen.

toggleHidden App in der Finder Toolbar: OFF

Nach einem Klick auf den Kreis wird der Finder neu gestartet, das Icon getauscht und fortan alle versteckten Dateien angezeigt. Das könnte dann so aussehen.

toggleHidden App in der Finder Toolbar: ON

Have fun!