Index: .cproject
===================================================================
--- .cproject	(revision 77d8df82f5dfc0eadc7b81c42db2c4f4773a428d)
+++ .cproject	(revision 9ddbf3e3b93004ac7df85a6f7d2ae557d8dac5a9)
@@ -25,9 +25,10 @@
 							</tool>
 							<tool id="cdt.managedbuild.tool.gnu.c.compiler.base.862022870" name="GCC C Compiler" superClass="cdt.managedbuild.tool.gnu.c.compiler.base">
-								<option id="gnu.c.compiler.option.include.paths.2032588655" name="Include paths (-I)" superClass="gnu.c.compiler.option.include.paths" valueType="includePath">
+								<option id="gnu.c.compiler.option.include.paths.2032588655" name="Include paths (-I)" superClass="gnu.c.compiler.option.include.paths" useByScannerDiscovery="false" valueType="includePath">
 									<listOptionValue builtIn="false" value="&quot;${workspace_loc:/buchla-emu/cpu}&quot;"/>
 									<listOptionValue builtIn="false" value="&quot;${workspace_loc:/buchla-emu/emu}&quot;"/>
 									<listOptionValue builtIn="false" value="&quot;${workspace_loc:/buchla-emu/build}&quot;"/>
 									<listOptionValue builtIn="false" value="/opt/sdl2/include"/>
+									<listOptionValue builtIn="false" value="/opt/rtmidi/include"/>
 								</option>
 								<inputType id="cdt.managedbuild.tool.gnu.c.compiler.input.1138147073" superClass="cdt.managedbuild.tool.gnu.c.compiler.input"/>
Index: .settings/language.settings.xml
===================================================================
--- .settings/language.settings.xml	(revision 77d8df82f5dfc0eadc7b81c42db2c4f4773a428d)
+++ .settings/language.settings.xml	(revision 9ddbf3e3b93004ac7df85a6f7d2ae557d8dac5a9)
@@ -6,5 +6,5 @@
 			<provider-reference id="org.eclipse.cdt.core.ReferencedProjectsLanguageSettingsProvider" ref="shared-provider"/>
 			<provider copy-of="extension" id="org.eclipse.cdt.managedbuilder.core.GCCBuildCommandParser"/>
-			<provider class="org.eclipse.cdt.managedbuilder.language.settings.providers.GCCBuiltinSpecsDetector" console="false" env-hash="-521499554224989883" id="org.eclipse.cdt.managedbuilder.core.GCCBuiltinSpecsDetector" keep-relative-paths="false" name="CDT GCC Built-in Compiler Settings" parameter="${COMMAND} ${FLAGS} -E -P -v -dD &quot;${INPUTS}&quot;" prefer-non-shared="true">
+			<provider class="org.eclipse.cdt.managedbuilder.language.settings.providers.GCCBuiltinSpecsDetector" console="false" env-hash="882153106844088736" id="org.eclipse.cdt.managedbuilder.core.GCCBuiltinSpecsDetector" keep-relative-paths="false" name="CDT GCC Built-in Compiler Settings" parameter="${COMMAND} ${FLAGS} -E -P -v -dD &quot;${INPUTS}&quot;" prefer-non-shared="true">
 				<language-scope id="org.eclipse.cdt.core.gcc"/>
 				<language-scope id="org.eclipse.cdt.core.g++"/>
Index: Makefile
===================================================================
--- Makefile	(revision 77d8df82f5dfc0eadc7b81c42db2c4f4773a428d)
+++ Makefile	(revision 9ddbf3e3b93004ac7df85a6f7d2ae557d8dac5a9)
@@ -59,8 +59,8 @@
 				-framework AudioToolbox \
 				-framework Carbon \
-				-framework CoreMIDI \
 				-framework CoreAudio \
 				-framework CoreFoundation \
 				-framework CoreGraphics \
+				-framework CoreMIDI \
 				-framework CoreVideo \
 				-framework ForceFeedback \
@@ -70,5 +70,5 @@
 else
 FLAGS_EMU +=	-D EMU_WIN
-FLAGS_LNK :=	$(FLAGS) -Wall -Wextra -static -static-libstdc++
+FLAGS_LNK :=	$(FLAGS) -Wall -Wextra -static
 LIBS :=			-l mingw32 \
 				$(SDL2_LIB)/libSDL2.a \
