Warning: this is an htmlized version!
The original is here, and
the conversion rules are here.
--% Our types:
--% rawarr:  an array of raw char images, each padded to 32 bytes.
--% rawfont: a string of nchars*height bytes.
--% font:    an array with entries nchars, height, 0..nchars-1 (w/len 32 each).
--% psf:     four magic bytes followed by a rawfont.
--% bigstr:  a user-friendly 2D representation, like demo_bigstr.
--% vcsa:    nrows,ncols,crsr_x,crsr_y,nrows*ncols*(char,attr)
--%
--% The conversions (modulo extra info like height and nchars):
--% psffile <-> psf <-> rawfont <-> font <-> bigstr
--%     rawfontfile <-> rawfont
--%
--% Here's how to do some of the conversions:
--% psffile -> psf                   readfile(fname)
--% psffile <- psf                   writefile(fname, psf)
--%            psf -> font           psftofont(psf)
--%            psf <- font           fonttopsf(psf)
--%                   font -> bigstr fonttobigstr(font, 0, font.nchars-1)
--%                   font <- bigstr bigstrtofont(bigstr, nchars, height)
--%
--% rawfontfile -> rawfont           readfile(fname)
--% rawfontfile <- rawfont           writefile(fname, rawfont)
--%                rawfont -> font   rawfonttofont(rawfont, nchars, height)
--%                rawfont <- font   fonttorawfont(font, font.height)
--%
--% "vcsa" corresponds to the contents of a "/dev/vcsann" in Linux,
--% and is used for taking screenshots.

--% «.tools_and_samples» (to "tools_and_samples")
--%  «.demo_bigstr»	(to "demo_bigstr")
--% «.psf_stuff»	(to "psf_stuff")
--%   «.psftofont»	(to "psftofont")
--%   «.fonttopsf»	(to "fonttopsf")
--% «.bigstr_stuff»	(to "bigstr_stuff")
--%   «.bigstrtorawarr»	(to "bigstrtorawarr")
--%   «.bigstrtofont»	(to "bigstrtofont")
--%   «.fonttobigstr»	(to "fonttobigstr")
--% «.other_conversions» (to "other_conversions")
--%   «.rawfonttofont»	(to "rawfonttofont")
--%   «.fonttorawfont»	(to "fonttorawfont")
--%   «.vcsatounix»	(to "vcsatounix")

--% «.explode»		(to "explode")
--% «.split_clines»	(to "split_clines")
--% «.changefont»	(to "changefont")
--% «.makecomposes»	(to "makecomposes")
--% «.trfont»		(to "trfont")
--% «.setfont»		(to "setfont")
--% «.e_scripts»	(to "e_scripts")
--% «.vcsatoBIGstring»	(to "vcsatoBIGstring")




--%%%%%
--%
--% «tools_and_samples»  (to ".tools_and_samples")
--%
--%%%%%

--% «demo_bigstr»  (to ".demo_bigstr")
demo_bigstr = [[
+--------+--------+--------+--------+--------+--------+--------+--------+
|     o  | o      |    oo  |        |        |        |        |        |
|    oo  | o      |   oo o |   o    | o   o  |  o  o  |        |o       |
|ooo  o  | ooo    |   oo   |  o o   | o   o  |  o  o  | oo oo  |o       |
|     o  | o o    |   oo   |  o o   |  o o   |  o  o  |o  o  o |oo   oo |
|    ooo | ooo    |   oo   | o   o  |  o o   |  o  o  |o  o  o |o o o   |
|        |   o    |   oo   | o   o  |   o    | oooooo | oo oo  |o o oo  |
|        |   o    | o oo   |        |        |        |        |oo  o   |
|        |        |  oo    |        |        |        |        |    o   |
+--------+--------+--------+--------+--------+--------+--------+--------+
|  oooo  |  oooo  |ooo ooo |        |        |
|  o     |     o  |o     o |        |        |
|  o     |     o  |o     o |        | o   o  |
|  o     |     o  |o     o |oo oooo |o     o |
|        |        |        |o  o o o|o     o |
|        |        |        |o  o o o|o  o  o |
|        |        |        |o  o o o| oo oo  |
|        |        |        |        |        |
+--------+--------+--------+--------+--------+]]

bits = {128, 64, 32, 16, 8, 4, 2, 1}
padbytes_zeroes = strrep("\000", 32)
function padbytes(bytes)
  return strsub(bytes..padbytes_zeroes, 1, 32)
