Index: src/Command.mm
==================================================================
--- src/Command.mm
+++ src/Command.mm
@@ -44,52 +44,38 @@
 	case ARG_NONE:
 		if (isDown)
 			((void(__cdecl *)())_function)();
 		break;
 	case ARG_1STR:
-		if (isDown) {
-			@autoreleasepool {
-				((void(__cdecl *)(OFString *))_function)(
-				    @(arguments[1]));
-			}
-		}
+		if (isDown)
+			((void(__cdecl *)(OFString *))_function)(
+			    @(arguments[1]));
 		break;
 	case ARG_2STR:
-		if (isDown) {
-			@autoreleasepool {
-				((void(__cdecl *)(
-				    OFString *, OFString *))_function)(
-				    @(arguments[1]), @(arguments[2]));
-			}
-		}
+		if (isDown)
+			((void(__cdecl *)(OFString *, OFString *))_function)(
+			    @(arguments[1]), @(arguments[2]));
 		break;
 	case ARG_3STR:
-		if (isDown) {
-			@autoreleasepool {
-				((void(__cdecl *)(OFString *, OFString *,
-				    OFString *))_function)(@(arguments[1]),
-				    @(arguments[2]), @(arguments[3]));
-			}
-		}
+		if (isDown)
+			((void(__cdecl *)(
+			    OFString *, OFString *, OFString *))_function)(
+			    @(arguments[1]), @(arguments[2]), @(arguments[3]));
 		break;
 	case ARG_5STR:
-		if (isDown) {
-			@autoreleasepool {
-				((void(__cdecl *)(OFString *, OFString *,
-				    OFString *, OFString *,
-				    OFString *))_function)(@(arguments[1]),
-				    @(arguments[2]), @(arguments[3]),
-				    @(arguments[4]), @(arguments[5]));
-			}
-		}
+		if (isDown)
+			((void(__cdecl *)(OFString *, OFString *, OFString *,
+			    OFString *, OFString *))_function)(@(arguments[1]),
+			    @(arguments[2]), @(arguments[3]), @(arguments[4]),
+			    @(arguments[5]));
 		break;
 	case ARG_DOWN:
 		((void(__cdecl *)(bool))_function)(isDown);
 		break;
 	case ARG_DWN1:
-		((void(__cdecl *)(bool, char *))_function)(
-		    isDown, arguments[1]);
+		((void(__cdecl *)(bool, OFString *))_function)(
+		    isDown, @(arguments[1]));
 		break;
 	case ARG_1EXP:
 		if (isDown)
 			return ((int(__cdecl *)(int))_function)(
 			    execute(arguments[1]));
@@ -99,17 +85,18 @@
 			return ((int(__cdecl *)(int, int))_function)(
 			    execute(arguments[1]), execute(arguments[2]));
 		break;
 	case ARG_1EST:
 		if (isDown)
-			return ((int(__cdecl *)(char *))_function)(
-			    arguments[1]);
+			return ((int(__cdecl *)(OFString *))_function)(
+			    @(arguments[1]));
 		break;
 	case ARG_2EST:
 		if (isDown)
-			return ((int(__cdecl *)(char *, char *))_function)(
-			    arguments[1], arguments[2]);
+			return (
+			    (int(__cdecl *)(OFString *, OFString *))_function)(
+			    @(arguments[1]), @(arguments[2]));
 		break;
 	case ARG_VARI:
 		if (isDown) {
 			// limit, remove
 			string r;
@@ -119,13 +106,13 @@
 				strcat_s(r, arguments[i]);
 				if (i == numArguments - 1)
 					break;
 				strcat_s(r, " ");
 			}
-			((void(__cdecl *)(char *))_function)(r);
+			((void(__cdecl *)(OFString *))_function)(@(r));
 		}
 		break;
 	}
 
 	return 0;
 }
 @end

Index: src/client.mm
==================================================================
--- src/client.mm
+++ src/client.mm
@@ -164,20 +164,22 @@
 	disconnect(0, !disconnecting);
 }
 
 string ctext;
 void
-toserver(const char *text)
+toserver(OFString *text)
 {
-	conoutf(@"%s:\f %s", player1->name, text);
-	strn0cpy(ctext, text, 80);
+	@autoreleasepool {
+		conoutf(@"%s:\f %@", player1->name, text);
+		strn0cpy(ctext, text.UTF8String, 80);
+	}
 }
 
 void
-echo(char *text)
+echo(OFString *text)
 {
-	conoutf(@"%s", text);
+	conoutf(@"%@", text);
 }
 
 COMMAND(echo, ARG_VARI)
 COMMANDN(say, toserver, ARG_VARI)
 COMMANDN(connect, connects, ARG_1STR)

Index: src/clientextras.mm
==================================================================
--- src/clientextras.mm
+++ src/clientextras.mm
@@ -202,13 +202,14 @@
 		p += mapdata.count;
 		*(ushort *)start = ENET_HOST_TO_NET_16(p - start);
 		enet_packet_resize(packet, p - start);
 		sendpackettoserv(packet);
 		conoutf(@"sending map %@ to server...", mapname);
-		sprintf_sd(msg)(
-		    "[map %@ uploaded to server, \"getmap\" to receive it]",
-		    mapname);
+		OFString *msg =
+		    [OFString stringWithFormat:@"[map %@ uploaded to server, "
+		                               @"\"getmap\" to receive it]",
+		              mapname];
 		toserver(msg);
 	}
 }
 
 void

Index: src/commands.mm
==================================================================
--- src/commands.mm
+++ src/commands.mm
@@ -461,43 +461,52 @@
 			execute(body.get());
 	}
 }
 
 void