Index: emu/all.h
===================================================================
--- emu/all.h	(revision 77d8df82f5dfc0eadc7b81c42db2c4f4773a428d)
+++ emu/all.h	(revision 9ddbf3e3b93004ac7df85a6f7d2ae557d8dac5a9)
@@ -30,4 +30,15 @@
 #include <SDL2/SDL_net.h>
 #include <SDL2/SDL_ttf.h>
+
+// work around RtMidi's C++-isms
+
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wstrict-prototypes"
+
+typedef struct RtMidiWrapper RtMidiWrapper;
+
+#include <rtmidi/rtmidi_c.h>
+
+#pragma GCC diagnostic pop
 
 #define inf(...) SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, __VA_ARGS__);
@@ -65,4 +76,6 @@
 extern const char *font;
 
+extern int32_t mid_port;
+
 extern SDL_atomic_t run;
 
@@ -70,6 +83,4 @@
 extern uint32_t ser_win;
 extern uint32_t lcd_win;
-
-extern uint32_t mid_port;
 
 extern void sdl_init(void);
Index: emu/main.c
===================================================================
--- emu/main.c	(revision 77d8df82f5dfc0eadc7b81c42db2c4f4773a428d)
+++ emu/main.c	(revision 9ddbf3e3b93004ac7df85a6f7d2ae557d8dac5a9)
@@ -43,12 +43,13 @@
 const char *font = "ttf/vera-sans-mono.ttf";
 
+int32_t mid_port = -1;
+
 SDL_atomic_t run;
 
-uint32_t mid_port = 0;
-
 static void usage(FILE *fh)
 {
-	fprintf(fh, "usage: buchla [-h] [-v comp [-v comp [...]]] [-b bios] [-d disk] [-f font] [-m midiport] \n");
-	fprintf(fh, "where comp is one of: ");
+	fprintf(fh, "usage: buchla [-h] [-v comp [-v comp [...]]] [-b bios] [-d disk] [-f font] [-m port]\n");
+	fprintf(fh, "with\n");
+	fprintf(fh, "  comp - one of: ");
 
 	for (int32_t i = 0; i < ARRAY_COUNT(verb_flags); ++i) {
@@ -57,6 +58,9 @@
 
 	fprintf(fh, "all\n");
-	fprintf(fh, "and midiport is the number of the desired MIDI port\n");
-	fprintf(fh, "list all available MIDI ports with: buchla [-m list]\n");
+	fprintf(fh, "  bios - BIOS ROM file (default: bios.abs)\n");
+	fprintf(fh, "  disk - disk image file (default: buchla.disk)\n");
+	fprintf(fh, "  font - console and LCD font (default: ttf/vera-sans-mono.ttf)\n");
+	fprintf(fh, "  port - number of the desired MIDI port (default: 0)\n");
+	fprintf(fh, "         \"list\" instead of a port number lists available ports\n");
 }
 
@@ -145,9 +149,16 @@
 				mid_list();
 				exit(0);
-				continue;
-			}
-
-			// TODO: Assign midi port number
-			 mid_port = (uint32_t) atoi(argv[i]);
+			}
+
+			char *end;
+			int64_t tmp = strtol(argv[i], &end, 10);
+
+			if (*end != 0 || tmp < 0 || tmp > 15) {
+				usage(stderr);
+				fprintf(stderr, "invalid argument to -m: %s\n", argv[i]);
+				exit(1);
+			}
+
+			mid_port = (int32_t)tmp;
 			continue;
 		}
