Skip to main content

How to Create a Morse Code Decoder in Batch Script

Morse code is a communication system that uses sequences of dots (.) and dashes (-) to represent letters and numbers. Translating these patterns into readable text within a Batch environment involves string splitting, character comparison, and the effective use of delayed expansion to build the translated message.

In this guide, we will implement a Morse code decoder that transforms a string of Morse signals into standard English text using a simple lookup table.

The Decoder Method: Character-by-Character Translation

To decode Morse code, we must process each "letter block" (separated by spaces) individually, look it up in our dictionary, and append the result to our output. We also need to handle word boundaries (often represented as double spaces or slashes).

Implementation Script

@echo off
setlocal enabledelayedexpansion

:: -------------------------------------------------------
:: Define Morse-to-Alpha Dictionary
:: Dots (.) are stored as 'd', dashes (-) as 't' in the
:: variable name to avoid Batch parsing conflicts.
:: -------------------------------------------------------
set "M_dt=A" & set "M_tddd=B" & set "M_tdtd=C" & set "M_tdd=D"
set "M_d=E" & set "M_ddtd=F" & set "M_ttd=G" & set "M_dddd=H"
set "M_dd=I" & set "M_dttt=J" & set "M_tdt=K" & set "M_dtdd=L"
set "M_tt=M" & set "M_td=N" & set "M_ttt=O" & set "M_dttd=P"
set "M_ttdt=Q" & set "M_dtd=R" & set "M_ddd=S" & set "M_t=T"
set "M_ddt=U" & set "M_dddt=V" & set "M_dtt=W" & set "M_tddt=X"
set "M_tdtt=Y" & set "M_ttdd=Z"

set "M_ttttt=0" & set "M_dtttt=1" & set "M_ddttt=2" & set "M_dddtt=3"
set "M_ddddt=4" & set "M_ddddd=5" & set "M_tdddd=6" & set "M_ttddd=7"
set "M_tttdd=8" & set "M_tttd=9"

:: -------------------------------------------------------
:: Input Morse Code
:: Letters separated by spaces, words separated by '/'
:: -------------------------------------------------------
set "Input=.... . .-.. .-.. --- / .-- --- .-. .-.. -.."
echo Input Morse: %Input%

set "Output="

:: -------------------------------------------------------
:: Process each token
:: -------------------------------------------------------
for %%A in (%Input%) do (
set "Symbol=%%A"

if "!Symbol!"=="/" (
set "Output=!Output! "
) else (
:: Convert . to d and - to t for safe variable lookup
set "Key=!Symbol!"
set "Key=!Key:.=d!"
set "Key=!Key:-=t!"

:: Look up the sanitized key in our dictionary
set "Result=?"
if defined M_!Key! (
call set "Result=%%M_!Key!%%"
)
set "Output=!Output!!Result!"
)
)

echo Decoded Text: !Output!
pause
endlocal
exit /b 0

Multi-Stage Word Decoding

If you need more advanced parsing that handles word boundaries, you can split on a delimiter like / for words first, then process individual letter blocks within each word.

@echo off
setlocal enabledelayedexpansion

:: -------------------------------------------------------
:: Dictionary Setup
:: Use safe characters: d = dot, t = dash
:: -------------------------------------------------------
set "Dict_dt=A"
set "Dict_tddd=B"
set "Dict_tdtd=C"
set "Dict_tdd=D"
set "Dict_d=E"
set "Dict_ddtd=F"
set "Dict_ttd=G"
set "Dict_dddd=H"
set "Dict_dd=I"
set "Dict_dttt=J"
set "Dict_tdt=K"
set "Dict_dtdd=L"
set "Dict_tt=M"
set "Dict_td=N"
set "Dict_ttt=O"
set "Dict_dttd=P"
set "Dict_ttdt=Q"
set "Dict_dtd=R"
set "Dict_ddd=S"
set "Dict_t=T"
set "Dict_ddt=U"
set "Dict_dddt=V"
set "Dict_dtt=W"
set "Dict_tddt=X"
set "Dict_tdtt=Y"
set "Dict_ttdd=Z"