-onrelease(bool on, char *body)
-{
-	if (!on)
-		execute(body);
-}
-
-void
-concat(char *s)
-{
-	@autoreleasepool {
-		alias(@"s", @(s));
-	}
-}
-
-void
-concatword(char *s)
-{
-	for (char *a = s, *b = s; *a = *b; b++)
-		if (*a != ' ')
-			a++;
-	concat(s);
-}
-
-int
-listlen(char *a)
-{
-	if (!*a)
-		return 0;
-	int n = 0;
-	while (*a)
-		if (*a++ == ' ')
-			n++;
-	return n + 1;
+onrelease(bool on, OFString *body)
+{
+	if (!on) {
+		std::unique_ptr<char> copy(strdup(body.UTF8String));
+		execute(copy.get());
+	}
+}
+
+void
+concat(OFString *s)
+{
+	@autoreleasepool {
+		alias(@"s", s);
+	}
+}
+
+void
+concatword(OFString *s)
+{
+	// The original used this code which does nothing:
+	// for (char *a = s, *b = s; *a = *b; b++)
+	//	if (*a != ' ')
+	//		a++;
+	concat(s);
+}
+
+int
+listlen(OFString *a_)
+{
+	@autoreleasepool {
+		const char *a = a_.UTF8String;
+
+		if (!*a)
+			return 0;
+
+		int n = 0;
+		while (*a)
+			if (*a++ == ' ')
+				n++;
+
+		return n + 1;
+	}
 }
 
 void
 at(OFString *s_, OFString *pos)
 {
@@ -506,11 +515,11 @@
 		std::unique_ptr<char> copy(strdup(s_.UTF8String));
 		char *s = copy.get();
 
 		loopi(n) s += strspn(s += strcspn(s, " \0"), " ");
 		s[strcspn(s, " \0")] = 0;
-		concat(s);
+		concat(@(s));
 	}
 }
 
 COMMANDN(loop, loopa, ARG_2STR)
 COMMANDN(while, whilea, ARG_2STR)
@@ -577,13 +586,13 @@
 	return (int)(a > b);
 }
 COMMANDN(>, gt, ARG_2EXP)
 
 int
-strcmpa(char *a, char *b)
+strcmpa(OFString *a, OFString *b)
 {
-	return strcmp(a, b) == 0;
+	return [a isEqual:b];
 }
 COMMANDN(strcmp, strcmpa, ARG_2EST)
 
 int
 rndn(int a)

Index: src/console.mm
==================================================================
--- src/console.mm
+++ src/console.mm
@@ -126,25 +126,25 @@
 	conoutf(@"unknown key \"%@\"", key);
 }
 COMMANDN(bind, bindkey, ARG_2STR)
 
 void
-saycommand(const char *init) // turns input to the command line on or off
+saycommand(OFString *init) // turns input to the command line on or off
 {
-	saycommandon = (init != NULL);
+	saycommandon = (init != nil);
 	if (saycommandon)
 		SDL_StartTextInput();
 	else
 		SDL_StopTextInput();
 
 	if (!editmode)
 		Cube.sharedInstance.repeatsKeys = saycommandon;
 
-	if (!init)
-		init = "";
+	if (init == nil)
+		init = @"";
 
-	commandbuf = [[OFMutableString alloc] initWithUTF8String:init];
+	commandbuf = [init mutableCopy];
 }
 COMMAND(saycommand, ARG_VARI)
 
 void
 mapmsg(OFString *s)
@@ -253,11 +253,11 @@
 						std::unique_ptr<char> copy(
 						    strdup(
 						        commandbuf.UTF8String));
 						execute(copy.get(), true);
 					} else
-						toserver(commandbuf.UTF8String);
+						toserver(commandbuf);
 				}
 				saycommand(NULL);
 			} else if (code == SDLK_ESCAPE) {
 				saycommand(NULL);
 			}

Index: src/protos.h
==================================================================
--- src/protos.h
+++ src/protos.h
@@ -69,11 +69,11 @@
 
 // client
 extern void localservertoclient(uchar *buf, int len);
 extern void connects(OFString *servername);
 extern void disconnect(int onlyclean = 0, int async = 0);
-extern void toserver(const char *text);
+extern void toserver(OFString *text);
 extern void addmsg(int rel, int num, int type, ...);
 extern bool multiplayer();
 extern bool allowedittoggle();
 extern void sendpackettoserv(void *packet);
 extern void gets2c();

Index: src/sound.mm
==================================================================
--- src/sound.mm
+++ src/sound.mm
@@ -129,30 +129,27 @@
 #endif
 
 static OFMutableArray<OFString *> *snames;
 
 int
-registersound(char *name_)
-{
-	@autoreleasepool {
-		OFString *name = @(name_);
-
-		int i = 0;
-		for (OFString *iter in snames) {
-			if ([iter isEqual:name])
-				return i;
-
-			i++;
-		}
-
-		if (snames == nil)
-			snames = [[OFMutableArray alloc] init];
-
-		[snames addObject:name];
-		samples.add(NULL);
-		return samples.length() - 1;
-	}
+registersound(OFString *name)
+{
+	int i = 0;
+	for (OFString *iter in snames) {
+		if ([iter isEqual:name])
+			return i;
+
+		i++;
+	}
+
+	if (snames == nil)
+		snames = [[OFMutableArray alloc] init];
+
+	[snames addObject:name];
+	samples.add(NULL);
+
+	return samples.length() - 1;
 }
 COMMAND(registersound, ARG_1EST)
 
 void
 cleansound()