end
function pixelstobyte(str)
  local byte, i, bit = 0
  for i, bit in bits do
    if strbyte(str, i) ~= 32 then
      byte = byte + bit
    end
  end
  return byte
end
function bytetopixels(byte)
  local str, i, bit = ""
  for i, bit in bits do
    if band(byte, bit) ~= 0 then
      str = str .. "o"
    else
      str = str .. " "
    end
  end
  return str
end



--%%%%%
--%
--% «psf_stuff»  (to ".psf_stuff")
--%
--%%%%%

--% «psftofont»  (to ".psftofont")
function psftofont(psf)
  -- (find-fline "/usr/doc/console-tools/file-formats/psf" "psf_header =")
  local magic1, magic2, filemode, height
  magic1   = strbyte(psf, 1)		-- 0x36
  magic2   = strbyte(psf, 2)		-- 0x04
  filemode = strbyte(psf, 3)		-- 0 means 256 chars, no unicode
  height   = strbyte(psf, 4)		-- in scanlines; typically 8, 14 or 16
  -- I'm not checking magic1, magic2, and filemode yet
  return rawfonttofont(strsub(psf, 5), 256, height)
end

--% «fonttopsf»  (to ".fonttopsf")
function fonttopsf(font)
  return strchar(54, 4, 0, font.height) .. fonttorawfont(font, font.height)
end




--%%%%%
--%
--% «bigstr_stuff»  (to ".bigstr_stuff")
--%
--%%%%%

--% «bigstrtorawarr»  (to ".bigstrtorawarr")
--% Convert a "bigstr" (like demo_bigstr, above) to an array containing
--% a string of length 32 with each character in raw form.
--%
--% Rationale for the naming of variables in "bigstrtorawarr":
--% 73 = 1+8+1+8+1+8+1+8+1+8+1+8+1+8+1+8+1
--% 74 = 73+1   (\n)
--% 592 = 74*8
--% bigstr = 74+592+74+592+...+74
--%
bigstrtorawarr_re = regex("^\n?[-+]+\n" .. "((\\|(([ o]+\\|)+)\n)+)(.*)$")
function bigstrtorawarr(bigstr)
  local p1, p2, a, s592, rest
  local arr = {}
  while 1 do
    -- p1, p2, a = match(bigstr, re)
    p1, p2, a = match(bigstr, bigstrtorawarr_re)
    if a then
      s592, rest = a[1], a[5]
      arr.nready = getn(arr)
      gsub(s592, "([ o|]+)\n", function(s73)
          local arr = %arr
          arr.nnow = arr.nready
          gsub(s73, "([ o]+)", function(s8)
              local arr = %arr
              arr.nnow = arr.nnow + 1
              arr[arr.nnow] = arr[arr.nnow] or {}
              tinsert(arr[arr.nnow], s8)
            end)
        end)
      bigstr = rest
    else
      local rawarr = {}
      foreachi(arr, function(_, prows)
          local bytes = ""
          local i
          for i = 1,getn(prows) do
             bytes = bytes .. strchar(pixelstobyte(prows[i]))
          end
          tinsert(%rawarr, padbytes(bytes))
        end)
      -- return rawarr, arr
      return rawarr
    end
  end
end


--% «bigstrtofont»  (to ".bigstrtofont")
--% This function isn't very useful, as bigstrings are used mainly
--% for modifying fonts, not for storing fonts in a readable format.
--%
function bigstrtofont(bigstr, nchars, height)
  local font = {nchars = nchars, height = height}
  local rawarr = bigstrtorawarr(bigstr)
  local i
  if getn(rawarr) ~= nchars then
    printf("Warning: getn(rawarr)=%d, nchars=%d\n", getn(rawarr), nchars)
  end
  for i=0,nchars-1 do
    font[i] = rawarr[i+1]
  end
  return font
end


--% «fonttobigstr»  (to ".fonttobigstr")
--% Convert a font to a "bigstr".
--%
function horizontalbar(nchars)
  return "+" .. strrep("--------+", nchars) .. "\n"
end
function fontto3Dmatrix(font, c0, c1)
  local bigstr = ""
  local scanline, nchar
  for scanline = 1,font.height do
    bigstr = bigstr .. "|"
    for nchar = c0,c1 do
      bigstr = bigstr .. bytetopixels(strbyte(font[nchar], scanline)) .. "|"
    end
    bigstr = bigstr .. "\n"
  end
  return bigstr