:: -------------------------------------------------------
:: Input: "A B D" in standard Morse
:: -------------------------------------------------------
set "MorseInput=.- -... -.."

echo Input Morse: %MorseInput%

set "FinalText="
for %%W in (%MorseInput%) do (
set "MorseSymbol=%%W"

:: Sanitize: replace . with d, - with t
set "Key=!MorseSymbol:.=d!"
set "Key=!Key:-=t!"

:: Safe lookup via call set
set "Lookup="
if defined Dict_!Key! (
call set "Lookup=%%Dict_!Key!%%"
)

if defined Lookup (
set "FinalText=!FinalText!!Lookup!"
) else (
set "FinalText=!FinalText!?"
)
)

echo Result: !FinalText!
pause
endlocal

Creating an Interactive Prompt

To make the tool useful, we can wrap the decoder in a simple input prompt so you can paste Morse strings directly.

Implementation Script

@echo off
setlocal enabledelayedexpansion

:: -------------------------------------------------------
:: Morse-to-Alpha Dictionary
:: Sanitized keys: . = d, - = t
:: -------------------------------------------------------

:: Letters
set "char_dt=A"
set "char_tddd=B"
set "char_tdtd=C"
set "char_tdd=D"
set "char_d=E"
set "char_ddtd=F"
set "char_ttd=G"
set "char_dddd=H"
set "char_dd=I"
set "char_dttt=J"
set "char_tdt=K"
set "char_dtdd=L"
set "char_tt=M"
set "char_td=N"
set "char_ttt=O"
set "char_dttd=P"
set "char_ttdt=Q"
set "char_dtd=R"
set "char_ddd=S"
set "char_t=T"
set "char_ddt=U"
set "char_dddt=V"
set "char_dtt=W"
set "char_tddt=X"
set "char_tdtt=Y"
set "char_ttdd=Z"

:: Numbers
set "char_ttttt=0"
set "char_dtttt=1"
set "char_ddttt=2"
set "char_dddtt=3"
set "char_ddddt=4"
set "char_ddddd=5"
set "char_tdddd=6"
set "char_ttddd=7"
set "char_tttdd=8"
set "char_tttdt=9"

:: -------------------------------------------------------
:: Interactive Prompt Loop
:: -------------------------------------------------------
:prompt
echo.
set "MorseString="
set /p "MorseString=Paste Morse (space between letters, / between words): "

if not defined MorseString goto :eof

set "DecodedResult="
for %%A in (%MorseString%) do (
set "Bit=%%A"

if "!Bit!"=="/" (
set "DecodedResult=!DecodedResult! "
) else (
:: Sanitize: . becomes d, - becomes t
set "Key=!Bit:.=d!"
set "Key=!Key:-=t!"

:: Lookup using call set
set "Lookup=?"
call set "Lookup=%%char_!Key!%%"

set "DecodedResult=!DecodedResult!!Lookup!"
)
)

echo.
echo Decoded Message: !DecodedResult!
goto prompt

Best Practices

  1. Standardize Separators: Morse code usually uses one space between letters and a slash / between words. Treat / as a word-gap token inside your for loop rather than trying to replace it with spaces, which would lose word boundary information.
  2. Use call set for Nested Lookups: When a variable name contains another variable (e.g., char.!Bit!), use call set "Lookup=%%char.!Bit!%%" to force double expansion. Direct syntax like !char%Bit%! fails because %Bit% is expanded at parse time before !Bit! receives its value.
  3. Prefix Dictionary Keys: Adding a prefix like M., Dict., or char. to dictionary variable names prevents collisions with built-in environment variables and makes cleanup easier.
  4. Delayed Expansion: Any dictionary lookup involving a loop variable must take place while delayed expansion is active. Always pair setlocal enabledelayedexpansion at the top of your script.
  5. Variable Length Limit: For very long Morse documents, the for loop is remarkably fast. However, if your decoded string grows beyond ~8192 characters, consider breaking the message into separate lines to avoid hitting the cmd.exe variable length limit.

Conclusion

Building a Morse code decoder in Batch demonstrates the power of variable indexing. By treating Morse signals as keys in a virtual dictionary, you can transform a complex stream of symbols into readable text with just a few lines of loop-driven logic.