Index: emu/mid.c
===================================================================
--- emu/mid.c	(revision 77d8df82f5dfc0eadc7b81c42db2c4f4773a428d)
+++ emu/mid.c	(revision 9ddbf3e3b93004ac7df85a6f7d2ae557d8dac5a9)
@@ -1,4 +1,4 @@
 /*
- *  Copyright (C) 2017 The Contributors
+ *  Copyright (C) 2017-2018 The Contributors
  *
  *  This program is free software: you can redistribute it and/or modify
@@ -17,9 +17,10 @@
 
 #include <all.h>
-#include <rtmidi/rtmidi_c.h>
 
 #define ver(...) _ver(mid_verbose, 0, __VA_ARGS__)
 #define ver2(...) _ver(mid_verbose, 1, __VA_ARGS__)
 #define ver3(...) _ver(mid_verbose, 2, __VA_ARGS__)
+
+int32_t mid_verbose = 0;
 
 #define REG_IER_ISR 0
@@ -45,7 +46,5 @@
 };
 
-int32_t mid_verbose = 0;
-
-struct RtMidiWrapper* mid_in;
+static struct RtMidiWrapper *mid_in = NULL;
 
 static void xmit(int32_t un)
@@ -74,6 +73,10 @@
 }
 
-static void out_lk(int32_t un, uint8_t c)
-{
+static void out(int32_t un, uint8_t c)
+{
+	if (SDL_LockMutex(cpu_mutex) < 0) {
+		fail("SDL_LockMutex() failed: %s", SDL_GetError());
+	}
+
 	int32_t i = state[un].buf_hd;
 	ver2("mid out %d %d 0x%02x", state[un].buf_tl, i, c);
@@ -90,13 +93,4 @@
 		xmit(un);
 	}
-}
-
-static void out(int32_t un, uint8_t c)
-{
-	if (SDL_LockMutex(cpu_mutex) < 0) {
-		fail("SDL_LockMutex() failed: %s", SDL_GetError());
-	}
-
-	out_lk(un, c);
 
 	if (SDL_UnlockMutex(cpu_mutex) < 0) {
@@ -105,13 +99,63 @@
 }
 
-static void mid_callback(double timeStamp, const unsigned char* message, size_t size, void *userData) {
-	(void) size;
-	(void) userData;
-
-	ver2("Timestamp %f\n", timeStamp);
-
-	for (uint8_t i = 0; i < sizeof(message); i++) {
-		ver2("Message %i %u", i, (uint8_t) message[i]);
-		out(0, message[i]);
+static void callback(double time, const uint8_t *midi, void *data)
+{
+	(void)data;
+
+	int32_t len;
+
+	switch (midi[0] & 0xf0) {
+	case 0x80: // note on
+	case 0x90: // note off
+	case 0xa0: // polyphonic key pressure
+	case 0xb0: // control change
+	case 0xe0: // pitch bend change
+		len = 3;
+		break;
+
+	case 0xc0: // program change
+	case 0xd0: // channel pressure
+		len = 2;
+		break;
+
+	case 0xf0:
+		switch (midi[0]) {
+		case 0xf0: // system exclusive
+		case 0xf4: // undefined
+		case 0xf5: // undefined
+		case 0xf7: // end of exclusive
+		case 0xf9: // undefined
+		case 0xfd: // undefined
+			len = -1;
+			break;
+
+		case 0xf1: // MIDI time code quarter frame
+		case 0xf3: // song select
+			len = 2;
+			break;
+
+		case 0xf2: // song position pointer
+			len = 3;
+			break;
+
+		case 0xf6: // tune request
+		case 0xf8: // timing clock
+		case 0xfa: // start
+		case 0xfb: // continue
+		case 0xfc: // stop
+		case 0xfe: // active sensing
+		case 0xff: // reset
+			len = 1;
+			break;
+		}
+
+		break;
+	}
+
+	ver2("time %f", time);
+
+	for (int32_t i = 0; i < len; ++i) {
+		ver2("midi[%d] 0x%02x", i, midi[i]);
+		out(0, midi[i]);
 	}
 }
@@ -121,33 +165,41 @@
 	ver("mid init");
 
+	if (mid_port < 0) {
+		ver("no MIDI requested");
+		return;
+	}
+
 	mid_in = rtmidi_in_create_default();
-	ver2("%p", mid_in->ptr);
-	// check if null
-
-	uint32_t portcount = rtmidi_get_port_count(mid_in);
-	if (portcount == 0) {
+
+	if (!mid_in->ok) {
+		fail("rtmidi_in_create_default() failed: %s", mid_in->msg);
+	}
+
+	int32_t n_ports = (int32_t)rtmidi_get_port_count(mid_in);
+
+	if (n_ports == 0) {
+		inf("no MIDI ports\n");
+		rtmidi_in_free(mid_in);
 		mid_in = NULL;
-		ver2("No MIDI ports\n");
-		return;
-	}
-
-	if (mid_port > portcount) {
-		mid_in = NULL;
-		ver2("Selected MIDI port larger than number of midi ports");
-		return;
-	}
-
-	rtmidi_open_port(mid_in, mid_port, rtmidi_get_port_name(mid_in, mid_port));
-
-	if(mid_in->ok == 0) {
-		fail("Failed to open MIDI port");
-	}
-
-	ver2("Using MIDI port %u", mid_port);
-
-	rtmidi_in_set_callback(mid_in, mid_callback, mid_in->data);
-
-	if(mid_in->ok == 0) {
-		fail("Failed to set MIDI Callback");
+		return;
+	}
+
+	if (mid_port >= n_ports) {
+		fail("invalid MIDI port %d selected (%d available)", mid_port, n_ports);
+	}
+
+	const char *name = rtmidi_get_port_name(mid_in, (uint32_t)mid_port);
+	rtmidi_open_port(mid_in, (uint32_t)mid_port, name);
+
+	if (!mid_in->ok) {
+		fail("error while opening MIDI port %d (%s): %s", mid_port, name, mid_in->msg);
+	}
+
+	inf("using MIDI port %d (%s)", mid_port, name);
+
+	rtmidi_in_set_callback(mid_in, callback, mid_in->data);
+
+	if (!mid_in->ok) {
+		fail("rtmidi_in_set_callback() failed: %s", mid_in->msg);
 	}
 }
@@ -155,10 +207,12 @@
 void mid_quit(void)
 {
-	if(mid_in) {
-		rtmidi_close_port(mid_in);
-		rtmidi_in_free(mid_in);
-	}
-
 	ver("mid quit");
+
+	if (mid_in == NULL) {
+		return;
+	}
+
+	rtmidi_close_port(mid_in);
+	rtmidi_in_free(mid_in);
 }
 
@@ -237,19 +291,22 @@
 }
 
-void mid_list(void) {
+void mid_list(void)
+{
 	mid_in = rtmidi_in_create_default();
 
-	uint32_t portcount = rtmidi_get_port_count(mid_in);
-
-	if (portcount == 0) {
-		mid_in = NULL;
-		ver2("no MIDI ports\n");
-		return;
-	}
-
-	fprintf(stdout, "the following MIDI ports are available:\n");
-
-	for (uint32_t i = 0; i < portcount; i++) {
-		fprintf(stdout, "port %d: %s\n", i, rtmidi_get_port_name(mid_in, i));
+	if (!mid_in->ok) {
+		fprintf(stderr, "rtmidi_in_create_default() failed: %s\n", mid_in->msg);
+		return;
+	}
+
+	uint32_t n_ports = rtmidi_get_port_count(mid_in);
+
+	if (n_ports == 0) {
+		fprintf(stdout, "no available MIDI ports\n");
+	}
+	else {
+		for (uint32_t i = 0; i < n_ports; i++) {
+			fprintf(stdout, "port %u: %s\n", i, rtmidi_get_port_name(mid_in, i));
+		}
 	}
 
Index: readme.txt
===================================================================
--- readme.txt	(revision 77d8df82f5dfc0eadc7b81c42db2c4f4773a428d)
+++ readme.txt	(revision 9ddbf3e3b93004ac7df85a6f7d2ae557d8dac5a9)
@@ -93,14 +93,14 @@
   make
   make install
-  
-  # Build and install rtmidi
-  
+
+  # Build and install RtMidi
+
   tar zxvf rtmidi-3.0.0.tar.gz
   cd rtmidi-3.0.0
   mkdir build
   cd build
-  
+
   ../configure --prefix=/opt/rtmidi
-  
+
   make
   make install
@@ -116,7 +116,10 @@
 
   * We use "--prefix=/opt/sdl2-win" instead of "--prefix=/opt/sdl2",
-    so that the Windows versions of the libraries go to a different
-    directory. That's where our Makefile expects to find them when
-    cross-building.
+    so that the Windows versions of the SDL2 libraries go to a
+    different directory. That's where our Makefile expects to find
+    them when cross-building.
+
+    Analogously, we use "--prefix=/opt/rtmidi-win" when building
+    RtMidi.
 
   * We additionally specify "--host=x86_64-w64-mingw32" to enable