end
function fonttobigstr(font, c0, c1)
  local hbar = horizontalbar(8)
  local bigstr, nchar = hbar
  for nchar = c0,c1-7,8 do
    bigstr = bigstr .. fontto3Dmatrix(font, nchar, nchar+7) .. hbar
  end
  return bigstr
end



--%%%%%
--%
--% «other_conversions»  (to ".other_conversions")
--%
--%%%%%

--% «rawfonttofont»  (to ".rawfonttofont")
--% Convert a font in raw or psf form to a "font" array,
--% that has indices "nchars", "height", 0, 1, 2, ..., 255.
--% Each entry with a numeric index contains a char in raw
--% form (a string with length 32).
--%
function rawfonttofont(rawfont, nchars, height)
  nchars = nchars or 256
  height = height or floor(strlen(rawfont)/nchars)
  local font = {nchars = nchars, height = height}
  local nchar
  if strlen(rawfont) ~= nchars*height then
    printf("Bad len: rawfont=%d nchars*height=%d\n",
      strlen(rawfont), nchars*height)
  end
  for nchar=0,nchars-1 do
    font[nchar] = padbytes(strsub(rawfont, nchar*height+1, (nchar+1)*height))
  end
  return font
end

--% «fonttorawfont»  (to ".fonttorawfont")
function fonttorawfont(font, scanlines)
  local rawfont = ""
  local nchar
  for nchar=0,font.nchars-1 do
    rawfont = rawfont .. strsub(font[nchar], 1, scanlines)
  end
  return rawfont
end

--% «vcsatounix»  (to ".vcsatounix")
--% (find-angg ".zshrc" "vt")
--% (find-luanode "gsub" "gsub (s, pat, repl [, n])" "If repl is a function")
--% (find-luanode "gsub" "Here are some examples:" "function")
--% (find-luanode "Patterns" "followed by -" "shortest")
--% mylua -e 'p(gsub("abcdefg", "(.).", "%1"))'
--%
function vcsatounix(vcsa)
  local lines, columns, cursorx, cursory =
    strbyte(vcsa, 1), strbyte(vcsa, 2), strbyte(vcsa, 3), strbyte(vcsa, 4)
  local bigstr = ""
  for y=1,lines-1 do
    pairs = strsub(vcsa, y*columns*2+5, (y+1)*columns*2+4)
    str = gsub(pairs, "(.).", "%1")
    str = gsub(str, "(.) -", "%1")
    bigstr = bigstr .. str .. "\n"
  end
  return bigstr
end




--%%%%%
--%
--% Functions for modifying fonts and keymaps
--%
--%%%%%

--% «explode»  (to ".explode")
function explode_(i, n, arr)
  if i>=n then
    return arr[n]
  end
  return arr[i], explode_(i+1, n, arr)
end
function explode(arr)
  return explode_(1, getn(arr), arr)
end

--% «split_clines»  (to ".split_clines")
function split_clines(n, ...)
  local i, j, strs, arrs
  strs = {}
  for i=1,n do
    strs[i] = ""
  end
  for i=0,getn(arg)-n,n do
    for j=1,n do
      strs[j] = strs[j] .. " " .. arg[i+j]
    end
  end
  arrs = {}
  for i=1,n do
    tinsert(arrs, split(strs[i]))
  end
  return explode(arrs)
end

--% «changefont»  (to ".changefont")
function changefont(origfont, rawarr, cchars)
  local i, c
  for i=1,getn(cchars) do
    c = cchars[i]
    if strlen(c) == 1 and c ~= "." then
      origfont[strbyte(c)] = rawarr[i]
    end
  end
  return origfont
end

--% «makecomposes»  (to ".makecomposes")
function tickchar(c)
  return "'"..gsub(c, "(['\\])", "\\%1").."'"
end
function makecomposes(cchars, ckeyps)
  local i,c,thiscompose
  local composes = ""
  for i=1,getn(cchars) do
    c = cchars[i]
    if c ~= "." then
      key1 = strsub(ckeyps[i], 1, 1)
      key2 = strsub(ckeyps[i], 2, 2)
      thiscompose = format("compose %s %s to %s\n",
			   tickchar(key1), tickchar(key2), tickchar(c))
      if strlen(c) == 1 and c ~= "." then
        composes = composes .. thiscompose
      else
        composes = composes .. "# " .. thiscompose
      end
    end
  end
  return composes
end



-- (find-node "(elisp)Mapping Functions")
-- (find-fline "~/MTA/128")
-- (find-fline "~/MTA/128c")
-- (insert (mapconcat (lambda (c1) (format "\\%03d" c1)) "abcd" ""))

