diff --git a/source/AY8910.cpp b/source/AY8910.cpp
index c4633f19..afbcb23f 100644
--- a/source/AY8910.cpp
+++ b/source/AY8910.cpp
@@ -1160,11 +1160,10 @@ bool CAY8910::LoadSnapshot(YamlLoadHelper& yamlLoadHelper, const std::string& su
 	{
 		while(1)
 		{
-			char szIndex[7];
-			sprintf_s(szIndex, sizeof(szIndex), "0x%04X", ay_change_count);
+			std::string strIndex = StrFormat("0x%04X", ay_change_count);
 
 			bool bFound;
-			std::string value = yamlLoadHelper.LoadString_NoThrow(szIndex, bFound);
+			std::string value = yamlLoadHelper.LoadString_NoThrow(strIndex, bFound);
 			if (!bFound)
 				break;	// done
 
diff --git a/source/Configuration/PageConfig.cpp b/source/Configuration/PageConfig.cpp
index 996c56fe..1a8ffb15 100644
--- a/source/Configuration/PageConfig.cpp
+++ b/source/Configuration/PageConfig.cpp
@@ -220,7 +220,7 @@ INT_PTR CPageConfig::DlgProcInternal(HWND hWnd, UINT message, WPARAM wparam, LPA
 			if (GetCardMgr().IsSSCInstalled())
 			{
 				CSuperSerialCard* pSSC = GetCardMgr().GetSSC();
-				m_PropertySheetHelper.FillComboBox(hWnd, IDC_SERIALPORT, pSSC->GetSerialPortChoices(), pSSC->GetSerialPort());
+				m_PropertySheetHelper.FillComboBox(hWnd, IDC_SERIALPORT, pSSC->GetSerialPortChoices().c_str(), pSSC->GetSerialPort());
 				EnableWindow(GetDlgItem(hWnd, IDC_SERIALPORT), !pSSC->IsActive() ? TRUE : FALSE);
 			}
 			else
diff --git a/source/Debugger/Debug.cpp b/source/Debugger/Debug.cpp
index f4037065..818dd02c 100644
--- a/source/Debugger/Debug.cpp
+++ b/source/Debugger/Debug.cpp
@@ -1700,15 +1700,9 @@ Update_t CmdBreakpointEnable (int nArgs) {
 void _BWZ_List( const Breakpoint_t * aBreakWatchZero, const int iBWZ ) //, bool bZeroBased )
 {
 	static const char sFlags[] = "-*";
-	static       char sName[ MAX_SYMBOLS_LEN+1 ];
 
-	WORD nAddress = aBreakWatchZero[ iBWZ ].nAddress;
-	const char*  pSymbol = GetSymbol( nAddress, 2 );
-	if (! pSymbol)
-	{
-		sName[0] = 0;
-		pSymbol = sName;
-	}
+	std::string strAddressBuf;
+	std::string const& symbol = GetSymbol(aBreakWatchZero[iBWZ].nAddress, 2, strAddressBuf);
 
 	char cBPM = aBreakWatchZero[iBWZ].eSource == BP_SRC_MEM_READ_ONLY ? 'R'
 				: aBreakWatchZero[iBWZ].eSource == BP_SRC_MEM_WRITE_ONLY ? 'W'
@@ -1717,10 +1711,10 @@ void _BWZ_List( const Breakpoint_t * aBreakWatchZero, const int iBWZ ) //, bool
 	ConsoleBufferPushFormat( "  #%d %c %04X %c %s",
 //		(bZeroBased ? iBWZ + 1 : iBWZ),
 		iBWZ,
-		sFlags[ (int) aBreakWatchZero[ iBWZ ].bEnabled ],
+		sFlags[ aBreakWatchZero[ iBWZ ].bEnabled ? 1 : 0 ],
 		aBreakWatchZero[ iBWZ ].nAddress,
 		cBPM,
-		pSymbol
+		symbol.c_str()
 	);
 }
 
@@ -2270,9 +2264,8 @@ void _CmdColorGet( const int iScheme, const int iColor )
 	}
 	else
 	{
-		TCHAR sText[ CONSOLE_WIDTH ];
-		wsprintf( sText, "Color: %d\nOut of range!", iColor );
-		GetFrame().FrameMessageBox(sText, TEXT("ERROR"), MB_OK );
+		std::string strText = StrFormat( "Color: %d\nOut of range!", iColor );
+		GetFrame().FrameMessageBox(strText.c_str(), "ERROR", MB_OK);
 	}
 }
 
@@ -5774,7 +5767,6 @@ Update_t CmdOutputCalc (int nArgs)
 		return Help_Arg_1( CMD_OUTPUT_CALC );
 
 	WORD nAddress = g_aArgs[1].nValue;
-	TCHAR sText [ CONSOLE_WIDTH ];
 
 	bool bHi = false;
 	bool bLo = false;
@@ -5796,28 +5788,27 @@ Update_t CmdOutputCalc (int nArgs)
 	//    CHC_NUM_DEC
 	//    CHC_ARG_
 	//    CHC_STRING
-	wsprintf( sText, TEXT("$%04X  0z%08X  %5d  '%c' "),
-		nAddress, nBit, nAddress, c );
+	std::string strText = StrFormat( "$%04X  0z%08X  %5d  '%c' ", nAddress, nBit, nAddress, c );
 
 	if (bParen)
-		strcat( sText, TEXT("(") );
+		strText += '(';
 
 	if (bHi & bLo)
-		strcat( sText, TEXT("High Ctrl") );
+		strText += "High Ctrl";
 	else
 	if (bHi)
-		strcat( sText, TEXT("High") );
+		strText += "High";
 	else
 	if (bLo)
-		strcat( sText, TEXT("Ctrl") );
+		strText += "Ctrl";
 
 	if (bParen)
-		strcat( sText, TEXT(")") );
+		strText += ')';
 
-	ConsoleBufferPush( sText );
+	ConsoleBufferPush( strText.c_str() );
 
 // If we colorize then w must also guard against character ouput $60
-//	ConsolePrint( sText );
+//	ConsolePrint( strText.c_str() );
 
 	return ConsoleUpdate();
 }
@@ -8420,33 +8411,33 @@ void DebugContinueStepping(const bool bCallerWillUpdateDisplay/*=false*/)
 
 		if (regs.pc == g_nDebugStepUntil || g_bDebugBreakpointHit)
 		{
-			char szStopMessage[CONSOLE_WIDTH];
-			const char* pszStopReason = szStopMessage;
+			std::string strStopMessage;
+			const char* pszStopReason = "";
 
 			if (regs.pc == g_nDebugStepUntil)
-				pszStopReason = TEXT("PC matches 'Go until' address");
+				pszStopReason = "PC matches 'Go until' address";
 			else if (g_bDebugBreakpointHit & BP_HIT_INVALID)
-				pszStopReason = TEXT("Invalid opcode");
+				pszStopReason = "Invalid opcode";
 			else if (g_bDebugBreakpointHit & BP_HIT_OPCODE)
-				pszStopReason = TEXT("Opcode match");
+				pszStopReason = "Opcode match";
 			else if (g_bDebugBreakpointHit & BP_HIT_REG)
-				pszStopReason = TEXT("Register matches value");
+				pszStopReason = "Register matches value";
 			else if (g_bDebugBreakpointHit & BP_HIT_MEM)
-				sprintf_s(szStopMessage, sizeof(szStopMessage), "Memory access at $%04X", g_uBreakMemoryAddress);
+				pszStopReason = (strStopMessage = StrFormat("Memory access at $%04X", g_uBreakMemoryAddress)).c_str();
 			else if (g_bDebugBreakpointHit & BP_HIT_MEMW)
-				sprintf_s(szStopMessage, sizeof(szStopMessage), "Write access at $%04X", g_uBreakMemoryAddress);
+				pszStopReason = (strStopMessage = StrFormat("Write access at $%04X", g_uBreakMemoryAddress)).c_str();
 			else if (g_bDebugBreakpointHit & BP_HIT_MEMR)
-				sprintf_s(szStopMessage, sizeof(szStopMessage), "Read access at $%04X", g_uBreakMemoryAddress);
+				pszStopReason = (strStopMessage = StrFormat("Read access at $%04X", g_uBreakMemoryAddress)).c_str();
 			else if (g_bDebugBreakpointHit & BP_HIT_PC_READ_FLOATING_BUS_OR_IO_MEM)
-				pszStopReason = TEXT("PC reads from floating bus or I/O memory");
+				pszStopReason = "PC reads from floating bus or I/O memory";
 			else if (g_bDebugBreakpointHit & BP_HIT_INTERRUPT)
-				sprintf_s(szStopMessage, sizeof(szStopMessage), "Interrupt occurred at $%04X", g_LBR);
+				pszStopReason = (strStopMessage = StrFormat("Interrupt occurred at $%04X", g_LBR)).c_str();
 			else if (g_bDebugBreakpointHit & BP_DMA_TO_IO_MEM)
-				sprintf_s(szStopMessage, sizeof(szStopMessage), "HDD DMA to I/O memory or ROM $%04X", g_uDebugBreakOnDmaIoMemoryAddr);
+				pszStopReason = (strStopMessage = StrFormat("HDD DMA to I/O memory or ROM $%04X", g_uDebugBreakOnDmaIoMemoryAddr)).c_str();
 			else if (g_bDebugBreakpointHit & BP_DMA_FROM_IO_MEM)
-				sprintf_s(szStopMessage, sizeof(szStopMessage), "HDD DMA from I/O memory $%04X", g_uDebugBreakOnDmaIoMemoryAddr);
+				pszStopReason = (strStopMessage = StrFormat("HDD DMA from I/O memory $%04X", g_uDebugBreakOnDmaIoMemoryAddr)).c_str();
 			else
-				pszStopReason = TEXT("Unknown!");
+				pszStopReason = "Unknown!";
 
 			ConsoleBufferPushFormat( "Stop reason: %s", pszStopReason );
 			ConsoleUpdate();
diff --git a/source/Debugger/Debugger_Assembler.cpp b/source/Debugger/Debugger_Assembler.cpp
index 6fff4887..a618ca6b 100644
--- a/source/Debugger/Debugger_Assembler.cpp
+++ b/source/Debugger/Debugger_Assembler.cpp
@@ -1216,9 +1216,8 @@ bool AssemblerGetArgs( int iArg, int nArgs, WORD nBaseAddress )
 				else
 				{
 					// if valid hex address, don't have delayed target
-					TCHAR sAddress[ 32 ];
-					wsprintf( sAddress, "%X", m_nAsmTargetAddress);
-					if (_tcscmp( sAddress, pArg->sArg))
+					std::string strAddress = StrFormat( "%X", m_nAsmTargetAddress);
+					if (strAddress != pArg->sArg)
 					{
 						DelayedTarget_t tDelayedTarget;
 
diff --git a/source/Debugger/Debugger_Color.cpp b/source/Debugger/Debugger_Color.cpp
index 7c5d6440..6abb68b2 100644
--- a/source/Debugger/Debugger_Color.cpp
+++ b/source/Debugger/Debugger_Color.cpp
@@ -184,9 +184,6 @@ bool DebuggerSetColor( const int iScheme, const int iColor, const COLORREF nColo
 static void _SetupColorRamp(const int iPrimary, int & iColor_)
 {
 	std::string strRamp;
-#if DEBUG_COLOR_RAMP
-	char sText[CONSOLE_WIDTH];
-#endif
 
 	bool bR = (iPrimary & 1) ? true : false;
 	bool bG = (iPrimary & 2) ? true : false;
@@ -202,14 +199,12 @@ static void _SetupColorRamp(const int iPrimary, int & iColor_)
 		DWORD nColor = RGB(nR, nG, nB);
 		g_aColorPalette[iColor_] = nColor;
 #if DEBUG_COLOR_RAMP
-		int len = snprintf_s(sText, _TRUNCATE, "RGB(%3d,%3d,%3d), ", nR, nG, nB);
-		strRamp.append(sText, len);
+		strRamp += StrFormat("RGB(%3d,%3d,%3d), ", nR, nG, nB);
 #endif
 		iColor_++;
 	}
 #if DEBUG_COLOR_RAMP
-	int len = snprintf_s(sText, _TRUNCATE, " // %d%d%d\n", bB, bG, bR);
-	strRamp.append(sText, len);
+	strRamp += StrFormat(" // %d%d%d\n", bB, bG, bR);
 	OutputDebugString(strRamp.c_str());
 #endif
 }
diff --git a/source/Debugger/Debugger_Disassembler.cpp b/source/Debugger/Debugger_Disassembler.cpp
index 3ea1983a..d0e0c0ee 100644
--- a/source/Debugger/Debugger_Disassembler.cpp
+++ b/source/Debugger/Debugger_Disassembler.cpp
@@ -28,18 +28,17 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 #include "../Memory.h"
 
 //===========================================================================
-const char* FormatAddress(WORD nAddress, int nBytes)
+std::string FormatAddress(WORD nAddress, int nBytes)
 {
-	// There is no symbol for this nAddress
-	static TCHAR sSymbol[8] = TEXT("");
 	switch (nBytes)
 	{
-	case  2:	wsprintf(sSymbol, TEXT("$%02X"), (unsigned)nAddress);  break;
-	case  3:	wsprintf(sSymbol, TEXT("$%04X"), (unsigned)nAddress);  break;
-		// TODO: FIXME: Can we get called with nBytes == 16 ??
-	default:	sSymbol[0] = 0; break; // clear since is static
+	case  2:	return StrFormat("$%02X", (unsigned)nAddress); break;
+	case  3:	return StrFormat("$%04X", (unsigned)nAddress); break;
+	// TODO: FIXME: Can we get called with nBytes == 16 ??
+	default:	break; // clear since is static
 	}
-	return sSymbol;
+	// There is no symbol for this nAddress
+	return std::string();
 }
 
 //===========================================================================
@@ -272,14 +271,13 @@ int GetDisassemblyLine(WORD nBaseAddress, DisasmLine_t& line_)
 		{
 			line_.nTarget = nTarget;
 
-			const char* pTarget = NULL;
-			const char* pSymbol = 0;
-
-			pSymbol = FindSymbolFromAddress(nTarget, &line_.iTargetTable);
+			std::string const* pTarget = NULL;
+			std::string const* pSymbol = FindSymbolFromAddress(nTarget, &line_.iTargetTable);
+			std::string strAddressBuf;
 
 			// Data Assembler
 			if (pData && (!pData->bSymbolLookup))
-				pSymbol = 0;
+				pSymbol = NULL;
 
 			// Try exact match first
 			if (pSymbol)
@@ -324,7 +322,8 @@ int GetDisassemblyLine(WORD nBaseAddress, DisasmLine_t& line_)
 
 			if (!(bDisasmFormatFlags & DISASM_FORMAT_SYMBOL))
 			{
-				pTarget = FormatAddress(nTarget, (iOpmode != AM_R) ? nOpbyte : 3);	// GH#587: For Bcc opcodes, pretend it's a 3-byte opcode to print a 16-bit target addr
+				strAddressBuf = FormatAddress(nTarget, (iOpmode != AM_R) ? nOpbyte : 3);	// GH#587: For Bcc opcodes, pretend it's a 3-byte opcode to print a 16-bit target addr
+				pTarget = &strAddressBuf;
 			}
 
 			//			sprintf( sTarget, g_aOpmodes[ iOpmode ]._sFormat, pTarget );
@@ -333,8 +332,7 @@ int GetDisassemblyLine(WORD nBaseAddress, DisasmLine_t& line_)
 				int nAbsTargetOffset = (line_.nTargetOffset > 0) ? line_.nTargetOffset : -line_.nTargetOffset;
 				sprintf(line_.sTargetOffset, "%d", nAbsTargetOffset);
 			}
-			sprintf(line_.sTarget, "%s", pTarget);
-
+			strncpy_s(line_.sTarget, pTarget->c_str(), _TRUNCATE);
 
 			// Indirect / Indexed
 			int nTargetPartial;
diff --git a/source/Debugger/Debugger_Disassembler.h b/source/Debugger/Debugger_Disassembler.h
index 6915a730..89df445a 100644
--- a/source/Debugger/Debugger_Disassembler.h
+++ b/source/Debugger/Debugger_Disassembler.h
@@ -9,7 +9,7 @@ void FormatDisassemblyLine(const DisasmLine_t& line, char* sDisassembly_, const
 void FormatOpcodeBytes(WORD nBaseAddress, DisasmLine_t& line_);
 void FormatNopcodeBytes(WORD nBaseAddress, DisasmLine_t& line_);
 
-const char* FormatAddress(WORD nAddress, int nBytes);
+std::string FormatAddress(WORD nAddress, int nBytes);
 char* FormatCharCopy(char* pDst, const char* pSrc, const int nLen);
 
 char  FormatCharTxtAsci(const BYTE b, bool* pWasAsci_ = NULL);
diff --git a/source/Debugger/Debugger_Display.cpp b/source/Debugger/Debugger_Display.cpp
index 8d2a02a1..768e6ac1 100644
--- a/source/Debugger/Debugger_Display.cpp
+++ b/source/Debugger/Debugger_Display.cpp
@@ -1331,8 +1331,8 @@ WORD DrawDisassemblyLine ( int iLine, const WORD nBaseAddress )
 	int nOpbyte;
 	DisasmLine_t line;
 
-	int         iTable    = NUM_SYMBOL_TABLES;
-	const char* pSymbol   = FindSymbolFromAddress( nBaseAddress, &iTable );
+	int iTable = NUM_SYMBOL_TABLES;
+	std::string const* pSymbol = FindSymbolFromAddress( nBaseAddress, &iTable );
 	const char* pMnemonic = NULL;
 
 	// Data Disassembler
@@ -1563,7 +1563,7 @@ WORD DrawDisassemblyLine ( int iLine, const WORD nBaseAddress )
 			else
 				DebuggerSetColorFG( DebuggerGetColor( FG_DISASM_SYMBOL ) );
 		}
-		PrintTextCursorX( pSymbol, linerect );
+		PrintTextCursorX( pSymbol->c_str(), linerect );
 	}
 
 	// Instruction / Mnemonic
@@ -2941,33 +2941,30 @@ void DrawZeroPagePointers ( int line )
 			BYTE nZPAddr1 = (g_aZeroPagePointers[iZP].nAddress  ) & 0xFF; // +MJP missig: "& 0xFF", or "(BYTE) ..."
 			BYTE nZPAddr2 = (g_aZeroPagePointers[iZP].nAddress+1) & 0xFF;
 
-			// Get nZPAddr1 last (for when neither symbol is not found - GetSymbol() return ptr to static buffer)
-			const char* pSymbol2 = GetSymbol(nZPAddr2, 2);		// 2:8-bit value (if symbol not found)
-			const char* pSymbol1 = GetSymbol(nZPAddr1, 2);		// 2:8-bit value (if symbol not found)
+			std::string strAddressBuf1;
+			std::string strAddressBuf2;
+			std::string const& symbol1 = GetSymbol(nZPAddr1, 2, strAddressBuf1);	// 2:8-bit value (if symbol not found)
+			std::string const& symbol2 = GetSymbol(nZPAddr2, 2, strAddressBuf2);	// 2:8-bit value (if symbol not found)
 
-			int nLen1 = strlen( pSymbol1 );
-			int nLen2 = strlen( pSymbol2 );
-
-
-//			if ((nLen1 == 1) && (nLen2 == 1))
-//				sprintf( sText, "%s%s", pszSymbol1, pszSymbol2);
+//			if ((symbol1.length() == 1) && (symbol2.length() == 1))
+//				sprintf( sText, "%s%s", symbol1.c_str(), symbol2.c_str());
 
 			DebuggerSetColorFG( DebuggerGetColor( FG_DISASM_ADDRESS ));
 
-			int x;
-			for( x = 0; x < nMaxSymbolLen; x++ )
+			for( int x = 0; x < nMaxSymbolLen; x++ )
 			{
 				sText[ x ] = CHAR_SPACE;
 			}
+
 			sText[nMaxSymbolLen] = 0;
 			
-			if ((nLen1) && (pSymbol1[0] == '$'))
+			if (!symbol1.empty() && symbol1[0] == '$')
 			{
 //				sprintf( sText, "%s%s", pSymbol1 );
 //				sprintf( sText, "%04X", nZPAddr1 );
 			}
 			else
-			if ((nLen2) && (pSymbol2[0] == '$'))
+			if (!symbol2.empty() && symbol2[0] == '$')
 			{
 //				sprintf( sText, "%s%s", pSymbol2 );
 //				sprintf( sText, "%04X", nZPAddr2 );
@@ -2975,8 +2972,8 @@ void DrawZeroPagePointers ( int line )
 			}
 			else
 			{
-				int nMin = MIN( nLen1, nMaxSymbolLen );
-				memcpy(sText, pSymbol1, nMin);
+				int nMin = MIN( symbol1.length(), nMaxSymbolLen );
+				memcpy(sText, symbol1.c_str(), nMin);
 				DebuggerSetColorFG( DebuggerGetColor( FG_DISASM_SYMBOL ) );
 			}
 //			DrawRegister( line+iZP, szZP, 2, nTarget16);
@@ -3255,17 +3252,13 @@ static void DrawVideoScannerValue(int line, int vert, int horz, bool isVisible)
 		else        PrintText("h:", rect);
 		rect.left += nameWidth * nFontWidth;
 
-		char sValue[8];
-		if (g_videoScannerDisplayInfo.isDecimal)
-			sprintf_s(sValue, sizeof(sValue), "%03u", nValue);
-		else
-			sprintf_s(sValue, sizeof(sValue), "%03X", nValue);
+		std::string strValue = StrFormat((g_videoScannerDisplayInfo.isDecimal) ? "%03u" : "%03X", nValue);
 
 		if (!isVisible)
 			DebuggerSetColorFG(DebuggerGetColor(FG_VIDEOSCANNER_INVISIBLE));	// yellow
 		else
 			DebuggerSetColorFG(DebuggerGetColor(FG_VIDEOSCANNER_VISIBLE));		// green
-		PrintText(sValue, rect);
+		PrintText(strValue.c_str(), rect);
 		rect.left += (numberWidth+gapWidth) * nFontWidth;
 	}
 }
@@ -3327,9 +3320,7 @@ static void DrawVideoScannerInfo(int line)
 	else // "part"
 		cycles = (UINT)g_videoScannerDisplayInfo.lastCumulativeCycles - (UINT)g_videoScannerDisplayInfo.savedCumulativeCycles;
 
-	char sValue[10];
-	sprintf_s(sValue, sizeof(sValue), "%08X", cycles);
-	PrintText(sValue, rect);
+	PrintText(StrFormat("%08X", cycles).c_str(), rect);
 }
 
 //===========================================================================
diff --git a/source/Debugger/Debugger_Help.cpp b/source/Debugger/Debugger_Help.cpp
index b8003253..2a767df0 100644
--- a/source/Debugger/Debugger_Help.cpp
+++ b/source/Debugger/Debugger_Help.cpp
@@ -127,7 +127,7 @@ Update_t Help_Arg_1( int iCommandHelp )
 {
 	_Arg_1( iCommandHelp );
 
-	wsprintf( g_aArgs[ 1 ].sArg, "%s", g_aCommands[ iCommandHelp ].m_sName ); // .3 Fixed: Help_Arg_1() now copies command name into arg.name
+	strncpy_s(g_aArgs[1].sArg, g_aCommands[iCommandHelp].m_sName, _TRUNCATE); // .3 Fixed: Help_Arg_1() now copies command name into arg.name
 
 	return CmdHelpSpecific( 1 );
 }
@@ -544,8 +544,6 @@ Update_t CmdMOTD( int nArgs )	// Message Of The Day
 Update_t CmdHelpSpecific (int nArgs)
 {
 	int iArg;
-	char sText[ CONSOLE_WIDTH * 2 ];
-	memset( sText, 0, CONSOLE_WIDTH*2 );
 
 	if (! nArgs)
 	{
@@ -737,96 +735,78 @@ Update_t CmdHelpSpecific (int nArgs)
 //		if (nFound && (! bAllCommands) && (! bCategory))
 		if (nFound && (! bAllCommands) && bDisplayCategory)
 		{
-			char sCategory[ CONSOLE_WIDTH ];
+			const char* pszCategory = "";
 			int iCmd = g_aCommands[ iCommand ].iCommand; // Unaliased command
 
 			// HACK: Major kludge to display category!!!
 			if (iCmd <= CMD_UNASSEMBLE)
-				wsprintf( sCategory, "%s", g_aParameters[ PARAM_CAT_CPU ].m_sName );
+				pszCategory = g_aParameters[ PARAM_CAT_CPU ].m_sName;
 			else
 			if (iCmd <= CMD_BOOKMARK_SAVE)
-				wsprintf( sCategory, "%s", g_aParameters[ PARAM_CAT_BOOKMARKS ].m_sName );
+				pszCategory = g_aParameters[ PARAM_CAT_BOOKMARKS ].m_sName;
 			else
 			if (iCmd <= CMD_BREAKPOINT_SAVE)
-				wsprintf( sCategory, "%s", g_aParameters[ PARAM_CAT_BREAKPOINTS ].m_sName );
+				pszCategory = g_aParameters[ PARAM_CAT_BREAKPOINTS ].m_sName;
 			else
 			if (iCmd <= CMD_CONFIG_SET_DEBUG_DIR)
-				wsprintf( sCategory, "%s", g_aParameters[ PARAM_CAT_CONFIG ].m_sName );
+				pszCategory = g_aParameters[ PARAM_CAT_CONFIG ].m_sName;
 			else
 			if (iCmd <= CMD_CURSOR_PAGE_DOWN_4K)
-				wsprintf( sCategory, "Scrolling" );
+				pszCategory = "Scrolling";
 			else
 			if (iCmd <= CMD_FLAG_SET_N)
-				wsprintf( sCategory, "%s", g_aParameters[ PARAM_CAT_FLAGS ].m_sName );
+				pszCategory = g_aParameters[ PARAM_CAT_FLAGS ].m_sName;
 			else
 			if (iCmd <= CMD_MOTD)
-				wsprintf( sCategory, "%s", g_aParameters[ PARAM_CAT_HELP ].m_sName );
+				pszCategory = g_aParameters[ PARAM_CAT_HELP ].m_sName;
 			else
 			if (iCmd <= CMD_MEMORY_FILL)
-				wsprintf( sCategory, "%s", g_aParameters[ PARAM_CAT_MEMORY ].m_sName );
+				pszCategory = g_aParameters[ PARAM_CAT_MEMORY ].m_sName;
 			else
 			if (iCmd <= CMD_OUTPUT_RUN)
-				wsprintf( sCategory, "%s", g_aParameters[ PARAM_CAT_OUTPUT ].m_sName );
+				pszCategory = g_aParameters[ PARAM_CAT_OUTPUT ].m_sName;
 			else
 			if (iCmd <= CMD_SYNC)
-				wsprintf( sCategory, "Source" );
+				pszCategory = "Source";
 			else
 			if (iCmd <= CMD_SYMBOLS_LIST)
-				wsprintf( sCategory, "%s", g_aParameters[ PARAM_CAT_SYMBOLS ].m_sName );
+				pszCategory = g_aParameters[ PARAM_CAT_SYMBOLS ].m_sName;
 			else
 			if (iCmd <= CMD_VIEW_DHGR2)
-				wsprintf( sCategory, "%s", g_aParameters[ PARAM_CAT_VIEW ].m_sName );
+				pszCategory = g_aParameters[ PARAM_CAT_VIEW ].m_sName;
 			else
 			if (iCmd <= CMD_WATCH_SAVE)
-				wsprintf( sCategory, "%s", g_aParameters[ PARAM_CAT_WATCHES ].m_sName );
+				pszCategory = g_aParameters[ PARAM_CAT_WATCHES ].m_sName;
 			else
 			if (iCmd <= CMD_WINDOW_OUTPUT)
-				wsprintf( sCategory, "%s", g_aParameters[ PARAM_CAT_WINDOW ].m_sName );
+				pszCategory = g_aParameters[ PARAM_CAT_WINDOW ].m_sName;
 			else
 			if (iCmd <= CMD_ZEROPAGE_POINTER_SAVE)
-				wsprintf( sCategory, "%s", g_aParameters[ PARAM_CAT_ZEROPAGE ].m_sName );
+				pszCategory = g_aParameters[ PARAM_CAT_ZEROPAGE ].m_sName;
 			else
-				wsprintf( sCategory, "Unknown!" );
+				pszCategory = "Unknown!";
 
 			ConsolePrintFormat( "%sCategory%s: %s%s"
 				, CHC_USAGE
 				, CHC_DEFAULT
 				, CHC_CATEGORY
-				, sCategory );
+				, pszCategory );
 
 			if (bCategory)
-				if (bDisplayCategory)
-					bDisplayCategory = false;
+				bDisplayCategory = false;
 		}
 		
 		if (pCommand)
 		{
-			const char *pHelp = pCommand->pHelpSummary;
+			const char *const pHelp = pCommand->pHelpSummary;
 			if (pHelp)
 			{
-				if (bCategory)
-					sprintf( sText, "%s%8s%s, "
-						, CHC_COMMAND
-						, pCommand->m_sName
-						, CHC_ARG_SEP
-					);
-				else
-					sprintf( sText, "%s%s%s, "
-						, CHC_COMMAND
-						, pCommand->m_sName
-						, CHC_ARG_SEP
-					);
-
-//				if (! TryStringCat( sText, pHelp, g_nConsoleDisplayWidth ))
-//				{
-//					if (! TryStringCat( sText, pHelp, CONSOLE_WIDTH-1 ))
-//					{
-						strncat( sText, CHC_DEFAULT, CONSOLE_WIDTH );
-						strncat( sText, pHelp      , CONSOLE_WIDTH );
-//						ConsoleBufferPush( sText );
-//					}
-//				}
-				ConsolePrint( sText );
+				std::string strText = StrFormat((bCategory) ? "%s%8s%s%s%s, "
+														    : "%s%s%s%s%s, ",
+												CHC_COMMAND, pCommand->m_sName, CHC_ARG_SEP,
+												CHC_DEFAULT, pHelp);
+				//ConsoleBufferPush( strText.c_str() );
+				ConsolePrint( strText.c_str() );
 			}
 			else
 			{
diff --git a/source/Debugger/Debugger_Symbols.cpp b/source/Debugger/Debugger_Symbols.cpp
index 9efff43a..9c84371e 100644
--- a/source/Debugger/Debugger_Symbols.cpp
+++ b/source/Debugger/Debugger_Symbols.cpp
@@ -125,13 +125,13 @@ Update_t _PrintSymbolInvalidTable()
 
 
 //===========================================================================
-const char* GetSymbol (WORD nAddress, int nBytes)
+std::string const& GetSymbol (WORD nAddress, int nBytes, std::string& strAddressBuf)
 {
-	const char* pSymbol = FindSymbolFromAddress( nAddress );
+	std::string const* pSymbol = FindSymbolFromAddress( nAddress );
 	if (pSymbol)
-		return pSymbol;
+		return *pSymbol;
 
-	return FormatAddress( nAddress, nBytes );
+	return strAddressBuf = FormatAddress( nAddress, nBytes );
 }
 
 //===========================================================================
@@ -142,7 +142,7 @@ int GetSymbolTableFromCommand()
 
 // @param iTable_ Which symbol table the symbol is in if any.  If none will be NUM_SYMBOL_TABLES
 //===========================================================================
-const char* FindSymbolFromAddress (WORD nAddress, int * iTable_ )
+std::string const* FindSymbolFromAddress (WORD nAddress, int * iTable_ )
 {
 	// Bugfix/User feature: User symbols should be searched first
 	int iTable = NUM_SYMBOL_TABLES;
@@ -166,10 +166,10 @@ const char* FindSymbolFromAddress (WORD nAddress, int * iTable_ )
 			{
 				*iTable_ = iTable;
 			}
-			return iSymbols->second.c_str();
+			return &iSymbols->second;
 		}
 	}	
-	return NULL;	
+	return NULL;
 }
 
 //===========================================================================
@@ -411,14 +411,14 @@ int _GetSymbolTableFromFlag( int bSymbolTables )
 //=========================================================================== */
 bool _CmdSymbolList_Address2Symbol( int nAddress, int bSymbolTables )
 {
-	int  iTable;
-	const char* pSymbol = FindSymbolFromAddress( nAddress, &iTable );
+	int iTable = 0;
+	std::string const* pSymbol = FindSymbolFromAddress( nAddress, &iTable );
 
 	if (pSymbol)
 	{				
 		if (_FindSymbolTable( bSymbolTables, iTable ))
 		{
-			_CmdPrintSymbol( pSymbol, nAddress, iTable );
+			_CmdPrintSymbol( pSymbol->c_str(), nAddress, iTable);
 			return true;
 		}
 	}
@@ -564,16 +564,8 @@ int ParseSymbolTable(const std::string & pPathFileName, SymbolTable_Index_e eSym
 	if (pPathFileName.empty())
 		return nSymbolsLoaded;
 
-//#if _UNICODE
-//	TCHAR sFormat1[ MAX_SYMBOLS_LEN ];
-//	TCHAR sFormat2[ MAX_SYMBOLS_LEN ];
-//	wsprintf( sFormat1, "%%x %%%ds", MAX_SYMBOLS_LEN ); // i.e. "%x %13s"
-//	wsprintf( sFormat2, "%%%ds %%x", MAX_SYMBOLS_LEN ); // i.e. "%13s %x"
-// ascii
-	char sFormat1[ MAX_SYMBOLS_LEN ];
-	char sFormat2[ MAX_SYMBOLS_LEN ];
-	sprintf( sFormat1, "%%x %%%ds", MAX_SYMBOLS_LEN ); // i.e. "%x %13s"
-	sprintf( sFormat2, "%%%ds %%x", MAX_SYMBOLS_LEN ); // i.e. "%13s %x"
+	std::string strFormat1 = StrFormat( "%%x %%%ds", MAX_SYMBOLS_LEN ); // i.e. "%x %13s"
+	std::string strFormat2 = StrFormat( "%%%ds %%x", MAX_SYMBOLS_LEN ); // i.e. "%13s %x"
 
 	FILE *hFile = fopen( pPathFileName.c_str(), "rt" );
 
@@ -612,7 +604,7 @@ int ParseSymbolTable(const std::string & pPathFileName, SymbolTable_Index_e eSym
 
 			if(strstr(szLine, "$") == NULL)
 			{
-				sscanf(szLine, sFormat1, &nAddress, sName);
+				sscanf(szLine, strFormat1.c_str(), &nAddress, sName);
 			}
 			else
 			{
@@ -631,7 +623,7 @@ int ParseSymbolTable(const std::string & pPathFileName, SymbolTable_Index_e eSym
 						memset(&szLine[MAX_SYMBOLS_LEN], ' ', nLen - MAX_SYMBOLS_LEN);	// sscanf fails for nAddress if string too long
 					}
 				}
-				sscanf(szLine, sFormat2, sName, &nAddress);
+				sscanf(szLine, strFormat2.c_str(), sName, &nAddress);
 			}
 
 			// SymbolOffset
@@ -640,10 +632,6 @@ int ParseSymbolTable(const std::string & pPathFileName, SymbolTable_Index_e eSym
 			if( (nAddress > _6502_MEM_END) || (sName[0] == 0) )
 				continue;
 
-			// If updating symbol, print duplicate symbols
-			WORD nAddressPrev;
-			int  iTable;
-
 			// 2.9.0.11 Bug #479
 			int nLen = strlen( sName );
 			if (nLen > nMaxLen)
@@ -663,8 +651,10 @@ int ParseSymbolTable(const std::string & pPathFileName, SymbolTable_Index_e eSym
 				ConsoleUpdate(); // Flush buffered output so we don't ask the user to pause
 			}
 
+			int iTable = 0;
+
 			// 2.8.0.5 Bug #244 (Debugger) Duplicate symbols for identical memory addresses in APPLE2E.SYM
-			const char *pSymbolPrev = FindSymbolFromAddress( (WORD)nAddress, &iTable ); // don't care which table it is in
+			std::string const* pSymbolPrev = FindSymbolFromAddress( (WORD)nAddress, &iTable ); // don't care which table it is in
 			if( pSymbolPrev )
 			{
 				if( !bFileDisplayed )
@@ -687,7 +677,7 @@ int ParseSymbolTable(const std::string & pPathFileName, SymbolTable_Index_e eSym
 					, CHC_ADDRESS
 					, nAddress
 					, CHC_SYMBOL
-					, pSymbolPrev
+					, pSymbolPrev->c_str()
 					, CHC_DEFAULT
 					, CHC_STRING
 					, g_aSymbolTableNames[ iTable ]
@@ -718,6 +708,9 @@ int ParseSymbolTable(const std::string & pPathFileName, SymbolTable_Index_e eSym
 */
 			}
 
+			// If updating symbol, print duplicate symbols
+			WORD nAddressPrev = 0;
+
 			bool bExists  = FindAddressFromSymbol( sName, &nAddressPrev, &iTable );
 			if( bExists )
 			{
@@ -883,7 +876,7 @@ void SymbolUpdate( SymbolTable_Index_e eSymbolTable, const char *pSymbolName, WO
 		if (bUpdateSymbol)
 		{
 #if _DEBUG
-			const char* pSymbol = FindSymbolFromAddress( nAddress, &iTable );
+			std::string const* pSymbol = FindSymbolFromAddress( nAddress, &iTable );
 			{
 				// Found another symbol for this address.  Harmless.
 				// TODO: Probably should check if same name?
diff --git a/source/Debugger/Debugger_Symbols.h b/source/Debugger/Debugger_Symbols.h
index 0481434b..b497ecd5 100644
--- a/source/Debugger/Debugger_Symbols.h
+++ b/source/Debugger/Debugger_Symbols.h
@@ -19,5 +19,5 @@
 	bool FindAddressFromSymbol(const char* pSymbol, WORD* pAddress_ = NULL, int* iTable_ = NULL);
 	WORD GetAddressFromSymbol(const char* symbol); // HACK: returns 0 if symbol not found
 	void SymbolUpdate(SymbolTable_Index_e eSymbolTable, const char* pSymbolName, WORD nAddrss, bool bRemoveSymbol, bool bUpdateSymbol);
-	const char* FindSymbolFromAddress(WORD nAdress, int* iTable_ = NULL);
-	const char* GetSymbol(WORD nAddress, int nBytes);
+	std::string const* FindSymbolFromAddress(WORD nAdress, int* iTable_ = NULL);
+	std::string const& GetSymbol(WORD nAddress, int nBytes, std::string& strAddressBuf);
diff --git a/source/DiskFormatTrack.cpp b/source/DiskFormatTrack.cpp
index 774d89a3..38d70156 100644
--- a/source/DiskFormatTrack.cpp
+++ b/source/DiskFormatTrack.cpp
@@ -269,9 +269,8 @@ void FormatTrack::DecodeLatchNibble(BYTE floppylatch, bool bIsWrite, bool bIsSyn
 			if (!bIsWrite)
 			{
 				BYTE addrPrologue = m_bAddressPrologueIsDOS3_2 ? (BYTE)kADDR_PROLOGUE_DOS3_2 : (BYTE)kADDR_PROLOGUE_DOS3_3;
-				char str[100];
-				sprintf_s(str, sizeof(str), "read D5AA%02X detected - Vol:%02X Trk:%02X Sec:%02X Chk:%02X %s", addrPrologue, m_VolTrkSecChk[0], m_VolTrkSecChk[1], m_VolTrkSecChk[2], m_VolTrkSecChk[3], chk?"":"(bad)");
-				m_strReadD5AAxxDetected = str;
+				m_strReadD5AAxxDetected = StrFormat("read D5AA%02X detected - Vol:%02X Trk:%02X Sec:%02X Chk:%02X %s",
+					addrPrologue, m_VolTrkSecChk[0], m_VolTrkSecChk[1], m_VolTrkSecChk[2], m_VolTrkSecChk[3], chk?"":"(bad)");
 				if (!m_bSuppressReadD5AAxxDetected)
 				{
 					LOG_DISK("%s\r\n", str);
diff --git a/source/Joystick.cpp b/source/Joystick.cpp
index 84479487..4c138476 100644
--- a/source/Joystick.cpp
+++ b/source/Joystick.cpp
@@ -952,9 +952,8 @@ void JoySaveSnapshot(YamlSaveHelper& yamlSaveHelper)
 
 	for (UINT n = 0; n < 4; n++)
 	{
-		char str[sizeof(SS_YAML_KEY_PDL_INACTIVE_CYCLE)+1];
-		sprintf_s(str, sizeof(str), SS_YAML_KEY_PDL_INACTIVE_CYCLE, n);
-		yamlSaveHelper.SaveHexUint64(str, g_paddleInactiveCycle[n]);
+		std::string str = StrFormat(SS_YAML_KEY_PDL_INACTIVE_CYCLE, n);
+		yamlSaveHelper.SaveHexUint64(str.c_str(), g_paddleInactiveCycle[n]);
 	}
 }
 
@@ -972,8 +971,7 @@ void JoyLoadSnapshot(YamlLoadHelper& yamlLoadHelper, UINT version)
 	{
 		for (UINT n = 0; n < 4; n++)
 		{
-			char str[sizeof(SS_YAML_KEY_PDL_INACTIVE_CYCLE) + 1];
-			sprintf_s(str, sizeof(str), SS_YAML_KEY_PDL_INACTIVE_CYCLE, n);
+			std::string str = StrFormat(SS_YAML_KEY_PDL_INACTIVE_CYCLE, n);
 			g_paddleInactiveCycle[n] = yamlLoadHelper.LoadUint64(str);
 		}
 	}
diff --git a/source/SSI263.cpp b/source/SSI263.cpp
index 984fd5f4..9b6ab73e 100644
--- a/source/SSI263.cpp
+++ b/source/SSI263.cpp
@@ -175,9 +175,8 @@ void SSI263::Write(BYTE nReg, BYTE nValue)
 		//
 		{
 			bool H2L = (m_ctrlArtAmp & CONTROL_MASK) && !(nValue & CONTROL_MASK);
-			char newMode[20];
-			sprintf_s(newMode, sizeof(newMode), "(new mode=%d)", m_durationPhoneme>>6);
-			LogOutput("CTRL  = %d->%d, ART = 0x%02X, AMP=0x%02X %s\n", m_ctrlArtAmp>>7, nValue>>7, (nValue&ARTICULATION_MASK)>>4, nValue&AMPLITUDE_MASK, H2L?newMode:"");
+			std::string newMode = StrFormat(" (new mode=%d)", m_durationPhoneme>>6);
+			LogOutput("CTRL  = %d->%d, ART = 0x%02X, AMP=0x%02X%s\n", m_ctrlArtAmp>>7, nValue>>7, (nValue&ARTICULATION_MASK)>>4, nValue&AMPLITUDE_MASK, H2L?newMode.c_str() : "");
 		}
 #endif
 #if LOG_SSI263B
diff --git a/source/SerialComms.cpp b/source/SerialComms.cpp
index 90867116..905e494c 100644
--- a/source/SerialComms.cpp
+++ b/source/SerialComms.cpp
@@ -66,7 +66,7 @@ SSC_DIPSW CSuperSerialCard::m_DIPSWDefault =
 
 CSuperSerialCard::CSuperSerialCard(UINT slot) :
 	Card(CT_SSC, slot),
-	m_aySerialPortChoices(NULL),
+	m_strSerialPortChoices(1, '\0'), // Combo box friendly, just in case.
 	m_uTCPChoiceItemIdx(0),
 	m_bCfgSupportDCD(false),
 	m_pExpansionRom(NULL)
@@ -91,7 +91,8 @@ CSuperSerialCard::CSuperSerialCard(UINT slot) :
 
 	//
 
-	char serialPortName[CSuperSerialCard::SIZEOF_SERIALCHOICE_ITEM];
+	const size_t SERIALCHOICE_ITEM_LENGTH = 12;
+	char serialPortName[SERIALCHOICE_ITEM_LENGTH];
 	std::string regSection = RegGetConfigSlotSection(m_slot);
 	RegLoadString(regSection.c_str(), REGVALUE_SERIAL_PORT_NAME, TRUE, serialPortName, sizeof(serialPortName), TEXT(""));
 
@@ -125,7 +126,6 @@ void CSuperSerialCard::InternalReset()
 
 CSuperSerialCard::~CSuperSerialCard()
 {
-	delete [] m_aySerialPortChoices;
 }
 
 //===========================================================================
@@ -266,16 +266,15 @@ bool CSuperSerialCard::CheckComm()
 	else if (m_dwSerialPortItem)
 	{
 		_ASSERT(m_dwSerialPortItem < m_vecSerialPortsItems.size()-1);	// size()-1 is TCP item
-		TCHAR portname[SIZEOF_SERIALCHOICE_ITEM];
-		wsprintf(portname, TEXT("\\\\.\\COM%u"), m_vecSerialPortsItems[m_dwSerialPortItem]);
+		std::string portname = StrFormat("\\\\.\\COM%u", m_vecSerialPortsItems[m_dwSerialPortItem]);
 
-		m_hCommHandle = CreateFile(portname,
-								GENERIC_READ | GENERIC_WRITE,
-								0,								// exclusive access
-								(LPSECURITY_ATTRIBUTES)NULL,	// default security attributes
-								OPEN_EXISTING,
-								FILE_FLAG_OVERLAPPED,			// required for WaitCommEvent()
-								NULL);
+		m_hCommHandle = CreateFile(portname.c_str(),
+								   GENERIC_READ | GENERIC_WRITE,
+								   0,								// exclusive access
+								   (LPSECURITY_ATTRIBUTES)NULL,		// default security attributes
+								   OPEN_EXISTING,
+								   FILE_FLAG_OVERLAPPED,			// required for WaitCommEvent()
+								   NULL);
 
 		if (m_hCommHandle != INVALID_HANDLE_VALUE)
 		{
@@ -1009,9 +1008,7 @@ void CSuperSerialCard::CommSetSerialPort(DWORD dwNewSerialPortItem)
 	}
 	else if (m_dwSerialPortItem != 0)
 	{
-		TCHAR temp[SIZEOF_SERIALCHOICE_ITEM];
-		sprintf(temp, TEXT_SERIAL_COM"%d", m_vecSerialPortsItems[m_dwSerialPortItem]);
-		m_currentSerialPortName = temp;
+		m_currentSerialPortName = StrFormat(TEXT_SERIAL_COM "%d", m_vecSerialPortsItems[m_dwSerialPortItem]);
 	}
 	else
 	{
@@ -1297,16 +1294,15 @@ void CSuperSerialCard::ScanCOMPorts()
 
 	for (UINT i=1; i<32; i++)	// Arbitrary upper limit
 	{
-		TCHAR portname[SIZEOF_SERIALCHOICE_ITEM];
-		wsprintf(portname, TEXT("\\\\.\\COM%u"), i);
+		std::string portname = StrFormat("\\\\.\\COM%u", i);
 
-		HANDLE hCommHandle = CreateFile(portname,
-								GENERIC_READ | GENERIC_WRITE,
-								0,								// exclusive access
-								(LPSECURITY_ATTRIBUTES)NULL,	// default security attributes
-								OPEN_EXISTING,
-								FILE_FLAG_OVERLAPPED,			// required for WaitCommEvent()
-								NULL);
+		HANDLE hCommHandle = CreateFile(portname.c_str(),
+										GENERIC_READ | GENERIC_WRITE,
+										0,								// exclusive access
+										(LPSECURITY_ATTRIBUTES)NULL,	// default security attributes
+										OPEN_EXISTING,
+										FILE_FLAG_OVERLAPPED,			// required for WaitCommEvent()
+										NULL);
 
 		if (hCommHandle != INVALID_HANDLE_VALUE)
 		{
@@ -1321,38 +1317,28 @@ void CSuperSerialCard::ScanCOMPorts()
 	m_uTCPChoiceItemIdx = m_vecSerialPortsItems.size()-1;
 }
 
-char* CSuperSerialCard::GetSerialPortChoices()
+std::string const& CSuperSerialCard::GetSerialPortChoices()
 {
 	if (IsActive())
-		return m_aySerialPortChoices;
+		return m_strSerialPortChoices;
 
-	//
+	ScanCOMPorts();	// Do this every time in case news ones available (eg. for USB COM ports)
 
-	ScanCOMPorts();				// Do this every time in case news ones available (eg. for USB COM ports)
-	delete [] m_aySerialPortChoices;
-	m_aySerialPortChoices = new TCHAR [ GetNumSerialPortChoices() * SIZEOF_SERIALCHOICE_ITEM + 1 ];	// +1 for final NULL item
+	m_strSerialPortChoices = "None";
+	m_strSerialPortChoices += '\0'; // NULL char for combo box selection.
 
-	TCHAR* pNextSerialChoice = m_aySerialPortChoices;
-
-	//
-
-	pNextSerialChoice += wsprintf(pNextSerialChoice, TEXT("None"));
-	pNextSerialChoice++;		// Skip NULL char
-
-	for (UINT i=1; i<m_uTCPChoiceItemIdx; i++)
+	for (UINT i = 1; i < m_uTCPChoiceItemIdx; i++)
 	{
-		pNextSerialChoice += wsprintf(pNextSerialChoice, TEXT("COM%u"), m_vecSerialPortsItems[i]);
-		pNextSerialChoice++;	// Skip NULL char
+		m_strSerialPortChoices += StrFormat("COM%u", m_vecSerialPortsItems[i]);
+		m_strSerialPortChoices += '\0'; // NULL char for combo box selection.
 	}
 
-	pNextSerialChoice += wsprintf(pNextSerialChoice, TEXT("TCP"));
-	pNextSerialChoice++;		// Skip NULL char
+	m_strSerialPortChoices += "TCP";
+	m_strSerialPortChoices += '\0'; // NULL char for combo box selection.
 
-	*pNextSerialChoice = 0;
+	// std::string()'s implicit nul terminator becomes combo box end of list marker.
 
-	//
-
-	return m_aySerialPortChoices;
+	return m_strSerialPortChoices;
 }
 
 // Called by ctor & LoadSnapshot()
diff --git a/source/SerialComms.h b/source/SerialComms.h
index 9f83fa67..05c905d3 100644
--- a/source/SerialComms.h
+++ b/source/SerialComms.h
@@ -40,7 +40,7 @@ public:
 	virtual void	SaveSnapshot(YamlSaveHelper& yamlSaveHelper);
 	virtual bool	LoadSnapshot(YamlLoadHelper& yamlLoadHelper, UINT version);
 
-	char*	GetSerialPortChoices();
+	std::string const& GetSerialPortChoices();
 	DWORD	GetSerialPort() { return m_dwSerialPortItem; }	// Drop-down list item
 	const std::string& GetSerialPortName() { return m_currentSerialPortName; }
 	bool	IsActive() { return (m_hCommHandle != INVALID_HANDLE_VALUE) || (m_hCommListenSocket != INVALID_SOCKET); }
@@ -87,16 +87,13 @@ private:
 
 	//
 
-public:
-	static const UINT SIZEOF_SERIALCHOICE_ITEM = 12*sizeof(char);
-
 private:
 	std::string m_currentSerialPortName;
 	DWORD	m_dwSerialPortItem;
 
 	static const UINT SERIALPORTITEM_INVALID_COM_PORT = 0;
 	std::vector<UINT> m_vecSerialPortsItems;	// Includes "None" & "TCP" items
-	char*	m_aySerialPortChoices;
+	std::string m_strSerialPortChoices;
 	UINT	m_uTCPChoiceItemIdx;
 
 	static SSC_DIPSW	m_DIPSWDefault;
diff --git a/source/Speaker.cpp b/source/Speaker.cpp
index 3603a52d..e147f2c8 100644
--- a/source/Speaker.cpp
+++ b/source/Speaker.cpp
@@ -98,15 +98,12 @@ static void DisplayBenchmarkResults ()
 {
   DWORD totaltime = GetTickCount()-extbench;
   GetFrame().VideoRedrawScreen();
-  TCHAR buffer[64];
-  wsprintf(buffer,
-           TEXT("This benchmark took %u.%02u seconds."),
-           (unsigned)(totaltime / 1000),
-           (unsigned)((totaltime / 10) % 100));
-  GetFrame().FrameMessageBox(
-             buffer,
-             TEXT("Benchmark Results"),
-             MB_ICONINFORMATION | MB_SETFOREGROUND);
+  std::string strText = StrFormat("This benchmark took %u.%02u seconds.",
+								  (unsigned)(totaltime / 1000),
+								  (unsigned)((totaltime / 10) % 100));
+  GetFrame().FrameMessageBox(strText.c_str(),
+							 "Benchmark Results",
+							 MB_ICONINFORMATION | MB_SETFOREGROUND);
 }
 
 //=============================================================================
diff --git a/source/Windows/AppleWin.cpp b/source/Windows/AppleWin.cpp
index 48c1c92b..0acae02d 100644
--- a/source/Windows/AppleWin.cpp
+++ b/source/Windows/AppleWin.cpp
@@ -357,18 +357,17 @@ static void GetProgramDirectory(void)
 
 void RegisterExtensions(void)
 {
-	TCHAR szCommandTmp[MAX_PATH];
-	GetModuleFileName((HMODULE)0,szCommandTmp,MAX_PATH);
+	char szModuleFileName[MAX_PATH];
+	GetModuleFileName(static_cast<HMODULE>(NULL), szModuleFileName, sizeof(szModuleFileName));
 
-	TCHAR command[MAX_PATH];
-	wsprintf(command, "\"%s\"",	szCommandTmp);	// Wrap	path & filename	in quotes &	null terminate
+	// Wrap	path & filename	in quotes &	null terminate
+	std::string command = std::string("\"") + szModuleFileName + '"';
 
-	TCHAR icon[MAX_PATH];
-	wsprintf(icon,TEXT("%s,1"),(LPCTSTR)command);
+	std::string const icon = command + ",1";
 
-	strcat(command,TEXT(" \"%1\""));			// Append "%1"
-//	strcat(command,TEXT("-d1 %1\""));			// Append "%1"
-//	sprintf(command, "\"%s\" \"-d1 %%1\"", szCommandTmp);	// Wrap	path & filename	in quotes &	null terminate
+	command += " \"%1\"";			// Append ' "%1"'
+//	command += " -d1 \"%1\"";		// Append ' -d1 "%1"'
+//	command += " \"-d1 %1\"";		// Append ' "-d1 %1"'
 
 	// NB. Registry access to HKLM typically results in ErrorCode 5(ACCESS DENIED), as UAC requires elevated permissions (Run as administrator).
 	// . HKEY_CLASSES_ROOT\CLSID is a merged view of HKLM\SOFTWARE\Classes and HKCU\SOFTWARE\Classes
@@ -408,13 +407,13 @@ void RegisterExtensions(void)
 	pValueName = "DiskImage";
 	res = RegSetValue(HKEY_CLASSES_ROOT,
 				pValueName,
-				REG_SZ,"Disk Image",0);
+				REG_SZ, "Disk Image", 0);
 	if (res != NOERROR) LogFileOutput("RegSetValue(%s) failed (0x%08X)\n", pValueName, res);
 
 	pValueName = "DiskImage\\DefaultIcon";
 	res = RegSetValue(HKEY_CLASSES_ROOT,
 				pValueName,
-				REG_SZ,icon,0);
+				REG_SZ, icon.c_str(), 0);
 	if (res != NOERROR) LogFileOutput("RegSetValue(%s) failed (0x%08X)\n", pValueName, res);
 
 // This key can interfere....
@@ -423,26 +422,26 @@ void RegisterExtensions(void)
 	pValueName = "DiskImage\\shell\\open\\command";
 	res = RegSetValue(HKEY_CLASSES_ROOT,
 				pValueName,
-				REG_SZ,command,_tcslen(command)+1);
+				REG_SZ, command.c_str(), command.length() + 1);
 	if (res != NOERROR) LogFileOutput("RegSetValue(%s) failed (0x%08X)\n", pValueName, res);
 
 	pValueName = "DiskImage\\shell\\open\\ddeexec";
 	res = RegSetValue(HKEY_CLASSES_ROOT,
 				pValueName,
-				REG_SZ,"%1",3);
+				REG_SZ, "%1", 3);
 	if (res != NOERROR) LogFileOutput("RegSetValue(%s) failed (0x%08X)\n", pValueName, res);
 
 	pValueName = "DiskImage\\shell\\open\\ddeexec\\application";
 	res = RegSetValue(HKEY_CLASSES_ROOT,
 				pValueName,
-				REG_SZ,"applewin",_tcslen("applewin")+1);
-//				REG_SZ,szCommandTmp,_tcslen(szCommandTmp)+1);
+				REG_SZ, "applewin", strlen("applewin") + 1);
+//				REG_SZ, szModuleFileName, strlen(szModuleFileName)+1);
 	if (res != NOERROR) LogFileOutput("RegSetValue(%s) failed (0x%08X)\n", pValueName, res);
 
 	pValueName = "DiskImage\\shell\\open\\ddeexec\\topic";
 	res = RegSetValue(HKEY_CLASSES_ROOT,
 				pValueName,
-				REG_SZ,"system",_tcslen("system")+1);
+				REG_SZ, "system", strlen("system") + 1);
 	if (res != NOERROR) LogFileOutput("RegSetValue(%s) failed (0x%08X)\n", pValueName, res);
 }
 
diff --git a/source/Windows/Win32Frame.cpp b/source/Windows/Win32Frame.cpp
index dc607a2a..275e6125 100644
--- a/source/Windows/Win32Frame.cpp
+++ b/source/Windows/Win32Frame.cpp
@@ -63,10 +63,10 @@ Win32Frame::Win32Frame()
 	g_nTrackDrive2 = -1;
 	g_nSectorDrive1 = -1;
 	g_nSectorDrive2 = -1;
-	strcpy_s(g_sTrackDrive1, sizeof(g_sTrackDrive1), "??");
-	strcpy_s(g_sTrackDrive2, sizeof(g_sTrackDrive1), "??");
-	strcpy_s(g_sSectorDrive1, sizeof(g_sTrackDrive1), "??");
-	strcpy_s(g_sSectorDrive2, sizeof(g_sTrackDrive1), "??");
+	g_strTrackDrive1 = "??";
+	g_strTrackDrive2 = "??";
+	g_strSectorDrive1 = "??";
+	g_strSectorDrive2 = "??";
 
 	g_eStatusDrive1 = DISK_STATUS_OFF;
 	g_eStatusDrive2 = DISK_STATUS_OFF;
@@ -259,28 +259,27 @@ void Win32Frame::Benchmark(void)
 				}
 			}
 			if (error) {
-				TCHAR outstr[256];
-				wsprintf(outstr,
-					TEXT("The emulator experienced an error %u clock cycles ")
-					TEXT("into the CPU benchmark.  Prior to the error, the ")
-					TEXT("program counter was at $%04X.  After the error, it ")
-					TEXT("had jumped to $%04X."),
+				std::string strText = StrFormat(
+					"The emulator experienced an error %u clock cycles "
+					"into the CPU benchmark.  Prior to the error, the "
+					"program counter was at $%04X.  After the error, it "
+					"had jumped to $%04X.",
 					(unsigned)loop,
 					(unsigned)lastpc,
 					(unsigned)regs.pc);
 				FrameMessageBox(
-					outstr,
-					TEXT("Benchmarks"),
+					strText.c_str(),
+					"Benchmarks",
 					MB_ICONINFORMATION | MB_SETFOREGROUND);
 			}
 			else
 				FrameMessageBox(
-					TEXT("The emulator was unable to locate the exact ")
-					TEXT("point of the error.  This probably means that ")
-					TEXT("the problem is external to the emulator, ")
-					TEXT("happening asynchronously, such as a problem in ")
-					TEXT("a timer interrupt handler."),
-					TEXT("Benchmarks"),
+					"The emulator was unable to locate the exact "
+					"point of the error.  This probably means that "
+					"the problem is external to the emulator, "
+					"happening asynchronously, such as a problem in "
+					"a timer interrupt handler.",
+					"Benchmarks",
 					MB_ICONINFORMATION | MB_SETFOREGROUND);
 		}
 
@@ -315,21 +314,20 @@ void Win32Frame::Benchmark(void)
 
 	// DISPLAY THE RESULTS
 	DisplayLogo();
-	TCHAR outstr[256];
-	wsprintf(outstr,
-		TEXT("Pure Video FPS:\t%u hires, %u text\n")
-		TEXT("Pure CPU MHz:\t%u.%u%s (video update)\n")
-		TEXT("Pure CPU MHz:\t%u.%u%s (full-speed)\n\n")
-		TEXT("EXPECTED AVERAGE VIDEO GAME\n")
-		TEXT("PERFORMANCE: %u FPS"),
+	std::string strText = StrFormat(
+		"Pure Video FPS:\t%u hires, %u text\n"
+		"Pure CPU MHz:\t%u.%u%s (video update)\n"
+		"Pure CPU MHz:\t%u.%u%s (full-speed)\n\n"
+		"EXPECTED AVERAGE VIDEO GAME\n"
+		"PERFORMANCE: %u FPS",
 		(unsigned)totalhiresfps,
 		(unsigned)totaltextfps,
-		(unsigned)(totalmhz10[0] / 10), (unsigned)(totalmhz10[0] % 10), (LPCTSTR)(IS_APPLE2 ? TEXT(" (6502)") : TEXT("")),
-		(unsigned)(totalmhz10[1] / 10), (unsigned)(totalmhz10[1] % 10), (LPCTSTR)(IS_APPLE2 ? TEXT(" (6502)") : TEXT("")),
+		(unsigned)(totalmhz10[0] / 10), (unsigned)(totalmhz10[0] % 10), (LPCTSTR)(IS_APPLE2 ? " (6502)" : ""),
+		(unsigned)(totalmhz10[1] / 10), (unsigned)(totalmhz10[1] % 10), (LPCTSTR)(IS_APPLE2 ? " (6502)" : ""),
 		(unsigned)realisticfps);
 	FrameMessageBox(
-		outstr,
-		TEXT("Benchmarks"),
+		strText.c_str(),
+		"Benchmarks",
 		MB_ICONINFORMATION | MB_SETFOREGROUND);
 }
 
diff --git a/source/Windows/Win32Frame.h b/source/Windows/Win32Frame.h
index ecd27de4..b345200c 100644
--- a/source/Windows/Win32Frame.h
+++ b/source/Windows/Win32Frame.h
@@ -185,10 +185,10 @@ private:
 	int    g_nTrackDrive2;
 	int    g_nSectorDrive1;
 	int    g_nSectorDrive2;
-	TCHAR  g_sTrackDrive1[8];
-	TCHAR  g_sTrackDrive2[8];
-	TCHAR  g_sSectorDrive1[8];
-	TCHAR  g_sSectorDrive2[8];
+	std::string g_strTrackDrive1;
+	std::string g_strTrackDrive2;
+	std::string g_strSectorDrive1;
+	std::string g_strSectorDrive2;
 	Disk_Status_e g_eStatusDrive1;
 	Disk_Status_e g_eStatusDrive2;
 
diff --git a/source/Windows/WinFrame.cpp b/source/Windows/WinFrame.cpp
index f90f5af6..44e8bbfb 100644
--- a/source/Windows/WinFrame.cpp
+++ b/source/Windows/WinFrame.cpp
@@ -661,13 +661,11 @@ void Win32Frame::FrameDrawDiskStatus( HDC passdc )
 		else                    g_nSectorDrive2 = -1;
 	}
 
-	sprintf_s( g_sTrackDrive1 , sizeof(g_sTrackDrive1 ), "%2d", g_nTrackDrive1 );
-	if (g_nSectorDrive1 < 0) sprintf_s( g_sSectorDrive1, sizeof(g_sSectorDrive1), "??" );
-	else                     sprintf_s( g_sSectorDrive1, sizeof(g_sSectorDrive1), "%2d", g_nSectorDrive1 ); 
+	g_strTrackDrive1 = StrFormat( "%2d", g_nTrackDrive1 );
+	g_strSectorDrive1 = (g_nSectorDrive1 < 0) ? "??" : StrFormat( "%2d", g_nSectorDrive1 );
 
-	sprintf_s( g_sTrackDrive2 , sizeof(g_sTrackDrive2),  "%2d", g_nTrackDrive2 );
-	if (g_nSectorDrive2 < 0) sprintf_s( g_sSectorDrive2, sizeof(g_sSectorDrive2), "??" );
-	else                     sprintf_s( g_sSectorDrive2, sizeof(g_sSectorDrive2), "%2d", g_nSectorDrive2 );
+	g_strTrackDrive2 = StrFormat( "%2d", g_nTrackDrive2 );
+	g_strSectorDrive2 = (g_nSectorDrive2 < 0) ? "??" : StrFormat( "%2d", g_nSectorDrive2 );
 
 	// Draw Track/Sector
 	FrameReleaseDC();
@@ -681,8 +679,6 @@ void Win32Frame::FrameDrawDiskStatus( HDC passdc )
 	SetBkColor(dc,RGB(0,0,0));
 	SetTextAlign(dc,TA_LEFT | TA_TOP);
 
-	char text[ 16 ];
-
 	if (g_bIsFullScreen)
 	{
 		// GH#57 - drive lights in full screen mode
@@ -690,20 +686,19 @@ void Win32Frame::FrameDrawDiskStatus( HDC passdc )
 		if (!g_bFullScreen_ShowSubunitStatus)
 			return;
 
-		SetTextColor(dc, g_aDiskFullScreenColorsLED[ g_eStatusDrive1 ] );
-		TextOut(dc,x+ 3,y+2,TEXT("1"),1);
+		SetTextColor(dc, g_aDiskFullScreenColorsLED[ g_eStatusDrive1 ]);
+		TextOut(dc, x+ 3, y+2, TEXT("1"), 1);
 
-		SetTextColor(dc, g_aDiskFullScreenColorsLED[ g_eStatusDrive2 ] );
-		TextOut(dc,x+13,y+2,TEXT("2"),1);
+		SetTextColor(dc, g_aDiskFullScreenColorsLED[ g_eStatusDrive2 ]);
+		TextOut(dc, x+13, y+2, TEXT("2"), 1);
 
 		int dx = 0;
-		if( nActiveFloppy == 0 )
-			sprintf( text, "%s/%s    ", g_sTrackDrive1, g_sSectorDrive1 );
-		else
-			sprintf( text, "%s/%s    ", g_sTrackDrive2, g_sSectorDrive2 );
+		std::string text = ( nActiveFloppy == 0 )
+			? StrFormat( "%s/%s    ", g_strTrackDrive1.c_str(), g_strSectorDrive1.c_str() )
+			: StrFormat( "%s/%s    ", g_strTrackDrive2.c_str(), g_strSectorDrive2.c_str() );
 
 		SetTextColor(dc, g_aDiskFullScreenColorsLED[ DISK_STATUS_READ ] );
-		TextOut(dc,x+dx,y-12,text, strlen(text) ); // original: y+2; y-12 puts status in the Configuration Button Icon
+		TextOut(dc, x+dx, y-12, text.c_str(), text.length()); // original: y+2; y-12 puts status in the Configuration Button Icon
 	}
 	else
 	{
@@ -712,22 +707,23 @@ void Win32Frame::FrameDrawDiskStatus( HDC passdc )
 			return;
 
 		// Erase background
-		SelectObject(dc,GetStockObject(NULL_PEN));
-		SelectObject(dc,btnfacebrush);
-		Rectangle(dc,x+4,y+32,x+BUTTONCX+1,y+56); // y+35 -> 44 -> 56
+		SelectObject(dc, GetStockObject(NULL_PEN));
+		SelectObject(dc, btnfacebrush);
+		Rectangle(dc, x+4, y+32, x+BUTTONCX+1, y+56); // y+35 -> 44 -> 56
 
-		SetTextColor(dc,RGB(0,0,0));
-		SetBkMode(dc,TRANSPARENT);
+		SetTextColor(dc, RGB(0,0,0));
+		SetBkMode(dc, TRANSPARENT);
 
-		sprintf( text, "T%s", g_sTrackDrive1 );
-		TextOut(dc,x+6, y+32, text, strlen(text) );
-		sprintf( text, "S%s", g_sSectorDrive1 );
-		TextOut(dc,x+6, y+42, text, strlen(text) );
+		std::string text;
+		text = "T" + g_strTrackDrive1;
+		TextOut(dc, x+6, y+32, text.c_str(), text.length());
+		text = "S" + g_strSectorDrive1;
+		TextOut(dc, x+6, y+42, text.c_str(), text.length());
 
-		sprintf( text, "T%s", g_sTrackDrive2 );
-		TextOut(dc,x+26,y+32, text, strlen(text) );
-		sprintf( text, "S%s", g_sSectorDrive2 );
-		TextOut(dc,x+26,y+42, text, strlen(text) );
+		text = "T" + g_strTrackDrive2;
+		TextOut(dc, x+26, y+32, text.c_str(), text.length());
+		text = "S" + g_strSectorDrive2;
+		TextOut(dc, x+26, y+42, text.c_str(), text.length());
 	}
 }