If you want to display text in the 1x1 pixel resolution "graphics" screen, a method to map a font definition table into pixels in the screen is needed. I developed a preliminary Batch-JScript hybrid version of such method as a prototype before write the assembler .exe final version. The result is very good:
The prototype version use a simple one-byte wide table for the font definition, so all characters are 8-pixels wide although they may have any height size. Joseph Gil's
fntcol16.zip package is a collection with 280 files of such simple font definition tables, although many of them have the same characters in 32-127 range and just a few different characters in the high range; previous image was created using VGA-ROM.F08, VGA-ROM.F14 and VGA-ROM.F16 files from such collection. The final version of the show text routine will use .FNT format files instead that have not restrictions in the font size. Currently exist programs to convert .FON and .TTF files into .FNT ones.
DaFont.com is a site with more than 23,000 fonts divided in a large range of themes where you can download .FON and .TTF font files.
The image below show a few of the fonts included in fntcol16.zip collection.
The code of the program that create previous images is included below. Of course, you must previously download and extract the *.F## files from fntcol16.zip collection in order for this program to work.
Code: Select all
@if (@CodeSection == @Batch) @then
@echo off
REM Example of LoadFont and ShowText prototype subroutines
REM Antonio Perez Ayala
setlocal DisableDelayedExpansion
set text= !"#$%%&'()*+,-./0123456789:;<=>?[\]^_{|}~
setlocal EnableDelayedExpansion
rem Define colors for Rainbow Bands
set prev=1
for %%a in (F E D C B A 9 8 7 6 5 4 3 2 1) do (
set "band[/!prev!]=/%%a"
set "prev=%%a"
)
set "myself=%~F0"
if not exist CursorPos.exe call :ExtractBinaryFile CursorPos.exe
rem Draw first example screen (sizes and colors)
cls
call :LoadFont VGA-ROM.F16 32 127
call :ShowText "You may show text in the 1x1 pixel size text screen: "
call :ShowText V:text
for /L %%i in (1,1,%fontSize%) do echo/
call :ShowText "The size of the text may be adjusted by an horizontal and"
call :ShowText "vertical factors that are applied to the base font size:"
for /L %%i in (1,1,8) do echo/
call :ShowText /S:3x4 "16:3x4" /S:2x4 " 2x4" /S:1x4 " 1x4 " /S:3x3 "3x3" /S:2x3 " 2x3" /S:1x3 " 1x3 " /S:2x2 "2x2" /S:1x2 " 1x2"
set /A adjust=fontSize*3/2
CursorPos 480 -%adjust%
call :ShowText /S:1x1 "1x1"
CursorPos 0 +6
call :LoadFont VGA-ROM.F14 48 120
call :ShowText /S:3x4 "14:3x4" /S:2x4 " 2x4" /S:1x4 " 1x4 " /S:3x3 "3x3" /S:2x3 " 2x3" /S:1x3 " 1x3 " /S:2x2 "2x2" /S:1x2 " 1x2"
set /A adjust=fontSize*3/2
CursorPos 480 -%adjust%
call :ShowText /S:1x1 "1x1"
CursorPos 0 +12
call :LoadFont VGA-ROM.F08 48 120
call :ShowText /S:3x4 "08:3x4" /S:2x4 " 2x4" /S:1x4 " 1x4 " /S:3x3 "3x3" /S:2x3 " 2x3" /S:1x3 " 1x3 " /S:2x2 "2x2" /S:1x2 " 1x2"
set /A adjust=fontSize*3/2
CursorPos 480 -%adjust%
call :ShowText /S:1x1 "1x1"
CursorPos 0 +16
call :LoadFont VGA-ROM.F14 65 122
call :ShowText /S:2x3 "You may also show text with"
call :ShowText /E "D" /1 "I" /D "F" /2 "F" /C "E" /3 "R" /B "E" /4 "N" /A "T " /7 "C" /5 "O" /9 "L" /6 "O" /8 "R" /F "S" /S:1x3 /7 " or " /S:2x3 /RB "RAINBOW " "BANDS"
for /L %%i in (1,1,4) do echo/
call :ShowText /S:1x1 /7 "Press any key when ready . . ."
pause > NUL
rem Draw second example screen (fonts)
cls
call :LoadFont INVERTED.F14 32 116
CursorPos 50 0
call :ShowText /S:2x2 "41F.DETREVNI si tnof sihT"
call :LoadFont COMPUTER.F14 32 116
CursorPos 30 30
call :ShowText /S:2x2 "This font is COMPUTER.F14"
call :LoadFont FRACTUR.F14 32 116
CursorPos 50 +8
call :ShowText /S:2x2 "This font is FRACTUR.F14"
call :LoadFont ITALICS.F14 32 116
CursorPos 75 +8
call :ShowText /S:2x2 "This font is ITALICS.F14"
call :LoadFont THAI.F14 32 116
CursorPos 100 +8
call :ShowText /S:2x2 "This font is THAI.F14"
call :LoadFont THIN.F10 32 122
CursorPos 100 +0
call :ShowText "(Previous font is THAI.F14, this one is THIN.F10)"
call :LoadFont PC.F24 32 116
CursorPos 150 +8
call :ShowText /S:2x2 "This font is PC.F24"
call :LoadFont SCRIPT.F14 32 116
CursorPos 125 +8
call :ShowText /S:2x2 "This font is SCRIPT.F14"
call :LoadFont SQUARE.F12 32 116
CursorPos 100 +8
call :ShowText /S:2x2 "This font is SQUARE.F12"
call :LoadFont MEDIEVAL.F14 32 116
CursorPos 75 +8
call :ShowText /S:2x2 "This font is MEDIEVAL.F14"
call :LoadFont BACKWARD.F14 32 116
CursorPos 50 +8
call :ShowText /S:2x2 "41F.DRAWKCAB si tnof sihT"
call :LoadFont SIDE.F10 32 116
CursorPos 8 2
call :ShowText /S:2x2
for %%a in (0 1 F . E D I S " " t n o f " " s i h T) do (
CursorPos 8 +0
call :ShowText "%%~a"
)
pause > NUL
cls
goto :EOF
:LoadFont fontFile.F## firstChar lastChar
if "%~3" equ "" echo ERROR - Bad syntax, should be: :LoadFont fontFile.F## firstChar lastChar & exit /B 1
if not exist "%~1" echo ERROR - Font file not found: %1 & exit /B 2
set fontSize=%~1
set fontSize=%fontSize:~-2%
if %fontSize:~0,1% equ 0 set fontSize=%fontSize:~1%
set /A char=%2, byte=1
for /F %%a in ('Cscript //nologo //E:JScript "%~F0" LoadFont "%~1" %fontSize% %2 %3') do (
set "font[!char!][!byte!]=%%a"
set /A byte+=1
if !byte! gtr %fontSize% set /A char+=1, byte=1
)
rem Reset global font parameters
set "color="
set "rb="
set /A horSize=verSize=1
exit /B
ShowText [/S:hXv] [/bf] "Text"
[/S:hXv] Font size: horizontal pixels are displayed H times, vertical pixels V times.
[/bf] Color attribute, see: COLOR /? You may use /RB for Rainbow Bands.
"Text" String to show in quotes, or V:varName with no quotes.
Several groups of {[/Size] [/BF] "Text"} may be given in the same :ShowText invocation,
in this case all Text's are displayed in the same "line".
When :ShowText ends, the cursor is placed at beginning of the "next line" (like ECHO command).
The last Size/Color values are preserved between :ShowText invocations.
:ShowText [/S:hXv] [/bf] "Text"
set lastPos=0
:nextParam
rem Process /Size switch
set "param=%~1"
if /I "%param:~0,2%" equ "/S" (
for /F "tokens=2,3 delims=:X" %%a in ("%param:x=X%") do set /A horSize=%%a, verSize=%%b
shift
)
rem Process /BF color switch
set "param=%~1"
if "%param:~0,1%" equ "/" (
set "color=%~1"
if /I "%~1" equ "/RB" (
set "color=/1"
set rb=true
) else (
set "rb="
)
shift
)
rem Get the start position of first scan line
CursorPos
set startPos=%errorlevel%
set "endPos="
rem Show each font scan line of the string, from top to bottom
for /F "delims=" %%a in ('Cscript //nologo //E:JScript "%myself%" StringFontLines "%~1"') do (
for /L %%i in (1,1,%verSize%) do (
ColorChar !color! "%%a"
if not defined endPos (
rem Get the end position of (first scan line of) this string
CursorPos
set endPos=!errorlevel!
)
rem Set cursor position to start point of next scan line
set /A "startPos+=1<<16"
CursorPos !startPos!
)
if defined rb for %%c in ("!color!") do set "color=!band[%%~c]!"
)
if %startPos% gtr %lastPos% set lastPos=%startPos%
rem Set cursor position to end of this string
CursorPos %endPos%
shift
if "%~1" neq "" goto nextParam
rem Set cursor position to beginning of "next line"
CursorPos %lastPos%
echo/
exit /B
rem Extract Binary File from hexadecimal digits placed in a "resource" in this .bat file
:ExtractBinaryFile filename.ext
setlocal EnableDelayedExpansion
set "start="
set "end="
for /F "tokens=1,3 delims=:=>" %%a in ('findstr /N /B "</*resource" "%~F0"') do (
if not defined start (
if "%%~b" equ "%~1" set start=%%a
) else if not defined end set end=%%a
)
(for /F "skip=%start% tokens=1* delims=:" %%a in ('findstr /N "^" "%~F0"') do (
if "%%a" == "%end%" goto decodeHexFile
echo %%b
)) > "%~1.hex"
:decodeHexFile
< "%~1.hex" Cscript //nologo //E:JScript "%~F0" Extract "%~1"
del "%~1.hex"
exit /B
<resource id="CursorPos.exe">
4d5a900003[3]04[3]ffff[2]b8[7]40[35]b0[3]0e1fba0e00b409cd21b8014ccd21546869732070726f6772616d2063616e6e6f74206265207275
6e20696e20444f53206d6f64652e0d0d0a24[7]55b5b8fd11d4d6ae11d4d6ae11d4d6ae9fcbc5ae18d4d6aeedf4c4ae13d4d6ae5269636811d4d6ae
[8]5045[2]4c010200eb84e24f[8]e0000f010b01050c0002[3]02[7]10[3]10[3]20[4]40[2]10[3]02[2]04[7]04[8]30[3]02[6]03[5]10[2]10
[4]10[2]10[6]10[11]1c20[2]28[84]20[2]1c[27]2e74657874[3]4201[3]10[3]02[3]02[14]20[2]602e7264617461[2]f6[4]20[3]02[3]04[14]
40[2]40[8]e806[3]50e81301[2]558bec83c4e06af5e81201[2]8945fc8d45e650ff75fce8fd[3]668b45ec668945e4e8bc[3]e8db[3]803e007505
8b45eaeb5c803e3d750646e8c6[3]668b4deae84a[3]8945eae8b5[3]803e007418803e2c750646e8a5[3]668b4de4e829[3]668945ec8b5dea53ff
75fce8ae[3]8d45e650536a018d45e350ff75fce895[3]0fb645e3c9c333c032db33d28a164680fa2b740880fa2d750980cb0280cb018a164680fa30
720f80fa39770a80ea306bc00a03c2ebe9f6c301740bf6c302740366f7d86603c14ec3[13xcc]e847[3]8bf08a06463c2275098a06463c2275f9eb0c
8a06463c20740484c075f54ec38a06463c2074f94ec3ccff2514204000ff2500204000ff2504204000ff2508204000ff250c204000ff25102040[191]
6e20[2]8c20[2]9c20[2]ba20[2]d620[2]6020[6]4420[10]e820[3]20[22]6e20[2]8c20[2]9c20[2]ba20[2]d620[2]6020[6]9b004578697450
726f6365737300f500476574436f6e736f6c6553637265656e427566666572496e666f[2]6a0147657453746448616e646c65[2]380252656164436f
6e736f6c654f757470757443686172616374657241006d02536574436f6e736f6c65437572736f72506f736974696f6e[2]e600476574436f6d6d61
6e644c696e6541006b65726e656c33322e646c6c[268]
</resource>
@end
// JScript section
if ( WScript.Arguments(0) == "LoadFont" ) {
// LoadFont fontFile.F## fontSize firstChar lastChar
var adjustment = "\u20AC\u0081\u201A\u0192\u201E\u2026\u2020\u2021" +
"\u02C6\u2030\u0160\u2039\u0152\u008D\u017D\u008F" +
"\u0090\u2018\u2019\u201C\u201D\u2022\u2013\u2014" +
"\u02DC\u2122\u0161\u203A\u0153\u009D\u017E\u0178" ;
ado = WScript.CreateObject("ADODB.Stream");
ado.Type = 2; // adTypeText = 2
ado.CharSet = "iso-8859-1"; // code page with minimum adjustments for input
ado.Open();
ado.LoadFromFile(WScript.Arguments(1));
var font = ado.ReadText(),
fontSize = parseInt(WScript.Arguments(2)),
firstChar = parseInt(WScript.Arguments(3)) * fontSize,
lastChar = (parseInt(WScript.Arguments(4))+1) * fontSize;
for ( var i = firstChar; i < lastChar; i++ ) {
var code = font.charCodeAt(i);
if ( code > 255 ) code = 128 + adjustment.indexOf(font.charAt(i));
WScript.Stdout.WriteLine(code);
}
} else if ( WScript.Arguments(0) == "StringFontLines" ) {
// StringFontLines string
var string = WScript.Arguments(1),
EnvVar = WScript.CreateObject("WScript.Shell").Environment("PROCESS"),
fontSize = parseInt(EnvVar("fontSize")),
horSize = parseInt(EnvVar("horSize"));
if ( string.substr(0,2) == "V:" ) string = EnvVar(string.substr(2));
// Assemble and output each font scan line of the string, from top to bottom
for ( var y = 1; y <= fontSize; y++ ) {
// Each scan line is comprised of all characters in the string
var line = "";
for ( var x = 0; x < string.length; x++ ) {
// Get the font byte of this character and scan line
var byte = EnvVar("font["+string.charCodeAt(x)+"]["+y+"]");
// Each byte contain 8 pixels (bits), from MSB to LSB
for ( var bit = 1<<7; bit; bit >>= 1 ) {
var pixel = (byte&bit) ? "X" : " ";
for ( var i = 1; i <= horSize; i++ ) line += pixel;
}
}
WScript.Stdout.WriteLine(line);
}
} else if ( WScript.Arguments(0) == "Extract" ) {
// Extract a hexadecimal "resource" into a binary file
// Convert Ascii hexadecimal digits from Stdin to a binary string
var count, byte, output = "";
while ( !WScript.Stdin.AtEndOfStream ) {
var input = WScript.Stdin.ReadLine();
for ( var index = 0; index < input.length; ) {
if ( input.charAt(index) == '[' ) {
for ( count = ++index; input.charAt(index) != 'x' &&
input.charAt(index) != ']' ; index++ ) ;
count = parseInt(input.slice(count,index++));
if ( input.charAt(index-1) == 'x' ) {
byte = String.fromCharCode(parseInt(input.substr(index,2),16));
index += 3;
} else {
byte = String.fromCharCode(0);
}
for ( var i = 1; i <= count; i++ ) output += byte;
} else {
output += String.fromCharCode(parseInt(input.substr(index,2),16));
index += 2;
}
}
}
// Write the binary string to the output file
var ado = WScript.CreateObject("ADODB.Stream");
ado.Type = 2; // adTypeText = 2
ado.CharSet = "iso-8859-1"; // right code page for output (no adjustments)
ado.Open();
ado.WriteText(output);
ado.SaveToFile(WScript.Arguments(1),2); // adSaveCreateOverWrite = 2
ado.Close();
}
IMPORTANT: Previous program must run in a MS-DOS command-line window with the Terminal 1x1 font installed and requires ColorChar.exe auxiliary program, as described in the first post of this thread; these requirements will be fulfilled when you successfully draw the Mandelbrot Set at any resolution. This example program was adjusted for 512x384 screen resolution, but it will also show correct results in larger resolutions although with apparently smaller characters.
Antonio