highglyphs_latin =
  "\128\129\130\131\132\133\134\135\136\137\138\139\140\141\142\143" ..
  "\144\145\146\147\148\149\150\151\152\153\154\155\156\157\158\159" ..
  "\160\161\162\163\164\165\166\167\168\169\170\171\172\173\174\175" ..
  "\176\177\178\179\180\181\182\183\184\185\186\187\188\189\190\191" ..
  "\192\193\194\195\196\197\198\199\200\201\202\203\204\205\206\207" ..
  "\208\209\210\211\212\213\214\215\216\217\218\219\220\221\222\223" ..
  "\224\225\226\227\228\229\230\231\232\233\234\235\236\237\238\239" ..
  "\240\241\242\243\244\245\246\247\248\249\250\251\252\253\254\255"
highglyphs_850 =
  "\213\159\242\254\196\179\218\191\192\217\195\180\194\193\197\205" ..
  "\186\201\187\200\188\204\185\203\202\206\223\220\219\176\177\178" ..
  "\255\173\189\156\207\190\221\245\249\184\166\174\170\240\169\238" ..
  "\248\241\253\252\239\230\244\250\247\251\167\175\172\171\243\168" ..
  "\183\181\182\199\142\143\146\128\212\144\210\211\222\214\215\216" ..
  "\209\165\227\224\226\229\153\158\157\235\233\234\154\237\232\225" ..
  "\133\160\131\198\132\134\145\135\138\130\136\137\141\161\140\139" ..
  "\208\164\149\162\147\228\148\246\155\151\163\150\129\236\231\152"

--% «trfont»  (to ".trfont")
function trfont(font, trstr1, trstr2)
  local newfont, i, c1, c2
  newfont = copy(font)
  for i=1,strlen(trstr1) do
    c1 = strbyte(trstr1, i)
    c2 = strbyte(trstr2, i)
    newfont[c2] = font[c1]
  end
  return newfont
end

--% «setfont»  (to ".setfont")
--% (find-angg "LUA/pio_fontx.c")
function setfont(font, forcedheight)
  local rawfont32 = fonttorawfont(font, 32)
  local err
  if not pio_fontx then
    -- loadextension(getenv("HOME").."/LUA/pio_fontx.so", "pio_fontx_init")
    loadextension("./pio_fontx.so", "pio_fontx_init")
  end
  err = pio_fontx(rawfont32, font.nchars, forcedheight or font.height)
  if err then
    prinf("pio_fontx: %s\n", err)
  end
end

function setfont_force(font)
  setfont(font, font.height-1)
  setfont(font)
end



--% «vcsatoBIGstring»  (to ".vcsatoBIGstring")
--% (find-k22file "drivers/char/vc_screen.c" "4 bytes lines,columns,x,y")
--% (find-angg "MTA/vtutilsh.c" "vcsa2pnmdata")
--% (find-angg "MTA/vtutil" "vcsa2pnm")
--% (find-status "netpbm-dev")
--% (find-vldifile "netpbm-dev.list")
--% (find-man "5 ppm")

vcsa_colors = {
   [0]=" 0 0 0",  [1]=" 0 0 2",  [2]=" 0 2 0",  [3]=" 0 2 2",
   [4]=" 2 0 0",  [5]=" 2 0 2",  [6]=" 2 1 0",  [7]=" 2 2 2",
   [8]=" 1 1 1",  [9]=" 1 1 3", [10]=" 1 3 1", [11]=" 1 3 3",
  [12]=" 3 1 1", [13]=" 3 1 3", [14]=" 3 3 1", [15]=" 3 3 3",
}

function vcsatoBIGstr(vcsa, font, width, colors)
  local lines, columns, cursorx, cursory =
    strbyte(vcsa, 1), strbyte(vcsa, 2), strbyte(vcsa, 3), strbyte(vcsa, 4)
  local header = format("P3\n%d %d\n3\n", columns*width, lines*font.height) 
  local bigstr = ""
  local bigy, rowpairs, bigrowstr, scanline, rowstr, col, char, attr,
        charscanline, fg, bg, minirowstr, i, bit
  for bigy=0,lines-1 do
    rowpairs = strsub(vcsa, bigy*columns*2+5, (bigy+1)*columns*2+4)
    bigrowstr = ""
    for scanline=1,font.height do
      rowstr = ""
      for col=0,columns-1 do
	char = strbyte(rowpairs, col*2+1)
	attr = strbyte(rowpairs, col*2+2)
	-- px(char, scanline)
	charscanline = strbyte(font[char], scanline)
	bg = colors[rshift(attr, 4)]
	fg = colors[band(attr, 15)]
	minirowstr = ""
	for i,bit in bits do
	  if band(charscanline, bit) ~= 0 then
	    minirowstr = minirowstr .. fg
	  else
	    minirowstr = minirowstr .. bg
	  end
	end
	if width == 9 then
	  minirowstr = minirowstr .. bg
	end
	rowstr = rowstr .. minirowstr
      end
      bigrowstr = bigrowstr .. rowstr .. "\n"
    end
    bigstr = bigstr .. bigrowstr
  end
  return header .. bigstr
end

function loadfont(str)
  if strlen(str) < 1024 then
    str = readfile(expandfname(str))
  end
  if band(strlen(str), 255) == 0 then
    return rawfonttofont(str)
  elseif band(strlen(str), 255) == 4 then
    return psftofont(str)
  end
  printf("loadfont: str is not a font (len=%d\n)", strlen(str))
end

function savefont(font, ...)
  local i, fname
  for i=1,getn(arg) do
    fname = arg[i]
    if strsub(fname, -4) == ".psf" then
      writefile(expandfname(fname), fonttopsf(font))
      printf("Saved as psf:         %s\n", fname)
    elseif strsub(fname, -7) == ".matrix" then
      writefile(expandfname(fname), fonttobigstr(font, 0, 255))
      printf("Saved as text matrix: %s\n", fname)
    else
      writefile(expandfname(fname), fonttorawfont(font, font.height))
      printf("Saved as raw font:    %s\n", fname)
    end
  end
end




-- (find-luafile "README.rttpatch")
-- (find-luanode "For Statement")
-- (find-luanode "strbyte")

--% «e_scripts»  (to ".e_scripts")
E_SCRIPTS = [[
#*
cd ~/vtutil/
dllua inc.lua vtutil.lua mathchars.lua \
  -e 'font850=loadfont("ega1.8")' makefonts_8.lua
#*
cd ~/vtutil/
dllua inc.lua vtutil.lua -e 'setfont(loadfont("latin.8"))'
#*
cd ~/vtutil/
dllua inc.lua vtutil.lua -e 'setfont_force(loadfont("latin.8"))'
#*
lua ~/vtutil/inc.lua ~/vtutil/vtutil.lua \
  -e 'savefont("foo.psf"); savefont("aa")'
#*
lua ~/vtutil/inc.lua ~/vtutil/vtutil.lua \
  -e "print(fonttobigstr(rawfonttofont(readfile(\"$HOME/MTA/math1.8\"), 256, 8), 0, 255))"
#*
lua ~/vtutil/inc.lua ~/vtutil/vtutil.lua \
  -e "print(fonttobigstr(psftofont(readfile(\"$HOME/MTA/math1.8.psf\")), 0, 255))"
#*
lua ~/vtutil/inc.lua ~/vtutil/vtutil.lua \
  -e 'px(bigstrtorawarr(demo_bigstr))' |& l
#*
# (find-angg "LUA/pio_fontx.c")
cd ~/vtutil/; gcc -g -Wall -shared -o pio_fontx.so pio_fontx.c
#*
dllua ~/vtutil/inc.lua ~/vtutil/vtutil.lua \
  -e "setfont(psftofont(readfile(\"$HOME/vtutil/math1.8.psf\")))"
#*
lua ~/vtutil/inc.lua ~/vtutil/vtutil.lua \
  -e 'writefile("/tmp/v.ppm",
		vcsatoBIGstr(readfile("/dev/vcsa4"),
			     psftofont(readfile("/home/root/MTA/ega1.8.psf")),
			     9, vcsa_colors))'
#*
pnmtopng < /tmp/v.ppm > /tmp/v.png
#*
cd ~/vtutil/
lua inc.lua vtutil.lua -e '
  px(split_clines(2, "A B C", "a b c", "D E F", "d e f"))
'
#*
cd ~/vtutil/
dllua inc.lua vtutil.lua \
  -e 'write(vcsatounix(readfile("/debian/tmp/vcsa1")))'
#*
]]






--  Local Variables:
--  coding:               no-conversion
--  ee-anchor-format:     "«%s»"
--  ee-charset-indicator: "Ñ"
--  ee-comment-format:    "-- %s\n"
--  End: