<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://wiki.thedarkmod.com/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Geep</id>
	<title>The DarkMod Wiki - User contributions [en]</title>
	<link rel="self" type="application/atom+xml" href="https://wiki.thedarkmod.com/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Geep"/>
	<link rel="alternate" type="text/html" href="https://wiki.thedarkmod.com/index.php?title=Special:Contributions/Geep"/>
	<updated>2026-05-02T15:41:38Z</updated>
	<subtitle>User contributions</subtitle>
	<generator>MediaWiki 1.45.3</generator>
	<entry>
		<id>https://wiki.thedarkmod.com/index.php?title=ExportUnicodeFontToDoom3&amp;diff=34466</id>
		<title>ExportUnicodeFontToDoom3</title>
		<link rel="alternate" type="text/html" href="https://wiki.thedarkmod.com/index.php?title=ExportUnicodeFontToDoom3&amp;diff=34466"/>
		<updated>2026-04-01T00:42:21Z</updated>

		<summary type="html">&lt;p&gt;Geep: /* Relationship to Other Parameters */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;By Geep, 2025&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
== Introduction ==&lt;br /&gt;
&lt;br /&gt;
In 2025, kalinovka in [https://forums.thedarkmod.com/index.php?/topic/22736-font-localization Font localization] sought to extend TDM’s Mason 48pt font, used in the main menu, to include missing Cyrillic glyphs. This would allow this font to be used in an FM and still support a Russian translation.&lt;br /&gt;
&lt;br /&gt;
This offshoot of [https://wiki.thedarkmod.com/index.php?title=ExportFontToDoom3 ExportFontToDoom3All256] is a generalized response to that. The main idea to select an input TTF font that includes not just ASCII or ANSI, but offers additional Unicode characters, like Cyrillic. The program still limits output to a maximum of 256 characters, consistent with the DAT format.&lt;br /&gt;
&lt;br /&gt;
To achieve this, it reads in an external human-readable &amp;quot;unicodeMap&amp;quot; file, in Unicode.org’s &amp;quot;Format A&amp;quot;. This format provides a mapping from the traditional 8-bit encoding that TDM uses to the corresponding UCS (Unicode 16-bit) value. Unicode.org provides stock files for standard ISO and Windows 8-bit encodings. Of specific interest here is [https://www.unicode.org/Public/MAPPINGS/VENDORS/MICSFT/WINDOWS/CP1251.TXT cp1251.txt for Cyrillic]. This requires just trivial editing for [https://wiki.thedarkmod.com/index.php?title=I18N_-_Charset TDM-specific codepoints]. As discussed below, you can further edit a unicodeMap file in advance, if you want to generate just a subset of glyphs.&lt;br /&gt;
&lt;br /&gt;
More broadly, this program supersedes ExportFontToDoom3 and ExportFontToDoom3All256.&lt;br /&gt;
&lt;br /&gt;
== New Command Line Arguments ==&lt;br /&gt;
&lt;br /&gt;
These are in-addition to those of [https://wiki.thedarkmod.com/index.php?title=ExportFontToDoom3 ExportFontToDoom3All256].&lt;br /&gt;
&lt;br /&gt;
=== unicodeMap &amp;lt;file&amp;gt; ===&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
 -unicodeMap &amp;quot;./Test/cp1251.txt&amp;quot;&lt;br /&gt;
&lt;br /&gt;
You can edit the unicodeMap file in advance, to specify which particular glyphs you want to generate by suppressing unwanted glyphs, either by:&lt;br /&gt;
&lt;br /&gt;
* Deleting an unwanted line (or block of lines) entirely, or&lt;br /&gt;
* Prepending a &amp;quot;#&amp;quot; to comment-out the line.&lt;br /&gt;
&lt;br /&gt;
Also, this file format allows the Unicode value (e.g., &amp;quot;0x1234&amp;quot;) to be replaced by 6 space characters, when the ISO or Windows standard leaves that character undefined.&lt;br /&gt;
&lt;br /&gt;
In all 3 of those cases, every suppressed character in the output DAT file will be represented by the glyph that the font uses for U+0000. A hollow box is common.&lt;br /&gt;
&lt;br /&gt;
IMPORTANT: If you edit lines, the remaining active glyph lines MUST be in ascending order by the 2-hex-digit codepoint value that starts each line. Otherwise, results will go astray.&lt;br /&gt;
&lt;br /&gt;
=== startFileNumber &amp;lt;n&amp;gt; ===&lt;br /&gt;
When a set of TGA/DDS files are generated for a particular font size, by default the first file&#039;s name contains _0_, which increments for additional files. You can optionally specify a different 1- or 2-digit start number, e.g., &amp;quot;-startFileNumber 7&amp;quot;. Why? Because...&lt;br /&gt;
&lt;br /&gt;
* the file(s) you are generating are supplemental to, not replacements for, existing TGA/DDS files; and&lt;br /&gt;
* in this run, you are generating just one of the 3 possible font sizes (assuming each size has a different count of existing TGA/DDS files).&lt;br /&gt;
&lt;br /&gt;
When you generate a supplemental set, the new DAT file has no knowledge of what&#039;s in the original set and its DAT file. You will have to interleave-edit the old and new DAT files (e.g., with reFont&#039;s REF files) to create a single DAT file spanning old and new glyphs. There may be a redundant NULL glyph in your new TGA set; just ignore it.&lt;br /&gt;
&lt;br /&gt;
=== awayFromEdge &amp;lt;n&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
Allows specifying in positive integer pixels (e.g., &amp;quot;-awayFromEdge 2&amp;quot;) a small extra boundary at the top and left edges of the overall bitmap. This is for fonts like Mason where extra space (typically 2 pixels) is needed around every character to create a &amp;quot;glow variant&amp;quot;. Routine glyph layout provides usually enough space for this except at the top and (arguably) left edges. See also the &amp;quot;compact&amp;quot; parameter.&lt;br /&gt;
&lt;br /&gt;
Note: The spacing value is relative to 256x256 bitmaps. If you specify &amp;quot;hirez&amp;quot;, then for proportionality, your specified value is doubled internally when laying out the 512x512 bitmaps.&lt;br /&gt;
&lt;br /&gt;
=== compact ===&lt;br /&gt;
If specified (i.e, &amp;quot;-compact&amp;quot;), packs the character glyphs more closely together. Particularly recommended for 48pt fonts; it will generate roughly half the files.&lt;br /&gt;
&lt;br /&gt;
Whether &amp;quot;compact&amp;quot; is specified or not, packing is controlled by simply &amp;quot;padding&amp;quot; each glyph’s bounding box. Specifically, this doesn’t change the bounding box, but adds pixel &amp;quot;padding&amp;quot; to just the right and bottom of the bounding box, a simple though asymmetric process. One reason for padding was given ExportFontToDoom3 author Grant Davies in code comments:&lt;br /&gt;
&lt;br /&gt;
&amp;quot;Because of the way Doom 3 Indexes the texture page (using floating point numbers), it is unable to reference exact pixels – there is error. How much error, I don’t know. For this reason, the rectangles needs to be padded out.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Geep suspects that such error with the TDM engine is not really a problem. Likely some error in the past was due to editing with Q3Font and its low floating-point precision. Nevertheless, some padding is good because:&lt;br /&gt;
&lt;br /&gt;
* For the Mason font, 2 pixels around each glyph are needed for &amp;quot;glow&amp;quot; effects (either done as a separate smudge font for /english/ or as a bidirection offset effect for /russian/.)&lt;br /&gt;
* Keeping glyphs separated improves visualization of boundaries with datBounds, and makes editing tweaks easier.&lt;br /&gt;
&lt;br /&gt;
The &amp;quot;compact&amp;quot; setting restores Grant Davies&#039; first algorithm, which just pads the bounding box by 5 pixels to the right and 5 pixels below.&lt;br /&gt;
&lt;br /&gt;
Without &amp;quot;compact&amp;quot;, the default is Grant Davies&#039; second algorithm found in ExportFontToDoom3 v1.02. This likewise first pads each bounding box by 5 pixels to the right and 5 pixels below. It then further pads to make both the width and height a factor of 2; this makes 48pt quite sparse.  (It is possible this improved rendering performance in 2005; not important now. Also, in practice for major fonts, much of this &amp;quot;factor of 2&amp;quot; spacing was overridden by subsequent Font Patcher work.)&lt;br /&gt;
&lt;br /&gt;
=== hirez or hires ===&lt;br /&gt;
&#039;&#039;Added with v1.1, March 2026&#039;&#039; &lt;br /&gt;
&lt;br /&gt;
Instead of 256x256 bitmaps (and associated DAT), this exports double-sized 512x512 bitmaps with larger, thus potentially-crisper glyphs. (TDM has had a few such 512x512 bitmaps for redrawn fonts since 2014.) Specifically, it: &lt;br /&gt;
* outputs requested 512x512 TGAs and their DAT(s).&lt;br /&gt;
* internally, doubles the pointsize requested of the TTF, resulting in 2x character glyph sizes. Because both the container bitmap and each glyph is (nominally) doubled in size, the [0...1] s, s2, t, t2 values stored in the DAT would be very similar to those for a 256x256 bitmap.&lt;br /&gt;
* Other DAT layout metrics remain as if scaled to a 256x256 layout:&lt;br /&gt;
** imageHeight&lt;br /&gt;
** imageWidth&lt;br /&gt;
** skip&lt;br /&gt;
** top (with bottom ignored as usual)&lt;br /&gt;
** pitch&lt;br /&gt;
&lt;br /&gt;
For example, if you request –hirez with a carleton font in just 24pt type, it will create 512x512 files with usual names like carleton_0_24.tga, etc., and fontimage_24.dat, with the console showing “Exporting carleton 24pt”.&lt;br /&gt;
But internally, 48pt characters are drawn on the bitmaps. The imageHeight and imageWidth metrics will be as if the requested 24pt size was generated, so in effect causing the game engine to scale down by a factor of 2 from the 48pt glyph.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;TIPS on Using a HiRez DAT file&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
If subsequently using Refont to make a REF file from this DAT, add the “scaling_ok” option, to suppress otherwise voluminous console warnings about per-character scaling.&lt;br /&gt;
&lt;br /&gt;
If you further plan to generate bounds visualizations with datBounds:&lt;br /&gt;
* For 512x512 bitmaps, you must generate from the REF file, not directly from DAT.&lt;br /&gt;
* Be sure to first edit the REF to add headers of the form:&lt;br /&gt;
&lt;br /&gt;
 # bitmap_&amp;lt;n&amp;gt;_size=512&lt;br /&gt;
 &lt;br /&gt;
  , where &amp;lt;n&amp;gt; is 0 to 9, and refers to shaders present in the REF file with names like, e.g., carleton_3_48.tga; n would be 3 for this.&lt;br /&gt;
&lt;br /&gt;
* datBounds also has a worthwhile “scaling_ok” option.&lt;br /&gt;
* Uncommonly, the raw_metrics option may be of interest.&lt;br /&gt;
&lt;br /&gt;
=== bolding &amp;lt;n&amp;gt; ===&lt;br /&gt;
&#039;&#039;Added with v1.1, March 2026&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Sometimes, a TTF font does not offer a “bold” variant, or, more generally, a font’s overall stroke thickness is not ideal. It is possible to alter character outlines, then render those as bitmap glyphs.&lt;br /&gt;
The result is usually better than post-bitmap thickening or thinning. The FreeType library offers an embolding function for outline alteration, used here.&lt;br /&gt;
&lt;br /&gt;
The integer parameter &amp;lt;n&amp;gt; is in units of 1/64th pixel. A positive value adjusts the outline to embolden the character. Negative thins. The change affects both the overall height and width of the outline.&lt;br /&gt;
You may think of the left and bottom character borders as unchanged. The allowed range of &amp;lt;n&amp;gt; is from -128 (i.e., -2 pixels) to 256 (4 pixels). The -2 limit is arbitrary, but for sanity. The 4 limit is the maximum FreeType permits.&lt;br /&gt;
&lt;br /&gt;
Caution: The adjustment algorithm moves the outline controls points, but doesn&#039;t change the number of such points;&lt;br /&gt;
this means that certain situations like acute angles or intersections are sometimes handled incorrectly.&lt;br /&gt;
&lt;br /&gt;
=== inPlace &amp;lt;filename of input layout file&amp;gt; ===&lt;br /&gt;
&#039;&#039;This experimental feature, new in v 1.2, reads a DAT file for input layout. It may be extended to REF and FTN filetypes in the future. Specifications are subject to change.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Rather than having an algorithm decide where each glyph should go within a set of bitmaps, this option lets a pre-existing layout file determine it. This is designed to be used with only one point size at a time, so deploy it in conjunction with the “-size” parameter.&lt;br /&gt;
This is helpful in building up aligned layers in a GIMP file, particularly as a step in making a “hybrid” or composite TDM font from multiple sources.&lt;br /&gt;
This forces a particular layout, great as a “first draft”, but improvable with further bitmap and DAT editing. You can expect some glyph collisions will occur; perhaps incrementally manage this by suppressing some glyphs with a custom unicodeMap?&lt;br /&gt;
&lt;br /&gt;
====File Generation &amp;amp; Naming====&lt;br /&gt;
The number of TGA files created, and their names, and their references in the output DAT, will exactly match that specified by the input layout file.&lt;br /&gt;
To avoid confusion or name conflict between input and output layout files, either rename the input file, e.g., from “fontimage_24.dat” to “fontimage_24_in.dat”, or place the input layout file in a separate child directory, e.g., “placeAt/fontimage_24.dat”&lt;br /&gt;
&lt;br /&gt;
====Glyph Alignment &amp;amp; Placement====&lt;br /&gt;
During placement, for each glyph, only 4 input DAT values are used:&lt;br /&gt;
* s&lt;br /&gt;
* t&lt;br /&gt;
* top&lt;br /&gt;
* shaderName&lt;br /&gt;
&lt;br /&gt;
The rest are derived from the TTF file, as influenced by other command-line parameters. Specifically, an output glyph is aligned with the baseline and left-boundary of the corresponding input glyph. That is, the upper-left origin of the output glyph is given by (s, t+top_input-top_TTF), placed into bitmap “shaderName”. (Exception: Negative origin coordinates are replaced by zero.) Aligning vertically by baseline in this way seemed more helpful than aligning by t value alone.&lt;br /&gt;
&lt;br /&gt;
If a codepoint requested by the input DAT has no glyph in the TTF, this codepoint will be skipped during output, i.e., no empty box is generated in its place... because the empty box just gets in the way during subsequent GIMP work. Exception: Codepoint 0x0000 does generate an empty box.&lt;br /&gt;
&lt;br /&gt;
====Relationship to Other Parameters====&lt;br /&gt;
These are required:&lt;br /&gt;
* The input TTF filename (in addition to inPlace&#039;s input layout file; as noted, the contents of the latter file will determine what TGA files are generated.)&lt;br /&gt;
* The size &amp;lt;fontsize&amp;gt; option. As usual, this will determine the font size requested from the TTF file, as well as the name of the output fontImage_&amp;lt;filesize&amp;gt;.dat file. However, unlike the usual case, not the naming of the output TGA files.&lt;br /&gt;
&lt;br /&gt;
These options are optional:&lt;br /&gt;
* unicodeMap &amp;lt;filename&amp;gt;&lt;br /&gt;
* hirez [with DAT file as input, to generate 512x512 output files; situation may change with future REF file.]&lt;br /&gt;
* bolding &amp;lt;value&amp;gt;&lt;br /&gt;
* name &amp;lt;alternative font name&amp;gt;. As usual, this will name the (generated if necessary) folder into which output files are placed. However, unlike the usual case, the naming of the output TGA files will be as given in the input DAT file.&lt;br /&gt;
&lt;br /&gt;
These options are ignored, by design:&lt;br /&gt;
* compact [whether present or absent; no algorithimic layout applied.]&lt;br /&gt;
* awayFromEdge &amp;lt;value&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This option is probably problematic and should be avoided for now:&lt;br /&gt;
* startFileNumber&lt;br /&gt;
&lt;br /&gt;
== Changed Behavior for Font Title from ExportFontToDoom3All256 ==&lt;br /&gt;
In ExportFontToDoom3All256, if the font title was more that 20 characters long, it would truncate it to fit in the DAT file as part of the shader names (i.e., paths to TGA files). But this threshold was wrong. Now, truncation and a warning happens if the font title is more that 17 characters long (or 16 if generated TGAs include any with a 2-digit count instead of 1-digit). If truncation occurs, the user is asked to consider using or revising the -name argument.&lt;br /&gt;
&lt;br /&gt;
== Downloads ==&lt;br /&gt;
Release v1.2 of 2025-03-31 &#039;&#039;(which adds inPlace option; makes clearer a command-line message about xOffset and pitch).&#039;&#039;&lt;br /&gt;
* [https://drive.google.com/file/d/1CG_BXsTTYi7E3nQPKtBWi-94Cj3R5eOY/view?usp=sharing ExportUnicodeFontToDoom3_release_1_2_exe.zip] . Windows binary and required archived versions of FreeType and DevIL DLLs.&lt;br /&gt;
* [https://drive.google.com/file/d/1Nw4RdKKx2YHoPR6D-YQzdnEFx-vyYUhk/view?usp=sharing ExportUnicodeFontToDoom3_release_1_2_source_project.zip] . The C++ project file with source code, including source &amp;amp; build project of archived library.&lt;br /&gt;
&lt;br /&gt;
Release v1.1 of 2025-03-03:&lt;br /&gt;
* [https://drive.google.com/file/d/1f3Jj53qtJGIp0_mz7Riing9Fi8ESFDr5/view?usp=sharing ExportUnicodeFontToDoom3_release_1_1_exe.zip]&lt;br /&gt;
* [https://drive.google.com/file/d/1nutMBfcIWw63wNTUdnlnzP397tGVpnpd/view?usp=sharing ExportUnicodeFontToDoom3_release_1_1_source_project.zip] .&lt;br /&gt;
&lt;br /&gt;
Release 1 of 2024-09-10:&lt;br /&gt;
* [https://drive.google.com/file/d/1MqoOfhc5-ovoxoHfRquYAcIEdHEOJAQV/view?usp=sharing ExportUnicodeFontToDoom3_release_1_exe.zip]&lt;br /&gt;
* [https://drive.google.com/file/d/1Frk_byfdtCcMqdr27ulw1XyuFj8vYp9x/view?usp=sharing ExportUnicodeFontToDoom3_release_1_source_project.zip]&lt;br /&gt;
&lt;br /&gt;
== See Also ==&lt;br /&gt;
The Cyrillic coverage of Lora Regular TTF font, projected to used as Russian Mason supplement in TDM 2.14, may be viewed and font downloaded [https://www.fontsquirrel.com/fonts/lora?filter%5Bclassifications%5D%5B0%5D=serif&amp;amp;filter%5Blanguages%5D%5B0%5D=cyrillic#eula here].&lt;/div&gt;</summary>
		<author><name>Geep</name></author>
	</entry>
	<entry>
		<id>https://wiki.thedarkmod.com/index.php?title=ExportUnicodeFontToDoom3&amp;diff=34465</id>
		<title>ExportUnicodeFontToDoom3</title>
		<link rel="alternate" type="text/html" href="https://wiki.thedarkmod.com/index.php?title=ExportUnicodeFontToDoom3&amp;diff=34465"/>
		<updated>2026-04-01T00:41:57Z</updated>

		<summary type="html">&lt;p&gt;Geep: /* Relationship to Other Parameters */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;By Geep, 2025&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
== Introduction ==&lt;br /&gt;
&lt;br /&gt;
In 2025, kalinovka in [https://forums.thedarkmod.com/index.php?/topic/22736-font-localization Font localization] sought to extend TDM’s Mason 48pt font, used in the main menu, to include missing Cyrillic glyphs. This would allow this font to be used in an FM and still support a Russian translation.&lt;br /&gt;
&lt;br /&gt;
This offshoot of [https://wiki.thedarkmod.com/index.php?title=ExportFontToDoom3 ExportFontToDoom3All256] is a generalized response to that. The main idea to select an input TTF font that includes not just ASCII or ANSI, but offers additional Unicode characters, like Cyrillic. The program still limits output to a maximum of 256 characters, consistent with the DAT format.&lt;br /&gt;
&lt;br /&gt;
To achieve this, it reads in an external human-readable &amp;quot;unicodeMap&amp;quot; file, in Unicode.org’s &amp;quot;Format A&amp;quot;. This format provides a mapping from the traditional 8-bit encoding that TDM uses to the corresponding UCS (Unicode 16-bit) value. Unicode.org provides stock files for standard ISO and Windows 8-bit encodings. Of specific interest here is [https://www.unicode.org/Public/MAPPINGS/VENDORS/MICSFT/WINDOWS/CP1251.TXT cp1251.txt for Cyrillic]. This requires just trivial editing for [https://wiki.thedarkmod.com/index.php?title=I18N_-_Charset TDM-specific codepoints]. As discussed below, you can further edit a unicodeMap file in advance, if you want to generate just a subset of glyphs.&lt;br /&gt;
&lt;br /&gt;
More broadly, this program supersedes ExportFontToDoom3 and ExportFontToDoom3All256.&lt;br /&gt;
&lt;br /&gt;
== New Command Line Arguments ==&lt;br /&gt;
&lt;br /&gt;
These are in-addition to those of [https://wiki.thedarkmod.com/index.php?title=ExportFontToDoom3 ExportFontToDoom3All256].&lt;br /&gt;
&lt;br /&gt;
=== unicodeMap &amp;lt;file&amp;gt; ===&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
 -unicodeMap &amp;quot;./Test/cp1251.txt&amp;quot;&lt;br /&gt;
&lt;br /&gt;
You can edit the unicodeMap file in advance, to specify which particular glyphs you want to generate by suppressing unwanted glyphs, either by:&lt;br /&gt;
&lt;br /&gt;
* Deleting an unwanted line (or block of lines) entirely, or&lt;br /&gt;
* Prepending a &amp;quot;#&amp;quot; to comment-out the line.&lt;br /&gt;
&lt;br /&gt;
Also, this file format allows the Unicode value (e.g., &amp;quot;0x1234&amp;quot;) to be replaced by 6 space characters, when the ISO or Windows standard leaves that character undefined.&lt;br /&gt;
&lt;br /&gt;
In all 3 of those cases, every suppressed character in the output DAT file will be represented by the glyph that the font uses for U+0000. A hollow box is common.&lt;br /&gt;
&lt;br /&gt;
IMPORTANT: If you edit lines, the remaining active glyph lines MUST be in ascending order by the 2-hex-digit codepoint value that starts each line. Otherwise, results will go astray.&lt;br /&gt;
&lt;br /&gt;
=== startFileNumber &amp;lt;n&amp;gt; ===&lt;br /&gt;
When a set of TGA/DDS files are generated for a particular font size, by default the first file&#039;s name contains _0_, which increments for additional files. You can optionally specify a different 1- or 2-digit start number, e.g., &amp;quot;-startFileNumber 7&amp;quot;. Why? Because...&lt;br /&gt;
&lt;br /&gt;
* the file(s) you are generating are supplemental to, not replacements for, existing TGA/DDS files; and&lt;br /&gt;
* in this run, you are generating just one of the 3 possible font sizes (assuming each size has a different count of existing TGA/DDS files).&lt;br /&gt;
&lt;br /&gt;
When you generate a supplemental set, the new DAT file has no knowledge of what&#039;s in the original set and its DAT file. You will have to interleave-edit the old and new DAT files (e.g., with reFont&#039;s REF files) to create a single DAT file spanning old and new glyphs. There may be a redundant NULL glyph in your new TGA set; just ignore it.&lt;br /&gt;
&lt;br /&gt;
=== awayFromEdge &amp;lt;n&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
Allows specifying in positive integer pixels (e.g., &amp;quot;-awayFromEdge 2&amp;quot;) a small extra boundary at the top and left edges of the overall bitmap. This is for fonts like Mason where extra space (typically 2 pixels) is needed around every character to create a &amp;quot;glow variant&amp;quot;. Routine glyph layout provides usually enough space for this except at the top and (arguably) left edges. See also the &amp;quot;compact&amp;quot; parameter.&lt;br /&gt;
&lt;br /&gt;
Note: The spacing value is relative to 256x256 bitmaps. If you specify &amp;quot;hirez&amp;quot;, then for proportionality, your specified value is doubled internally when laying out the 512x512 bitmaps.&lt;br /&gt;
&lt;br /&gt;
=== compact ===&lt;br /&gt;
If specified (i.e, &amp;quot;-compact&amp;quot;), packs the character glyphs more closely together. Particularly recommended for 48pt fonts; it will generate roughly half the files.&lt;br /&gt;
&lt;br /&gt;
Whether &amp;quot;compact&amp;quot; is specified or not, packing is controlled by simply &amp;quot;padding&amp;quot; each glyph’s bounding box. Specifically, this doesn’t change the bounding box, but adds pixel &amp;quot;padding&amp;quot; to just the right and bottom of the bounding box, a simple though asymmetric process. One reason for padding was given ExportFontToDoom3 author Grant Davies in code comments:&lt;br /&gt;
&lt;br /&gt;
&amp;quot;Because of the way Doom 3 Indexes the texture page (using floating point numbers), it is unable to reference exact pixels – there is error. How much error, I don’t know. For this reason, the rectangles needs to be padded out.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Geep suspects that such error with the TDM engine is not really a problem. Likely some error in the past was due to editing with Q3Font and its low floating-point precision. Nevertheless, some padding is good because:&lt;br /&gt;
&lt;br /&gt;
* For the Mason font, 2 pixels around each glyph are needed for &amp;quot;glow&amp;quot; effects (either done as a separate smudge font for /english/ or as a bidirection offset effect for /russian/.)&lt;br /&gt;
* Keeping glyphs separated improves visualization of boundaries with datBounds, and makes editing tweaks easier.&lt;br /&gt;
&lt;br /&gt;
The &amp;quot;compact&amp;quot; setting restores Grant Davies&#039; first algorithm, which just pads the bounding box by 5 pixels to the right and 5 pixels below.&lt;br /&gt;
&lt;br /&gt;
Without &amp;quot;compact&amp;quot;, the default is Grant Davies&#039; second algorithm found in ExportFontToDoom3 v1.02. This likewise first pads each bounding box by 5 pixels to the right and 5 pixels below. It then further pads to make both the width and height a factor of 2; this makes 48pt quite sparse.  (It is possible this improved rendering performance in 2005; not important now. Also, in practice for major fonts, much of this &amp;quot;factor of 2&amp;quot; spacing was overridden by subsequent Font Patcher work.)&lt;br /&gt;
&lt;br /&gt;
=== hirez or hires ===&lt;br /&gt;
&#039;&#039;Added with v1.1, March 2026&#039;&#039; &lt;br /&gt;
&lt;br /&gt;
Instead of 256x256 bitmaps (and associated DAT), this exports double-sized 512x512 bitmaps with larger, thus potentially-crisper glyphs. (TDM has had a few such 512x512 bitmaps for redrawn fonts since 2014.) Specifically, it: &lt;br /&gt;
* outputs requested 512x512 TGAs and their DAT(s).&lt;br /&gt;
* internally, doubles the pointsize requested of the TTF, resulting in 2x character glyph sizes. Because both the container bitmap and each glyph is (nominally) doubled in size, the [0...1] s, s2, t, t2 values stored in the DAT would be very similar to those for a 256x256 bitmap.&lt;br /&gt;
* Other DAT layout metrics remain as if scaled to a 256x256 layout:&lt;br /&gt;
** imageHeight&lt;br /&gt;
** imageWidth&lt;br /&gt;
** skip&lt;br /&gt;
** top (with bottom ignored as usual)&lt;br /&gt;
** pitch&lt;br /&gt;
&lt;br /&gt;
For example, if you request –hirez with a carleton font in just 24pt type, it will create 512x512 files with usual names like carleton_0_24.tga, etc., and fontimage_24.dat, with the console showing “Exporting carleton 24pt”.&lt;br /&gt;
But internally, 48pt characters are drawn on the bitmaps. The imageHeight and imageWidth metrics will be as if the requested 24pt size was generated, so in effect causing the game engine to scale down by a factor of 2 from the 48pt glyph.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;TIPS on Using a HiRez DAT file&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
If subsequently using Refont to make a REF file from this DAT, add the “scaling_ok” option, to suppress otherwise voluminous console warnings about per-character scaling.&lt;br /&gt;
&lt;br /&gt;
If you further plan to generate bounds visualizations with datBounds:&lt;br /&gt;
* For 512x512 bitmaps, you must generate from the REF file, not directly from DAT.&lt;br /&gt;
* Be sure to first edit the REF to add headers of the form:&lt;br /&gt;
&lt;br /&gt;
 # bitmap_&amp;lt;n&amp;gt;_size=512&lt;br /&gt;
 &lt;br /&gt;
  , where &amp;lt;n&amp;gt; is 0 to 9, and refers to shaders present in the REF file with names like, e.g., carleton_3_48.tga; n would be 3 for this.&lt;br /&gt;
&lt;br /&gt;
* datBounds also has a worthwhile “scaling_ok” option.&lt;br /&gt;
* Uncommonly, the raw_metrics option may be of interest.&lt;br /&gt;
&lt;br /&gt;
=== bolding &amp;lt;n&amp;gt; ===&lt;br /&gt;
&#039;&#039;Added with v1.1, March 2026&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Sometimes, a TTF font does not offer a “bold” variant, or, more generally, a font’s overall stroke thickness is not ideal. It is possible to alter character outlines, then render those as bitmap glyphs.&lt;br /&gt;
The result is usually better than post-bitmap thickening or thinning. The FreeType library offers an embolding function for outline alteration, used here.&lt;br /&gt;
&lt;br /&gt;
The integer parameter &amp;lt;n&amp;gt; is in units of 1/64th pixel. A positive value adjusts the outline to embolden the character. Negative thins. The change affects both the overall height and width of the outline.&lt;br /&gt;
You may think of the left and bottom character borders as unchanged. The allowed range of &amp;lt;n&amp;gt; is from -128 (i.e., -2 pixels) to 256 (4 pixels). The -2 limit is arbitrary, but for sanity. The 4 limit is the maximum FreeType permits.&lt;br /&gt;
&lt;br /&gt;
Caution: The adjustment algorithm moves the outline controls points, but doesn&#039;t change the number of such points;&lt;br /&gt;
this means that certain situations like acute angles or intersections are sometimes handled incorrectly.&lt;br /&gt;
&lt;br /&gt;
=== inPlace &amp;lt;filename of input layout file&amp;gt; ===&lt;br /&gt;
&#039;&#039;This experimental feature, new in v 1.2, reads a DAT file for input layout. It may be extended to REF and FTN filetypes in the future. Specifications are subject to change.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Rather than having an algorithm decide where each glyph should go within a set of bitmaps, this option lets a pre-existing layout file determine it. This is designed to be used with only one point size at a time, so deploy it in conjunction with the “-size” parameter.&lt;br /&gt;
This is helpful in building up aligned layers in a GIMP file, particularly as a step in making a “hybrid” or composite TDM font from multiple sources.&lt;br /&gt;
This forces a particular layout, great as a “first draft”, but improvable with further bitmap and DAT editing. You can expect some glyph collisions will occur; perhaps incrementally manage this by suppressing some glyphs with a custom unicodeMap?&lt;br /&gt;
&lt;br /&gt;
====File Generation &amp;amp; Naming====&lt;br /&gt;
The number of TGA files created, and their names, and their references in the output DAT, will exactly match that specified by the input layout file.&lt;br /&gt;
To avoid confusion or name conflict between input and output layout files, either rename the input file, e.g., from “fontimage_24.dat” to “fontimage_24_in.dat”, or place the input layout file in a separate child directory, e.g., “placeAt/fontimage_24.dat”&lt;br /&gt;
&lt;br /&gt;
====Glyph Alignment &amp;amp; Placement====&lt;br /&gt;
During placement, for each glyph, only 4 input DAT values are used:&lt;br /&gt;
* s&lt;br /&gt;
* t&lt;br /&gt;
* top&lt;br /&gt;
* shaderName&lt;br /&gt;
&lt;br /&gt;
The rest are derived from the TTF file, as influenced by other command-line parameters. Specifically, an output glyph is aligned with the baseline and left-boundary of the corresponding input glyph. That is, the upper-left origin of the output glyph is given by (s, t+top_input-top_TTF), placed into bitmap “shaderName”. (Exception: Negative origin coordinates are replaced by zero.) Aligning vertically by baseline in this way seemed more helpful than aligning by t value alone.&lt;br /&gt;
&lt;br /&gt;
If a codepoint requested by the input DAT has no glyph in the TTF, this codepoint will be skipped during output, i.e., no empty box is generated in its place... because the empty box just gets in the way during subsequent GIMP work. Exception: Codepoint 0x0000 does generate an empty box.&lt;br /&gt;
&lt;br /&gt;
====Relationship to Other Parameters====&lt;br /&gt;
These are required:&lt;br /&gt;
* The input TTF filename (in addition to inPlace&#039;s input layout file; as noted, the contents of the latter file will determine what TGA files are generated.)&lt;br /&gt;
* The size &amp;lt;fontsize&amp;gt; option. As usual, this will determine the font size requested from the TTF file, as well as the name of the output fontImage_&amp;lt;filesize&amp;gt;.dat file. However, unlike the usual case, not the naming of the output TGA files.&lt;br /&gt;
&lt;br /&gt;
These options are optional:&lt;br /&gt;
* unicodeMap &amp;lt;filename&amp;gt;&lt;br /&gt;
* hirez [with DAT file as input, to generate 512x512 output files; situation may change with future REF file.]&lt;br /&gt;
* bolding &amp;lt;value&amp;gt;&lt;br /&gt;
* name &amp;lt;alternative font name&amp;gt;. As usual, this will name the (generated if necessary) folder into which output files are placed. However, unlike the usual case, the naming of the output TGA files will be as given in the input DAT file.&lt;br /&gt;
&lt;br /&gt;
These options are ignored, by design:&lt;br /&gt;
* compact [whether present or absent; no algorithimic layout applied.]&lt;br /&gt;
* awayFromEdge &amp;lt;value&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Thes option is probably problematic and should be avoided for now:&lt;br /&gt;
* startFileNumber&lt;br /&gt;
&lt;br /&gt;
== Changed Behavior for Font Title from ExportFontToDoom3All256 ==&lt;br /&gt;
In ExportFontToDoom3All256, if the font title was more that 20 characters long, it would truncate it to fit in the DAT file as part of the shader names (i.e., paths to TGA files). But this threshold was wrong. Now, truncation and a warning happens if the font title is more that 17 characters long (or 16 if generated TGAs include any with a 2-digit count instead of 1-digit). If truncation occurs, the user is asked to consider using or revising the -name argument.&lt;br /&gt;
&lt;br /&gt;
== Downloads ==&lt;br /&gt;
Release v1.2 of 2025-03-31 &#039;&#039;(which adds inPlace option; makes clearer a command-line message about xOffset and pitch).&#039;&#039;&lt;br /&gt;
* [https://drive.google.com/file/d/1CG_BXsTTYi7E3nQPKtBWi-94Cj3R5eOY/view?usp=sharing ExportUnicodeFontToDoom3_release_1_2_exe.zip] . Windows binary and required archived versions of FreeType and DevIL DLLs.&lt;br /&gt;
* [https://drive.google.com/file/d/1Nw4RdKKx2YHoPR6D-YQzdnEFx-vyYUhk/view?usp=sharing ExportUnicodeFontToDoom3_release_1_2_source_project.zip] . The C++ project file with source code, including source &amp;amp; build project of archived library.&lt;br /&gt;
&lt;br /&gt;
Release v1.1 of 2025-03-03:&lt;br /&gt;
* [https://drive.google.com/file/d/1f3Jj53qtJGIp0_mz7Riing9Fi8ESFDr5/view?usp=sharing ExportUnicodeFontToDoom3_release_1_1_exe.zip]&lt;br /&gt;
* [https://drive.google.com/file/d/1nutMBfcIWw63wNTUdnlnzP397tGVpnpd/view?usp=sharing ExportUnicodeFontToDoom3_release_1_1_source_project.zip] .&lt;br /&gt;
&lt;br /&gt;
Release 1 of 2024-09-10:&lt;br /&gt;
* [https://drive.google.com/file/d/1MqoOfhc5-ovoxoHfRquYAcIEdHEOJAQV/view?usp=sharing ExportUnicodeFontToDoom3_release_1_exe.zip]&lt;br /&gt;
* [https://drive.google.com/file/d/1Frk_byfdtCcMqdr27ulw1XyuFj8vYp9x/view?usp=sharing ExportUnicodeFontToDoom3_release_1_source_project.zip]&lt;br /&gt;
&lt;br /&gt;
== See Also ==&lt;br /&gt;
The Cyrillic coverage of Lora Regular TTF font, projected to used as Russian Mason supplement in TDM 2.14, may be viewed and font downloaded [https://www.fontsquirrel.com/fonts/lora?filter%5Bclassifications%5D%5B0%5D=serif&amp;amp;filter%5Blanguages%5D%5B0%5D=cyrillic#eula here].&lt;/div&gt;</summary>
		<author><name>Geep</name></author>
	</entry>
	<entry>
		<id>https://wiki.thedarkmod.com/index.php?title=ExportUnicodeFontToDoom3&amp;diff=34464</id>
		<title>ExportUnicodeFontToDoom3</title>
		<link rel="alternate" type="text/html" href="https://wiki.thedarkmod.com/index.php?title=ExportUnicodeFontToDoom3&amp;diff=34464"/>
		<updated>2026-04-01T00:40:14Z</updated>

		<summary type="html">&lt;p&gt;Geep: /* Downloads */ updates to release 1.2&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;By Geep, 2025&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
== Introduction ==&lt;br /&gt;
&lt;br /&gt;
In 2025, kalinovka in [https://forums.thedarkmod.com/index.php?/topic/22736-font-localization Font localization] sought to extend TDM’s Mason 48pt font, used in the main menu, to include missing Cyrillic glyphs. This would allow this font to be used in an FM and still support a Russian translation.&lt;br /&gt;
&lt;br /&gt;
This offshoot of [https://wiki.thedarkmod.com/index.php?title=ExportFontToDoom3 ExportFontToDoom3All256] is a generalized response to that. The main idea to select an input TTF font that includes not just ASCII or ANSI, but offers additional Unicode characters, like Cyrillic. The program still limits output to a maximum of 256 characters, consistent with the DAT format.&lt;br /&gt;
&lt;br /&gt;
To achieve this, it reads in an external human-readable &amp;quot;unicodeMap&amp;quot; file, in Unicode.org’s &amp;quot;Format A&amp;quot;. This format provides a mapping from the traditional 8-bit encoding that TDM uses to the corresponding UCS (Unicode 16-bit) value. Unicode.org provides stock files for standard ISO and Windows 8-bit encodings. Of specific interest here is [https://www.unicode.org/Public/MAPPINGS/VENDORS/MICSFT/WINDOWS/CP1251.TXT cp1251.txt for Cyrillic]. This requires just trivial editing for [https://wiki.thedarkmod.com/index.php?title=I18N_-_Charset TDM-specific codepoints]. As discussed below, you can further edit a unicodeMap file in advance, if you want to generate just a subset of glyphs.&lt;br /&gt;
&lt;br /&gt;
More broadly, this program supersedes ExportFontToDoom3 and ExportFontToDoom3All256.&lt;br /&gt;
&lt;br /&gt;
== New Command Line Arguments ==&lt;br /&gt;
&lt;br /&gt;
These are in-addition to those of [https://wiki.thedarkmod.com/index.php?title=ExportFontToDoom3 ExportFontToDoom3All256].&lt;br /&gt;
&lt;br /&gt;
=== unicodeMap &amp;lt;file&amp;gt; ===&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
 -unicodeMap &amp;quot;./Test/cp1251.txt&amp;quot;&lt;br /&gt;
&lt;br /&gt;
You can edit the unicodeMap file in advance, to specify which particular glyphs you want to generate by suppressing unwanted glyphs, either by:&lt;br /&gt;
&lt;br /&gt;
* Deleting an unwanted line (or block of lines) entirely, or&lt;br /&gt;
* Prepending a &amp;quot;#&amp;quot; to comment-out the line.&lt;br /&gt;
&lt;br /&gt;
Also, this file format allows the Unicode value (e.g., &amp;quot;0x1234&amp;quot;) to be replaced by 6 space characters, when the ISO or Windows standard leaves that character undefined.&lt;br /&gt;
&lt;br /&gt;
In all 3 of those cases, every suppressed character in the output DAT file will be represented by the glyph that the font uses for U+0000. A hollow box is common.&lt;br /&gt;
&lt;br /&gt;
IMPORTANT: If you edit lines, the remaining active glyph lines MUST be in ascending order by the 2-hex-digit codepoint value that starts each line. Otherwise, results will go astray.&lt;br /&gt;
&lt;br /&gt;
=== startFileNumber &amp;lt;n&amp;gt; ===&lt;br /&gt;
When a set of TGA/DDS files are generated for a particular font size, by default the first file&#039;s name contains _0_, which increments for additional files. You can optionally specify a different 1- or 2-digit start number, e.g., &amp;quot;-startFileNumber 7&amp;quot;. Why? Because...&lt;br /&gt;
&lt;br /&gt;
* the file(s) you are generating are supplemental to, not replacements for, existing TGA/DDS files; and&lt;br /&gt;
* in this run, you are generating just one of the 3 possible font sizes (assuming each size has a different count of existing TGA/DDS files).&lt;br /&gt;
&lt;br /&gt;
When you generate a supplemental set, the new DAT file has no knowledge of what&#039;s in the original set and its DAT file. You will have to interleave-edit the old and new DAT files (e.g., with reFont&#039;s REF files) to create a single DAT file spanning old and new glyphs. There may be a redundant NULL glyph in your new TGA set; just ignore it.&lt;br /&gt;
&lt;br /&gt;
=== awayFromEdge &amp;lt;n&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
Allows specifying in positive integer pixels (e.g., &amp;quot;-awayFromEdge 2&amp;quot;) a small extra boundary at the top and left edges of the overall bitmap. This is for fonts like Mason where extra space (typically 2 pixels) is needed around every character to create a &amp;quot;glow variant&amp;quot;. Routine glyph layout provides usually enough space for this except at the top and (arguably) left edges. See also the &amp;quot;compact&amp;quot; parameter.&lt;br /&gt;
&lt;br /&gt;
Note: The spacing value is relative to 256x256 bitmaps. If you specify &amp;quot;hirez&amp;quot;, then for proportionality, your specified value is doubled internally when laying out the 512x512 bitmaps.&lt;br /&gt;
&lt;br /&gt;
=== compact ===&lt;br /&gt;
If specified (i.e, &amp;quot;-compact&amp;quot;), packs the character glyphs more closely together. Particularly recommended for 48pt fonts; it will generate roughly half the files.&lt;br /&gt;
&lt;br /&gt;
Whether &amp;quot;compact&amp;quot; is specified or not, packing is controlled by simply &amp;quot;padding&amp;quot; each glyph’s bounding box. Specifically, this doesn’t change the bounding box, but adds pixel &amp;quot;padding&amp;quot; to just the right and bottom of the bounding box, a simple though asymmetric process. One reason for padding was given ExportFontToDoom3 author Grant Davies in code comments:&lt;br /&gt;
&lt;br /&gt;
&amp;quot;Because of the way Doom 3 Indexes the texture page (using floating point numbers), it is unable to reference exact pixels – there is error. How much error, I don’t know. For this reason, the rectangles needs to be padded out.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Geep suspects that such error with the TDM engine is not really a problem. Likely some error in the past was due to editing with Q3Font and its low floating-point precision. Nevertheless, some padding is good because:&lt;br /&gt;
&lt;br /&gt;
* For the Mason font, 2 pixels around each glyph are needed for &amp;quot;glow&amp;quot; effects (either done as a separate smudge font for /english/ or as a bidirection offset effect for /russian/.)&lt;br /&gt;
* Keeping glyphs separated improves visualization of boundaries with datBounds, and makes editing tweaks easier.&lt;br /&gt;
&lt;br /&gt;
The &amp;quot;compact&amp;quot; setting restores Grant Davies&#039; first algorithm, which just pads the bounding box by 5 pixels to the right and 5 pixels below.&lt;br /&gt;
&lt;br /&gt;
Without &amp;quot;compact&amp;quot;, the default is Grant Davies&#039; second algorithm found in ExportFontToDoom3 v1.02. This likewise first pads each bounding box by 5 pixels to the right and 5 pixels below. It then further pads to make both the width and height a factor of 2; this makes 48pt quite sparse.  (It is possible this improved rendering performance in 2005; not important now. Also, in practice for major fonts, much of this &amp;quot;factor of 2&amp;quot; spacing was overridden by subsequent Font Patcher work.)&lt;br /&gt;
&lt;br /&gt;
=== hirez or hires ===&lt;br /&gt;
&#039;&#039;Added with v1.1, March 2026&#039;&#039; &lt;br /&gt;
&lt;br /&gt;
Instead of 256x256 bitmaps (and associated DAT), this exports double-sized 512x512 bitmaps with larger, thus potentially-crisper glyphs. (TDM has had a few such 512x512 bitmaps for redrawn fonts since 2014.) Specifically, it: &lt;br /&gt;
* outputs requested 512x512 TGAs and their DAT(s).&lt;br /&gt;
* internally, doubles the pointsize requested of the TTF, resulting in 2x character glyph sizes. Because both the container bitmap and each glyph is (nominally) doubled in size, the [0...1] s, s2, t, t2 values stored in the DAT would be very similar to those for a 256x256 bitmap.&lt;br /&gt;
* Other DAT layout metrics remain as if scaled to a 256x256 layout:&lt;br /&gt;
** imageHeight&lt;br /&gt;
** imageWidth&lt;br /&gt;
** skip&lt;br /&gt;
** top (with bottom ignored as usual)&lt;br /&gt;
** pitch&lt;br /&gt;
&lt;br /&gt;
For example, if you request –hirez with a carleton font in just 24pt type, it will create 512x512 files with usual names like carleton_0_24.tga, etc., and fontimage_24.dat, with the console showing “Exporting carleton 24pt”.&lt;br /&gt;
But internally, 48pt characters are drawn on the bitmaps. The imageHeight and imageWidth metrics will be as if the requested 24pt size was generated, so in effect causing the game engine to scale down by a factor of 2 from the 48pt glyph.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;TIPS on Using a HiRez DAT file&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
If subsequently using Refont to make a REF file from this DAT, add the “scaling_ok” option, to suppress otherwise voluminous console warnings about per-character scaling.&lt;br /&gt;
&lt;br /&gt;
If you further plan to generate bounds visualizations with datBounds:&lt;br /&gt;
* For 512x512 bitmaps, you must generate from the REF file, not directly from DAT.&lt;br /&gt;
* Be sure to first edit the REF to add headers of the form:&lt;br /&gt;
&lt;br /&gt;
 # bitmap_&amp;lt;n&amp;gt;_size=512&lt;br /&gt;
 &lt;br /&gt;
  , where &amp;lt;n&amp;gt; is 0 to 9, and refers to shaders present in the REF file with names like, e.g., carleton_3_48.tga; n would be 3 for this.&lt;br /&gt;
&lt;br /&gt;
* datBounds also has a worthwhile “scaling_ok” option.&lt;br /&gt;
* Uncommonly, the raw_metrics option may be of interest.&lt;br /&gt;
&lt;br /&gt;
=== bolding &amp;lt;n&amp;gt; ===&lt;br /&gt;
&#039;&#039;Added with v1.1, March 2026&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Sometimes, a TTF font does not offer a “bold” variant, or, more generally, a font’s overall stroke thickness is not ideal. It is possible to alter character outlines, then render those as bitmap glyphs.&lt;br /&gt;
The result is usually better than post-bitmap thickening or thinning. The FreeType library offers an embolding function for outline alteration, used here.&lt;br /&gt;
&lt;br /&gt;
The integer parameter &amp;lt;n&amp;gt; is in units of 1/64th pixel. A positive value adjusts the outline to embolden the character. Negative thins. The change affects both the overall height and width of the outline.&lt;br /&gt;
You may think of the left and bottom character borders as unchanged. The allowed range of &amp;lt;n&amp;gt; is from -128 (i.e., -2 pixels) to 256 (4 pixels). The -2 limit is arbitrary, but for sanity. The 4 limit is the maximum FreeType permits.&lt;br /&gt;
&lt;br /&gt;
Caution: The adjustment algorithm moves the outline controls points, but doesn&#039;t change the number of such points;&lt;br /&gt;
this means that certain situations like acute angles or intersections are sometimes handled incorrectly.&lt;br /&gt;
&lt;br /&gt;
=== inPlace &amp;lt;filename of input layout file&amp;gt; ===&lt;br /&gt;
&#039;&#039;This experimental feature, new in v 1.2, reads a DAT file for input layout. It may be extended to REF and FTN filetypes in the future. Specifications are subject to change.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Rather than having an algorithm decide where each glyph should go within a set of bitmaps, this option lets a pre-existing layout file determine it. This is designed to be used with only one point size at a time, so deploy it in conjunction with the “-size” parameter.&lt;br /&gt;
This is helpful in building up aligned layers in a GIMP file, particularly as a step in making a “hybrid” or composite TDM font from multiple sources.&lt;br /&gt;
This forces a particular layout, great as a “first draft”, but improvable with further bitmap and DAT editing. You can expect some glyph collisions will occur; perhaps incrementally manage this by suppressing some glyphs with a custom unicodeMap?&lt;br /&gt;
&lt;br /&gt;
====File Generation &amp;amp; Naming====&lt;br /&gt;
The number of TGA files created, and their names, and their references in the output DAT, will exactly match that specified by the input layout file.&lt;br /&gt;
To avoid confusion or name conflict between input and output layout files, either rename the input file, e.g., from “fontimage_24.dat” to “fontimage_24_in.dat”, or place the input layout file in a separate child directory, e.g., “placeAt/fontimage_24.dat”&lt;br /&gt;
&lt;br /&gt;
====Glyph Alignment &amp;amp; Placement====&lt;br /&gt;
During placement, for each glyph, only 4 input DAT values are used:&lt;br /&gt;
* s&lt;br /&gt;
* t&lt;br /&gt;
* top&lt;br /&gt;
* shaderName&lt;br /&gt;
&lt;br /&gt;
The rest are derived from the TTF file, as influenced by other command-line parameters. Specifically, an output glyph is aligned with the baseline and left-boundary of the corresponding input glyph. That is, the upper-left origin of the output glyph is given by (s, t+top_input-top_TTF), placed into bitmap “shaderName”. (Exception: Negative origin coordinates are replaced by zero.) Aligning vertically by baseline in this way seemed more helpful than aligning by t value alone.&lt;br /&gt;
&lt;br /&gt;
If a codepoint requested by the input DAT has no glyph in the TTF, this codepoint will be skipped during output, i.e., no empty box is generated in its place... because the empty box just gets in the way during subsequent GIMP work. Exception: Codepoint 0x0000 does generate an empty box.&lt;br /&gt;
&lt;br /&gt;
====Relationship to Other Parameters====&lt;br /&gt;
These are required:&lt;br /&gt;
* The input TTF filename (in addition to inPlace&#039;s input layout file; as noted, the contents of the latter file will determine what TGA files are generated.)&lt;br /&gt;
* The size &amp;lt;fontsize&amp;gt; option. As usual, this will determine the font size requested from the TTF file, as well as the name of the output fontImage_&amp;lt;filesize&amp;gt;.dat file. However, unlike the usual case, not the naming of the output TGA files.&lt;br /&gt;
&lt;br /&gt;
These options are optional:&lt;br /&gt;
* unicodeMap &amp;lt;filename&amp;gt;&lt;br /&gt;
* hirez [with DAT file as input, to generate 512x512 output files; situation may change with future REF file.]&lt;br /&gt;
* bolding &amp;lt;value&amp;gt;&lt;br /&gt;
* name &amp;lt;alternative font name&amp;gt;. As usual, this will name the (generated if necessary) folder into which output files are placed. However, unlike the usual case, the naming of the output TGA files will be as given in the input DAT file.&lt;br /&gt;
&lt;br /&gt;
These options are ignored, by design:&lt;br /&gt;
* compact [whether present or absent; no algorithimic layout applied.]&lt;br /&gt;
* awayFromEdge &amp;lt;value&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Theis option is probably problematic and should be avoided for now:&lt;br /&gt;
* startFileNumber&lt;br /&gt;
&lt;br /&gt;
== Changed Behavior for Font Title from ExportFontToDoom3All256 ==&lt;br /&gt;
In ExportFontToDoom3All256, if the font title was more that 20 characters long, it would truncate it to fit in the DAT file as part of the shader names (i.e., paths to TGA files). But this threshold was wrong. Now, truncation and a warning happens if the font title is more that 17 characters long (or 16 if generated TGAs include any with a 2-digit count instead of 1-digit). If truncation occurs, the user is asked to consider using or revising the -name argument.&lt;br /&gt;
&lt;br /&gt;
== Downloads ==&lt;br /&gt;
Release v1.2 of 2025-03-31 &#039;&#039;(which adds inPlace option; makes clearer a command-line message about xOffset and pitch).&#039;&#039;&lt;br /&gt;
* [https://drive.google.com/file/d/1CG_BXsTTYi7E3nQPKtBWi-94Cj3R5eOY/view?usp=sharing ExportUnicodeFontToDoom3_release_1_2_exe.zip] . Windows binary and required archived versions of FreeType and DevIL DLLs.&lt;br /&gt;
* [https://drive.google.com/file/d/1Nw4RdKKx2YHoPR6D-YQzdnEFx-vyYUhk/view?usp=sharing ExportUnicodeFontToDoom3_release_1_2_source_project.zip] . The C++ project file with source code, including source &amp;amp; build project of archived library.&lt;br /&gt;
&lt;br /&gt;
Release v1.1 of 2025-03-03:&lt;br /&gt;
* [https://drive.google.com/file/d/1f3Jj53qtJGIp0_mz7Riing9Fi8ESFDr5/view?usp=sharing ExportUnicodeFontToDoom3_release_1_1_exe.zip]&lt;br /&gt;
* [https://drive.google.com/file/d/1nutMBfcIWw63wNTUdnlnzP397tGVpnpd/view?usp=sharing ExportUnicodeFontToDoom3_release_1_1_source_project.zip] .&lt;br /&gt;
&lt;br /&gt;
Release 1 of 2024-09-10:&lt;br /&gt;
* [https://drive.google.com/file/d/1MqoOfhc5-ovoxoHfRquYAcIEdHEOJAQV/view?usp=sharing ExportUnicodeFontToDoom3_release_1_exe.zip]&lt;br /&gt;
* [https://drive.google.com/file/d/1Frk_byfdtCcMqdr27ulw1XyuFj8vYp9x/view?usp=sharing ExportUnicodeFontToDoom3_release_1_source_project.zip]&lt;br /&gt;
&lt;br /&gt;
== See Also ==&lt;br /&gt;
The Cyrillic coverage of Lora Regular TTF font, projected to used as Russian Mason supplement in TDM 2.14, may be viewed and font downloaded [https://www.fontsquirrel.com/fonts/lora?filter%5Bclassifications%5D%5B0%5D=serif&amp;amp;filter%5Blanguages%5D%5B0%5D=cyrillic#eula here].&lt;/div&gt;</summary>
		<author><name>Geep</name></author>
	</entry>
	<entry>
		<id>https://wiki.thedarkmod.com/index.php?title=ExportUnicodeFontToDoom3&amp;diff=34463</id>
		<title>ExportUnicodeFontToDoom3</title>
		<link rel="alternate" type="text/html" href="https://wiki.thedarkmod.com/index.php?title=ExportUnicodeFontToDoom3&amp;diff=34463"/>
		<updated>2026-03-31T21:24:13Z</updated>

		<summary type="html">&lt;p&gt;Geep: Add inPlace option&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;By Geep, 2025&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
== Introduction ==&lt;br /&gt;
&lt;br /&gt;
In 2025, kalinovka in [https://forums.thedarkmod.com/index.php?/topic/22736-font-localization Font localization] sought to extend TDM’s Mason 48pt font, used in the main menu, to include missing Cyrillic glyphs. This would allow this font to be used in an FM and still support a Russian translation.&lt;br /&gt;
&lt;br /&gt;
This offshoot of [https://wiki.thedarkmod.com/index.php?title=ExportFontToDoom3 ExportFontToDoom3All256] is a generalized response to that. The main idea to select an input TTF font that includes not just ASCII or ANSI, but offers additional Unicode characters, like Cyrillic. The program still limits output to a maximum of 256 characters, consistent with the DAT format.&lt;br /&gt;
&lt;br /&gt;
To achieve this, it reads in an external human-readable &amp;quot;unicodeMap&amp;quot; file, in Unicode.org’s &amp;quot;Format A&amp;quot;. This format provides a mapping from the traditional 8-bit encoding that TDM uses to the corresponding UCS (Unicode 16-bit) value. Unicode.org provides stock files for standard ISO and Windows 8-bit encodings. Of specific interest here is [https://www.unicode.org/Public/MAPPINGS/VENDORS/MICSFT/WINDOWS/CP1251.TXT cp1251.txt for Cyrillic]. This requires just trivial editing for [https://wiki.thedarkmod.com/index.php?title=I18N_-_Charset TDM-specific codepoints]. As discussed below, you can further edit a unicodeMap file in advance, if you want to generate just a subset of glyphs.&lt;br /&gt;
&lt;br /&gt;
More broadly, this program supersedes ExportFontToDoom3 and ExportFontToDoom3All256.&lt;br /&gt;
&lt;br /&gt;
== New Command Line Arguments ==&lt;br /&gt;
&lt;br /&gt;
These are in-addition to those of [https://wiki.thedarkmod.com/index.php?title=ExportFontToDoom3 ExportFontToDoom3All256].&lt;br /&gt;
&lt;br /&gt;
=== unicodeMap &amp;lt;file&amp;gt; ===&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
 -unicodeMap &amp;quot;./Test/cp1251.txt&amp;quot;&lt;br /&gt;
&lt;br /&gt;
You can edit the unicodeMap file in advance, to specify which particular glyphs you want to generate by suppressing unwanted glyphs, either by:&lt;br /&gt;
&lt;br /&gt;
* Deleting an unwanted line (or block of lines) entirely, or&lt;br /&gt;
* Prepending a &amp;quot;#&amp;quot; to comment-out the line.&lt;br /&gt;
&lt;br /&gt;
Also, this file format allows the Unicode value (e.g., &amp;quot;0x1234&amp;quot;) to be replaced by 6 space characters, when the ISO or Windows standard leaves that character undefined.&lt;br /&gt;
&lt;br /&gt;
In all 3 of those cases, every suppressed character in the output DAT file will be represented by the glyph that the font uses for U+0000. A hollow box is common.&lt;br /&gt;
&lt;br /&gt;
IMPORTANT: If you edit lines, the remaining active glyph lines MUST be in ascending order by the 2-hex-digit codepoint value that starts each line. Otherwise, results will go astray.&lt;br /&gt;
&lt;br /&gt;
=== startFileNumber &amp;lt;n&amp;gt; ===&lt;br /&gt;
When a set of TGA/DDS files are generated for a particular font size, by default the first file&#039;s name contains _0_, which increments for additional files. You can optionally specify a different 1- or 2-digit start number, e.g., &amp;quot;-startFileNumber 7&amp;quot;. Why? Because...&lt;br /&gt;
&lt;br /&gt;
* the file(s) you are generating are supplemental to, not replacements for, existing TGA/DDS files; and&lt;br /&gt;
* in this run, you are generating just one of the 3 possible font sizes (assuming each size has a different count of existing TGA/DDS files).&lt;br /&gt;
&lt;br /&gt;
When you generate a supplemental set, the new DAT file has no knowledge of what&#039;s in the original set and its DAT file. You will have to interleave-edit the old and new DAT files (e.g., with reFont&#039;s REF files) to create a single DAT file spanning old and new glyphs. There may be a redundant NULL glyph in your new TGA set; just ignore it.&lt;br /&gt;
&lt;br /&gt;
=== awayFromEdge &amp;lt;n&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
Allows specifying in positive integer pixels (e.g., &amp;quot;-awayFromEdge 2&amp;quot;) a small extra boundary at the top and left edges of the overall bitmap. This is for fonts like Mason where extra space (typically 2 pixels) is needed around every character to create a &amp;quot;glow variant&amp;quot;. Routine glyph layout provides usually enough space for this except at the top and (arguably) left edges. See also the &amp;quot;compact&amp;quot; parameter.&lt;br /&gt;
&lt;br /&gt;
Note: The spacing value is relative to 256x256 bitmaps. If you specify &amp;quot;hirez&amp;quot;, then for proportionality, your specified value is doubled internally when laying out the 512x512 bitmaps.&lt;br /&gt;
&lt;br /&gt;
=== compact ===&lt;br /&gt;
If specified (i.e, &amp;quot;-compact&amp;quot;), packs the character glyphs more closely together. Particularly recommended for 48pt fonts; it will generate roughly half the files.&lt;br /&gt;
&lt;br /&gt;
Whether &amp;quot;compact&amp;quot; is specified or not, packing is controlled by simply &amp;quot;padding&amp;quot; each glyph’s bounding box. Specifically, this doesn’t change the bounding box, but adds pixel &amp;quot;padding&amp;quot; to just the right and bottom of the bounding box, a simple though asymmetric process. One reason for padding was given ExportFontToDoom3 author Grant Davies in code comments:&lt;br /&gt;
&lt;br /&gt;
&amp;quot;Because of the way Doom 3 Indexes the texture page (using floating point numbers), it is unable to reference exact pixels – there is error. How much error, I don’t know. For this reason, the rectangles needs to be padded out.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Geep suspects that such error with the TDM engine is not really a problem. Likely some error in the past was due to editing with Q3Font and its low floating-point precision. Nevertheless, some padding is good because:&lt;br /&gt;
&lt;br /&gt;
* For the Mason font, 2 pixels around each glyph are needed for &amp;quot;glow&amp;quot; effects (either done as a separate smudge font for /english/ or as a bidirection offset effect for /russian/.)&lt;br /&gt;
* Keeping glyphs separated improves visualization of boundaries with datBounds, and makes editing tweaks easier.&lt;br /&gt;
&lt;br /&gt;
The &amp;quot;compact&amp;quot; setting restores Grant Davies&#039; first algorithm, which just pads the bounding box by 5 pixels to the right and 5 pixels below.&lt;br /&gt;
&lt;br /&gt;
Without &amp;quot;compact&amp;quot;, the default is Grant Davies&#039; second algorithm found in ExportFontToDoom3 v1.02. This likewise first pads each bounding box by 5 pixels to the right and 5 pixels below. It then further pads to make both the width and height a factor of 2; this makes 48pt quite sparse.  (It is possible this improved rendering performance in 2005; not important now. Also, in practice for major fonts, much of this &amp;quot;factor of 2&amp;quot; spacing was overridden by subsequent Font Patcher work.)&lt;br /&gt;
&lt;br /&gt;
=== hirez or hires ===&lt;br /&gt;
&#039;&#039;Added with v1.1, March 2026&#039;&#039; &lt;br /&gt;
&lt;br /&gt;
Instead of 256x256 bitmaps (and associated DAT), this exports double-sized 512x512 bitmaps with larger, thus potentially-crisper glyphs. (TDM has had a few such 512x512 bitmaps for redrawn fonts since 2014.) Specifically, it: &lt;br /&gt;
* outputs requested 512x512 TGAs and their DAT(s).&lt;br /&gt;
* internally, doubles the pointsize requested of the TTF, resulting in 2x character glyph sizes. Because both the container bitmap and each glyph is (nominally) doubled in size, the [0...1] s, s2, t, t2 values stored in the DAT would be very similar to those for a 256x256 bitmap.&lt;br /&gt;
* Other DAT layout metrics remain as if scaled to a 256x256 layout:&lt;br /&gt;
** imageHeight&lt;br /&gt;
** imageWidth&lt;br /&gt;
** skip&lt;br /&gt;
** top (with bottom ignored as usual)&lt;br /&gt;
** pitch&lt;br /&gt;
&lt;br /&gt;
For example, if you request –hirez with a carleton font in just 24pt type, it will create 512x512 files with usual names like carleton_0_24.tga, etc., and fontimage_24.dat, with the console showing “Exporting carleton 24pt”.&lt;br /&gt;
But internally, 48pt characters are drawn on the bitmaps. The imageHeight and imageWidth metrics will be as if the requested 24pt size was generated, so in effect causing the game engine to scale down by a factor of 2 from the 48pt glyph.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;TIPS on Using a HiRez DAT file&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
If subsequently using Refont to make a REF file from this DAT, add the “scaling_ok” option, to suppress otherwise voluminous console warnings about per-character scaling.&lt;br /&gt;
&lt;br /&gt;
If you further plan to generate bounds visualizations with datBounds:&lt;br /&gt;
* For 512x512 bitmaps, you must generate from the REF file, not directly from DAT.&lt;br /&gt;
* Be sure to first edit the REF to add headers of the form:&lt;br /&gt;
&lt;br /&gt;
 # bitmap_&amp;lt;n&amp;gt;_size=512&lt;br /&gt;
 &lt;br /&gt;
  , where &amp;lt;n&amp;gt; is 0 to 9, and refers to shaders present in the REF file with names like, e.g., carleton_3_48.tga; n would be 3 for this.&lt;br /&gt;
&lt;br /&gt;
* datBounds also has a worthwhile “scaling_ok” option.&lt;br /&gt;
* Uncommonly, the raw_metrics option may be of interest.&lt;br /&gt;
&lt;br /&gt;
=== bolding &amp;lt;n&amp;gt; ===&lt;br /&gt;
&#039;&#039;Added with v1.1, March 2026&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Sometimes, a TTF font does not offer a “bold” variant, or, more generally, a font’s overall stroke thickness is not ideal. It is possible to alter character outlines, then render those as bitmap glyphs.&lt;br /&gt;
The result is usually better than post-bitmap thickening or thinning. The FreeType library offers an embolding function for outline alteration, used here.&lt;br /&gt;
&lt;br /&gt;
The integer parameter &amp;lt;n&amp;gt; is in units of 1/64th pixel. A positive value adjusts the outline to embolden the character. Negative thins. The change affects both the overall height and width of the outline.&lt;br /&gt;
You may think of the left and bottom character borders as unchanged. The allowed range of &amp;lt;n&amp;gt; is from -128 (i.e., -2 pixels) to 256 (4 pixels). The -2 limit is arbitrary, but for sanity. The 4 limit is the maximum FreeType permits.&lt;br /&gt;
&lt;br /&gt;
Caution: The adjustment algorithm moves the outline controls points, but doesn&#039;t change the number of such points;&lt;br /&gt;
this means that certain situations like acute angles or intersections are sometimes handled incorrectly.&lt;br /&gt;
&lt;br /&gt;
=== inPlace &amp;lt;filename of input layout file&amp;gt; ===&lt;br /&gt;
&#039;&#039;This experimental feature, new in v 1.2, reads a DAT file for input layout. It may be extended to REF and FTN filetypes in the future. Specifications are subject to change.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Rather than having an algorithm decide where each glyph should go within a set of bitmaps, this option lets a pre-existing layout file determine it. This is designed to be used with only one point size at a time, so deploy it in conjunction with the “-size” parameter.&lt;br /&gt;
This is helpful in building up aligned layers in a GIMP file, particularly as a step in making a “hybrid” or composite TDM font from multiple sources.&lt;br /&gt;
This forces a particular layout, great as a “first draft”, but improvable with further bitmap and DAT editing. You can expect some glyph collisions will occur; perhaps incrementally manage this by suppressing some glyphs with a custom unicodeMap?&lt;br /&gt;
&lt;br /&gt;
====File Generation &amp;amp; Naming====&lt;br /&gt;
The number of TGA files created, and their names, and their references in the output DAT, will exactly match that specified by the input layout file.&lt;br /&gt;
To avoid confusion or name conflict between input and output layout files, either rename the input file, e.g., from “fontimage_24.dat” to “fontimage_24_in.dat”, or place the input layout file in a separate child directory, e.g., “placeAt/fontimage_24.dat”&lt;br /&gt;
&lt;br /&gt;
====Glyph Alignment &amp;amp; Placement====&lt;br /&gt;
During placement, for each glyph, only 4 input DAT values are used:&lt;br /&gt;
* s&lt;br /&gt;
* t&lt;br /&gt;
* top&lt;br /&gt;
* shaderName&lt;br /&gt;
&lt;br /&gt;
The rest are derived from the TTF file, as influenced by other command-line parameters. Specifically, an output glyph is aligned with the baseline and left-boundary of the corresponding input glyph. That is, the upper-left origin of the output glyph is given by (s, t+top_input-top_TTF), placed into bitmap “shaderName”. (Exception: Negative origin coordinates are replaced by zero.) Aligning vertically by baseline in this way seemed more helpful than aligning by t value alone.&lt;br /&gt;
&lt;br /&gt;
If a codepoint requested by the input DAT has no glyph in the TTF, this codepoint will be skipped during output, i.e., no empty box is generated in its place... because the empty box just gets in the way during subsequent GIMP work. Exception: Codepoint 0x0000 does generate an empty box.&lt;br /&gt;
&lt;br /&gt;
====Relationship to Other Parameters====&lt;br /&gt;
These are required:&lt;br /&gt;
* The input TTF filename (in addition to inPlace&#039;s input layout file; as noted, the contents of the latter file will determine what TGA files are generated.)&lt;br /&gt;
* The size &amp;lt;fontsize&amp;gt; option. As usual, this will determine the font size requested from the TTF file, as well as the name of the output fontImage_&amp;lt;filesize&amp;gt;.dat file. However, unlike the usual case, not the naming of the output TGA files.&lt;br /&gt;
&lt;br /&gt;
These options are optional:&lt;br /&gt;
* unicodeMap &amp;lt;filename&amp;gt;&lt;br /&gt;
* hirez [with DAT file as input, to generate 512x512 output files; situation may change with future REF file.]&lt;br /&gt;
* bolding &amp;lt;value&amp;gt;&lt;br /&gt;
* name &amp;lt;alternative font name&amp;gt;. As usual, this will name the (generated if necessary) folder into which output files are placed. However, unlike the usual case, the naming of the output TGA files will be as given in the input DAT file.&lt;br /&gt;
&lt;br /&gt;
These options are ignored, by design:&lt;br /&gt;
* compact [whether present or absent; no algorithimic layout applied.]&lt;br /&gt;
* awayFromEdge &amp;lt;value&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Theis option is probably problematic and should be avoided for now:&lt;br /&gt;
* startFileNumber&lt;br /&gt;
&lt;br /&gt;
== Changed Behavior for Font Title from ExportFontToDoom3All256 ==&lt;br /&gt;
In ExportFontToDoom3All256, if the font title was more that 20 characters long, it would truncate it to fit in the DAT file as part of the shader names (i.e., paths to TGA files). But this threshold was wrong. Now, truncation and a warning happens if the font title is more that 17 characters long (or 16 if generated TGAs include any with a 2-digit count instead of 1-digit). If truncation occurs, the user is asked to consider using or revising the -name argument.&lt;br /&gt;
&lt;br /&gt;
== Downloads ==&lt;br /&gt;
Release v1.2 of 2025-03-31&lt;br /&gt;
* [REAL SOON]&lt;br /&gt;
&lt;br /&gt;
Release v1.1 of 2025-03-03:&lt;br /&gt;
* [https://drive.google.com/file/d/1f3Jj53qtJGIp0_mz7Riing9Fi8ESFDr5/view?usp=sharing ExportUnicodeFontToDoom3_release_1_1_exe.zip] . Windows binary and required archived versions of FreeType and DevIL DLLs.&lt;br /&gt;
* [https://drive.google.com/file/d/1nutMBfcIWw63wNTUdnlnzP397tGVpnpd/view?usp=sharing ExportUnicodeFontToDoom3_release_1_1_source_project.zip] . The C++ project file with source code, including source &amp;amp; build project of archived library.&lt;br /&gt;
&lt;br /&gt;
Release 1 of 2024-09-10:&lt;br /&gt;
* [https://drive.google.com/file/d/1MqoOfhc5-ovoxoHfRquYAcIEdHEOJAQV/view?usp=sharing ExportUnicodeFontToDoom3_release_1_exe.zip]&lt;br /&gt;
* [https://drive.google.com/file/d/1Frk_byfdtCcMqdr27ulw1XyuFj8vYp9x/view?usp=sharing ExportUnicodeFontToDoom3_release_1_source_project.zip]&lt;br /&gt;
&lt;br /&gt;
== See Also ==&lt;br /&gt;
The Cyrillic coverage of Lora Regular TTF font, projected to used as Russian Mason supplement in TDM 2.14, may be viewed and font downloaded [https://www.fontsquirrel.com/fonts/lora?filter%5Bclassifications%5D%5B0%5D=serif&amp;amp;filter%5Blanguages%5D%5B0%5D=cyrillic#eula here].&lt;/div&gt;</summary>
		<author><name>Geep</name></author>
	</entry>
	<entry>
		<id>https://wiki.thedarkmod.com/index.php?title=Refont&amp;diff=34460</id>
		<title>Refont</title>
		<link rel="alternate" type="text/html" href="https://wiki.thedarkmod.com/index.php?title=Refont&amp;diff=34460"/>
		<updated>2026-03-21T22:16:13Z</updated>

		<summary type="html">&lt;p&gt;Geep: /* Downloads */  Add comments about 2.7, 2.8 improvements&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;By Geep, 2024, and similar to the article about Q3Font.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Introduced in 2024, the &amp;quot;refont&amp;quot; command-line utility allows inspection and alteration of [[Font Metrics &amp;amp; DAT File Format | font metrics]].&lt;br /&gt;
It is designed to be an easier-to-use version of the inspection/alteration functionalities of [[Q3Font]].&lt;br /&gt;
It also provides a font analysis feature.&lt;br /&gt;
&lt;br /&gt;
== Comparison with Font Patcher ==&lt;br /&gt;
&lt;br /&gt;
Refont can be seen as complementary to [[Font Patcher]]. The latter has additional features that may be better if planning a wholesale rearrangement or expansion of characters within a bitmap, particularly for a new font immediately after conversion from a TTF font. But refont is easier to use in later years, and  Font Patcher requires installation of Perl, while refont.exe is more drop and go.&lt;br /&gt;
&lt;br /&gt;
== Comparison with Q3Font ==&lt;br /&gt;
&lt;br /&gt;
For metric alteration, q3font has a native &amp;quot;*.fnt&amp;quot; human-readable format, and supports DAT &amp;lt;==&amp;gt; FNT conversions. For compatibility, so does refont.&lt;br /&gt;
&lt;br /&gt;
=== Advantages of Q3Font ===&lt;br /&gt;
&lt;br /&gt;
* This has been an important traditional tool for Doom3/TDM font manipulation.&lt;br /&gt;
* In addition to production/consumption of FNT, it -&lt;br /&gt;
** Allows creation of DAT &amp;amp; TGA files from a TrueType font (although for this purpose, [[ExportFontToDoom3]] has been preferred in practice).&lt;br /&gt;
** Can write (but not read) an alternative &amp;quot;compact report&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
=== Advantages of Refont ===&lt;br /&gt;
&lt;br /&gt;
* It&#039;s open-source, so further C++ development is possible.&lt;br /&gt;
* It has its own native human-readable format, &amp;quot;*.ref&amp;quot;, similar to .fnt but better.&lt;br /&gt;
* The REF format can be read by [[datBounds]] to generate bitmap boundary &amp;amp; metrics visualizations.&lt;br /&gt;
&lt;br /&gt;
The better features of REF are:&lt;br /&gt;
&lt;br /&gt;
* Codepoints are enumerated in not just decimal, but also hex.&lt;br /&gt;
* Coordinates of the overall image box within its bitmap are expressed in pixel units, rather than [0...1] fractional floating point. So the user is spared having to manually do this tedious and error-prone calculation.&lt;br /&gt;
* This overcomes a drawback of FNT, that expresses the coordinates with only 6 digits after the decimal point, not quite enough to avoid minor mis-precisions.&lt;br /&gt;
* if optionally provided, a separate, read-only annotation file will automatically decorate the .ref file with helpful information as the file is generated. This is explained below.&lt;br /&gt;
&lt;br /&gt;
Because the code is open-source, there&#039;s better clarity about -&lt;br /&gt;
* how parsing and calculations are done.&lt;br /&gt;
* what warnings are emitted.&lt;br /&gt;
&lt;br /&gt;
Also, using &amp;quot;-stats&amp;quot;, refont can write (but not read) an analysis of a DAT file, particularly looking for problematic/unimplemented Western-language characters.&lt;br /&gt;
&lt;br /&gt;
== For Inspection &amp;amp; Correction of DAT files ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;To Get the Data in Readable, Editable Form&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
For viewing and altering in a text editor, two formats are provided. Both list every codepoint, in order from 0 to 255, as a block of data. Within each block, every item gets its own line.&lt;br /&gt;
&lt;br /&gt;
=== As a FNT File ===&lt;br /&gt;
&lt;br /&gt;
To create a q3font-compatable &amp;quot;&amp;lt;dat-name&amp;gt;.fnt&amp;quot; file:&lt;br /&gt;
&lt;br /&gt;
 refont -decompile &amp;lt;path to given .dat file&amp;gt; -fnt&lt;br /&gt;
&lt;br /&gt;
where the path can be a full path, a relative path (e.g., starting with &amp;quot;./&amp;quot; or &amp;quot;../&amp;quot;), or just the file name in the current working directory. The resulting .fnt file will appear in the same directory. It have the same name as the .dat file, except for the extension. As a convenience to keep track of versions, it is not required that the file name be in the standard fontImage_nn.dat form.&lt;br /&gt;
&lt;br /&gt;
Example code block for the letter A:&lt;br /&gt;
 	...&lt;br /&gt;
 	char 65&lt;br /&gt;
 	{&lt;br /&gt;
 		height 18&lt;br /&gt;
 		top 18&lt;br /&gt;
 		bottom 0&lt;br /&gt;
 		pitch 3&lt;br /&gt;
 		xSkip 18&lt;br /&gt;
 		imageWidth 20&lt;br /&gt;
 		imageHeight 18&lt;br /&gt;
 		s 0.769531&lt;br /&gt;
 		t 0.250000&lt;br /&gt;
 		s2 0.847656&lt;br /&gt;
 		t2 0.320313&lt;br /&gt;
 		glyph 0&lt;br /&gt;
 		shaderName fonts/stone_0_24.tga&lt;br /&gt;
 	}&lt;br /&gt;
  	...&lt;br /&gt;
&lt;br /&gt;
Note that Q3Font FNT expresses the s, t, s2, and t2 coordinates with only 6 digits after the decimal point, causing minor low-precision rounding during DAT --&amp;gt; FNT --&amp;gt; DAT roundtrips. For compatibility, Refont FNT does likewise.&lt;br /&gt;
&lt;br /&gt;
=== As a REF File ===&lt;br /&gt;
&#039;&#039;Starting with Refont v2.5, a mixture of 256x256 and 512x512 bitmap shaders, encountered with Carleton and Mason family fonts, can be handled. See further below.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
To create a refont-specific &amp;quot;&amp;lt;dat-name&amp;gt;.ref&amp;quot; file:&lt;br /&gt;
&lt;br /&gt;
 refont -decompile &amp;lt;path to given .dat file&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The same path and naming conventions as for .fnt generation discussed above apply here.&lt;br /&gt;
&lt;br /&gt;
Example code block for the letter A when no supplemental annotation file is present (nor any per-line comments, e.g., with warnings):&lt;br /&gt;
&lt;br /&gt;
 	...&lt;br /&gt;
 	char 65 &amp;lt;b&amp;gt;(0x41)&amp;lt;/b&amp;gt;&lt;br /&gt;
 	{&lt;br /&gt;
 		height 18&lt;br /&gt;
 		top 18&lt;br /&gt;
 		bottom 0&lt;br /&gt;
 		pitch 3&lt;br /&gt;
 		xSkip 18&lt;br /&gt;
 		imageWidth 20&lt;br /&gt;
 		imageHeight 18&lt;br /&gt;
 		&amp;lt;b&amp;gt;coord_s 197&lt;br /&gt;
 		coord_t 64&lt;br /&gt;
 		coord_s2 217&lt;br /&gt;
 		coord_t2 82&amp;lt;/b&amp;gt;&lt;br /&gt;
 		glyph 0&lt;br /&gt;
 		shaderName fonts/stone_0_24.tga&lt;br /&gt;
 	}&lt;br /&gt;
 	...&lt;br /&gt;
&lt;br /&gt;
Items bolded differ from FNT format. The starting line expresses the value in hex. And rather than s, t, s2, t2 in fractional [0...1] floating point, the &amp;quot;coord_...&amp;quot; values are expressed (and editable) as integer coordinates of the bitmap, with a range reflecting bitmap size. The default TDM bitmap size is 256x256, but a few fonts use 512x512 and require special treatment discussed further below.&lt;br /&gt;
&lt;br /&gt;
== When Editing ==&lt;br /&gt;
Refont has a minimal parser. To keep it happy, preserve the file&#039;s line structure. In particular:&lt;br /&gt;
* every REF and FNT file has the same number of lines. &#039;&#039;(Exception: REF may have additional starting lines to flag 512x512 bitmaps, discussed below. Generally, you won&#039;t edit these.)&#039;&#039;&lt;br /&gt;
* all keywords within a block must be present, and in a particular order.&lt;br /&gt;
* each block must have exactly the same number of lines (except for the special one at the end).&lt;br /&gt;
&lt;br /&gt;
The meaning of the font metrics are explained in [[Font_Metrics_%26_DAT_File_Format]]. The [[Q3Font]] article has an example of simple metric editing that is also pertinent to refont.&lt;br /&gt;
&lt;br /&gt;
== To Move Changed FNT or REF Data Back to a DAT ==&lt;br /&gt;
&lt;br /&gt;
 refont -compile &amp;lt;path to given .fnt or .ref file&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This reverses the -decompile process, to create a .dat file whose name is derived from the .fnt or .ref file. Importantly, this decompile/compile cycle leaves .tga/.dds files untouched.&lt;br /&gt;
&lt;br /&gt;
== The Annotation File ==&lt;br /&gt;
When told to generate a REF file (but not FNT), refont.exe also looks for a file called &amp;quot;refont_char_annotations.txt&amp;quot;, in the same folder as refont.exe.  That file should have exactly 256 data lines in it, one for each of the codepoints, in order. As the REF is generated, the line that starts a codepoint&#039;s data block gets the corresponding annotation line appended  to it. Having the annotations come from an external file, instead of hard-coded into refont, allows required flexibility as to what information is presented. It even potentially allows refont to be used with other idTech3/4 games that don&#039;t necessarily used the TDM-specific codepoints. Also, the annotation files contain helpful specific comments (as lines that start with &amp;quot;;&amp;quot;).&lt;br /&gt;
&lt;br /&gt;
Each annotation:&lt;br /&gt;
* indicates what character symbol is &#039;&#039;expected&#039;&#039;; it is oblivious as to what character if any is actually within the bounding box described by the DAT data.&lt;br /&gt;
* lives only in a REF file, and is not retained when converted to a DAT file. This also true for any manual supplementary annotations you might make.&lt;br /&gt;
&lt;br /&gt;
This is clearer with examples. In &#039;Downloads&#039; below are 4 different versions of &amp;quot;refont_char_annotations[...].txt&amp;quot;. Three of these, specific to TDM&#039;s custom &#039;english&#039; (i.e., composite European) codepage, are discussed here. To deploy, edit the filename of one of them to remove the square bracket text.&lt;br /&gt;
&lt;br /&gt;
=== English with Symbol Only ===&lt;br /&gt;
&lt;br /&gt;
This simple format is best for most purposes. The file entry for letter &#039;A&#039; is just:&lt;br /&gt;
&lt;br /&gt;
 A&lt;br /&gt;
&lt;br /&gt;
Then the block in a generated REF file would have that string appended, but with &amp;quot; // &amp;quot; inserted.&lt;br /&gt;
 	...&lt;br /&gt;
 	char 65 (0x41) // A&lt;br /&gt;
 	{&lt;br /&gt;
 		height 18&lt;br /&gt;
 		top 18&lt;br /&gt;
 		bottom 0&lt;br /&gt;
 		pitch 3&lt;br /&gt;
 		xSkip 18&lt;br /&gt;
 		imageWidth 20&lt;br /&gt;
 		imageHeight 18&lt;br /&gt;
 		coord_s 197&lt;br /&gt;
 		coord_t 64&lt;br /&gt;
 		coord_s2 217&lt;br /&gt;
 		coord_t2 82&lt;br /&gt;
 		glyph 0&lt;br /&gt;
 		shaderName fonts/stone_0_24.tga&lt;br /&gt;
 	}&lt;br /&gt;
 	...&lt;br /&gt;
&lt;br /&gt;
=== English with Unicode-16 Codes and Names ===&lt;br /&gt;
&lt;br /&gt;
This supplies the Unicode Consortium&#039;s official 16-bit codepoints (where U+NNNN = 0xNNNN) and their names, in the formal all-caps convention.&lt;br /&gt;
&lt;br /&gt;
The file entry for letter &#039;A&#039; is:&lt;br /&gt;
&lt;br /&gt;
 U+0041 LATIN CAPITAL LETTER A&lt;br /&gt;
&lt;br /&gt;
Then the first line of the corresponding block in a generated REF file would show:&lt;br /&gt;
 	...&lt;br /&gt;
 	char 65 (0x41) // U+0041 LATIN CAPITAL LETTER A&lt;br /&gt;
 	...&lt;br /&gt;
Here&#039;s another example from that REF:&lt;br /&gt;
 	...&lt;br /&gt;
 	char 129 (0x81) // U+015A LATIN CAPITAL LETTER S WITH ACUTE&lt;br /&gt;
 	...&lt;br /&gt;
For control or TDM undefined characters, this annotation file assumes a hollow box glyph is the appropriate mapping:&lt;br /&gt;
 	...&lt;br /&gt;
 	char 0 (0x00) // U+24A1 WHITE SQUARE&lt;br /&gt;
 	...&lt;br /&gt;
But there are other choices, so edit the annotation file as you see fit.&lt;br /&gt;
=== English with 8859-x Source ===&lt;br /&gt;
&lt;br /&gt;
This verbose format may be useful during font analysis. For letters that are in their expected locations as defined by ASCII or ISO 8859-1 (Latin-1) or Windows-1252 (&amp;quot;Western Europe&amp;quot;), the annotation is fairly minimal. Thus, letter &#039;A&#039; has this:&lt;br /&gt;
&lt;br /&gt;
 0x41 is A&lt;br /&gt;
&lt;br /&gt;
(TIP: If authoring your own annotation file, consider including a codepoint number on each line, like &amp;quot;0x41&amp;quot; here, to make the process easier.)&lt;br /&gt;
&lt;br /&gt;
Then the first line of the corresponding block in a generated REF file would show:&lt;br /&gt;
 	...&lt;br /&gt;
 	char 65 (0x41) // 0x41 is A&lt;br /&gt;
 	...&lt;br /&gt;
Here are a few more interesting examples from that REF, with more expansive annotations:&lt;br /&gt;
 	...&lt;br /&gt;
 	char 5 (0x05) // 0x05 is a control character, unusable in TDM&lt;br /&gt;
 	...&lt;br /&gt;
 	char 166 (0xa6) // 0xA6 is Š (not ISO 8859-1 ¦) (from A9 in ISO 8859-2) (TDM only)&lt;br /&gt;
 	...&lt;br /&gt;
&lt;br /&gt;
== Revising or Making Your Own Annotations File ==&lt;br /&gt;
If creating your own refont_char_annotations.txt file, note that encoding upper-range characters in UTF-8 will be more universal than using Windows region-specific codepages. To enter a UTF-8 character using its four digit hex Unicode (say, in a range of interest 0x0080-0x00FF):&lt;br /&gt;
* Under Windows, type the four hex digits followed by Alt-X.&lt;br /&gt;
* Under Linux, hold down Ctrl+Shift, type U followed by the 4 digits; release Ctrl+Shift.&lt;br /&gt;
&lt;br /&gt;
When refont reads refont_char_annotations.txt, any line that starts with &amp;quot;;&amp;quot; will be ignored. The latter is so that you can put comments into the file, that will not propagate to the generated REF file. TIP: If such commenting is unwanted, start the line with &amp;lt;space&amp;gt; before &amp;quot;;&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Other than that, be sure to have exactly 256 lines of annotations (though refont will check and issue a warning if not). A line can be empty, i.e., have only the linebreak.&lt;br /&gt;
&lt;br /&gt;
When generating a REF file, refont will automatically add &amp;quot; // &amp;quot; before each non-empty annotation, so don&#039;t include that.&lt;br /&gt;
&lt;br /&gt;
== Adding Your Own Annotations to a REF File ==&lt;br /&gt;
Beyond the refont_char_annotation.txt content, you can add certain commentary to the REF file without it affecting its ability to convert to a DAT file. Here are the rules:&lt;br /&gt;
* Don&#039;t add or subtract lines, or comment out non-blank lines&lt;br /&gt;
* Feel free to append a comment to the end of a line, by beginning the comment with &amp;quot; //&amp;quot;.&lt;br /&gt;
* Likewise, on a line starting with &amp;quot;char&amp;quot; that had an annotation automatically added, you can revise the annotation as you see fit.&lt;br /&gt;
&lt;br /&gt;
Example with revision in bold:&lt;br /&gt;
 	...&lt;br /&gt;
 	char 65 (0x41) // &#039;&#039;&#039;Capital A was slightly clipped. Decremented s, s2 by 1. Looks OK now.&#039;&#039;&#039;&lt;br /&gt;
 	{&lt;br /&gt;
 		height 18&lt;br /&gt;
 		top 18&lt;br /&gt;
 		bottom 0&lt;br /&gt;
 		pitch 3&lt;br /&gt;
 		xSkip 18&lt;br /&gt;
 		imageWidth 20&lt;br /&gt;
 		imageHeight 18&lt;br /&gt;
 		coord_s 196 &#039;&#039;&#039;// WAS: 197&#039;&#039;&#039;&lt;br /&gt;
 		coord_t 64&lt;br /&gt;
 		coord_s2 216 &#039;&#039;&#039;// WAS: 217&#039;&#039;&#039;&lt;br /&gt;
 		coord_t2 82&lt;br /&gt;
 		glyph 0&lt;br /&gt;
 		shaderName fonts/stone_0_24.tga&lt;br /&gt;
  	}&lt;br /&gt;
 	...&lt;br /&gt;
&lt;br /&gt;
In this way, you can markup a REF file as a record of work to do, work in progress, or work completed.&lt;br /&gt;
&lt;br /&gt;
==Errors, Warnings, and Auto-Corrections==&lt;br /&gt;
&#039;&#039;This covers the major overhaul of Refont v 2.1, and its added options -no_warn_comments and -scaling_ok.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
During the compile or decompile, errors and warnings may be generated in the console. Fatal errors are largely due to: &lt;br /&gt;
* file I/O problems;&lt;br /&gt;
* deviations from the strict DAT, REF, and FNT formats.&lt;br /&gt;
&lt;br /&gt;
Warnings, which are not fatal, are largely due to anomolous numeric values. The TDM engine can tolerant some of these, so they don&#039;t necessarily need fixing. &lt;br /&gt;
&lt;br /&gt;
===Fatal Errors when Parsing REF or FNT as Input===&lt;br /&gt;
A fatal error, due to divergence from the expected format while parsing, stops the program. While potentially due to many causes (e.g., adding or deleting lines), errors will be reported - with line number - as failures of:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Variable Name Checks.&#039;&#039; The parser expects every variable name in a particular order. A mismatch happened.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Integer Checks.&#039;&#039; Integer value was unparsable, or out of range for integer type. Checked for per-character variables height, top, bottom, pitch, xSkip, imageWidth, imageHeight, and glyph. Plus REF’s coord_s, coord_t, coord_s2, and coord_ t2.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Float Checks.&#039;&#039; Floating point value was unparsable, or out of range for float type. Checked for glyphScale, and FNT’s per-character variables s, t, s2, t2.&lt;br /&gt;
&lt;br /&gt;
===Post-Read MAJOR Warnings about REF, FNT, and DAT Input Values===&lt;br /&gt;
After parsing, the input process concludes with a separate loop of non-fatal warning analysis. Warnings during input, broadly categorized as major or minor, report to the console, but don’t do any value corrections (which is instead left to the subsequent file-write stage).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;For FNT’s and DAT’s s, t, s2, t2&#039;&#039;&lt;br /&gt;
* Inexact Integer. The given bounding box value, expected in the range 0-1, when multiplied by 256.0 should be exactly an integer. If not, the divergence is likely due to miscalculation.  (Actually, a divergence from an integer of under +/- 0.001 is tolerated by Refont and considered a minor warning, discussed below.) &lt;br /&gt;
* Float Out of Range 0.0 - 1.0. Or equivalently, post-multiplication, 0.0 - 256.0. (See the discussion of the edge cases under minor warnings below.)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;For Other Metrics of DAT, FNT, and REF&#039;&#039;&lt;br /&gt;
* Integer Out of Range 0-256. For height, top, bottom, pitch, xSkip, imageWidth, imageHeight, and REF’s coord_s, coord_t, coord_s2, and coord_t2.&lt;br /&gt;
* Integer Non Zero. For glyph.&lt;br /&gt;
* Float Less Than Zero. For glyphScale (which is independent of a particular character).&lt;br /&gt;
* Inconsistent Metrics. For a given character, this compares two metrics and looks for inconsistencies. We’ll state this here in REF terms, e.g., using “coord_s” rather than “ROUND_TO_INT(s * 256.0f)”:&lt;br /&gt;
** imageHeight == height?&lt;br /&gt;
** imageWidth == coord_s2 - coord_s?&lt;br /&gt;
** imageHeight == coord_t2 - coord_t?&lt;br /&gt;
&lt;br /&gt;
However, warnings about those last two &amp;quot;Inconsistent Metrics&amp;quot; criteria are suppressed if:&lt;br /&gt;
* you use refont&#039;s &amp;quot;-scaling_ok&amp;quot; option. This is helpful when there is extensive per-character scaling. (Only TDM’s mason and mason-glow use a lot of per-character scaling, specifically for all upper-case characters.)&lt;br /&gt;
* you have a 512x512 bitmap, where throughout, the imageWidth and imageHeight (and some other metrics) are expected to be scaled to &amp;quot;half&amp;quot; of the corresponding coord difference. As of refont 2.8, 1 pixel of wiggle-room is allowed for integer rounding. Only warnings will be issued that fail these checks:&lt;br /&gt;
** abs(imageWidth * 2 - (coord_s2 - coord_s)) &amp;gt; 1&lt;br /&gt;
** abs(imageHeight * 2 - (coord_t2 - coord_t)) &amp;gt; 1&lt;br /&gt;
&lt;br /&gt;
===Post-Read MINOR Warnings for FNT’s and DAT’s s, t, s2, t2===&lt;br /&gt;
&#039;&#039;Low Precision.&#039;&#039; This value, when multiplied by 256.0, should be exactly an integer. However, some generation or revision procedure (e.g., Q3Font’s DAT  FNT  DAT) may have not used sufficient precision to ensure this. An offset from an integer value of less than +/- 0.001 is considered a minor problem; otherwise, major as above.&lt;br /&gt;
&lt;br /&gt;
This problem, when it occurs with a file, typically happens a lot. Consequently, it is not reported in an itemized way, but instead, the console will show total counts of affected characters and values.&lt;br /&gt;
&lt;br /&gt;
Edge cases: a value of {s, s2, t, or t2} * 256.0 that is negative but closer to zero than -0.001000 is considered this type of minor problem (and is not considered out of range, which would be major). Likewise, if that value is greater than 256.000000, but less than 256.001000&lt;br /&gt;
===Automatic Corrections during Output to a REF File===&lt;br /&gt;
Certain problems, first detected during DAT input, are further addressed at write time. Because these problems were already reported to the console during the DAT read, nothing additional is written to console. Instead, there may be reporting within the REF file itself.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Automatic Corrections.&#039;&#039; When writing a REF file, the integer values of coord_s, coord_t, coord_s2, and coord_t2 are calculated from DAT floats s, t, s2, and t2 respectively. A calculated coord_... value, if not already resulting in an integer, is automatically forced to the nearest integer. This is so whether it was earlier reported to the console as a Major or Minor Warning. (Before refont v 2.1, the REF might assign an unrounded decimal value; no longer true.)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Warnings Not Automatically Corrected.&#039;&#039; Automatic fixing of other warnings is unwise and not offered. Why? Because the fix is not obvious or complex, and sometimes, the corresponding character glyph in the bitmap needs adjustment. This pertains to Major Warnings about:&lt;br /&gt;
* Integer values outside their expected range (e.g., 0-256), including post-rounding coord_... values.&lt;br /&gt;
* Inconsistent Metrics&lt;br /&gt;
===Generated Within-REF Comments during Output===&lt;br /&gt;
For most causes of a Major Warning during DAT read, during subsequent writing of the REF file, a similar comment is also generated within the REF, on the same line as the parameter assignment. For example:&lt;br /&gt;
 char 95 (0x5f) // _&lt;br /&gt;
 {&lt;br /&gt;
    ...&lt;br /&gt;
    top -6 // WARNING: Not in range 0-256. Does bitmap or other metrics need adjusting?&lt;br /&gt;
    ...&lt;br /&gt;
 }&lt;br /&gt;
 ...&lt;br /&gt;
 char 140 (0x8c) // Ń&lt;br /&gt;
 {&lt;br /&gt;
    ...&lt;br /&gt;
    coord_t -10 // WARNING: Underlying DAT value -0.03906250, * 256.0 gave -10.000000000, not in range 0-256 once rounded. Does bitmap or other metrics need adjusting?&lt;br /&gt;
    ...&lt;br /&gt;
 }&lt;br /&gt;
&#039;&#039;Suppressing Comment Generation.&#039;&#039; Use the refont option “-no_warn_comments”. &#039;&#039;New to v 2.1.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
TIP: When editing a REF file with comments, you can keep them, change them, or delete them as you prefer. They have no impact on subsequent compiles to DAT.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Coverage of Generated Within-REF Comments.&#039;&#039; A calculated value of coord_s, coord_t, coord_s2, or coord_t2 would have been flagged as a “Major Warning” during read if:&lt;br /&gt;
* the discrepancy from being an integer was non-trivial (+/- 0.001 or more), or&lt;br /&gt;
* the calculated and rounded integer is outside the range given by bitmap size, e.g., 0-256.&lt;br /&gt;
&lt;br /&gt;
For these, a comment is generated. Other causes are:&lt;br /&gt;
* Integer Out of Range 0-256 &#039;&#039;(or 0-512 as applicable)&#039;&#039;. For height, top, bottom, pitch, xSkip, imageWidth, imageHeight.&lt;br /&gt;
* Integer Non Zero. For glyph.&lt;br /&gt;
* Float Less Than Zero. For glyphScale (which is independent of a particular character).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Major Warnings that Don’t Cause Within-REF Comments.&#039;&#039; Currently, this is limited to “Inconsistent Metrics”, which would probably require tagging on multiple lines.&lt;br /&gt;
&lt;br /&gt;
== Special Handling of Fonts with 512x512 Bitmaps ==&lt;br /&gt;
Some DAT files reference bitmap shaders where some or all are of size 512x512, instead of the default 256x256. Refont v2.5+ can support this (replacing an insufficient first attempt in v2.4).&lt;br /&gt;
&lt;br /&gt;
Font developers went to double-sized bitmaps to:&lt;br /&gt;
* in the case of Carleton, allow freehand drawing of missing European characters, which could be drawn more easily if twice standard size.&lt;br /&gt;
* in the case of Mason, have larger ASCII alphanumeric glyphs that would render with crisper edges.&lt;br /&gt;
&lt;br /&gt;
In either case, the font characters when rendered in, say, the game main menu will be the same size as if from 256x256. This is because the imageWidth, imageHeight, height, and top metrics are not doubled.&lt;br /&gt;
In effect, a scaling by half (approximately, as constrained by integer values) is requested for all characters in the DAT file and applied by the engine.&lt;br /&gt;
&lt;br /&gt;
=== When generating a REF file from a DAT file ===&lt;br /&gt;
&lt;br /&gt;
 refont -decompile &amp;lt;path to given .dat file&amp;gt; -512_&amp;lt;n&amp;gt;   &#039;&#039;where &amp;lt;n&amp;gt; is a single digit, e.g. &#039;1&#039; in referenced shader name &amp;quot;font/Carleton_1_24.tga&amp;quot; &#039;&#039;&lt;br /&gt;
&lt;br /&gt;
You should use multiple instances of the -512_&amp;lt;n&amp;gt; option, to cover all the 512x512 bitmaps found in the DAT file.&lt;br /&gt;
&lt;br /&gt;
If &#039;&#039;all&#039;&#039; of a given DATs shaders are 512x512, you can use this shorter form:&lt;br /&gt;
&lt;br /&gt;
 refont -decompile &amp;lt;path to given .dat file&amp;gt; -512&lt;br /&gt;
&lt;br /&gt;
Exercising -512... options will mean that in the generated REF file:&lt;br /&gt;
&lt;br /&gt;
* There will be a one or more starting lines like:&lt;br /&gt;
  # bitmap_&amp;lt;n&amp;gt;_size=512 &#039;&#039;(Refont will look for this if doing a subsequent compile to DAT)&#039;&#039;&lt;br /&gt;
* If you specified the short form, it will expand to just the right number of starting lines.&lt;br /&gt;
* Values for coord_s, coord_s2, coord_t, and coord_t2 will have a normal range of 0-512 when appropriate. [COMING SOON: Those values may then be read properly by datBounds.].&lt;br /&gt;
* Any warnings expressed (within the file or within the command-line window) will be in terms of the correct range of values. &lt;br /&gt;
* Warning checks will expect a scaling by half for all characters. That is, while 512... requires scaling down by half, that scaling will not generate a warning (unless it&#039;s not EXACTLY by half, or within 1 pixel of that), so the -scaling_ok option is not needed just for the exactly-by-half scaling.&lt;br /&gt;
&lt;br /&gt;
=== When generating a DAT file from a REF file ===&lt;br /&gt;
&lt;br /&gt;
During refont -compile, no special command line options are needed. Instead, REF&#039;s starting lines of form &amp;quot;# bitmap_&amp;lt;n&amp;gt;_size=512&amp;quot; are inspected and coord ranges will be interpreted as 0-512 whenever appropriate. &lt;br /&gt;
&lt;br /&gt;
=== Special Handling Recommendations for Carleton and Mason ===&lt;br /&gt;
&#039;&#039;For fonts shipped with TDM 2.12 in tdm_fonts01.pk4. Illustrative command paths are shown; adjust to your working copy.&#039;&#039;&lt;br /&gt;
==== Mason Family ====&lt;br /&gt;
The [[Mason Font]] uses within-DAT per-character scaling, as well as some but not all 512x512 bitmaps. Only 48pt Mason is shipped.&lt;br /&gt;
&lt;br /&gt;
Because, under /dds/fonts/english/mason/, bitmaps masonalternate_0_48.dds to _2_ are 512x512, but _3_ to _5_ are not, use:&lt;br /&gt;
&lt;br /&gt;
 -decompile /fonts/english/mason/fontimage_48.dat -512_0 -512_1 -512_2 -scaling_ok&lt;br /&gt;
&lt;br /&gt;
Because, under /dds/fonts/english/mason_glow/, bitmaps masonalternate_1_48.dds and _2_ are 512x512, but _0_ and _3_ to _5_ are not, use:&lt;br /&gt;
&lt;br /&gt;
 -decompile /fonts/english/mason_glow/fontimage_48.dat -512_1 -512_2 -scaling_ok&lt;br /&gt;
&lt;br /&gt;
Russian versions use the default 256x256. [These possibly benefit from -scaling_ok; didn&#039;t investigate.]&lt;br /&gt;
==== Carleton Family ====&lt;br /&gt;
The 24pt size of carleton has two bitmaps under /dds/fonts/english/carleton/, namely carleton_0_24.dds and _1_, both of size 512x512. So use:&lt;br /&gt;
&lt;br /&gt;
 -decompile /fonts/english/carleton/fontimage_24.dat -512_0 -512_1&lt;br /&gt;
  &#039;&#039;or&#039;&#039;&lt;br /&gt;
 -decompile /fonts/english/carleton/fontimage_24.dat -512&lt;br /&gt;
 &lt;br /&gt;
The 24pt size of carleton_bold has bitmaps with identical content to carleton&#039;s, so use the same options:&lt;br /&gt;
&lt;br /&gt;
 -decompile /fonts/english/carleton_bold/fontimage_24.dat -512_0 -512_1&lt;br /&gt;
  &#039;&#039;or&#039;&#039;&lt;br /&gt;
 -decompile /fonts/english/carleton_bold/fontimage_24.dat -512&lt;br /&gt;
&lt;br /&gt;
Other members of this family use the default 256x256 bitmaps:&lt;br /&gt;
* Sizes 12pt &amp;amp; 48pt&lt;br /&gt;
* carleton_condensed and carleton_glow. (Note: while helpful, it is not required that the base &amp;amp; glow have identical bitmap sizes.)&lt;br /&gt;
* Russian versions&lt;br /&gt;
&lt;br /&gt;
==== These Fonts with Stats ====&lt;br /&gt;
With -stats discussed next, if reading a DAT file, you may use the -512... and scaling_ok options to be most correct, although neglecting to specify them will likely have no significant impact on the analytical results. If reading a REF file, the included &amp;quot;# bitmap_...&amp;quot; lines will take care of that for you.&lt;br /&gt;
&lt;br /&gt;
== For Statistics on Unimplemented or Problematic Font Characters ==&lt;br /&gt;
DAT or (as of v2.3) REF file analysis here is primarily designed to benefit english/european fonts. It will use the optional annotation file if provided. Syntax:&lt;br /&gt;
&lt;br /&gt;
     refont -stats &amp;lt;path to given .dat or .ref file&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Use &amp;quot;-stats&amp;quot; by itself, not combined with &amp;quot;-compile&amp;quot; or &amp;quot;-decompile&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
The resulting analysis report will have the same name and location as the input file, but with a &amp;quot;.txt&amp;quot; suffix.&lt;br /&gt;
The report provides categorized totals and (for problematic characters) itemizations across all 256 character codepoints.&lt;br /&gt;
The counts of problems should be considered minimums, since no inspection of bitmap files (TGA or DDS) is done.&lt;br /&gt;
But a perhaps surprising amount of insight can be gleaned just from DAT/REF file metrics.&lt;br /&gt;
Itemizations include annotations from the &#039;ref_char_annotation&#039; file, if provided.&lt;br /&gt;
&lt;br /&gt;
In the hunt for missing characters, 3 signatures are important:&lt;br /&gt;
&lt;br /&gt;
* Presumed &#039;Hollow Box&#039; = glyph&#039;s &#039;shadername&#039; is &amp;lt;fontname&amp;gt;_0_&amp;lt;size&amp;gt;.dds only, and s &amp;amp; t are zero, but not s2 &amp;amp; t2&lt;br /&gt;
* &#039;&amp;lt;Space&amp;gt;&#039; = same test as &#039;Hollow Box&#039;, but pointed to by char 32 (0x20)&lt;br /&gt;
* &#039;Zero Box&#039; = No glyph box (s, t, s2, t2 all zero)&lt;br /&gt;
&lt;br /&gt;
A given analysis will assume either &#039;Hollow Box&#039; or &#039;&amp;lt;Space&amp;gt;&#039; but not both.&lt;br /&gt;
&lt;br /&gt;
The analysis provides totals and itemizations - grouped into lower (0-127) and upper ranges (128-255) - in several passes: &lt;br /&gt;
&lt;br /&gt;
* Pass 1 - Handling of unprintable/unsupported/missing codepoints, indicated by Hollow Box, Zero Box, or &amp;lt;Space&amp;gt;. Some of these are not a problem, but some are tagged as &amp;quot;Undesirable&amp;quot;.&lt;br /&gt;
* Pass 2 - Bad glyph box (negative s, t, s2, or t2; or s2 &amp;lt;= s, t2 &amp;lt;= t) or good glyph box with dubious metrics (imageHeight &amp;lt;= 0, imageWidth &amp;lt;=0, imageHeight != height). Excludes those already counted as &amp;quot;Undesirable&amp;quot; in Pass 1. &lt;br /&gt;
* Pass 3 - Detection of duplicate glyph boxes (other than Hollow Box, Zero Box, or &amp;lt;Space&amp;gt;). Detected by: glyph&#039;s values for shadername, s, t, s2, &amp;amp; t2 exactly match those of another codepoint. These are grouped into &amp;quot;Dup Sets&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Then, across passes 1-3, a count if given of the minimum &amp;quot;Total Glyphs Needing Work&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Refont version 2.3 adds additional passes:&lt;br /&gt;
&lt;br /&gt;
* Pass 4 - Reports &amp;quot;Overlap Sets&amp;quot; rather than just &amp;quot;Dup Sets&amp;quot;. A set here may include an unaccented &amp;quot;base character&amp;quot; that has been serving as a substitute work-around target for one or more missing accented characters. (What constitutes an &amp;quot;overlap&amp;quot; is idiosyncratic; see the source code for details.)&lt;br /&gt;
* Pass 5 - Same information as Pass 4, but sorted first by shader name (i.e., bitmap). Helpful for organizing bitmap-editing work.&lt;br /&gt;
* Pass 6 - An analysis focusing just on the planned migration of duplicate O/o-circumflex codepoints to G/g-cup glyphs.&lt;br /&gt;
&lt;br /&gt;
== Downloads ==&lt;br /&gt;
Release 2.8 of March 19, 2026:&lt;br /&gt;
* Supports partial coverage regeneration (i.e., unicodeMap with not all 256 represented) by ExportUnicodeFontToDoom3.&lt;br /&gt;
* With 512x512 bitmaps, suppresses scaling warnings if scaled by &amp;quot;half&amp;quot;, now +/- 1 pixel.&lt;br /&gt;
* [https://drive.google.com/file/d/1BHGkCOhgXP7bFp1mXyfgoRBUtqkbCVRb/view?usp=sharing refont.exe]&lt;br /&gt;
* [https://drive.google.com/file/d/1Cca_Xo3W5jYB_40RVo4aIPHAGIufA9V0/view?usp=sharing refont_source_v2.8.zip, with refont.cpp, refont.sln, open-source license]&lt;br /&gt;
&lt;br /&gt;
Version 2.7: Fixes poor detection of _&amp;lt;n&amp;gt;_ pattern in shadername, and allow &amp;lt;n&amp;gt; to be 1 or 2 digits, not just 1.&lt;br /&gt;
&lt;br /&gt;
Release 2.6 of July 28, 2025:&lt;br /&gt;
* [https://drive.google.com/file/d/1ABf4771Jr1C1hKbLx4xWq8lx8Kn7HdKP/view?usp=sharing refont.exe]&lt;br /&gt;
* [https://drive.google.com/file/d/1-k68eo0CHKZ-sM7JGP05axm49cc5De0T/view?usp=sharing source code: refont.cpp]&lt;br /&gt;
&lt;br /&gt;
===Annotations===&lt;br /&gt;
&#039;&#039;After download, to use any one of these, edit filename to remove &amp;quot;[...]&amp;quot; substring.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Update of June 20, 2024. This reflects a change to the TDM charmap for 2.13, to replace duplicate O/o circumflex characters with G/g breve:&lt;br /&gt;
&lt;br /&gt;
* refont_char_annotations[english with symbol only. With G-breve update].txt [https://drive.google.com/file/d/1rrt-O9DgD7Zn2Hxt7nBtViIlO4kv_gQB/view?usp=sharing here]. Recommended for most purposes with &#039;english&#039; fonts.&lt;br /&gt;
* refont_char_annotations[english with Unicode-16 codes &amp;amp; names. With G-breve update].txt [https://drive.google.com/file/d/1AMxDKQc_DE33gsExiEkGp3x67eb4aGFh/view?usp=sharing here].&lt;br /&gt;
* refont_char_annotations[english with 8859-x source. With G-breve update].txt [https://drive.google.com/file/d/1xoeZ1poTbmkls-gE5PnbbMxdoz5KnMD7/view?usp=sharing].&lt;br /&gt;
* For Russian, see the previous update next.&lt;br /&gt;
&lt;br /&gt;
Update of April 13, 2024:&lt;br /&gt;
&lt;br /&gt;
* refont_char_annotations[english with symbol only].txt [https://drive.google.com/file/d/1ItM-aXps0xQE655HdaJM7Aje5lHewUfC/view?usp=sharing here]. Recommended for most purposes with &#039;english&#039; fonts.&lt;br /&gt;
* refont_char_annotations[english with Unicode-16 codes and names].txt [https://drive.google.com/file/d/1gW7oO_wLqCEPSdm6b05OaTNYHnyuUSA-/view?usp=sharing here].&lt;br /&gt;
* refont_char_annotations[english with 8859-x source].txt [https://drive.google.com/file/d/1ZTcgA4QJYwXzNdqbolYkn0CCEDILD1bX/view?usp=sharing here]. Corrects and supersedes original english file.&lt;br /&gt;
* refont_char_annotations[russian].txt [https://drive.google.com/file/d/10txNXsSCtaTiT2iGT9o3iDxBU7HVYNxi/view?usp=sharing here]. Recommended for &#039;russian&#039; fonts.&lt;br /&gt;
&lt;br /&gt;
== For More ==&lt;br /&gt;
* See the [https://forums.thedarkmod.com/index.php?/topic/22427-analysis-of-212-tdm-fonts/ summary analysis of 2.12 TDM fonts], based on applying &#039;refont -stats ...&#039; to all &#039;english&#039; DAT files.&lt;br /&gt;
&lt;br /&gt;
{{tutorial}} [[Category:Fonts]]&lt;/div&gt;</summary>
		<author><name>Geep</name></author>
	</entry>
	<entry>
		<id>https://wiki.thedarkmod.com/index.php?title=Refont&amp;diff=34448</id>
		<title>Refont</title>
		<link rel="alternate" type="text/html" href="https://wiki.thedarkmod.com/index.php?title=Refont&amp;diff=34448"/>
		<updated>2026-03-19T17:46:28Z</updated>

		<summary type="html">&lt;p&gt;Geep: /* Downloads */ v 2.8 released&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;By Geep, 2024, and similar to the article about Q3Font.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Introduced in 2024, the &amp;quot;refont&amp;quot; command-line utility allows inspection and alteration of [[Font Metrics &amp;amp; DAT File Format | font metrics]].&lt;br /&gt;
It is designed to be an easier-to-use version of the inspection/alteration functionalities of [[Q3Font]].&lt;br /&gt;
It also provides a font analysis feature.&lt;br /&gt;
&lt;br /&gt;
== Comparison with Font Patcher ==&lt;br /&gt;
&lt;br /&gt;
Refont can be seen as complementary to [[Font Patcher]]. The latter has additional features that may be better if planning a wholesale rearrangement or expansion of characters within a bitmap, particularly for a new font immediately after conversion from a TTF font. But refont is easier to use in later years, and  Font Patcher requires installation of Perl, while refont.exe is more drop and go.&lt;br /&gt;
&lt;br /&gt;
== Comparison with Q3Font ==&lt;br /&gt;
&lt;br /&gt;
For metric alteration, q3font has a native &amp;quot;*.fnt&amp;quot; human-readable format, and supports DAT &amp;lt;==&amp;gt; FNT conversions. For compatibility, so does refont.&lt;br /&gt;
&lt;br /&gt;
=== Advantages of Q3Font ===&lt;br /&gt;
&lt;br /&gt;
* This has been an important traditional tool for Doom3/TDM font manipulation.&lt;br /&gt;
* In addition to production/consumption of FNT, it -&lt;br /&gt;
** Allows creation of DAT &amp;amp; TGA files from a TrueType font (although for this purpose, [[ExportFontToDoom3]] has been preferred in practice).&lt;br /&gt;
** Can write (but not read) an alternative &amp;quot;compact report&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
=== Advantages of Refont ===&lt;br /&gt;
&lt;br /&gt;
* It&#039;s open-source, so further C++ development is possible.&lt;br /&gt;
* It has its own native human-readable format, &amp;quot;*.ref&amp;quot;, similar to .fnt but better.&lt;br /&gt;
* The REF format can be read by [[datBounds]] to generate bitmap boundary &amp;amp; metrics visualizations.&lt;br /&gt;
&lt;br /&gt;
The better features of REF are:&lt;br /&gt;
&lt;br /&gt;
* Codepoints are enumerated in not just decimal, but also hex.&lt;br /&gt;
* Coordinates of the overall image box within its bitmap are expressed in pixel units, rather than [0...1] fractional floating point. So the user is spared having to manually do this tedious and error-prone calculation.&lt;br /&gt;
* This overcomes a drawback of FNT, that expresses the coordinates with only 6 digits after the decimal point, not quite enough to avoid minor mis-precisions.&lt;br /&gt;
* if optionally provided, a separate, read-only annotation file will automatically decorate the .ref file with helpful information as the file is generated. This is explained below.&lt;br /&gt;
&lt;br /&gt;
Because the code is open-source, there&#039;s better clarity about -&lt;br /&gt;
* how parsing and calculations are done.&lt;br /&gt;
* what warnings are emitted.&lt;br /&gt;
&lt;br /&gt;
Also, using &amp;quot;-stats&amp;quot;, refont can write (but not read) an analysis of a DAT file, particularly looking for problematic/unimplemented Western-language characters.&lt;br /&gt;
&lt;br /&gt;
== For Inspection &amp;amp; Correction of DAT files ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;To Get the Data in Readable, Editable Form&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
For viewing and altering in a text editor, two formats are provided. Both list every codepoint, in order from 0 to 255, as a block of data. Within each block, every item gets its own line.&lt;br /&gt;
&lt;br /&gt;
=== As a FNT File ===&lt;br /&gt;
&lt;br /&gt;
To create a q3font-compatable &amp;quot;&amp;lt;dat-name&amp;gt;.fnt&amp;quot; file:&lt;br /&gt;
&lt;br /&gt;
 refont -decompile &amp;lt;path to given .dat file&amp;gt; -fnt&lt;br /&gt;
&lt;br /&gt;
where the path can be a full path, a relative path (e.g., starting with &amp;quot;./&amp;quot; or &amp;quot;../&amp;quot;), or just the file name in the current working directory. The resulting .fnt file will appear in the same directory. It have the same name as the .dat file, except for the extension. As a convenience to keep track of versions, it is not required that the file name be in the standard fontImage_nn.dat form.&lt;br /&gt;
&lt;br /&gt;
Example code block for the letter A:&lt;br /&gt;
 	...&lt;br /&gt;
 	char 65&lt;br /&gt;
 	{&lt;br /&gt;
 		height 18&lt;br /&gt;
 		top 18&lt;br /&gt;
 		bottom 0&lt;br /&gt;
 		pitch 3&lt;br /&gt;
 		xSkip 18&lt;br /&gt;
 		imageWidth 20&lt;br /&gt;
 		imageHeight 18&lt;br /&gt;
 		s 0.769531&lt;br /&gt;
 		t 0.250000&lt;br /&gt;
 		s2 0.847656&lt;br /&gt;
 		t2 0.320313&lt;br /&gt;
 		glyph 0&lt;br /&gt;
 		shaderName fonts/stone_0_24.tga&lt;br /&gt;
 	}&lt;br /&gt;
  	...&lt;br /&gt;
&lt;br /&gt;
Note that Q3Font FNT expresses the s, t, s2, and t2 coordinates with only 6 digits after the decimal point, causing minor low-precision rounding during DAT --&amp;gt; FNT --&amp;gt; DAT roundtrips. For compatibility, Refont FNT does likewise.&lt;br /&gt;
&lt;br /&gt;
=== As a REF File ===&lt;br /&gt;
&#039;&#039;Starting with Refont v2.5, a mixture of 256x256 and 512x512 bitmap shaders, encountered with Carleton and Mason family fonts, can be handled. See further below.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
To create a refont-specific &amp;quot;&amp;lt;dat-name&amp;gt;.ref&amp;quot; file:&lt;br /&gt;
&lt;br /&gt;
 refont -decompile &amp;lt;path to given .dat file&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The same path and naming conventions as for .fnt generation discussed above apply here.&lt;br /&gt;
&lt;br /&gt;
Example code block for the letter A when no supplemental annotation file is present (nor any per-line comments, e.g., with warnings):&lt;br /&gt;
&lt;br /&gt;
 	...&lt;br /&gt;
 	char 65 &amp;lt;b&amp;gt;(0x41)&amp;lt;/b&amp;gt;&lt;br /&gt;
 	{&lt;br /&gt;
 		height 18&lt;br /&gt;
 		top 18&lt;br /&gt;
 		bottom 0&lt;br /&gt;
 		pitch 3&lt;br /&gt;
 		xSkip 18&lt;br /&gt;
 		imageWidth 20&lt;br /&gt;
 		imageHeight 18&lt;br /&gt;
 		&amp;lt;b&amp;gt;coord_s 197&lt;br /&gt;
 		coord_t 64&lt;br /&gt;
 		coord_s2 217&lt;br /&gt;
 		coord_t2 82&amp;lt;/b&amp;gt;&lt;br /&gt;
 		glyph 0&lt;br /&gt;
 		shaderName fonts/stone_0_24.tga&lt;br /&gt;
 	}&lt;br /&gt;
 	...&lt;br /&gt;
&lt;br /&gt;
Items bolded differ from FNT format. The starting line expresses the value in hex. And rather than s, t, s2, t2 in fractional [0...1] floating point, the &amp;quot;coord_...&amp;quot; values are expressed (and editable) as integer coordinates of the bitmap, with a range reflecting bitmap size. The default TDM bitmap size is 256x256, but a few fonts use 512x512 and require special treatment discussed further below.&lt;br /&gt;
&lt;br /&gt;
== When Editing ==&lt;br /&gt;
Refont has a minimal parser. To keep it happy, preserve the file&#039;s line structure. In particular:&lt;br /&gt;
* every REF and FNT file has the same number of lines. &#039;&#039;(Exception: REF may have additional starting lines to flag 512x512 bitmaps, discussed below. Generally, you won&#039;t edit these.)&#039;&#039;&lt;br /&gt;
* all keywords within a block must be present, and in a particular order.&lt;br /&gt;
* each block must have exactly the same number of lines (except for the special one at the end).&lt;br /&gt;
&lt;br /&gt;
The meaning of the font metrics are explained in [[Font_Metrics_%26_DAT_File_Format]]. The [[Q3Font]] article has an example of simple metric editing that is also pertinent to refont.&lt;br /&gt;
&lt;br /&gt;
== To Move Changed FNT or REF Data Back to a DAT ==&lt;br /&gt;
&lt;br /&gt;
 refont -compile &amp;lt;path to given .fnt or .ref file&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This reverses the -decompile process, to create a .dat file whose name is derived from the .fnt or .ref file. Importantly, this decompile/compile cycle leaves .tga/.dds files untouched.&lt;br /&gt;
&lt;br /&gt;
== The Annotation File ==&lt;br /&gt;
When told to generate a REF file (but not FNT), refont.exe also looks for a file called &amp;quot;refont_char_annotations.txt&amp;quot;, in the same folder as refont.exe.  That file should have exactly 256 data lines in it, one for each of the codepoints, in order. As the REF is generated, the line that starts a codepoint&#039;s data block gets the corresponding annotation line appended  to it. Having the annotations come from an external file, instead of hard-coded into refont, allows required flexibility as to what information is presented. It even potentially allows refont to be used with other idTech3/4 games that don&#039;t necessarily used the TDM-specific codepoints. Also, the annotation files contain helpful specific comments (as lines that start with &amp;quot;;&amp;quot;).&lt;br /&gt;
&lt;br /&gt;
Each annotation:&lt;br /&gt;
* indicates what character symbol is &#039;&#039;expected&#039;&#039;; it is oblivious as to what character if any is actually within the bounding box described by the DAT data.&lt;br /&gt;
* lives only in a REF file, and is not retained when converted to a DAT file. This also true for any manual supplementary annotations you might make.&lt;br /&gt;
&lt;br /&gt;
This is clearer with examples. In &#039;Downloads&#039; below are 4 different versions of &amp;quot;refont_char_annotations[...].txt&amp;quot;. Three of these, specific to TDM&#039;s custom &#039;english&#039; (i.e., composite European) codepage, are discussed here. To deploy, edit the filename of one of them to remove the square bracket text.&lt;br /&gt;
&lt;br /&gt;
=== English with Symbol Only ===&lt;br /&gt;
&lt;br /&gt;
This simple format is best for most purposes. The file entry for letter &#039;A&#039; is just:&lt;br /&gt;
&lt;br /&gt;
 A&lt;br /&gt;
&lt;br /&gt;
Then the block in a generated REF file would have that string appended, but with &amp;quot; // &amp;quot; inserted.&lt;br /&gt;
 	...&lt;br /&gt;
 	char 65 (0x41) // A&lt;br /&gt;
 	{&lt;br /&gt;
 		height 18&lt;br /&gt;
 		top 18&lt;br /&gt;
 		bottom 0&lt;br /&gt;
 		pitch 3&lt;br /&gt;
 		xSkip 18&lt;br /&gt;
 		imageWidth 20&lt;br /&gt;
 		imageHeight 18&lt;br /&gt;
 		coord_s 197&lt;br /&gt;
 		coord_t 64&lt;br /&gt;
 		coord_s2 217&lt;br /&gt;
 		coord_t2 82&lt;br /&gt;
 		glyph 0&lt;br /&gt;
 		shaderName fonts/stone_0_24.tga&lt;br /&gt;
 	}&lt;br /&gt;
 	...&lt;br /&gt;
&lt;br /&gt;
=== English with Unicode-16 Codes and Names ===&lt;br /&gt;
&lt;br /&gt;
This supplies the Unicode Consortium&#039;s official 16-bit codepoints (where U+NNNN = 0xNNNN) and their names, in the formal all-caps convention.&lt;br /&gt;
&lt;br /&gt;
The file entry for letter &#039;A&#039; is:&lt;br /&gt;
&lt;br /&gt;
 U+0041 LATIN CAPITAL LETTER A&lt;br /&gt;
&lt;br /&gt;
Then the first line of the corresponding block in a generated REF file would show:&lt;br /&gt;
 	...&lt;br /&gt;
 	char 65 (0x41) // U+0041 LATIN CAPITAL LETTER A&lt;br /&gt;
 	...&lt;br /&gt;
Here&#039;s another example from that REF:&lt;br /&gt;
 	...&lt;br /&gt;
 	char 129 (0x81) // U+015A LATIN CAPITAL LETTER S WITH ACUTE&lt;br /&gt;
 	...&lt;br /&gt;
For control or TDM undefined characters, this annotation file assumes a hollow box glyph is the appropriate mapping:&lt;br /&gt;
 	...&lt;br /&gt;
 	char 0 (0x00) // U+24A1 WHITE SQUARE&lt;br /&gt;
 	...&lt;br /&gt;
But there are other choices, so edit the annotation file as you see fit.&lt;br /&gt;
=== English with 8859-x Source ===&lt;br /&gt;
&lt;br /&gt;
This verbose format may be useful during font analysis. For letters that are in their expected locations as defined by ASCII or ISO 8859-1 (Latin-1) or Windows-1252 (&amp;quot;Western Europe&amp;quot;), the annotation is fairly minimal. Thus, letter &#039;A&#039; has this:&lt;br /&gt;
&lt;br /&gt;
 0x41 is A&lt;br /&gt;
&lt;br /&gt;
(TIP: If authoring your own annotation file, consider including a codepoint number on each line, like &amp;quot;0x41&amp;quot; here, to make the process easier.)&lt;br /&gt;
&lt;br /&gt;
Then the first line of the corresponding block in a generated REF file would show:&lt;br /&gt;
 	...&lt;br /&gt;
 	char 65 (0x41) // 0x41 is A&lt;br /&gt;
 	...&lt;br /&gt;
Here are a few more interesting examples from that REF, with more expansive annotations:&lt;br /&gt;
 	...&lt;br /&gt;
 	char 5 (0x05) // 0x05 is a control character, unusable in TDM&lt;br /&gt;
 	...&lt;br /&gt;
 	char 166 (0xa6) // 0xA6 is Š (not ISO 8859-1 ¦) (from A9 in ISO 8859-2) (TDM only)&lt;br /&gt;
 	...&lt;br /&gt;
&lt;br /&gt;
== Revising or Making Your Own Annotations File ==&lt;br /&gt;
If creating your own refont_char_annotations.txt file, note that encoding upper-range characters in UTF-8 will be more universal than using Windows region-specific codepages. To enter a UTF-8 character using its four digit hex Unicode (say, in a range of interest 0x0080-0x00FF):&lt;br /&gt;
* Under Windows, type the four hex digits followed by Alt-X.&lt;br /&gt;
* Under Linux, hold down Ctrl+Shift, type U followed by the 4 digits; release Ctrl+Shift.&lt;br /&gt;
&lt;br /&gt;
When refont reads refont_char_annotations.txt, any line that starts with &amp;quot;;&amp;quot; will be ignored. The latter is so that you can put comments into the file, that will not propagate to the generated REF file. TIP: If such commenting is unwanted, start the line with &amp;lt;space&amp;gt; before &amp;quot;;&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Other than that, be sure to have exactly 256 lines of annotations (though refont will check and issue a warning if not). A line can be empty, i.e., have only the linebreak.&lt;br /&gt;
&lt;br /&gt;
When generating a REF file, refont will automatically add &amp;quot; // &amp;quot; before each non-empty annotation, so don&#039;t include that.&lt;br /&gt;
&lt;br /&gt;
== Adding Your Own Annotations to a REF File ==&lt;br /&gt;
Beyond the refont_char_annotation.txt content, you can add certain commentary to the REF file without it affecting its ability to convert to a DAT file. Here are the rules:&lt;br /&gt;
* Don&#039;t add or subtract lines, or comment out non-blank lines&lt;br /&gt;
* Feel free to append a comment to the end of a line, by beginning the comment with &amp;quot; //&amp;quot;.&lt;br /&gt;
* Likewise, on a line starting with &amp;quot;char&amp;quot; that had an annotation automatically added, you can revise the annotation as you see fit.&lt;br /&gt;
&lt;br /&gt;
Example with revision in bold:&lt;br /&gt;
 	...&lt;br /&gt;
 	char 65 (0x41) // &#039;&#039;&#039;Capital A was slightly clipped. Decremented s, s2 by 1. Looks OK now.&#039;&#039;&#039;&lt;br /&gt;
 	{&lt;br /&gt;
 		height 18&lt;br /&gt;
 		top 18&lt;br /&gt;
 		bottom 0&lt;br /&gt;
 		pitch 3&lt;br /&gt;
 		xSkip 18&lt;br /&gt;
 		imageWidth 20&lt;br /&gt;
 		imageHeight 18&lt;br /&gt;
 		coord_s 196 &#039;&#039;&#039;// WAS: 197&#039;&#039;&#039;&lt;br /&gt;
 		coord_t 64&lt;br /&gt;
 		coord_s2 216 &#039;&#039;&#039;// WAS: 217&#039;&#039;&#039;&lt;br /&gt;
 		coord_t2 82&lt;br /&gt;
 		glyph 0&lt;br /&gt;
 		shaderName fonts/stone_0_24.tga&lt;br /&gt;
  	}&lt;br /&gt;
 	...&lt;br /&gt;
&lt;br /&gt;
In this way, you can markup a REF file as a record of work to do, work in progress, or work completed.&lt;br /&gt;
&lt;br /&gt;
==Errors, Warnings, and Auto-Corrections==&lt;br /&gt;
&#039;&#039;This covers the major overhaul of Refont v 2.1, and its added options -no_warn_comments and -scaling_ok.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
During the compile or decompile, errors and warnings may be generated in the console. Fatal errors are largely due to: &lt;br /&gt;
* file I/O problems;&lt;br /&gt;
* deviations from the strict DAT, REF, and FNT formats.&lt;br /&gt;
&lt;br /&gt;
Warnings, which are not fatal, are largely due to anomolous numeric values. The TDM engine can tolerant some of these, so they don&#039;t necessarily need fixing. &lt;br /&gt;
&lt;br /&gt;
===Fatal Errors when Parsing REF or FNT as Input===&lt;br /&gt;
A fatal error, due to divergence from the expected format while parsing, stops the program. While potentially due to many causes (e.g., adding or deleting lines), errors will be reported - with line number - as failures of:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Variable Name Checks.&#039;&#039; The parser expects every variable name in a particular order. A mismatch happened.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Integer Checks.&#039;&#039; Integer value was unparsable, or out of range for integer type. Checked for per-character variables height, top, bottom, pitch, xSkip, imageWidth, imageHeight, and glyph. Plus REF’s coord_s, coord_t, coord_s2, and coord_ t2.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Float Checks.&#039;&#039; Floating point value was unparsable, or out of range for float type. Checked for glyphScale, and FNT’s per-character variables s, t, s2, t2.&lt;br /&gt;
&lt;br /&gt;
===Post-Read MAJOR Warnings about REF, FNT, and DAT Input Values===&lt;br /&gt;
After parsing, the input process concludes with a separate loop of non-fatal warning analysis. Warnings during input, broadly categorized as major or minor, report to the console, but don’t do any value corrections (which is instead left to the subsequent file-write stage).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;For FNT’s and DAT’s s, t, s2, t2&#039;&#039;&lt;br /&gt;
* Inexact Integer. The given bounding box value, expected in the range 0-1, when multiplied by 256.0 should be exactly an integer. If not, the divergence is likely due to miscalculation.  (Actually, a divergence from an integer of under +/- 0.001 is tolerated by Refont and considered a minor warning, discussed below.) &lt;br /&gt;
* Float Out of Range 0.0 - 1.0. Or equivalently, post-multiplication, 0.0 - 256.0. (See the discussion of the edge cases under minor warnings below.)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;For Other Metrics of DAT, FNT, and REF&#039;&#039;&lt;br /&gt;
* Integer Out of Range 0-256. For height, top, bottom, pitch, xSkip, imageWidth, imageHeight, and REF’s coord_s, coord_t, coord_s2, and coord_t2.&lt;br /&gt;
* Integer Non Zero. For glyph.&lt;br /&gt;
* Float Less Than Zero. For glyphScale (which is independent of a particular character).&lt;br /&gt;
* Inconsistent Metrics. For a given character, this compares two metrics and looks for inconsistencies. We’ll state this here in REF terms, e.g., using “coord_s” rather than “ROUND_TO_INT(s * 256.0f)”:&lt;br /&gt;
** imageHeight == height?&lt;br /&gt;
** imageWidth == coord_s2 - coord_s?&lt;br /&gt;
** imageHeight == coord_t2 - coord_t?&lt;br /&gt;
&lt;br /&gt;
However, warnings about those last two &amp;quot;Inconsistent Metrics&amp;quot; criteria are suppressed if:&lt;br /&gt;
* you use refont&#039;s &amp;quot;-scaling_ok&amp;quot; option. This is helpful when there is extensive per-character scaling. (Only TDM’s mason and mason-glow use a lot of per-character scaling, specifically for all upper-case characters.)&lt;br /&gt;
* you have a 512x512 bitmap, where throughout, the imageWidth and imageHeight (and some other metrics) are expected to be scaled to &amp;quot;half&amp;quot; of the corresponding coord difference. As of refont 2.8, 1 pixel of wiggle-room is allowed for integer rounding. Only warnings will be issued that fail these checks:&lt;br /&gt;
** abs(imageWidth * 2 - (coord_s2 - coord_s)) &amp;gt; 1&lt;br /&gt;
** abs(imageHeight * 2 - (coord_t2 - coord_t)) &amp;gt; 1&lt;br /&gt;
&lt;br /&gt;
===Post-Read MINOR Warnings for FNT’s and DAT’s s, t, s2, t2===&lt;br /&gt;
&#039;&#039;Low Precision.&#039;&#039; This value, when multiplied by 256.0, should be exactly an integer. However, some generation or revision procedure (e.g., Q3Font’s DAT  FNT  DAT) may have not used sufficient precision to ensure this. An offset from an integer value of less than +/- 0.001 is considered a minor problem; otherwise, major as above.&lt;br /&gt;
&lt;br /&gt;
This problem, when it occurs with a file, typically happens a lot. Consequently, it is not reported in an itemized way, but instead, the console will show total counts of affected characters and values.&lt;br /&gt;
&lt;br /&gt;
Edge cases: a value of {s, s2, t, or t2} * 256.0 that is negative but closer to zero than -0.001000 is considered this type of minor problem (and is not considered out of range, which would be major). Likewise, if that value is greater than 256.000000, but less than 256.001000&lt;br /&gt;
===Automatic Corrections during Output to a REF File===&lt;br /&gt;
Certain problems, first detected during DAT input, are further addressed at write time. Because these problems were already reported to the console during the DAT read, nothing additional is written to console. Instead, there may be reporting within the REF file itself.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Automatic Corrections.&#039;&#039; When writing a REF file, the integer values of coord_s, coord_t, coord_s2, and coord_t2 are calculated from DAT floats s, t, s2, and t2 respectively. A calculated coord_... value, if not already resulting in an integer, is automatically forced to the nearest integer. This is so whether it was earlier reported to the console as a Major or Minor Warning. (Before refont v 2.1, the REF might assign an unrounded decimal value; no longer true.)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Warnings Not Automatically Corrected.&#039;&#039; Automatic fixing of other warnings is unwise and not offered. Why? Because the fix is not obvious or complex, and sometimes, the corresponding character glyph in the bitmap needs adjustment. This pertains to Major Warnings about:&lt;br /&gt;
* Integer values outside their expected range (e.g., 0-256), including post-rounding coord_... values.&lt;br /&gt;
* Inconsistent Metrics&lt;br /&gt;
===Generated Within-REF Comments during Output===&lt;br /&gt;
For most causes of a Major Warning during DAT read, during subsequent writing of the REF file, a similar comment is also generated within the REF, on the same line as the parameter assignment. For example:&lt;br /&gt;
 char 95 (0x5f) // _&lt;br /&gt;
 {&lt;br /&gt;
    ...&lt;br /&gt;
    top -6 // WARNING: Not in range 0-256. Does bitmap or other metrics need adjusting?&lt;br /&gt;
    ...&lt;br /&gt;
 }&lt;br /&gt;
 ...&lt;br /&gt;
 char 140 (0x8c) // Ń&lt;br /&gt;
 {&lt;br /&gt;
    ...&lt;br /&gt;
    coord_t -10 // WARNING: Underlying DAT value -0.03906250, * 256.0 gave -10.000000000, not in range 0-256 once rounded. Does bitmap or other metrics need adjusting?&lt;br /&gt;
    ...&lt;br /&gt;
 }&lt;br /&gt;
&#039;&#039;Suppressing Comment Generation.&#039;&#039; Use the refont option “-no_warn_comments”. &#039;&#039;New to v 2.1.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
TIP: When editing a REF file with comments, you can keep them, change them, or delete them as you prefer. They have no impact on subsequent compiles to DAT.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Coverage of Generated Within-REF Comments.&#039;&#039; A calculated value of coord_s, coord_t, coord_s2, or coord_t2 would have been flagged as a “Major Warning” during read if:&lt;br /&gt;
* the discrepancy from being an integer was non-trivial (+/- 0.001 or more), or&lt;br /&gt;
* the calculated and rounded integer is outside the range given by bitmap size, e.g., 0-256.&lt;br /&gt;
&lt;br /&gt;
For these, a comment is generated. Other causes are:&lt;br /&gt;
* Integer Out of Range 0-256 &#039;&#039;(or 0-512 as applicable)&#039;&#039;. For height, top, bottom, pitch, xSkip, imageWidth, imageHeight.&lt;br /&gt;
* Integer Non Zero. For glyph.&lt;br /&gt;
* Float Less Than Zero. For glyphScale (which is independent of a particular character).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Major Warnings that Don’t Cause Within-REF Comments.&#039;&#039; Currently, this is limited to “Inconsistent Metrics”, which would probably require tagging on multiple lines.&lt;br /&gt;
&lt;br /&gt;
== Special Handling of Fonts with 512x512 Bitmaps ==&lt;br /&gt;
Some DAT files reference bitmap shaders where some or all are of size 512x512, instead of the default 256x256. Refont v2.5+ can support this (replacing an insufficient first attempt in v2.4).&lt;br /&gt;
&lt;br /&gt;
Font developers went to double-sized bitmaps to:&lt;br /&gt;
* in the case of Carleton, allow freehand drawing of missing European characters, which could be drawn more easily if twice standard size.&lt;br /&gt;
* in the case of Mason, have larger ASCII alphanumeric glyphs that would render with crisper edges.&lt;br /&gt;
&lt;br /&gt;
In either case, the font characters when rendered in, say, the game main menu will be the same size as if from 256x256. This is because the imageWidth, imageHeight, height, and top metrics are not doubled.&lt;br /&gt;
In effect, a scaling by half (approximately, as constrained by integer values) is requested for all characters in the DAT file and applied by the engine.&lt;br /&gt;
&lt;br /&gt;
=== When generating a REF file from a DAT file ===&lt;br /&gt;
&lt;br /&gt;
 refont -decompile &amp;lt;path to given .dat file&amp;gt; -512_&amp;lt;n&amp;gt;   &#039;&#039;where &amp;lt;n&amp;gt; is a single digit, e.g. &#039;1&#039; in referenced shader name &amp;quot;font/Carleton_1_24.tga&amp;quot; &#039;&#039;&lt;br /&gt;
&lt;br /&gt;
You should use multiple instances of the -512_&amp;lt;n&amp;gt; option, to cover all the 512x512 bitmaps found in the DAT file.&lt;br /&gt;
&lt;br /&gt;
If &#039;&#039;all&#039;&#039; of a given DATs shaders are 512x512, you can use this shorter form:&lt;br /&gt;
&lt;br /&gt;
 refont -decompile &amp;lt;path to given .dat file&amp;gt; -512&lt;br /&gt;
&lt;br /&gt;
Exercising -512... options will mean that in the generated REF file:&lt;br /&gt;
&lt;br /&gt;
* There will be a one or more starting lines like:&lt;br /&gt;
  # bitmap_&amp;lt;n&amp;gt;_size=512 &#039;&#039;(Refont will look for this if doing a subsequent compile to DAT)&#039;&#039;&lt;br /&gt;
* If you specified the short form, it will expand to just the right number of starting lines.&lt;br /&gt;
* Values for coord_s, coord_s2, coord_t, and coord_t2 will have a normal range of 0-512 when appropriate. [COMING SOON: Those values may then be read properly by datBounds.].&lt;br /&gt;
* Any warnings expressed (within the file or within the command-line window) will be in terms of the correct range of values. &lt;br /&gt;
* Warning checks will expect a scaling by half for all characters. That is, while 512... requires scaling down by half, that scaling will not generate a warning (unless it&#039;s not EXACTLY by half, or within 1 pixel of that), so the -scaling_ok option is not needed just for the exactly-by-half scaling.&lt;br /&gt;
&lt;br /&gt;
=== When generating a DAT file from a REF file ===&lt;br /&gt;
&lt;br /&gt;
During refont -compile, no special command line options are needed. Instead, REF&#039;s starting lines of form &amp;quot;# bitmap_&amp;lt;n&amp;gt;_size=512&amp;quot; are inspected and coord ranges will be interpreted as 0-512 whenever appropriate. &lt;br /&gt;
&lt;br /&gt;
=== Special Handling Recommendations for Carleton and Mason ===&lt;br /&gt;
&#039;&#039;For fonts shipped with TDM 2.12 in tdm_fonts01.pk4. Illustrative command paths are shown; adjust to your working copy.&#039;&#039;&lt;br /&gt;
==== Mason Family ====&lt;br /&gt;
The [[Mason Font]] uses within-DAT per-character scaling, as well as some but not all 512x512 bitmaps. Only 48pt Mason is shipped.&lt;br /&gt;
&lt;br /&gt;
Because, under /dds/fonts/english/mason/, bitmaps masonalternate_0_48.dds to _2_ are 512x512, but _3_ to _5_ are not, use:&lt;br /&gt;
&lt;br /&gt;
 -decompile /fonts/english/mason/fontimage_48.dat -512_0 -512_1 -512_2 -scaling_ok&lt;br /&gt;
&lt;br /&gt;
Because, under /dds/fonts/english/mason_glow/, bitmaps masonalternate_1_48.dds and _2_ are 512x512, but _0_ and _3_ to _5_ are not, use:&lt;br /&gt;
&lt;br /&gt;
 -decompile /fonts/english/mason_glow/fontimage_48.dat -512_1 -512_2 -scaling_ok&lt;br /&gt;
&lt;br /&gt;
Russian versions use the default 256x256. [These possibly benefit from -scaling_ok; didn&#039;t investigate.]&lt;br /&gt;
==== Carleton Family ====&lt;br /&gt;
The 24pt size of carleton has two bitmaps under /dds/fonts/english/carleton/, namely carleton_0_24.dds and _1_, both of size 512x512. So use:&lt;br /&gt;
&lt;br /&gt;
 -decompile /fonts/english/carleton/fontimage_24.dat -512_0 -512_1&lt;br /&gt;
  &#039;&#039;or&#039;&#039;&lt;br /&gt;
 -decompile /fonts/english/carleton/fontimage_24.dat -512&lt;br /&gt;
 &lt;br /&gt;
The 24pt size of carleton_bold has bitmaps with identical content to carleton&#039;s, so use the same options:&lt;br /&gt;
&lt;br /&gt;
 -decompile /fonts/english/carleton_bold/fontimage_24.dat -512_0 -512_1&lt;br /&gt;
  &#039;&#039;or&#039;&#039;&lt;br /&gt;
 -decompile /fonts/english/carleton_bold/fontimage_24.dat -512&lt;br /&gt;
&lt;br /&gt;
Other members of this family use the default 256x256 bitmaps:&lt;br /&gt;
* Sizes 12pt &amp;amp; 48pt&lt;br /&gt;
* carleton_condensed and carleton_glow. (Note: while helpful, it is not required that the base &amp;amp; glow have identical bitmap sizes.)&lt;br /&gt;
* Russian versions&lt;br /&gt;
&lt;br /&gt;
==== These Fonts with Stats ====&lt;br /&gt;
With -stats discussed next, if reading a DAT file, you may use the -512... and scaling_ok options to be most correct, although neglecting to specify them will likely have no significant impact on the analytical results. If reading a REF file, the included &amp;quot;# bitmap_...&amp;quot; lines will take care of that for you.&lt;br /&gt;
&lt;br /&gt;
== For Statistics on Unimplemented or Problematic Font Characters ==&lt;br /&gt;
DAT or (as of v2.3) REF file analysis here is primarily designed to benefit english/european fonts. It will use the optional annotation file if provided. Syntax:&lt;br /&gt;
&lt;br /&gt;
     refont -stats &amp;lt;path to given .dat or .ref file&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Use &amp;quot;-stats&amp;quot; by itself, not combined with &amp;quot;-compile&amp;quot; or &amp;quot;-decompile&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
The resulting analysis report will have the same name and location as the input file, but with a &amp;quot;.txt&amp;quot; suffix.&lt;br /&gt;
The report provides categorized totals and (for problematic characters) itemizations across all 256 character codepoints.&lt;br /&gt;
The counts of problems should be considered minimums, since no inspection of bitmap files (TGA or DDS) is done.&lt;br /&gt;
But a perhaps surprising amount of insight can be gleaned just from DAT/REF file metrics.&lt;br /&gt;
Itemizations include annotations from the &#039;ref_char_annotation&#039; file, if provided.&lt;br /&gt;
&lt;br /&gt;
In the hunt for missing characters, 3 signatures are important:&lt;br /&gt;
&lt;br /&gt;
* Presumed &#039;Hollow Box&#039; = glyph&#039;s &#039;shadername&#039; is &amp;lt;fontname&amp;gt;_0_&amp;lt;size&amp;gt;.dds only, and s &amp;amp; t are zero, but not s2 &amp;amp; t2&lt;br /&gt;
* &#039;&amp;lt;Space&amp;gt;&#039; = same test as &#039;Hollow Box&#039;, but pointed to by char 32 (0x20)&lt;br /&gt;
* &#039;Zero Box&#039; = No glyph box (s, t, s2, t2 all zero)&lt;br /&gt;
&lt;br /&gt;
A given analysis will assume either &#039;Hollow Box&#039; or &#039;&amp;lt;Space&amp;gt;&#039; but not both.&lt;br /&gt;
&lt;br /&gt;
The analysis provides totals and itemizations - grouped into lower (0-127) and upper ranges (128-255) - in several passes: &lt;br /&gt;
&lt;br /&gt;
* Pass 1 - Handling of unprintable/unsupported/missing codepoints, indicated by Hollow Box, Zero Box, or &amp;lt;Space&amp;gt;. Some of these are not a problem, but some are tagged as &amp;quot;Undesirable&amp;quot;.&lt;br /&gt;
* Pass 2 - Bad glyph box (negative s, t, s2, or t2; or s2 &amp;lt;= s, t2 &amp;lt;= t) or good glyph box with dubious metrics (imageHeight &amp;lt;= 0, imageWidth &amp;lt;=0, imageHeight != height). Excludes those already counted as &amp;quot;Undesirable&amp;quot; in Pass 1. &lt;br /&gt;
* Pass 3 - Detection of duplicate glyph boxes (other than Hollow Box, Zero Box, or &amp;lt;Space&amp;gt;). Detected by: glyph&#039;s values for shadername, s, t, s2, &amp;amp; t2 exactly match those of another codepoint. These are grouped into &amp;quot;Dup Sets&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Then, across passes 1-3, a count if given of the minimum &amp;quot;Total Glyphs Needing Work&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Refont version 2.3 adds additional passes:&lt;br /&gt;
&lt;br /&gt;
* Pass 4 - Reports &amp;quot;Overlap Sets&amp;quot; rather than just &amp;quot;Dup Sets&amp;quot;. A set here may include an unaccented &amp;quot;base character&amp;quot; that has been serving as a substitute work-around target for one or more missing accented characters. (What constitutes an &amp;quot;overlap&amp;quot; is idiosyncratic; see the source code for details.)&lt;br /&gt;
* Pass 5 - Same information as Pass 4, but sorted first by shader name (i.e., bitmap). Helpful for organizing bitmap-editing work.&lt;br /&gt;
* Pass 6 - An analysis focusing just on the planned migration of duplicate O/o-circumflex codepoints to G/g-cup glyphs.&lt;br /&gt;
&lt;br /&gt;
== Downloads ==&lt;br /&gt;
Release 2.8 of March 19, 2026:&lt;br /&gt;
* [https://drive.google.com/file/d/1BHGkCOhgXP7bFp1mXyfgoRBUtqkbCVRb/view?usp=sharing refont.exe]&lt;br /&gt;
* [https://drive.google.com/file/d/1Cca_Xo3W5jYB_40RVo4aIPHAGIufA9V0/view?usp=sharing refont_source_v2.8.zip, with refont.cpp, refont.sln, open-source license]&lt;br /&gt;
&lt;br /&gt;
Release 2.6 of July 28, 2025:&lt;br /&gt;
* [https://drive.google.com/file/d/1ABf4771Jr1C1hKbLx4xWq8lx8Kn7HdKP/view?usp=sharing refont.exe]&lt;br /&gt;
* [https://drive.google.com/file/d/1-k68eo0CHKZ-sM7JGP05axm49cc5De0T/view?usp=sharing source code: refont.cpp]&lt;br /&gt;
&lt;br /&gt;
===Annotations===&lt;br /&gt;
&#039;&#039;After download, to use any one of these, edit filename to remove &amp;quot;[...]&amp;quot; substring.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Update of June 20, 2024. This reflects a change to the TDM charmap for 2.13, to replace duplicate O/o circumflex characters with G/g breve:&lt;br /&gt;
&lt;br /&gt;
* refont_char_annotations[english with symbol only. With G-breve update].txt [https://drive.google.com/file/d/1rrt-O9DgD7Zn2Hxt7nBtViIlO4kv_gQB/view?usp=sharing here]. Recommended for most purposes with &#039;english&#039; fonts.&lt;br /&gt;
* refont_char_annotations[english with Unicode-16 codes &amp;amp; names. With G-breve update].txt [https://drive.google.com/file/d/1AMxDKQc_DE33gsExiEkGp3x67eb4aGFh/view?usp=sharing here].&lt;br /&gt;
* refont_char_annotations[english with 8859-x source. With G-breve update].txt [https://drive.google.com/file/d/1xoeZ1poTbmkls-gE5PnbbMxdoz5KnMD7/view?usp=sharing].&lt;br /&gt;
* For Russian, see the previous update next.&lt;br /&gt;
&lt;br /&gt;
Update of April 13, 2024:&lt;br /&gt;
&lt;br /&gt;
* refont_char_annotations[english with symbol only].txt [https://drive.google.com/file/d/1ItM-aXps0xQE655HdaJM7Aje5lHewUfC/view?usp=sharing here]. Recommended for most purposes with &#039;english&#039; fonts.&lt;br /&gt;
* refont_char_annotations[english with Unicode-16 codes and names].txt [https://drive.google.com/file/d/1gW7oO_wLqCEPSdm6b05OaTNYHnyuUSA-/view?usp=sharing here].&lt;br /&gt;
* refont_char_annotations[english with 8859-x source].txt [https://drive.google.com/file/d/1ZTcgA4QJYwXzNdqbolYkn0CCEDILD1bX/view?usp=sharing here]. Corrects and supersedes original english file.&lt;br /&gt;
* refont_char_annotations[russian].txt [https://drive.google.com/file/d/10txNXsSCtaTiT2iGT9o3iDxBU7HVYNxi/view?usp=sharing here]. Recommended for &#039;russian&#039; fonts.&lt;br /&gt;
&lt;br /&gt;
== For More ==&lt;br /&gt;
* See the [https://forums.thedarkmod.com/index.php?/topic/22427-analysis-of-212-tdm-fonts/ summary analysis of 2.12 TDM fonts], based on applying &#039;refont -stats ...&#039; to all &#039;english&#039; DAT files.&lt;br /&gt;
&lt;br /&gt;
{{tutorial}} [[Category:Fonts]]&lt;/div&gt;</summary>
		<author><name>Geep</name></author>
	</entry>
	<entry>
		<id>https://wiki.thedarkmod.com/index.php?title=Refont&amp;diff=34447</id>
		<title>Refont</title>
		<link rel="alternate" type="text/html" href="https://wiki.thedarkmod.com/index.php?title=Refont&amp;diff=34447"/>
		<updated>2026-03-18T17:25:03Z</updated>

		<summary type="html">&lt;p&gt;Geep: /* Special Handling of Fonts with 512x512 Bitmaps */ v2.8 adds 1-pixel slack, suppress warnings&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;By Geep, 2024, and similar to the article about Q3Font.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Introduced in 2024, the &amp;quot;refont&amp;quot; command-line utility allows inspection and alteration of [[Font Metrics &amp;amp; DAT File Format | font metrics]].&lt;br /&gt;
It is designed to be an easier-to-use version of the inspection/alteration functionalities of [[Q3Font]].&lt;br /&gt;
It also provides a font analysis feature.&lt;br /&gt;
&lt;br /&gt;
== Comparison with Font Patcher ==&lt;br /&gt;
&lt;br /&gt;
Refont can be seen as complementary to [[Font Patcher]]. The latter has additional features that may be better if planning a wholesale rearrangement or expansion of characters within a bitmap, particularly for a new font immediately after conversion from a TTF font. But refont is easier to use in later years, and  Font Patcher requires installation of Perl, while refont.exe is more drop and go.&lt;br /&gt;
&lt;br /&gt;
== Comparison with Q3Font ==&lt;br /&gt;
&lt;br /&gt;
For metric alteration, q3font has a native &amp;quot;*.fnt&amp;quot; human-readable format, and supports DAT &amp;lt;==&amp;gt; FNT conversions. For compatibility, so does refont.&lt;br /&gt;
&lt;br /&gt;
=== Advantages of Q3Font ===&lt;br /&gt;
&lt;br /&gt;
* This has been an important traditional tool for Doom3/TDM font manipulation.&lt;br /&gt;
* In addition to production/consumption of FNT, it -&lt;br /&gt;
** Allows creation of DAT &amp;amp; TGA files from a TrueType font (although for this purpose, [[ExportFontToDoom3]] has been preferred in practice).&lt;br /&gt;
** Can write (but not read) an alternative &amp;quot;compact report&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
=== Advantages of Refont ===&lt;br /&gt;
&lt;br /&gt;
* It&#039;s open-source, so further C++ development is possible.&lt;br /&gt;
* It has its own native human-readable format, &amp;quot;*.ref&amp;quot;, similar to .fnt but better.&lt;br /&gt;
* The REF format can be read by [[datBounds]] to generate bitmap boundary &amp;amp; metrics visualizations.&lt;br /&gt;
&lt;br /&gt;
The better features of REF are:&lt;br /&gt;
&lt;br /&gt;
* Codepoints are enumerated in not just decimal, but also hex.&lt;br /&gt;
* Coordinates of the overall image box within its bitmap are expressed in pixel units, rather than [0...1] fractional floating point. So the user is spared having to manually do this tedious and error-prone calculation.&lt;br /&gt;
* This overcomes a drawback of FNT, that expresses the coordinates with only 6 digits after the decimal point, not quite enough to avoid minor mis-precisions.&lt;br /&gt;
* if optionally provided, a separate, read-only annotation file will automatically decorate the .ref file with helpful information as the file is generated. This is explained below.&lt;br /&gt;
&lt;br /&gt;
Because the code is open-source, there&#039;s better clarity about -&lt;br /&gt;
* how parsing and calculations are done.&lt;br /&gt;
* what warnings are emitted.&lt;br /&gt;
&lt;br /&gt;
Also, using &amp;quot;-stats&amp;quot;, refont can write (but not read) an analysis of a DAT file, particularly looking for problematic/unimplemented Western-language characters.&lt;br /&gt;
&lt;br /&gt;
== For Inspection &amp;amp; Correction of DAT files ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;To Get the Data in Readable, Editable Form&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
For viewing and altering in a text editor, two formats are provided. Both list every codepoint, in order from 0 to 255, as a block of data. Within each block, every item gets its own line.&lt;br /&gt;
&lt;br /&gt;
=== As a FNT File ===&lt;br /&gt;
&lt;br /&gt;
To create a q3font-compatable &amp;quot;&amp;lt;dat-name&amp;gt;.fnt&amp;quot; file:&lt;br /&gt;
&lt;br /&gt;
 refont -decompile &amp;lt;path to given .dat file&amp;gt; -fnt&lt;br /&gt;
&lt;br /&gt;
where the path can be a full path, a relative path (e.g., starting with &amp;quot;./&amp;quot; or &amp;quot;../&amp;quot;), or just the file name in the current working directory. The resulting .fnt file will appear in the same directory. It have the same name as the .dat file, except for the extension. As a convenience to keep track of versions, it is not required that the file name be in the standard fontImage_nn.dat form.&lt;br /&gt;
&lt;br /&gt;
Example code block for the letter A:&lt;br /&gt;
 	...&lt;br /&gt;
 	char 65&lt;br /&gt;
 	{&lt;br /&gt;
 		height 18&lt;br /&gt;
 		top 18&lt;br /&gt;
 		bottom 0&lt;br /&gt;
 		pitch 3&lt;br /&gt;
 		xSkip 18&lt;br /&gt;
 		imageWidth 20&lt;br /&gt;
 		imageHeight 18&lt;br /&gt;
 		s 0.769531&lt;br /&gt;
 		t 0.250000&lt;br /&gt;
 		s2 0.847656&lt;br /&gt;
 		t2 0.320313&lt;br /&gt;
 		glyph 0&lt;br /&gt;
 		shaderName fonts/stone_0_24.tga&lt;br /&gt;
 	}&lt;br /&gt;
  	...&lt;br /&gt;
&lt;br /&gt;
Note that Q3Font FNT expresses the s, t, s2, and t2 coordinates with only 6 digits after the decimal point, causing minor low-precision rounding during DAT --&amp;gt; FNT --&amp;gt; DAT roundtrips. For compatibility, Refont FNT does likewise.&lt;br /&gt;
&lt;br /&gt;
=== As a REF File ===&lt;br /&gt;
&#039;&#039;Starting with Refont v2.5, a mixture of 256x256 and 512x512 bitmap shaders, encountered with Carleton and Mason family fonts, can be handled. See further below.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
To create a refont-specific &amp;quot;&amp;lt;dat-name&amp;gt;.ref&amp;quot; file:&lt;br /&gt;
&lt;br /&gt;
 refont -decompile &amp;lt;path to given .dat file&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The same path and naming conventions as for .fnt generation discussed above apply here.&lt;br /&gt;
&lt;br /&gt;
Example code block for the letter A when no supplemental annotation file is present (nor any per-line comments, e.g., with warnings):&lt;br /&gt;
&lt;br /&gt;
 	...&lt;br /&gt;
 	char 65 &amp;lt;b&amp;gt;(0x41)&amp;lt;/b&amp;gt;&lt;br /&gt;
 	{&lt;br /&gt;
 		height 18&lt;br /&gt;
 		top 18&lt;br /&gt;
 		bottom 0&lt;br /&gt;
 		pitch 3&lt;br /&gt;
 		xSkip 18&lt;br /&gt;
 		imageWidth 20&lt;br /&gt;
 		imageHeight 18&lt;br /&gt;
 		&amp;lt;b&amp;gt;coord_s 197&lt;br /&gt;
 		coord_t 64&lt;br /&gt;
 		coord_s2 217&lt;br /&gt;
 		coord_t2 82&amp;lt;/b&amp;gt;&lt;br /&gt;
 		glyph 0&lt;br /&gt;
 		shaderName fonts/stone_0_24.tga&lt;br /&gt;
 	}&lt;br /&gt;
 	...&lt;br /&gt;
&lt;br /&gt;
Items bolded differ from FNT format. The starting line expresses the value in hex. And rather than s, t, s2, t2 in fractional [0...1] floating point, the &amp;quot;coord_...&amp;quot; values are expressed (and editable) as integer coordinates of the bitmap, with a range reflecting bitmap size. The default TDM bitmap size is 256x256, but a few fonts use 512x512 and require special treatment discussed further below.&lt;br /&gt;
&lt;br /&gt;
== When Editing ==&lt;br /&gt;
Refont has a minimal parser. To keep it happy, preserve the file&#039;s line structure. In particular:&lt;br /&gt;
* every REF and FNT file has the same number of lines. &#039;&#039;(Exception: REF may have additional starting lines to flag 512x512 bitmaps, discussed below. Generally, you won&#039;t edit these.)&#039;&#039;&lt;br /&gt;
* all keywords within a block must be present, and in a particular order.&lt;br /&gt;
* each block must have exactly the same number of lines (except for the special one at the end).&lt;br /&gt;
&lt;br /&gt;
The meaning of the font metrics are explained in [[Font_Metrics_%26_DAT_File_Format]]. The [[Q3Font]] article has an example of simple metric editing that is also pertinent to refont.&lt;br /&gt;
&lt;br /&gt;
== To Move Changed FNT or REF Data Back to a DAT ==&lt;br /&gt;
&lt;br /&gt;
 refont -compile &amp;lt;path to given .fnt or .ref file&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This reverses the -decompile process, to create a .dat file whose name is derived from the .fnt or .ref file. Importantly, this decompile/compile cycle leaves .tga/.dds files untouched.&lt;br /&gt;
&lt;br /&gt;
== The Annotation File ==&lt;br /&gt;
When told to generate a REF file (but not FNT), refont.exe also looks for a file called &amp;quot;refont_char_annotations.txt&amp;quot;, in the same folder as refont.exe.  That file should have exactly 256 data lines in it, one for each of the codepoints, in order. As the REF is generated, the line that starts a codepoint&#039;s data block gets the corresponding annotation line appended  to it. Having the annotations come from an external file, instead of hard-coded into refont, allows required flexibility as to what information is presented. It even potentially allows refont to be used with other idTech3/4 games that don&#039;t necessarily used the TDM-specific codepoints. Also, the annotation files contain helpful specific comments (as lines that start with &amp;quot;;&amp;quot;).&lt;br /&gt;
&lt;br /&gt;
Each annotation:&lt;br /&gt;
* indicates what character symbol is &#039;&#039;expected&#039;&#039;; it is oblivious as to what character if any is actually within the bounding box described by the DAT data.&lt;br /&gt;
* lives only in a REF file, and is not retained when converted to a DAT file. This also true for any manual supplementary annotations you might make.&lt;br /&gt;
&lt;br /&gt;
This is clearer with examples. In &#039;Downloads&#039; below are 4 different versions of &amp;quot;refont_char_annotations[...].txt&amp;quot;. Three of these, specific to TDM&#039;s custom &#039;english&#039; (i.e., composite European) codepage, are discussed here. To deploy, edit the filename of one of them to remove the square bracket text.&lt;br /&gt;
&lt;br /&gt;
=== English with Symbol Only ===&lt;br /&gt;
&lt;br /&gt;
This simple format is best for most purposes. The file entry for letter &#039;A&#039; is just:&lt;br /&gt;
&lt;br /&gt;
 A&lt;br /&gt;
&lt;br /&gt;
Then the block in a generated REF file would have that string appended, but with &amp;quot; // &amp;quot; inserted.&lt;br /&gt;
 	...&lt;br /&gt;
 	char 65 (0x41) // A&lt;br /&gt;
 	{&lt;br /&gt;
 		height 18&lt;br /&gt;
 		top 18&lt;br /&gt;
 		bottom 0&lt;br /&gt;
 		pitch 3&lt;br /&gt;
 		xSkip 18&lt;br /&gt;
 		imageWidth 20&lt;br /&gt;
 		imageHeight 18&lt;br /&gt;
 		coord_s 197&lt;br /&gt;
 		coord_t 64&lt;br /&gt;
 		coord_s2 217&lt;br /&gt;
 		coord_t2 82&lt;br /&gt;
 		glyph 0&lt;br /&gt;
 		shaderName fonts/stone_0_24.tga&lt;br /&gt;
 	}&lt;br /&gt;
 	...&lt;br /&gt;
&lt;br /&gt;
=== English with Unicode-16 Codes and Names ===&lt;br /&gt;
&lt;br /&gt;
This supplies the Unicode Consortium&#039;s official 16-bit codepoints (where U+NNNN = 0xNNNN) and their names, in the formal all-caps convention.&lt;br /&gt;
&lt;br /&gt;
The file entry for letter &#039;A&#039; is:&lt;br /&gt;
&lt;br /&gt;
 U+0041 LATIN CAPITAL LETTER A&lt;br /&gt;
&lt;br /&gt;
Then the first line of the corresponding block in a generated REF file would show:&lt;br /&gt;
 	...&lt;br /&gt;
 	char 65 (0x41) // U+0041 LATIN CAPITAL LETTER A&lt;br /&gt;
 	...&lt;br /&gt;
Here&#039;s another example from that REF:&lt;br /&gt;
 	...&lt;br /&gt;
 	char 129 (0x81) // U+015A LATIN CAPITAL LETTER S WITH ACUTE&lt;br /&gt;
 	...&lt;br /&gt;
For control or TDM undefined characters, this annotation file assumes a hollow box glyph is the appropriate mapping:&lt;br /&gt;
 	...&lt;br /&gt;
 	char 0 (0x00) // U+24A1 WHITE SQUARE&lt;br /&gt;
 	...&lt;br /&gt;
But there are other choices, so edit the annotation file as you see fit.&lt;br /&gt;
=== English with 8859-x Source ===&lt;br /&gt;
&lt;br /&gt;
This verbose format may be useful during font analysis. For letters that are in their expected locations as defined by ASCII or ISO 8859-1 (Latin-1) or Windows-1252 (&amp;quot;Western Europe&amp;quot;), the annotation is fairly minimal. Thus, letter &#039;A&#039; has this:&lt;br /&gt;
&lt;br /&gt;
 0x41 is A&lt;br /&gt;
&lt;br /&gt;
(TIP: If authoring your own annotation file, consider including a codepoint number on each line, like &amp;quot;0x41&amp;quot; here, to make the process easier.)&lt;br /&gt;
&lt;br /&gt;
Then the first line of the corresponding block in a generated REF file would show:&lt;br /&gt;
 	...&lt;br /&gt;
 	char 65 (0x41) // 0x41 is A&lt;br /&gt;
 	...&lt;br /&gt;
Here are a few more interesting examples from that REF, with more expansive annotations:&lt;br /&gt;
 	...&lt;br /&gt;
 	char 5 (0x05) // 0x05 is a control character, unusable in TDM&lt;br /&gt;
 	...&lt;br /&gt;
 	char 166 (0xa6) // 0xA6 is Š (not ISO 8859-1 ¦) (from A9 in ISO 8859-2) (TDM only)&lt;br /&gt;
 	...&lt;br /&gt;
&lt;br /&gt;
== Revising or Making Your Own Annotations File ==&lt;br /&gt;
If creating your own refont_char_annotations.txt file, note that encoding upper-range characters in UTF-8 will be more universal than using Windows region-specific codepages. To enter a UTF-8 character using its four digit hex Unicode (say, in a range of interest 0x0080-0x00FF):&lt;br /&gt;
* Under Windows, type the four hex digits followed by Alt-X.&lt;br /&gt;
* Under Linux, hold down Ctrl+Shift, type U followed by the 4 digits; release Ctrl+Shift.&lt;br /&gt;
&lt;br /&gt;
When refont reads refont_char_annotations.txt, any line that starts with &amp;quot;;&amp;quot; will be ignored. The latter is so that you can put comments into the file, that will not propagate to the generated REF file. TIP: If such commenting is unwanted, start the line with &amp;lt;space&amp;gt; before &amp;quot;;&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Other than that, be sure to have exactly 256 lines of annotations (though refont will check and issue a warning if not). A line can be empty, i.e., have only the linebreak.&lt;br /&gt;
&lt;br /&gt;
When generating a REF file, refont will automatically add &amp;quot; // &amp;quot; before each non-empty annotation, so don&#039;t include that.&lt;br /&gt;
&lt;br /&gt;
== Adding Your Own Annotations to a REF File ==&lt;br /&gt;
Beyond the refont_char_annotation.txt content, you can add certain commentary to the REF file without it affecting its ability to convert to a DAT file. Here are the rules:&lt;br /&gt;
* Don&#039;t add or subtract lines, or comment out non-blank lines&lt;br /&gt;
* Feel free to append a comment to the end of a line, by beginning the comment with &amp;quot; //&amp;quot;.&lt;br /&gt;
* Likewise, on a line starting with &amp;quot;char&amp;quot; that had an annotation automatically added, you can revise the annotation as you see fit.&lt;br /&gt;
&lt;br /&gt;
Example with revision in bold:&lt;br /&gt;
 	...&lt;br /&gt;
 	char 65 (0x41) // &#039;&#039;&#039;Capital A was slightly clipped. Decremented s, s2 by 1. Looks OK now.&#039;&#039;&#039;&lt;br /&gt;
 	{&lt;br /&gt;
 		height 18&lt;br /&gt;
 		top 18&lt;br /&gt;
 		bottom 0&lt;br /&gt;
 		pitch 3&lt;br /&gt;
 		xSkip 18&lt;br /&gt;
 		imageWidth 20&lt;br /&gt;
 		imageHeight 18&lt;br /&gt;
 		coord_s 196 &#039;&#039;&#039;// WAS: 197&#039;&#039;&#039;&lt;br /&gt;
 		coord_t 64&lt;br /&gt;
 		coord_s2 216 &#039;&#039;&#039;// WAS: 217&#039;&#039;&#039;&lt;br /&gt;
 		coord_t2 82&lt;br /&gt;
 		glyph 0&lt;br /&gt;
 		shaderName fonts/stone_0_24.tga&lt;br /&gt;
  	}&lt;br /&gt;
 	...&lt;br /&gt;
&lt;br /&gt;
In this way, you can markup a REF file as a record of work to do, work in progress, or work completed.&lt;br /&gt;
&lt;br /&gt;
==Errors, Warnings, and Auto-Corrections==&lt;br /&gt;
&#039;&#039;This covers the major overhaul of Refont v 2.1, and its added options -no_warn_comments and -scaling_ok.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
During the compile or decompile, errors and warnings may be generated in the console. Fatal errors are largely due to: &lt;br /&gt;
* file I/O problems;&lt;br /&gt;
* deviations from the strict DAT, REF, and FNT formats.&lt;br /&gt;
&lt;br /&gt;
Warnings, which are not fatal, are largely due to anomolous numeric values. The TDM engine can tolerant some of these, so they don&#039;t necessarily need fixing. &lt;br /&gt;
&lt;br /&gt;
===Fatal Errors when Parsing REF or FNT as Input===&lt;br /&gt;
A fatal error, due to divergence from the expected format while parsing, stops the program. While potentially due to many causes (e.g., adding or deleting lines), errors will be reported - with line number - as failures of:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Variable Name Checks.&#039;&#039; The parser expects every variable name in a particular order. A mismatch happened.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Integer Checks.&#039;&#039; Integer value was unparsable, or out of range for integer type. Checked for per-character variables height, top, bottom, pitch, xSkip, imageWidth, imageHeight, and glyph. Plus REF’s coord_s, coord_t, coord_s2, and coord_ t2.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Float Checks.&#039;&#039; Floating point value was unparsable, or out of range for float type. Checked for glyphScale, and FNT’s per-character variables s, t, s2, t2.&lt;br /&gt;
&lt;br /&gt;
===Post-Read MAJOR Warnings about REF, FNT, and DAT Input Values===&lt;br /&gt;
After parsing, the input process concludes with a separate loop of non-fatal warning analysis. Warnings during input, broadly categorized as major or minor, report to the console, but don’t do any value corrections (which is instead left to the subsequent file-write stage).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;For FNT’s and DAT’s s, t, s2, t2&#039;&#039;&lt;br /&gt;
* Inexact Integer. The given bounding box value, expected in the range 0-1, when multiplied by 256.0 should be exactly an integer. If not, the divergence is likely due to miscalculation.  (Actually, a divergence from an integer of under +/- 0.001 is tolerated by Refont and considered a minor warning, discussed below.) &lt;br /&gt;
* Float Out of Range 0.0 - 1.0. Or equivalently, post-multiplication, 0.0 - 256.0. (See the discussion of the edge cases under minor warnings below.)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;For Other Metrics of DAT, FNT, and REF&#039;&#039;&lt;br /&gt;
* Integer Out of Range 0-256. For height, top, bottom, pitch, xSkip, imageWidth, imageHeight, and REF’s coord_s, coord_t, coord_s2, and coord_t2.&lt;br /&gt;
* Integer Non Zero. For glyph.&lt;br /&gt;
* Float Less Than Zero. For glyphScale (which is independent of a particular character).&lt;br /&gt;
* Inconsistent Metrics. For a given character, this compares two metrics and looks for inconsistencies. We’ll state this here in REF terms, e.g., using “coord_s” rather than “ROUND_TO_INT(s * 256.0f)”:&lt;br /&gt;
** imageHeight == height?&lt;br /&gt;
** imageWidth == coord_s2 - coord_s?&lt;br /&gt;
** imageHeight == coord_t2 - coord_t?&lt;br /&gt;
&lt;br /&gt;
However, warnings about those last two &amp;quot;Inconsistent Metrics&amp;quot; criteria are suppressed if:&lt;br /&gt;
* you use refont&#039;s &amp;quot;-scaling_ok&amp;quot; option. This is helpful when there is extensive per-character scaling. (Only TDM’s mason and mason-glow use a lot of per-character scaling, specifically for all upper-case characters.)&lt;br /&gt;
* you have a 512x512 bitmap, where throughout, the imageWidth and imageHeight (and some other metrics) are expected to be scaled to &amp;quot;half&amp;quot; of the corresponding coord difference. As of refont 2.8, 1 pixel of wiggle-room is allowed for integer rounding. Only warnings will be issued that fail these checks:&lt;br /&gt;
** abs(imageWidth * 2 - (coord_s2 - coord_s)) &amp;gt; 1&lt;br /&gt;
** abs(imageHeight * 2 - (coord_t2 - coord_t)) &amp;gt; 1&lt;br /&gt;
&lt;br /&gt;
===Post-Read MINOR Warnings for FNT’s and DAT’s s, t, s2, t2===&lt;br /&gt;
&#039;&#039;Low Precision.&#039;&#039; This value, when multiplied by 256.0, should be exactly an integer. However, some generation or revision procedure (e.g., Q3Font’s DAT  FNT  DAT) may have not used sufficient precision to ensure this. An offset from an integer value of less than +/- 0.001 is considered a minor problem; otherwise, major as above.&lt;br /&gt;
&lt;br /&gt;
This problem, when it occurs with a file, typically happens a lot. Consequently, it is not reported in an itemized way, but instead, the console will show total counts of affected characters and values.&lt;br /&gt;
&lt;br /&gt;
Edge cases: a value of {s, s2, t, or t2} * 256.0 that is negative but closer to zero than -0.001000 is considered this type of minor problem (and is not considered out of range, which would be major). Likewise, if that value is greater than 256.000000, but less than 256.001000&lt;br /&gt;
===Automatic Corrections during Output to a REF File===&lt;br /&gt;
Certain problems, first detected during DAT input, are further addressed at write time. Because these problems were already reported to the console during the DAT read, nothing additional is written to console. Instead, there may be reporting within the REF file itself.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Automatic Corrections.&#039;&#039; When writing a REF file, the integer values of coord_s, coord_t, coord_s2, and coord_t2 are calculated from DAT floats s, t, s2, and t2 respectively. A calculated coord_... value, if not already resulting in an integer, is automatically forced to the nearest integer. This is so whether it was earlier reported to the console as a Major or Minor Warning. (Before refont v 2.1, the REF might assign an unrounded decimal value; no longer true.)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Warnings Not Automatically Corrected.&#039;&#039; Automatic fixing of other warnings is unwise and not offered. Why? Because the fix is not obvious or complex, and sometimes, the corresponding character glyph in the bitmap needs adjustment. This pertains to Major Warnings about:&lt;br /&gt;
* Integer values outside their expected range (e.g., 0-256), including post-rounding coord_... values.&lt;br /&gt;
* Inconsistent Metrics&lt;br /&gt;
===Generated Within-REF Comments during Output===&lt;br /&gt;
For most causes of a Major Warning during DAT read, during subsequent writing of the REF file, a similar comment is also generated within the REF, on the same line as the parameter assignment. For example:&lt;br /&gt;
 char 95 (0x5f) // _&lt;br /&gt;
 {&lt;br /&gt;
    ...&lt;br /&gt;
    top -6 // WARNING: Not in range 0-256. Does bitmap or other metrics need adjusting?&lt;br /&gt;
    ...&lt;br /&gt;
 }&lt;br /&gt;
 ...&lt;br /&gt;
 char 140 (0x8c) // Ń&lt;br /&gt;
 {&lt;br /&gt;
    ...&lt;br /&gt;
    coord_t -10 // WARNING: Underlying DAT value -0.03906250, * 256.0 gave -10.000000000, not in range 0-256 once rounded. Does bitmap or other metrics need adjusting?&lt;br /&gt;
    ...&lt;br /&gt;
 }&lt;br /&gt;
&#039;&#039;Suppressing Comment Generation.&#039;&#039; Use the refont option “-no_warn_comments”. &#039;&#039;New to v 2.1.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
TIP: When editing a REF file with comments, you can keep them, change them, or delete them as you prefer. They have no impact on subsequent compiles to DAT.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Coverage of Generated Within-REF Comments.&#039;&#039; A calculated value of coord_s, coord_t, coord_s2, or coord_t2 would have been flagged as a “Major Warning” during read if:&lt;br /&gt;
* the discrepancy from being an integer was non-trivial (+/- 0.001 or more), or&lt;br /&gt;
* the calculated and rounded integer is outside the range given by bitmap size, e.g., 0-256.&lt;br /&gt;
&lt;br /&gt;
For these, a comment is generated. Other causes are:&lt;br /&gt;
* Integer Out of Range 0-256 &#039;&#039;(or 0-512 as applicable)&#039;&#039;. For height, top, bottom, pitch, xSkip, imageWidth, imageHeight.&lt;br /&gt;
* Integer Non Zero. For glyph.&lt;br /&gt;
* Float Less Than Zero. For glyphScale (which is independent of a particular character).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Major Warnings that Don’t Cause Within-REF Comments.&#039;&#039; Currently, this is limited to “Inconsistent Metrics”, which would probably require tagging on multiple lines.&lt;br /&gt;
&lt;br /&gt;
== Special Handling of Fonts with 512x512 Bitmaps ==&lt;br /&gt;
Some DAT files reference bitmap shaders where some or all are of size 512x512, instead of the default 256x256. Refont v2.5+ can support this (replacing an insufficient first attempt in v2.4).&lt;br /&gt;
&lt;br /&gt;
Font developers went to double-sized bitmaps to:&lt;br /&gt;
* in the case of Carleton, allow freehand drawing of missing European characters, which could be drawn more easily if twice standard size.&lt;br /&gt;
* in the case of Mason, have larger ASCII alphanumeric glyphs that would render with crisper edges.&lt;br /&gt;
&lt;br /&gt;
In either case, the font characters when rendered in, say, the game main menu will be the same size as if from 256x256. This is because the imageWidth, imageHeight, height, and top metrics are not doubled.&lt;br /&gt;
In effect, a scaling by half (approximately, as constrained by integer values) is requested for all characters in the DAT file and applied by the engine.&lt;br /&gt;
&lt;br /&gt;
=== When generating a REF file from a DAT file ===&lt;br /&gt;
&lt;br /&gt;
 refont -decompile &amp;lt;path to given .dat file&amp;gt; -512_&amp;lt;n&amp;gt;   &#039;&#039;where &amp;lt;n&amp;gt; is a single digit, e.g. &#039;1&#039; in referenced shader name &amp;quot;font/Carleton_1_24.tga&amp;quot; &#039;&#039;&lt;br /&gt;
&lt;br /&gt;
You should use multiple instances of the -512_&amp;lt;n&amp;gt; option, to cover all the 512x512 bitmaps found in the DAT file.&lt;br /&gt;
&lt;br /&gt;
If &#039;&#039;all&#039;&#039; of a given DATs shaders are 512x512, you can use this shorter form:&lt;br /&gt;
&lt;br /&gt;
 refont -decompile &amp;lt;path to given .dat file&amp;gt; -512&lt;br /&gt;
&lt;br /&gt;
Exercising -512... options will mean that in the generated REF file:&lt;br /&gt;
&lt;br /&gt;
* There will be a one or more starting lines like:&lt;br /&gt;
  # bitmap_&amp;lt;n&amp;gt;_size=512 &#039;&#039;(Refont will look for this if doing a subsequent compile to DAT)&#039;&#039;&lt;br /&gt;
* If you specified the short form, it will expand to just the right number of starting lines.&lt;br /&gt;
* Values for coord_s, coord_s2, coord_t, and coord_t2 will have a normal range of 0-512 when appropriate. [COMING SOON: Those values may then be read properly by datBounds.].&lt;br /&gt;
* Any warnings expressed (within the file or within the command-line window) will be in terms of the correct range of values. &lt;br /&gt;
* Warning checks will expect a scaling by half for all characters. That is, while 512... requires scaling down by half, that scaling will not generate a warning (unless it&#039;s not EXACTLY by half, or within 1 pixel of that), so the -scaling_ok option is not needed just for the exactly-by-half scaling.&lt;br /&gt;
&lt;br /&gt;
=== When generating a DAT file from a REF file ===&lt;br /&gt;
&lt;br /&gt;
During refont -compile, no special command line options are needed. Instead, REF&#039;s starting lines of form &amp;quot;# bitmap_&amp;lt;n&amp;gt;_size=512&amp;quot; are inspected and coord ranges will be interpreted as 0-512 whenever appropriate. &lt;br /&gt;
&lt;br /&gt;
=== Special Handling Recommendations for Carleton and Mason ===&lt;br /&gt;
&#039;&#039;For fonts shipped with TDM 2.12 in tdm_fonts01.pk4. Illustrative command paths are shown; adjust to your working copy.&#039;&#039;&lt;br /&gt;
==== Mason Family ====&lt;br /&gt;
The [[Mason Font]] uses within-DAT per-character scaling, as well as some but not all 512x512 bitmaps. Only 48pt Mason is shipped.&lt;br /&gt;
&lt;br /&gt;
Because, under /dds/fonts/english/mason/, bitmaps masonalternate_0_48.dds to _2_ are 512x512, but _3_ to _5_ are not, use:&lt;br /&gt;
&lt;br /&gt;
 -decompile /fonts/english/mason/fontimage_48.dat -512_0 -512_1 -512_2 -scaling_ok&lt;br /&gt;
&lt;br /&gt;
Because, under /dds/fonts/english/mason_glow/, bitmaps masonalternate_1_48.dds and _2_ are 512x512, but _0_ and _3_ to _5_ are not, use:&lt;br /&gt;
&lt;br /&gt;
 -decompile /fonts/english/mason_glow/fontimage_48.dat -512_1 -512_2 -scaling_ok&lt;br /&gt;
&lt;br /&gt;
Russian versions use the default 256x256. [These possibly benefit from -scaling_ok; didn&#039;t investigate.]&lt;br /&gt;
==== Carleton Family ====&lt;br /&gt;
The 24pt size of carleton has two bitmaps under /dds/fonts/english/carleton/, namely carleton_0_24.dds and _1_, both of size 512x512. So use:&lt;br /&gt;
&lt;br /&gt;
 -decompile /fonts/english/carleton/fontimage_24.dat -512_0 -512_1&lt;br /&gt;
  &#039;&#039;or&#039;&#039;&lt;br /&gt;
 -decompile /fonts/english/carleton/fontimage_24.dat -512&lt;br /&gt;
 &lt;br /&gt;
The 24pt size of carleton_bold has bitmaps with identical content to carleton&#039;s, so use the same options:&lt;br /&gt;
&lt;br /&gt;
 -decompile /fonts/english/carleton_bold/fontimage_24.dat -512_0 -512_1&lt;br /&gt;
  &#039;&#039;or&#039;&#039;&lt;br /&gt;
 -decompile /fonts/english/carleton_bold/fontimage_24.dat -512&lt;br /&gt;
&lt;br /&gt;
Other members of this family use the default 256x256 bitmaps:&lt;br /&gt;
* Sizes 12pt &amp;amp; 48pt&lt;br /&gt;
* carleton_condensed and carleton_glow. (Note: while helpful, it is not required that the base &amp;amp; glow have identical bitmap sizes.)&lt;br /&gt;
* Russian versions&lt;br /&gt;
&lt;br /&gt;
==== These Fonts with Stats ====&lt;br /&gt;
With -stats discussed next, if reading a DAT file, you may use the -512... and scaling_ok options to be most correct, although neglecting to specify them will likely have no significant impact on the analytical results. If reading a REF file, the included &amp;quot;# bitmap_...&amp;quot; lines will take care of that for you.&lt;br /&gt;
&lt;br /&gt;
== For Statistics on Unimplemented or Problematic Font Characters ==&lt;br /&gt;
DAT or (as of v2.3) REF file analysis here is primarily designed to benefit english/european fonts. It will use the optional annotation file if provided. Syntax:&lt;br /&gt;
&lt;br /&gt;
     refont -stats &amp;lt;path to given .dat or .ref file&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Use &amp;quot;-stats&amp;quot; by itself, not combined with &amp;quot;-compile&amp;quot; or &amp;quot;-decompile&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
The resulting analysis report will have the same name and location as the input file, but with a &amp;quot;.txt&amp;quot; suffix.&lt;br /&gt;
The report provides categorized totals and (for problematic characters) itemizations across all 256 character codepoints.&lt;br /&gt;
The counts of problems should be considered minimums, since no inspection of bitmap files (TGA or DDS) is done.&lt;br /&gt;
But a perhaps surprising amount of insight can be gleaned just from DAT/REF file metrics.&lt;br /&gt;
Itemizations include annotations from the &#039;ref_char_annotation&#039; file, if provided.&lt;br /&gt;
&lt;br /&gt;
In the hunt for missing characters, 3 signatures are important:&lt;br /&gt;
&lt;br /&gt;
* Presumed &#039;Hollow Box&#039; = glyph&#039;s &#039;shadername&#039; is &amp;lt;fontname&amp;gt;_0_&amp;lt;size&amp;gt;.dds only, and s &amp;amp; t are zero, but not s2 &amp;amp; t2&lt;br /&gt;
* &#039;&amp;lt;Space&amp;gt;&#039; = same test as &#039;Hollow Box&#039;, but pointed to by char 32 (0x20)&lt;br /&gt;
* &#039;Zero Box&#039; = No glyph box (s, t, s2, t2 all zero)&lt;br /&gt;
&lt;br /&gt;
A given analysis will assume either &#039;Hollow Box&#039; or &#039;&amp;lt;Space&amp;gt;&#039; but not both.&lt;br /&gt;
&lt;br /&gt;
The analysis provides totals and itemizations - grouped into lower (0-127) and upper ranges (128-255) - in several passes: &lt;br /&gt;
&lt;br /&gt;
* Pass 1 - Handling of unprintable/unsupported/missing codepoints, indicated by Hollow Box, Zero Box, or &amp;lt;Space&amp;gt;. Some of these are not a problem, but some are tagged as &amp;quot;Undesirable&amp;quot;.&lt;br /&gt;
* Pass 2 - Bad glyph box (negative s, t, s2, or t2; or s2 &amp;lt;= s, t2 &amp;lt;= t) or good glyph box with dubious metrics (imageHeight &amp;lt;= 0, imageWidth &amp;lt;=0, imageHeight != height). Excludes those already counted as &amp;quot;Undesirable&amp;quot; in Pass 1. &lt;br /&gt;
* Pass 3 - Detection of duplicate glyph boxes (other than Hollow Box, Zero Box, or &amp;lt;Space&amp;gt;). Detected by: glyph&#039;s values for shadername, s, t, s2, &amp;amp; t2 exactly match those of another codepoint. These are grouped into &amp;quot;Dup Sets&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Then, across passes 1-3, a count if given of the minimum &amp;quot;Total Glyphs Needing Work&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Refont version 2.3 adds additional passes:&lt;br /&gt;
&lt;br /&gt;
* Pass 4 - Reports &amp;quot;Overlap Sets&amp;quot; rather than just &amp;quot;Dup Sets&amp;quot;. A set here may include an unaccented &amp;quot;base character&amp;quot; that has been serving as a substitute work-around target for one or more missing accented characters. (What constitutes an &amp;quot;overlap&amp;quot; is idiosyncratic; see the source code for details.)&lt;br /&gt;
* Pass 5 - Same information as Pass 4, but sorted first by shader name (i.e., bitmap). Helpful for organizing bitmap-editing work.&lt;br /&gt;
* Pass 6 - An analysis focusing just on the planned migration of duplicate O/o-circumflex codepoints to G/g-cup glyphs.&lt;br /&gt;
&lt;br /&gt;
== Downloads ==&lt;br /&gt;
Release 2.6 of July 28, 2025:&lt;br /&gt;
* [https://drive.google.com/file/d/1ABf4771Jr1C1hKbLx4xWq8lx8Kn7HdKP/view?usp=sharing refont.exe]&lt;br /&gt;
* [https://drive.google.com/file/d/1-k68eo0CHKZ-sM7JGP05axm49cc5De0T/view?usp=sharing source code: refont.cpp]&lt;br /&gt;
&lt;br /&gt;
===Annotations===&lt;br /&gt;
&#039;&#039;After download, to use any one of these, edit filename to remove &amp;quot;[...]&amp;quot; substring.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Update of June 20, 2024. This reflects a change to the TDM charmap for 2.13, to replace duplicate O/o circumflex characters with G/g breve:&lt;br /&gt;
&lt;br /&gt;
* refont_char_annotations[english with symbol only. With G-breve update].txt [https://drive.google.com/file/d/1rrt-O9DgD7Zn2Hxt7nBtViIlO4kv_gQB/view?usp=sharing here]. Recommended for most purposes with &#039;english&#039; fonts.&lt;br /&gt;
* refont_char_annotations[english with Unicode-16 codes &amp;amp; names. With G-breve update].txt [https://drive.google.com/file/d/1AMxDKQc_DE33gsExiEkGp3x67eb4aGFh/view?usp=sharing here].&lt;br /&gt;
* refont_char_annotations[english with 8859-x source. With G-breve update].txt [https://drive.google.com/file/d/1xoeZ1poTbmkls-gE5PnbbMxdoz5KnMD7/view?usp=sharing].&lt;br /&gt;
* For Russian, see the previous update next.&lt;br /&gt;
&lt;br /&gt;
Update of April 13, 2024:&lt;br /&gt;
&lt;br /&gt;
* refont_char_annotations[english with symbol only].txt [https://drive.google.com/file/d/1ItM-aXps0xQE655HdaJM7Aje5lHewUfC/view?usp=sharing here]. Recommended for most purposes with &#039;english&#039; fonts.&lt;br /&gt;
* refont_char_annotations[english with Unicode-16 codes and names].txt [https://drive.google.com/file/d/1gW7oO_wLqCEPSdm6b05OaTNYHnyuUSA-/view?usp=sharing here].&lt;br /&gt;
* refont_char_annotations[english with 8859-x source].txt [https://drive.google.com/file/d/1ZTcgA4QJYwXzNdqbolYkn0CCEDILD1bX/view?usp=sharing here]. Corrects and supersedes original english file.&lt;br /&gt;
* refont_char_annotations[russian].txt [https://drive.google.com/file/d/10txNXsSCtaTiT2iGT9o3iDxBU7HVYNxi/view?usp=sharing here]. Recommended for &#039;russian&#039; fonts.&lt;br /&gt;
&lt;br /&gt;
== For More ==&lt;br /&gt;
* See the [https://forums.thedarkmod.com/index.php?/topic/22427-analysis-of-212-tdm-fonts/ summary analysis of 2.12 TDM fonts], based on applying &#039;refont -stats ...&#039; to all &#039;english&#039; DAT files.&lt;br /&gt;
&lt;br /&gt;
{{tutorial}} [[Category:Fonts]]&lt;/div&gt;</summary>
		<author><name>Geep</name></author>
	</entry>
	<entry>
		<id>https://wiki.thedarkmod.com/index.php?title=Refont&amp;diff=34446</id>
		<title>Refont</title>
		<link rel="alternate" type="text/html" href="https://wiki.thedarkmod.com/index.php?title=Refont&amp;diff=34446"/>
		<updated>2026-03-18T17:18:00Z</updated>

		<summary type="html">&lt;p&gt;Geep: /* Post-Read MAJOR Warnings about REF, FNT, and DAT Input Values */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;By Geep, 2024, and similar to the article about Q3Font.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Introduced in 2024, the &amp;quot;refont&amp;quot; command-line utility allows inspection and alteration of [[Font Metrics &amp;amp; DAT File Format | font metrics]].&lt;br /&gt;
It is designed to be an easier-to-use version of the inspection/alteration functionalities of [[Q3Font]].&lt;br /&gt;
It also provides a font analysis feature.&lt;br /&gt;
&lt;br /&gt;
== Comparison with Font Patcher ==&lt;br /&gt;
&lt;br /&gt;
Refont can be seen as complementary to [[Font Patcher]]. The latter has additional features that may be better if planning a wholesale rearrangement or expansion of characters within a bitmap, particularly for a new font immediately after conversion from a TTF font. But refont is easier to use in later years, and  Font Patcher requires installation of Perl, while refont.exe is more drop and go.&lt;br /&gt;
&lt;br /&gt;
== Comparison with Q3Font ==&lt;br /&gt;
&lt;br /&gt;
For metric alteration, q3font has a native &amp;quot;*.fnt&amp;quot; human-readable format, and supports DAT &amp;lt;==&amp;gt; FNT conversions. For compatibility, so does refont.&lt;br /&gt;
&lt;br /&gt;
=== Advantages of Q3Font ===&lt;br /&gt;
&lt;br /&gt;
* This has been an important traditional tool for Doom3/TDM font manipulation.&lt;br /&gt;
* In addition to production/consumption of FNT, it -&lt;br /&gt;
** Allows creation of DAT &amp;amp; TGA files from a TrueType font (although for this purpose, [[ExportFontToDoom3]] has been preferred in practice).&lt;br /&gt;
** Can write (but not read) an alternative &amp;quot;compact report&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
=== Advantages of Refont ===&lt;br /&gt;
&lt;br /&gt;
* It&#039;s open-source, so further C++ development is possible.&lt;br /&gt;
* It has its own native human-readable format, &amp;quot;*.ref&amp;quot;, similar to .fnt but better.&lt;br /&gt;
* The REF format can be read by [[datBounds]] to generate bitmap boundary &amp;amp; metrics visualizations.&lt;br /&gt;
&lt;br /&gt;
The better features of REF are:&lt;br /&gt;
&lt;br /&gt;
* Codepoints are enumerated in not just decimal, but also hex.&lt;br /&gt;
* Coordinates of the overall image box within its bitmap are expressed in pixel units, rather than [0...1] fractional floating point. So the user is spared having to manually do this tedious and error-prone calculation.&lt;br /&gt;
* This overcomes a drawback of FNT, that expresses the coordinates with only 6 digits after the decimal point, not quite enough to avoid minor mis-precisions.&lt;br /&gt;
* if optionally provided, a separate, read-only annotation file will automatically decorate the .ref file with helpful information as the file is generated. This is explained below.&lt;br /&gt;
&lt;br /&gt;
Because the code is open-source, there&#039;s better clarity about -&lt;br /&gt;
* how parsing and calculations are done.&lt;br /&gt;
* what warnings are emitted.&lt;br /&gt;
&lt;br /&gt;
Also, using &amp;quot;-stats&amp;quot;, refont can write (but not read) an analysis of a DAT file, particularly looking for problematic/unimplemented Western-language characters.&lt;br /&gt;
&lt;br /&gt;
== For Inspection &amp;amp; Correction of DAT files ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;To Get the Data in Readable, Editable Form&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
For viewing and altering in a text editor, two formats are provided. Both list every codepoint, in order from 0 to 255, as a block of data. Within each block, every item gets its own line.&lt;br /&gt;
&lt;br /&gt;
=== As a FNT File ===&lt;br /&gt;
&lt;br /&gt;
To create a q3font-compatable &amp;quot;&amp;lt;dat-name&amp;gt;.fnt&amp;quot; file:&lt;br /&gt;
&lt;br /&gt;
 refont -decompile &amp;lt;path to given .dat file&amp;gt; -fnt&lt;br /&gt;
&lt;br /&gt;
where the path can be a full path, a relative path (e.g., starting with &amp;quot;./&amp;quot; or &amp;quot;../&amp;quot;), or just the file name in the current working directory. The resulting .fnt file will appear in the same directory. It have the same name as the .dat file, except for the extension. As a convenience to keep track of versions, it is not required that the file name be in the standard fontImage_nn.dat form.&lt;br /&gt;
&lt;br /&gt;
Example code block for the letter A:&lt;br /&gt;
 	...&lt;br /&gt;
 	char 65&lt;br /&gt;
 	{&lt;br /&gt;
 		height 18&lt;br /&gt;
 		top 18&lt;br /&gt;
 		bottom 0&lt;br /&gt;
 		pitch 3&lt;br /&gt;
 		xSkip 18&lt;br /&gt;
 		imageWidth 20&lt;br /&gt;
 		imageHeight 18&lt;br /&gt;
 		s 0.769531&lt;br /&gt;
 		t 0.250000&lt;br /&gt;
 		s2 0.847656&lt;br /&gt;
 		t2 0.320313&lt;br /&gt;
 		glyph 0&lt;br /&gt;
 		shaderName fonts/stone_0_24.tga&lt;br /&gt;
 	}&lt;br /&gt;
  	...&lt;br /&gt;
&lt;br /&gt;
Note that Q3Font FNT expresses the s, t, s2, and t2 coordinates with only 6 digits after the decimal point, causing minor low-precision rounding during DAT --&amp;gt; FNT --&amp;gt; DAT roundtrips. For compatibility, Refont FNT does likewise.&lt;br /&gt;
&lt;br /&gt;
=== As a REF File ===&lt;br /&gt;
&#039;&#039;Starting with Refont v2.5, a mixture of 256x256 and 512x512 bitmap shaders, encountered with Carleton and Mason family fonts, can be handled. See further below.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
To create a refont-specific &amp;quot;&amp;lt;dat-name&amp;gt;.ref&amp;quot; file:&lt;br /&gt;
&lt;br /&gt;
 refont -decompile &amp;lt;path to given .dat file&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The same path and naming conventions as for .fnt generation discussed above apply here.&lt;br /&gt;
&lt;br /&gt;
Example code block for the letter A when no supplemental annotation file is present (nor any per-line comments, e.g., with warnings):&lt;br /&gt;
&lt;br /&gt;
 	...&lt;br /&gt;
 	char 65 &amp;lt;b&amp;gt;(0x41)&amp;lt;/b&amp;gt;&lt;br /&gt;
 	{&lt;br /&gt;
 		height 18&lt;br /&gt;
 		top 18&lt;br /&gt;
 		bottom 0&lt;br /&gt;
 		pitch 3&lt;br /&gt;
 		xSkip 18&lt;br /&gt;
 		imageWidth 20&lt;br /&gt;
 		imageHeight 18&lt;br /&gt;
 		&amp;lt;b&amp;gt;coord_s 197&lt;br /&gt;
 		coord_t 64&lt;br /&gt;
 		coord_s2 217&lt;br /&gt;
 		coord_t2 82&amp;lt;/b&amp;gt;&lt;br /&gt;
 		glyph 0&lt;br /&gt;
 		shaderName fonts/stone_0_24.tga&lt;br /&gt;
 	}&lt;br /&gt;
 	...&lt;br /&gt;
&lt;br /&gt;
Items bolded differ from FNT format. The starting line expresses the value in hex. And rather than s, t, s2, t2 in fractional [0...1] floating point, the &amp;quot;coord_...&amp;quot; values are expressed (and editable) as integer coordinates of the bitmap, with a range reflecting bitmap size. The default TDM bitmap size is 256x256, but a few fonts use 512x512 and require special treatment discussed further below.&lt;br /&gt;
&lt;br /&gt;
== When Editing ==&lt;br /&gt;
Refont has a minimal parser. To keep it happy, preserve the file&#039;s line structure. In particular:&lt;br /&gt;
* every REF and FNT file has the same number of lines. &#039;&#039;(Exception: REF may have additional starting lines to flag 512x512 bitmaps, discussed below. Generally, you won&#039;t edit these.)&#039;&#039;&lt;br /&gt;
* all keywords within a block must be present, and in a particular order.&lt;br /&gt;
* each block must have exactly the same number of lines (except for the special one at the end).&lt;br /&gt;
&lt;br /&gt;
The meaning of the font metrics are explained in [[Font_Metrics_%26_DAT_File_Format]]. The [[Q3Font]] article has an example of simple metric editing that is also pertinent to refont.&lt;br /&gt;
&lt;br /&gt;
== To Move Changed FNT or REF Data Back to a DAT ==&lt;br /&gt;
&lt;br /&gt;
 refont -compile &amp;lt;path to given .fnt or .ref file&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This reverses the -decompile process, to create a .dat file whose name is derived from the .fnt or .ref file. Importantly, this decompile/compile cycle leaves .tga/.dds files untouched.&lt;br /&gt;
&lt;br /&gt;
== The Annotation File ==&lt;br /&gt;
When told to generate a REF file (but not FNT), refont.exe also looks for a file called &amp;quot;refont_char_annotations.txt&amp;quot;, in the same folder as refont.exe.  That file should have exactly 256 data lines in it, one for each of the codepoints, in order. As the REF is generated, the line that starts a codepoint&#039;s data block gets the corresponding annotation line appended  to it. Having the annotations come from an external file, instead of hard-coded into refont, allows required flexibility as to what information is presented. It even potentially allows refont to be used with other idTech3/4 games that don&#039;t necessarily used the TDM-specific codepoints. Also, the annotation files contain helpful specific comments (as lines that start with &amp;quot;;&amp;quot;).&lt;br /&gt;
&lt;br /&gt;
Each annotation:&lt;br /&gt;
* indicates what character symbol is &#039;&#039;expected&#039;&#039;; it is oblivious as to what character if any is actually within the bounding box described by the DAT data.&lt;br /&gt;
* lives only in a REF file, and is not retained when converted to a DAT file. This also true for any manual supplementary annotations you might make.&lt;br /&gt;
&lt;br /&gt;
This is clearer with examples. In &#039;Downloads&#039; below are 4 different versions of &amp;quot;refont_char_annotations[...].txt&amp;quot;. Three of these, specific to TDM&#039;s custom &#039;english&#039; (i.e., composite European) codepage, are discussed here. To deploy, edit the filename of one of them to remove the square bracket text.&lt;br /&gt;
&lt;br /&gt;
=== English with Symbol Only ===&lt;br /&gt;
&lt;br /&gt;
This simple format is best for most purposes. The file entry for letter &#039;A&#039; is just:&lt;br /&gt;
&lt;br /&gt;
 A&lt;br /&gt;
&lt;br /&gt;
Then the block in a generated REF file would have that string appended, but with &amp;quot; // &amp;quot; inserted.&lt;br /&gt;
 	...&lt;br /&gt;
 	char 65 (0x41) // A&lt;br /&gt;
 	{&lt;br /&gt;
 		height 18&lt;br /&gt;
 		top 18&lt;br /&gt;
 		bottom 0&lt;br /&gt;
 		pitch 3&lt;br /&gt;
 		xSkip 18&lt;br /&gt;
 		imageWidth 20&lt;br /&gt;
 		imageHeight 18&lt;br /&gt;
 		coord_s 197&lt;br /&gt;
 		coord_t 64&lt;br /&gt;
 		coord_s2 217&lt;br /&gt;
 		coord_t2 82&lt;br /&gt;
 		glyph 0&lt;br /&gt;
 		shaderName fonts/stone_0_24.tga&lt;br /&gt;
 	}&lt;br /&gt;
 	...&lt;br /&gt;
&lt;br /&gt;
=== English with Unicode-16 Codes and Names ===&lt;br /&gt;
&lt;br /&gt;
This supplies the Unicode Consortium&#039;s official 16-bit codepoints (where U+NNNN = 0xNNNN) and their names, in the formal all-caps convention.&lt;br /&gt;
&lt;br /&gt;
The file entry for letter &#039;A&#039; is:&lt;br /&gt;
&lt;br /&gt;
 U+0041 LATIN CAPITAL LETTER A&lt;br /&gt;
&lt;br /&gt;
Then the first line of the corresponding block in a generated REF file would show:&lt;br /&gt;
 	...&lt;br /&gt;
 	char 65 (0x41) // U+0041 LATIN CAPITAL LETTER A&lt;br /&gt;
 	...&lt;br /&gt;
Here&#039;s another example from that REF:&lt;br /&gt;
 	...&lt;br /&gt;
 	char 129 (0x81) // U+015A LATIN CAPITAL LETTER S WITH ACUTE&lt;br /&gt;
 	...&lt;br /&gt;
For control or TDM undefined characters, this annotation file assumes a hollow box glyph is the appropriate mapping:&lt;br /&gt;
 	...&lt;br /&gt;
 	char 0 (0x00) // U+24A1 WHITE SQUARE&lt;br /&gt;
 	...&lt;br /&gt;
But there are other choices, so edit the annotation file as you see fit.&lt;br /&gt;
=== English with 8859-x Source ===&lt;br /&gt;
&lt;br /&gt;
This verbose format may be useful during font analysis. For letters that are in their expected locations as defined by ASCII or ISO 8859-1 (Latin-1) or Windows-1252 (&amp;quot;Western Europe&amp;quot;), the annotation is fairly minimal. Thus, letter &#039;A&#039; has this:&lt;br /&gt;
&lt;br /&gt;
 0x41 is A&lt;br /&gt;
&lt;br /&gt;
(TIP: If authoring your own annotation file, consider including a codepoint number on each line, like &amp;quot;0x41&amp;quot; here, to make the process easier.)&lt;br /&gt;
&lt;br /&gt;
Then the first line of the corresponding block in a generated REF file would show:&lt;br /&gt;
 	...&lt;br /&gt;
 	char 65 (0x41) // 0x41 is A&lt;br /&gt;
 	...&lt;br /&gt;
Here are a few more interesting examples from that REF, with more expansive annotations:&lt;br /&gt;
 	...&lt;br /&gt;
 	char 5 (0x05) // 0x05 is a control character, unusable in TDM&lt;br /&gt;
 	...&lt;br /&gt;
 	char 166 (0xa6) // 0xA6 is Š (not ISO 8859-1 ¦) (from A9 in ISO 8859-2) (TDM only)&lt;br /&gt;
 	...&lt;br /&gt;
&lt;br /&gt;
== Revising or Making Your Own Annotations File ==&lt;br /&gt;
If creating your own refont_char_annotations.txt file, note that encoding upper-range characters in UTF-8 will be more universal than using Windows region-specific codepages. To enter a UTF-8 character using its four digit hex Unicode (say, in a range of interest 0x0080-0x00FF):&lt;br /&gt;
* Under Windows, type the four hex digits followed by Alt-X.&lt;br /&gt;
* Under Linux, hold down Ctrl+Shift, type U followed by the 4 digits; release Ctrl+Shift.&lt;br /&gt;
&lt;br /&gt;
When refont reads refont_char_annotations.txt, any line that starts with &amp;quot;;&amp;quot; will be ignored. The latter is so that you can put comments into the file, that will not propagate to the generated REF file. TIP: If such commenting is unwanted, start the line with &amp;lt;space&amp;gt; before &amp;quot;;&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Other than that, be sure to have exactly 256 lines of annotations (though refont will check and issue a warning if not). A line can be empty, i.e., have only the linebreak.&lt;br /&gt;
&lt;br /&gt;
When generating a REF file, refont will automatically add &amp;quot; // &amp;quot; before each non-empty annotation, so don&#039;t include that.&lt;br /&gt;
&lt;br /&gt;
== Adding Your Own Annotations to a REF File ==&lt;br /&gt;
Beyond the refont_char_annotation.txt content, you can add certain commentary to the REF file without it affecting its ability to convert to a DAT file. Here are the rules:&lt;br /&gt;
* Don&#039;t add or subtract lines, or comment out non-blank lines&lt;br /&gt;
* Feel free to append a comment to the end of a line, by beginning the comment with &amp;quot; //&amp;quot;.&lt;br /&gt;
* Likewise, on a line starting with &amp;quot;char&amp;quot; that had an annotation automatically added, you can revise the annotation as you see fit.&lt;br /&gt;
&lt;br /&gt;
Example with revision in bold:&lt;br /&gt;
 	...&lt;br /&gt;
 	char 65 (0x41) // &#039;&#039;&#039;Capital A was slightly clipped. Decremented s, s2 by 1. Looks OK now.&#039;&#039;&#039;&lt;br /&gt;
 	{&lt;br /&gt;
 		height 18&lt;br /&gt;
 		top 18&lt;br /&gt;
 		bottom 0&lt;br /&gt;
 		pitch 3&lt;br /&gt;
 		xSkip 18&lt;br /&gt;
 		imageWidth 20&lt;br /&gt;
 		imageHeight 18&lt;br /&gt;
 		coord_s 196 &#039;&#039;&#039;// WAS: 197&#039;&#039;&#039;&lt;br /&gt;
 		coord_t 64&lt;br /&gt;
 		coord_s2 216 &#039;&#039;&#039;// WAS: 217&#039;&#039;&#039;&lt;br /&gt;
 		coord_t2 82&lt;br /&gt;
 		glyph 0&lt;br /&gt;
 		shaderName fonts/stone_0_24.tga&lt;br /&gt;
  	}&lt;br /&gt;
 	...&lt;br /&gt;
&lt;br /&gt;
In this way, you can markup a REF file as a record of work to do, work in progress, or work completed.&lt;br /&gt;
&lt;br /&gt;
==Errors, Warnings, and Auto-Corrections==&lt;br /&gt;
&#039;&#039;This covers the major overhaul of Refont v 2.1, and its added options -no_warn_comments and -scaling_ok.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
During the compile or decompile, errors and warnings may be generated in the console. Fatal errors are largely due to: &lt;br /&gt;
* file I/O problems;&lt;br /&gt;
* deviations from the strict DAT, REF, and FNT formats.&lt;br /&gt;
&lt;br /&gt;
Warnings, which are not fatal, are largely due to anomolous numeric values. The TDM engine can tolerant some of these, so they don&#039;t necessarily need fixing. &lt;br /&gt;
&lt;br /&gt;
===Fatal Errors when Parsing REF or FNT as Input===&lt;br /&gt;
A fatal error, due to divergence from the expected format while parsing, stops the program. While potentially due to many causes (e.g., adding or deleting lines), errors will be reported - with line number - as failures of:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Variable Name Checks.&#039;&#039; The parser expects every variable name in a particular order. A mismatch happened.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Integer Checks.&#039;&#039; Integer value was unparsable, or out of range for integer type. Checked for per-character variables height, top, bottom, pitch, xSkip, imageWidth, imageHeight, and glyph. Plus REF’s coord_s, coord_t, coord_s2, and coord_ t2.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Float Checks.&#039;&#039; Floating point value was unparsable, or out of range for float type. Checked for glyphScale, and FNT’s per-character variables s, t, s2, t2.&lt;br /&gt;
&lt;br /&gt;
===Post-Read MAJOR Warnings about REF, FNT, and DAT Input Values===&lt;br /&gt;
After parsing, the input process concludes with a separate loop of non-fatal warning analysis. Warnings during input, broadly categorized as major or minor, report to the console, but don’t do any value corrections (which is instead left to the subsequent file-write stage).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;For FNT’s and DAT’s s, t, s2, t2&#039;&#039;&lt;br /&gt;
* Inexact Integer. The given bounding box value, expected in the range 0-1, when multiplied by 256.0 should be exactly an integer. If not, the divergence is likely due to miscalculation.  (Actually, a divergence from an integer of under +/- 0.001 is tolerated by Refont and considered a minor warning, discussed below.) &lt;br /&gt;
* Float Out of Range 0.0 - 1.0. Or equivalently, post-multiplication, 0.0 - 256.0. (See the discussion of the edge cases under minor warnings below.)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;For Other Metrics of DAT, FNT, and REF&#039;&#039;&lt;br /&gt;
* Integer Out of Range 0-256. For height, top, bottom, pitch, xSkip, imageWidth, imageHeight, and REF’s coord_s, coord_t, coord_s2, and coord_t2.&lt;br /&gt;
* Integer Non Zero. For glyph.&lt;br /&gt;
* Float Less Than Zero. For glyphScale (which is independent of a particular character).&lt;br /&gt;
* Inconsistent Metrics. For a given character, this compares two metrics and looks for inconsistencies. We’ll state this here in REF terms, e.g., using “coord_s” rather than “ROUND_TO_INT(s * 256.0f)”:&lt;br /&gt;
** imageHeight == height?&lt;br /&gt;
** imageWidth == coord_s2 - coord_s?&lt;br /&gt;
** imageHeight == coord_t2 - coord_t?&lt;br /&gt;
&lt;br /&gt;
However, warnings about those last two &amp;quot;Inconsistent Metrics&amp;quot; criteria are suppressed if:&lt;br /&gt;
* you use refont&#039;s &amp;quot;-scaling_ok&amp;quot; option. This is helpful when there is extensive per-character scaling. (Only TDM’s mason and mason-glow use a lot of per-character scaling, specifically for all upper-case characters.)&lt;br /&gt;
* you have a 512x512 bitmap, where throughout, the imageWidth and imageHeight (and some other metrics) are expected to be scaled to &amp;quot;half&amp;quot; of the corresponding coord difference. As of refont 2.8, 1 pixel of wiggle-room is allowed for integer rounding. Only warnings will be issued that fail these checks:&lt;br /&gt;
** abs(imageWidth * 2 - (coord_s2 - coord_s)) &amp;gt; 1&lt;br /&gt;
** abs(imageHeight * 2 - (coord_t2 - coord_t)) &amp;gt; 1&lt;br /&gt;
&lt;br /&gt;
===Post-Read MINOR Warnings for FNT’s and DAT’s s, t, s2, t2===&lt;br /&gt;
&#039;&#039;Low Precision.&#039;&#039; This value, when multiplied by 256.0, should be exactly an integer. However, some generation or revision procedure (e.g., Q3Font’s DAT  FNT  DAT) may have not used sufficient precision to ensure this. An offset from an integer value of less than +/- 0.001 is considered a minor problem; otherwise, major as above.&lt;br /&gt;
&lt;br /&gt;
This problem, when it occurs with a file, typically happens a lot. Consequently, it is not reported in an itemized way, but instead, the console will show total counts of affected characters and values.&lt;br /&gt;
&lt;br /&gt;
Edge cases: a value of {s, s2, t, or t2} * 256.0 that is negative but closer to zero than -0.001000 is considered this type of minor problem (and is not considered out of range, which would be major). Likewise, if that value is greater than 256.000000, but less than 256.001000&lt;br /&gt;
===Automatic Corrections during Output to a REF File===&lt;br /&gt;
Certain problems, first detected during DAT input, are further addressed at write time. Because these problems were already reported to the console during the DAT read, nothing additional is written to console. Instead, there may be reporting within the REF file itself.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Automatic Corrections.&#039;&#039; When writing a REF file, the integer values of coord_s, coord_t, coord_s2, and coord_t2 are calculated from DAT floats s, t, s2, and t2 respectively. A calculated coord_... value, if not already resulting in an integer, is automatically forced to the nearest integer. This is so whether it was earlier reported to the console as a Major or Minor Warning. (Before refont v 2.1, the REF might assign an unrounded decimal value; no longer true.)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Warnings Not Automatically Corrected.&#039;&#039; Automatic fixing of other warnings is unwise and not offered. Why? Because the fix is not obvious or complex, and sometimes, the corresponding character glyph in the bitmap needs adjustment. This pertains to Major Warnings about:&lt;br /&gt;
* Integer values outside their expected range (e.g., 0-256), including post-rounding coord_... values.&lt;br /&gt;
* Inconsistent Metrics&lt;br /&gt;
===Generated Within-REF Comments during Output===&lt;br /&gt;
For most causes of a Major Warning during DAT read, during subsequent writing of the REF file, a similar comment is also generated within the REF, on the same line as the parameter assignment. For example:&lt;br /&gt;
 char 95 (0x5f) // _&lt;br /&gt;
 {&lt;br /&gt;
    ...&lt;br /&gt;
    top -6 // WARNING: Not in range 0-256. Does bitmap or other metrics need adjusting?&lt;br /&gt;
    ...&lt;br /&gt;
 }&lt;br /&gt;
 ...&lt;br /&gt;
 char 140 (0x8c) // Ń&lt;br /&gt;
 {&lt;br /&gt;
    ...&lt;br /&gt;
    coord_t -10 // WARNING: Underlying DAT value -0.03906250, * 256.0 gave -10.000000000, not in range 0-256 once rounded. Does bitmap or other metrics need adjusting?&lt;br /&gt;
    ...&lt;br /&gt;
 }&lt;br /&gt;
&#039;&#039;Suppressing Comment Generation.&#039;&#039; Use the refont option “-no_warn_comments”. &#039;&#039;New to v 2.1.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
TIP: When editing a REF file with comments, you can keep them, change them, or delete them as you prefer. They have no impact on subsequent compiles to DAT.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Coverage of Generated Within-REF Comments.&#039;&#039; A calculated value of coord_s, coord_t, coord_s2, or coord_t2 would have been flagged as a “Major Warning” during read if:&lt;br /&gt;
* the discrepancy from being an integer was non-trivial (+/- 0.001 or more), or&lt;br /&gt;
* the calculated and rounded integer is outside the range given by bitmap size, e.g., 0-256.&lt;br /&gt;
&lt;br /&gt;
For these, a comment is generated. Other causes are:&lt;br /&gt;
* Integer Out of Range 0-256 &#039;&#039;(or 0-512 as applicable)&#039;&#039;. For height, top, bottom, pitch, xSkip, imageWidth, imageHeight.&lt;br /&gt;
* Integer Non Zero. For glyph.&lt;br /&gt;
* Float Less Than Zero. For glyphScale (which is independent of a particular character).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Major Warnings that Don’t Cause Within-REF Comments.&#039;&#039; Currently, this is limited to “Inconsistent Metrics”, which would probably require tagging on multiple lines.&lt;br /&gt;
&lt;br /&gt;
== Special Handling of Fonts with 512x512 Bitmaps ==&lt;br /&gt;
Some DAT files reference bitmap shaders where some or all are of size 512x512, instead of the default 256x256. Refont v2.5+ can support this (replacing an insufficient first attempt in v2.4).&lt;br /&gt;
&lt;br /&gt;
Font developers went to double-sized bitmaps to:&lt;br /&gt;
* in the case of Carleton, allow freehand drawing of missing European characters, which could be drawn more easily if twice standard size.&lt;br /&gt;
* in the case of Mason, have larger ASCII alphanumeric glyphs that would render with crisper edges.&lt;br /&gt;
&lt;br /&gt;
In either case, the font characters when rendered in, say, the game main menu will be the same size as if from 256x256. This is because the imageWidth and imageHeight metrics are not doubled.&lt;br /&gt;
In effect, a scaling by half is requested for all characters in the DAT file and applied by the engine.&lt;br /&gt;
&lt;br /&gt;
=== When generating a REF file from a DAT file ===&lt;br /&gt;
&lt;br /&gt;
 refont -decompile &amp;lt;path to given .dat file&amp;gt; -512_&amp;lt;n&amp;gt;   &#039;&#039;where &amp;lt;n&amp;gt; is a single digit, e.g. &#039;1&#039; in referenced shader name &amp;quot;font/Carleton_1_24.tga&amp;quot; &#039;&#039;&lt;br /&gt;
&lt;br /&gt;
You should use multiple instances of the -512_&amp;lt;n&amp;gt; option, to cover all the 512x512 bitmaps found in the DAT file.&lt;br /&gt;
&lt;br /&gt;
If &#039;&#039;all&#039;&#039; of a given DATs shaders are 512x512, you can use this shorter form:&lt;br /&gt;
&lt;br /&gt;
 refont -decompile &amp;lt;path to given .dat file&amp;gt; -512&lt;br /&gt;
&lt;br /&gt;
Exercising -512... options will mean that in the generated REF file:&lt;br /&gt;
&lt;br /&gt;
* There will be a one or more starting lines like:&lt;br /&gt;
  # bitmap_&amp;lt;n&amp;gt;_size=512 &#039;&#039;(Refont will look for this if doing a subsequent compile to DAT)&#039;&#039;&lt;br /&gt;
* If you specified the short form, it will expand to just the right number of starting lines.&lt;br /&gt;
* Values for coord_s, coord_s2, coord_t, and coord_t2 will have a normal range of 0-512 when appropriate. [COMING SOON: Those values may then be read properly by datBounds.].&lt;br /&gt;
* Any warnings expressed (within the file or within the command-line window) will be in terms of the correct range of values. &lt;br /&gt;
* Warning checks will expect a scaling by half for all characters. That is, while 512... requires scaling down by half, that scaling will not generate a warning (unless it&#039;s not EXACTLY by half), so the -scaling_ok option is not needed just for the exactly-by-half scaling.&lt;br /&gt;
&lt;br /&gt;
=== When generating a DAT file from a REF file ===&lt;br /&gt;
&lt;br /&gt;
During refont -compile, no special command line options are needed. Instead, REF&#039;s starting lines of form &amp;quot;# bitmap_&amp;lt;n&amp;gt;_size=512&amp;quot; are inspected and coord ranges will be interpreted as 0-512 whenever appropriate. &lt;br /&gt;
&lt;br /&gt;
=== Special Handling Recommendations for Carleton and Mason ===&lt;br /&gt;
&#039;&#039;For fonts shipped with TDM 2.12 in tdm_fonts01.pk4. Illustrative command paths are shown; adjust to your working copy.&#039;&#039;&lt;br /&gt;
==== Mason Family ====&lt;br /&gt;
The [[Mason Font]] uses within-DAT per-character scaling, as well as some but not all 512x512 bitmaps. Only 48pt Mason is shipped.&lt;br /&gt;
&lt;br /&gt;
Because, under /dds/fonts/english/mason/, bitmaps masonalternate_0_48.dds to _2_ are 512x512, but _3_ to _5_ are not, use:&lt;br /&gt;
&lt;br /&gt;
 -decompile /fonts/english/mason/fontimage_48.dat -512_0 -512_1 -512_2 -scaling_ok&lt;br /&gt;
&lt;br /&gt;
Because, under /dds/fonts/english/mason_glow/, bitmaps masonalternate_1_48.dds and _2_ are 512x512, but _0_ and _3_ to _5_ are not, use:&lt;br /&gt;
&lt;br /&gt;
 -decompile /fonts/english/mason_glow/fontimage_48.dat -512_1 -512_2 -scaling_ok&lt;br /&gt;
&lt;br /&gt;
Russian versions use the default 256x256. [These possibly benefit from -scaling_ok; didn&#039;t investigate.]&lt;br /&gt;
==== Carleton Family ====&lt;br /&gt;
The 24pt size of carleton has two bitmaps under /dds/fonts/english/carleton/, namely carleton_0_24.dds and _1_, both of size 512x512. So use:&lt;br /&gt;
&lt;br /&gt;
 -decompile /fonts/english/carleton/fontimage_24.dat -512_0 -512_1&lt;br /&gt;
  &#039;&#039;or&#039;&#039;&lt;br /&gt;
 -decompile /fonts/english/carleton/fontimage_24.dat -512&lt;br /&gt;
 &lt;br /&gt;
The 24pt size of carleton_bold has bitmaps with identical content to carleton&#039;s, so use the same options:&lt;br /&gt;
&lt;br /&gt;
 -decompile /fonts/english/carleton_bold/fontimage_24.dat -512_0 -512_1&lt;br /&gt;
  &#039;&#039;or&#039;&#039;&lt;br /&gt;
 -decompile /fonts/english/carleton_bold/fontimage_24.dat -512&lt;br /&gt;
&lt;br /&gt;
Other members of this family use the default 256x256 bitmaps:&lt;br /&gt;
* Sizes 12pt &amp;amp; 48pt&lt;br /&gt;
* carleton_condensed and carleton_glow. (Note: while helpful, it is not required that the base &amp;amp; glow have identical bitmap sizes.)&lt;br /&gt;
* Russian versions&lt;br /&gt;
&lt;br /&gt;
==== These Fonts with Stats ====&lt;br /&gt;
With -stats discussed next, if reading a DAT file, you may use the -512... and scaling_ok options to be most correct, although neglecting to specify them will likely have no significant impact on the analytical results. If reading a REF file, the included &amp;quot;# bitmap_...&amp;quot; lines will take care of that for you.&lt;br /&gt;
&lt;br /&gt;
== For Statistics on Unimplemented or Problematic Font Characters ==&lt;br /&gt;
DAT or (as of v2.3) REF file analysis here is primarily designed to benefit english/european fonts. It will use the optional annotation file if provided. Syntax:&lt;br /&gt;
&lt;br /&gt;
     refont -stats &amp;lt;path to given .dat or .ref file&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Use &amp;quot;-stats&amp;quot; by itself, not combined with &amp;quot;-compile&amp;quot; or &amp;quot;-decompile&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
The resulting analysis report will have the same name and location as the input file, but with a &amp;quot;.txt&amp;quot; suffix.&lt;br /&gt;
The report provides categorized totals and (for problematic characters) itemizations across all 256 character codepoints.&lt;br /&gt;
The counts of problems should be considered minimums, since no inspection of bitmap files (TGA or DDS) is done.&lt;br /&gt;
But a perhaps surprising amount of insight can be gleaned just from DAT/REF file metrics.&lt;br /&gt;
Itemizations include annotations from the &#039;ref_char_annotation&#039; file, if provided.&lt;br /&gt;
&lt;br /&gt;
In the hunt for missing characters, 3 signatures are important:&lt;br /&gt;
&lt;br /&gt;
* Presumed &#039;Hollow Box&#039; = glyph&#039;s &#039;shadername&#039; is &amp;lt;fontname&amp;gt;_0_&amp;lt;size&amp;gt;.dds only, and s &amp;amp; t are zero, but not s2 &amp;amp; t2&lt;br /&gt;
* &#039;&amp;lt;Space&amp;gt;&#039; = same test as &#039;Hollow Box&#039;, but pointed to by char 32 (0x20)&lt;br /&gt;
* &#039;Zero Box&#039; = No glyph box (s, t, s2, t2 all zero)&lt;br /&gt;
&lt;br /&gt;
A given analysis will assume either &#039;Hollow Box&#039; or &#039;&amp;lt;Space&amp;gt;&#039; but not both.&lt;br /&gt;
&lt;br /&gt;
The analysis provides totals and itemizations - grouped into lower (0-127) and upper ranges (128-255) - in several passes: &lt;br /&gt;
&lt;br /&gt;
* Pass 1 - Handling of unprintable/unsupported/missing codepoints, indicated by Hollow Box, Zero Box, or &amp;lt;Space&amp;gt;. Some of these are not a problem, but some are tagged as &amp;quot;Undesirable&amp;quot;.&lt;br /&gt;
* Pass 2 - Bad glyph box (negative s, t, s2, or t2; or s2 &amp;lt;= s, t2 &amp;lt;= t) or good glyph box with dubious metrics (imageHeight &amp;lt;= 0, imageWidth &amp;lt;=0, imageHeight != height). Excludes those already counted as &amp;quot;Undesirable&amp;quot; in Pass 1. &lt;br /&gt;
* Pass 3 - Detection of duplicate glyph boxes (other than Hollow Box, Zero Box, or &amp;lt;Space&amp;gt;). Detected by: glyph&#039;s values for shadername, s, t, s2, &amp;amp; t2 exactly match those of another codepoint. These are grouped into &amp;quot;Dup Sets&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Then, across passes 1-3, a count if given of the minimum &amp;quot;Total Glyphs Needing Work&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Refont version 2.3 adds additional passes:&lt;br /&gt;
&lt;br /&gt;
* Pass 4 - Reports &amp;quot;Overlap Sets&amp;quot; rather than just &amp;quot;Dup Sets&amp;quot;. A set here may include an unaccented &amp;quot;base character&amp;quot; that has been serving as a substitute work-around target for one or more missing accented characters. (What constitutes an &amp;quot;overlap&amp;quot; is idiosyncratic; see the source code for details.)&lt;br /&gt;
* Pass 5 - Same information as Pass 4, but sorted first by shader name (i.e., bitmap). Helpful for organizing bitmap-editing work.&lt;br /&gt;
* Pass 6 - An analysis focusing just on the planned migration of duplicate O/o-circumflex codepoints to G/g-cup glyphs.&lt;br /&gt;
&lt;br /&gt;
== Downloads ==&lt;br /&gt;
Release 2.6 of July 28, 2025:&lt;br /&gt;
* [https://drive.google.com/file/d/1ABf4771Jr1C1hKbLx4xWq8lx8Kn7HdKP/view?usp=sharing refont.exe]&lt;br /&gt;
* [https://drive.google.com/file/d/1-k68eo0CHKZ-sM7JGP05axm49cc5De0T/view?usp=sharing source code: refont.cpp]&lt;br /&gt;
&lt;br /&gt;
===Annotations===&lt;br /&gt;
&#039;&#039;After download, to use any one of these, edit filename to remove &amp;quot;[...]&amp;quot; substring.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Update of June 20, 2024. This reflects a change to the TDM charmap for 2.13, to replace duplicate O/o circumflex characters with G/g breve:&lt;br /&gt;
&lt;br /&gt;
* refont_char_annotations[english with symbol only. With G-breve update].txt [https://drive.google.com/file/d/1rrt-O9DgD7Zn2Hxt7nBtViIlO4kv_gQB/view?usp=sharing here]. Recommended for most purposes with &#039;english&#039; fonts.&lt;br /&gt;
* refont_char_annotations[english with Unicode-16 codes &amp;amp; names. With G-breve update].txt [https://drive.google.com/file/d/1AMxDKQc_DE33gsExiEkGp3x67eb4aGFh/view?usp=sharing here].&lt;br /&gt;
* refont_char_annotations[english with 8859-x source. With G-breve update].txt [https://drive.google.com/file/d/1xoeZ1poTbmkls-gE5PnbbMxdoz5KnMD7/view?usp=sharing].&lt;br /&gt;
* For Russian, see the previous update next.&lt;br /&gt;
&lt;br /&gt;
Update of April 13, 2024:&lt;br /&gt;
&lt;br /&gt;
* refont_char_annotations[english with symbol only].txt [https://drive.google.com/file/d/1ItM-aXps0xQE655HdaJM7Aje5lHewUfC/view?usp=sharing here]. Recommended for most purposes with &#039;english&#039; fonts.&lt;br /&gt;
* refont_char_annotations[english with Unicode-16 codes and names].txt [https://drive.google.com/file/d/1gW7oO_wLqCEPSdm6b05OaTNYHnyuUSA-/view?usp=sharing here].&lt;br /&gt;
* refont_char_annotations[english with 8859-x source].txt [https://drive.google.com/file/d/1ZTcgA4QJYwXzNdqbolYkn0CCEDILD1bX/view?usp=sharing here]. Corrects and supersedes original english file.&lt;br /&gt;
* refont_char_annotations[russian].txt [https://drive.google.com/file/d/10txNXsSCtaTiT2iGT9o3iDxBU7HVYNxi/view?usp=sharing here]. Recommended for &#039;russian&#039; fonts.&lt;br /&gt;
&lt;br /&gt;
== For More ==&lt;br /&gt;
* See the [https://forums.thedarkmod.com/index.php?/topic/22427-analysis-of-212-tdm-fonts/ summary analysis of 2.12 TDM fonts], based on applying &#039;refont -stats ...&#039; to all &#039;english&#039; DAT files.&lt;br /&gt;
&lt;br /&gt;
{{tutorial}} [[Category:Fonts]]&lt;/div&gt;</summary>
		<author><name>Geep</name></author>
	</entry>
	<entry>
		<id>https://wiki.thedarkmod.com/index.php?title=ExportUnicodeFontToDoom3&amp;diff=34445</id>
		<title>ExportUnicodeFontToDoom3</title>
		<link rel="alternate" type="text/html" href="https://wiki.thedarkmod.com/index.php?title=ExportUnicodeFontToDoom3&amp;diff=34445"/>
		<updated>2026-03-16T20:40:25Z</updated>

		<summary type="html">&lt;p&gt;Geep: /* unicodeMap  */ Must keep file ordered&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;By Geep, 2025&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
== Introduction ==&lt;br /&gt;
&lt;br /&gt;
In 2025, kalinovka in [https://forums.thedarkmod.com/index.php?/topic/22736-font-localization Font localization] sought to extend TDM’s Mason 48pt font, used in the main menu, to include missing Cyrillic glyphs. This would allow this font to be used in an FM and still support a Russian translation.&lt;br /&gt;
&lt;br /&gt;
This offshoot of [https://wiki.thedarkmod.com/index.php?title=ExportFontToDoom3 ExportFontToDoom3All256] is a generalized response to that. The main idea to select an input TTF font that includes not just ASCII or ANSI, but offers additional Unicode characters, like Cyrillic. The program still limits output to a maximum of 256 characters, consistent with the DAT format.&lt;br /&gt;
&lt;br /&gt;
To achieve this, it reads in an external human-readable &amp;quot;unicodeMap&amp;quot; file, in Unicode.org’s &amp;quot;Format A&amp;quot;. This format provides a mapping from the traditional 8-bit encoding that TDM uses to the corresponding UCS (Unicode 16-bit) value. Unicode.org provides stock files for standard ISO and Windows 8-bit encodings. Of specific interest here is [https://www.unicode.org/Public/MAPPINGS/VENDORS/MICSFT/WINDOWS/CP1251.TXT cp1251.txt for Cyrillic]. This requires just trivial editing for [https://wiki.thedarkmod.com/index.php?title=I18N_-_Charset TDM-specific codepoints]. As discussed below, you can further edit a unicodeMap file in advance, if you want to generate just a subset of glyphs.&lt;br /&gt;
&lt;br /&gt;
More broadly, this program supersedes ExportFontToDoom3 and ExportFontToDoom3All256.&lt;br /&gt;
&lt;br /&gt;
== New Command Line Arguments ==&lt;br /&gt;
&lt;br /&gt;
These are in-addition to those of [https://wiki.thedarkmod.com/index.php?title=ExportFontToDoom3 ExportFontToDoom3All256].&lt;br /&gt;
&lt;br /&gt;
=== unicodeMap &amp;lt;file&amp;gt; ===&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
 -unicodeMap &amp;quot;./Test/cp1251.txt&amp;quot;&lt;br /&gt;
&lt;br /&gt;
You can edit the unicodeMap file in advance, to specify which particular glyphs you want to generate by suppressing unwanted glyphs, either by:&lt;br /&gt;
&lt;br /&gt;
* Deleting an unwanted line (or block of lines) entirely, or&lt;br /&gt;
* Prepending a &amp;quot;#&amp;quot; to comment-out the line.&lt;br /&gt;
&lt;br /&gt;
Also, this file format allows the Unicode value (e.g., &amp;quot;0x1234&amp;quot;) to be replaced by 6 space characters, when the ISO or Windows standard leaves that character undefined.&lt;br /&gt;
&lt;br /&gt;
In all 3 of those cases, every suppressed character in the output DAT file will be represented by the glyph that the font uses for U+0000. A hollow box is common.&lt;br /&gt;
&lt;br /&gt;
IMPORTANT: If you edit lines, the remaining active glyph lines MUST be in ascending order by the 2-hex-digit codepoint value that starts each line. Otherwise, results will go astray.&lt;br /&gt;
&lt;br /&gt;
=== startFileNumber &amp;lt;n&amp;gt; ===&lt;br /&gt;
When a set of TGA/DDS files are generated for a particular font size, by default the first file&#039;s name contains _0_, which increments for additional files. You can optionally specify a different 1- or 2-digit start number, e.g., &amp;quot;-startFileNumber 7&amp;quot;. Why? Because...&lt;br /&gt;
&lt;br /&gt;
* the file(s) you are generating are supplemental to, not replacements for, existing TGA/DDS files; and&lt;br /&gt;
* in this run, you are generating just one of the 3 possible font sizes (assuming each size has a different count of existing TGA/DDS files).&lt;br /&gt;
&lt;br /&gt;
When you generate a supplemental set, the new DAT file has no knowledge of what&#039;s in the original set and its DAT file. You will have to interleave-edit the old and new DAT files (e.g., with reFont&#039;s REF files) to create a single DAT file spanning old and new glyphs. There may be a redundant NULL glyph in your new TGA set; just ignore it.&lt;br /&gt;
&lt;br /&gt;
=== awayFromEdge &amp;lt;n&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
Allows specifying in positive integer pixels (e.g., &amp;quot;-awayFromEdge 2&amp;quot;) a small extra boundary at the top and left edges of the overall bitmap. This is for fonts like Mason where extra space (typically 2 pixels) is needed around every character to create a &amp;quot;glow variant&amp;quot;. Routine glyph layout provides usually enough space for this except at the top and (arguably) left edges. See also the &amp;quot;compact&amp;quot; parameter.&lt;br /&gt;
&lt;br /&gt;
Note: The spacing value is relative to 256x256 bitmaps. If you specify &amp;quot;hirez&amp;quot;, then for proportionality, your specified value is doubled internally when laying out the 512x512 bitmaps.&lt;br /&gt;
&lt;br /&gt;
=== compact ===&lt;br /&gt;
If specified (i.e, &amp;quot;-compact&amp;quot;), packs the character glyphs more closely together. Particularly recommended for 48pt fonts; it will generate roughly half the files.&lt;br /&gt;
&lt;br /&gt;
Whether &amp;quot;compact&amp;quot; is specified or not, packing is controlled by simply &amp;quot;padding&amp;quot; each glyph’s bounding box. Specifically, this doesn’t change the bounding box, but adds pixel &amp;quot;padding&amp;quot; to just the right and bottom of the bounding box, a simple though asymmetric process. One reason for padding was given ExportFontToDoom3 author Grant Davies in code comments:&lt;br /&gt;
&lt;br /&gt;
&amp;quot;Because of the way Doom 3 Indexes the texture page (using floating point numbers), it is unable to reference exact pixels – there is error. How much error, I don’t know. For this reason, the rectangles needs to be padded out.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Geep suspects that such error with the TDM engine is not really a problem. Likely some error in the past was due to editing with Q3Font and its low floating-point precision. Nevertheless, some padding is good because:&lt;br /&gt;
&lt;br /&gt;
* For the Mason font, 2 pixels around each glyph are needed for &amp;quot;glow&amp;quot; effects (either done as a separate smudge font for /english/ or as a bidirection offset effect for /russian/.)&lt;br /&gt;
* Keeping glyphs separated improves visualization of boundaries with datBounds, and makes editing tweaks easier.&lt;br /&gt;
&lt;br /&gt;
The &amp;quot;compact&amp;quot; setting restores Grant Davies&#039; first algorithm, which just pads the bounding box by 5 pixels to the right and 5 pixels below.&lt;br /&gt;
&lt;br /&gt;
Without &amp;quot;compact&amp;quot;, the default is Grant Davies&#039; second algorithm found in ExportFontToDoom3 v1.02. This likewise first pads each bounding box by 5 pixels to the right and 5 pixels below. It then further pads to make both the width and height a factor of 2; this makes 48pt quite sparse.  (It is possible this improved rendering performance in 2005; not important now. Also, in practice for major fonts, much of this &amp;quot;factor of 2&amp;quot; spacing was overridden by subsequent Font Patcher work.)&lt;br /&gt;
&lt;br /&gt;
=== hirez or hires ===&lt;br /&gt;
&#039;&#039;Added with v1.1, March 2026&#039;&#039; &lt;br /&gt;
&lt;br /&gt;
Instead of 256x256 bitmaps (and associated DAT), this exports double-sized 512x512 bitmaps with larger, thus potentially-crisper glyphs. (TDM has had a few such 512x512 bitmaps for redrawn fonts since 2014.) Specifically, it: &lt;br /&gt;
* outputs requested 512x512 TGAs and their DAT(s).&lt;br /&gt;
* internally, doubles the pointsize requested of the TTF, resulting in 2x character glyph sizes. Because both the container bitmap and each glyph is (nominally) doubled in size, the [0...1] s, s2, t, t2 values stored in the DAT would be very similar to those for a 256x256 bitmap.&lt;br /&gt;
* Other DAT layout metrics remain as if scaled to a 256x256 layout:&lt;br /&gt;
** imageHeight&lt;br /&gt;
** imageWidth&lt;br /&gt;
** skip&lt;br /&gt;
** top (with bottom ignored as usual)&lt;br /&gt;
** pitch&lt;br /&gt;
&lt;br /&gt;
For example, if you request –hirez with a carleton font in just 24pt type, it will create 512x512 files with usual names like carleton_0_24.tga, etc., and fontimage_24.dat, with the console showing “Exporting carleton 24pt”.&lt;br /&gt;
But internally, 48pt characters are drawn on the bitmaps. The imageHeight and imageWidth metrics will be as if the requested 24pt size was generated, so in effect causing the game engine to scale down by a factor of 2 from the 48pt glyph.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;TIPS on Using a HiRez DAT file&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
If subsequently using Refont to make a REF file from this DAT, add the “scaling_ok” option, to suppress otherwise voluminous console warnings about per-character scaling.&lt;br /&gt;
&lt;br /&gt;
If you further plan to generate bounds visualizations with datBounds:&lt;br /&gt;
* For 512x512 bitmaps, you must generate from the REF file, not directly from DAT.&lt;br /&gt;
* Be sure to first edit the REF to add headers of the form:&lt;br /&gt;
&lt;br /&gt;
 # bitmap_&amp;lt;n&amp;gt;_size=512&lt;br /&gt;
 &lt;br /&gt;
  , where &amp;lt;n&amp;gt; is 0 to 9, and refers to shaders present in the REF file with names like, e.g., carleton_3_48.tga; n would be 3 for this.&lt;br /&gt;
&lt;br /&gt;
* datBounds also has a worthwhile “scaling_ok” option.&lt;br /&gt;
* Uncommonly, the raw_metrics option may be of interest.&lt;br /&gt;
&lt;br /&gt;
=== bolding &amp;lt;n&amp;gt; ===&lt;br /&gt;
&#039;&#039;Added with v1.1, March 2026&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Sometimes, a TTF font does not offer a “bold” variant, or, more generally, a font’s overall stroke thickness is not ideal. It is possible to alter character outlines, then render those as bitmap glyphs.&lt;br /&gt;
The result is usually better than post-bitmap thickening or thinning. The FreeType library offers an embolding function for outline alteration, used here.&lt;br /&gt;
&lt;br /&gt;
The integer parameter &amp;lt;n&amp;gt; is in units of 1/64th pixel. A positive value adjusts the outline to embolden the character. Negative thins. The change affects both the overall height and width of the outline.&lt;br /&gt;
You may think of the left and bottom character borders as unchanged. The allowed range of &amp;lt;n&amp;gt; is from -128 (i.e., -2 pixels) to 256 (4 pixels). The -2 limit is arbitrary, but for sanity. The 4 limit is the maximum FreeType permits.&lt;br /&gt;
&lt;br /&gt;
Caution: The adjustment algorithm moves the outline controls points, but doesn&#039;t change the number of such points;&lt;br /&gt;
this means that certain situations like acute angles or intersections are sometimes handled incorrectly.&lt;br /&gt;
&lt;br /&gt;
== Changed Behavior for Font Title from ExportFontToDoom3All256 ==&lt;br /&gt;
In ExportFontToDoom3All256, if the font title was more that 20 characters long, it would truncate it to fit in the DAT file as part of the shader names (i.e., paths to TGA files). But this threshold was wrong. Now, truncation and a warning happens if the font title is more that 17 characters long (or 16 if generated TGAs include any with a 2-digit count instead of 1-digit). If truncation occurs, the user is asked to consider using or revising the -name argument.&lt;br /&gt;
&lt;br /&gt;
== Downloads ==&lt;br /&gt;
Release v1.1 of 2025-03-03:&lt;br /&gt;
* [https://drive.google.com/file/d/1f3Jj53qtJGIp0_mz7Riing9Fi8ESFDr5/view?usp=sharing ExportUnicodeFontToDoom3_release_1_1_exe.zip] . Windows binary and required archived versions of FreeType and DevIL DLLs.&lt;br /&gt;
* [https://drive.google.com/file/d/1nutMBfcIWw63wNTUdnlnzP397tGVpnpd/view?usp=sharing ExportUnicodeFontToDoom3_release_1_1_source_project.zip] . The C++ project file with source code, including source &amp;amp; build project of archived library.&lt;br /&gt;
&lt;br /&gt;
Release 1 of 2024-09-10:&lt;br /&gt;
* [https://drive.google.com/file/d/1MqoOfhc5-ovoxoHfRquYAcIEdHEOJAQV/view?usp=sharing ExportUnicodeFontToDoom3_release_1_exe.zip]&lt;br /&gt;
* [https://drive.google.com/file/d/1Frk_byfdtCcMqdr27ulw1XyuFj8vYp9x/view?usp=sharing ExportUnicodeFontToDoom3_release_1_source_project.zip]&lt;br /&gt;
&lt;br /&gt;
== See Also ==&lt;br /&gt;
The Cyrillic coverage of Lora Regular TTF font, projected to used as Russian Mason supplement in TDM 2.14, may be viewed and font downloaded [https://www.fontsquirrel.com/fonts/lora?filter%5Bclassifications%5D%5B0%5D=serif&amp;amp;filter%5Blanguages%5D%5B0%5D=cyrillic#eula here].&lt;/div&gt;</summary>
		<author><name>Geep</name></author>
	</entry>
	<entry>
		<id>https://wiki.thedarkmod.com/index.php?title=I18N_-_Charset&amp;diff=34444</id>
		<title>I18N - Charset</title>
		<link rel="alternate" type="text/html" href="https://wiki.thedarkmod.com/index.php?title=I18N_-_Charset&amp;diff=34444"/>
		<updated>2026-03-15T20:59:00Z</updated>

		<summary type="html">&lt;p&gt;Geep: /* Notes */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction ==&lt;br /&gt;
&lt;br /&gt;
The D3 code that handles the GUI bitmap font can only load a specific range of bytes as characters. To get the most out of the available entries, special charsets are used. The fonts (Carleton for the menu f.i.) are build/patched so that the right characters appear in the right place.&lt;br /&gt;
&lt;br /&gt;
== Encodings ==&lt;br /&gt;
&lt;br /&gt;
=== all.lang ===&lt;br /&gt;
&lt;br /&gt;
This file is in &#039;&#039;&#039;UTF-8&#039;&#039;&#039;, and converted with the help of the script &#039;&#039;&#039;devel/gen_lang.pl&#039;&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
 perl devel/gen_lang.pl&lt;br /&gt;
&lt;br /&gt;
This ensures that the generated language files are in their proper encodings (see below).&lt;br /&gt;
&lt;br /&gt;
=== All other language files ===&lt;br /&gt;
&lt;br /&gt;
Note that the language files (f.i. &#039;&#039;&#039;strings/german.lang&#039;&#039;&#039;) as well as the readables and the FM dictionariaries are expected to be in the following encodings:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Czech&#039;&#039;&#039;, &#039;&#039;&#039;Hungarian&#039;&#039;&#039;, &#039;&#039;&#039;Slovak&#039;&#039;&#039;, &#039;&#039;&#039;Polish:&#039;&#039;&#039; [https://secure.wikimedia.org/wikipedia/en/wiki/ISO/IEC_8859-2 ISO-8859-2] (&#039;&#039;&#039;not WIN-1250!)&lt;br /&gt;
* &#039;&#039;&#039;Russian:&#039;&#039;&#039; [https://secure.wikimedia.org/wikipedia/en/wiki/Win-1251 WIN-1251]&lt;br /&gt;
* &#039;&#039;&#039;French:&#039;&#039;&#039; [https://secure.wikimedia.org/wikipedia/en/wiki/ISO/IEC_8859-15 ISO-8859-15]&lt;br /&gt;
* &#039;&#039;&#039;Romanian:&#039;&#039;&#039; [https://secure.wikimedia.org/wikipedia/en/wiki/ISO/IEC_8859-16 ISO-8859-16] &lt;br /&gt;
* &#039;&#039;&#039;All other languages:&#039;&#039;&#039; [https://secure.wikimedia.org/wikipedia/en/wiki/ISO/IEC_8859-1 ISO-8859-1] (German, Dutch, Danish, Swedish, Portuguese, etc.)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{{infobox|The core dictionaries are automatically generated in the right encoding, but make sure that you use the right encoding for the FM dictionary, too!}}&lt;br /&gt;
&lt;br /&gt;
== Character remapping ==&lt;br /&gt;
&lt;br /&gt;
The characters are remapped upon loading the dictionary/readable, from their native encoding to the special one that TDM uses and that is described here.  Responsible for the remapping are [[I18N - Character mapping|mapping files]], f.i. &amp;quot;strings/czech.map&amp;quot;. If a map file for a specific language is not found, &amp;quot;strings/default.map&amp;quot; is used instead, if this is not found, no remapping takes place.&lt;br /&gt;
&lt;br /&gt;
See &#039;&#039;&#039;[[I18N - Character mapping|Character mapping]]&#039;&#039;&#039; for more information.&lt;br /&gt;
&lt;br /&gt;
=== European Languages ===&lt;br /&gt;
&lt;br /&gt;
This mapping is used for European languages, f.i. &#039;&#039;&#039;Czech&#039;&#039;&#039;, &#039;&#039;&#039;French&#039;&#039;&#039;, &#039;&#039;&#039;German&#039;&#039;&#039;, &#039;&#039;&#039;Spanish&#039;&#039;&#039;, &#039;&#039;&#039;Portuguese&#039;&#039;&#039;, &#039;&#039;&#039;Polish&#039;&#039;&#039;. Note that the double accented characters in Hungarian &#039;&#039;&#039;Ő, ő, Ű and ű&#039;&#039;&#039; look a bit different from &#039;&#039;&#039;Ö, ö, Ü and ü&#039;&#039;&#039;!&lt;br /&gt;
&lt;br /&gt;
In the table below, the original ISO 8859-1 characters are given in &#039;&#039;()&#039;&#039; below the TDM character.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Color code:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
{{box|#f0d0d0|Character not usable by TDM|Unusable}}{{box|#d0e0d0|Character not yet used in TDM|Unused}}{{box|#c0ffc0|Character displayed in v1.08 or newer|Usable in v1.08}}{{box|#80f080|Character displayed in v2.03 or newer|Usable in v2.03}}{{box|#d0d0f0|Changed from the ISO-8859-1 default, usable by TDM 1.0 or newer|Changed from ISO 8859-1}}&lt;br /&gt;
&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot; border=1 style=&amp;quot;border-collapse: collapse; font-size: 95%&amp;quot; cellspacing=0 cellpadding=2 width=100%&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
!&lt;br /&gt;
!…0&lt;br /&gt;
!…1&lt;br /&gt;
!…2&lt;br /&gt;
!…3&lt;br /&gt;
!…4&lt;br /&gt;
!…5&lt;br /&gt;
!…6&lt;br /&gt;
!…7&lt;br /&gt;
!…8&lt;br /&gt;
!…9&lt;br /&gt;
!…A&lt;br /&gt;
!…B&lt;br /&gt;
!…C&lt;br /&gt;
!…D&lt;br /&gt;
!…E&lt;br /&gt;
!…F&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
!0…&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #f0d0d0&#039;|00&amp;lt;br&amp;gt;&#039;&#039;&#039;–&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #f0d0d0&#039;|01&amp;lt;br&amp;gt;&#039;&#039;&#039;–&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #f0d0d0&#039;|02&amp;lt;br&amp;gt;&#039;&#039;&#039;–&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #f0d0d0&#039;|03&amp;lt;br&amp;gt;&#039;&#039;&#039;–&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #f0d0d0&#039;|04&amp;lt;br&amp;gt;&#039;&#039;&#039;–&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #f0d0d0&#039;|05&amp;lt;br&amp;gt;&#039;&#039;&#039;–&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #f0d0d0&#039;|06&amp;lt;br&amp;gt;&#039;&#039;&#039;–&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #f0d0d0&#039;|07&amp;lt;br&amp;gt;&#039;&#039;&#039;–&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #f0d0d0&#039;|08&amp;lt;br&amp;gt;&#039;&#039;&#039;–&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #f0d0d0&#039;|09&amp;lt;br&amp;gt;&#039;&#039;&#039;–&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #f0d0d0&#039;|0A&amp;lt;br&amp;gt;&#039;&#039;&#039;–&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #f0d0d0&#039;|0B&amp;lt;br&amp;gt;&#039;&#039;&#039;–&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #f0d0d0&#039;|0C&amp;lt;br&amp;gt;&#039;&#039;&#039;–&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #f0d0d0&#039;|0D&amp;lt;br&amp;gt;&#039;&#039;&#039;–&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #f0d0d0&#039;|0E&amp;lt;br&amp;gt;&#039;&#039;&#039;–&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #f0d0d0&#039;|0F&amp;lt;br&amp;gt;&#039;&#039;&#039;–&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
!1…&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #f0d0d0&#039;|10&amp;lt;br&amp;gt;&#039;&#039;&#039;–&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #f0d0d0&#039;|11&amp;lt;br&amp;gt;&#039;&#039;&#039;–&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #f0d0d0&#039;|12&amp;lt;br&amp;gt;&#039;&#039;&#039;–&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #f0d0d0&#039;|13&amp;lt;br&amp;gt;&#039;&#039;&#039;–&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #f0d0d0&#039;|14&amp;lt;br&amp;gt;&#039;&#039;&#039;–&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #f0d0d0&#039;|15&amp;lt;br&amp;gt;&#039;&#039;&#039;–&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #f0d0d0&#039;|16&amp;lt;br&amp;gt;&#039;&#039;&#039;–&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #f0d0d0&#039;|17&amp;lt;br&amp;gt;&#039;&#039;&#039;–&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #f0d0d0&#039;|18&amp;lt;br&amp;gt;&#039;&#039;&#039;–&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #f0d0d0&#039;|19&amp;lt;br&amp;gt;&#039;&#039;&#039;–&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #f0d0d0&#039;|1A&amp;lt;br&amp;gt;&#039;&#039;&#039;–&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #f0d0d0&#039;|1B&amp;lt;br&amp;gt;&#039;&#039;&#039;–&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #f0d0d0&#039;|1C&amp;lt;br&amp;gt;&#039;&#039;&#039;–&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #f0d0d0&#039;|1D&amp;lt;br&amp;gt;&#039;&#039;&#039;–&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #f0d0d0&#039;|1E&amp;lt;br&amp;gt;&#039;&#039;&#039;–&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #f0d0d0&#039;|1F&amp;lt;br&amp;gt;&#039;&#039;&#039;–&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
!2…&lt;br /&gt;
|align=&#039;center&#039;|20&amp;lt;br&amp;gt;&#039;&#039;&#039;&amp;amp;nbsp;&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|21&amp;lt;br&amp;gt;&#039;&#039;&#039;!&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|22&amp;lt;br&amp;gt;&#039;&#039;&#039;&amp;quot;&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|23&amp;lt;br&amp;gt;&#039;&#039;&#039;#&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|24&amp;lt;br&amp;gt;&#039;&#039;&#039;$&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|25&amp;lt;br&amp;gt;&#039;&#039;&#039;%&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|26&amp;lt;br&amp;gt;&#039;&#039;&#039;&amp;amp;&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|27&amp;lt;br&amp;gt;&#039;&#039;&#039;&#039;&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|28&amp;lt;br&amp;gt;&#039;&#039;&#039;(&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|29&amp;lt;br&amp;gt;&#039;&#039;&#039;)&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|2A&amp;lt;br&amp;gt;&#039;&#039;&#039;*&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|2B&amp;lt;br&amp;gt;&#039;&#039;&#039;+&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|2C&amp;lt;br&amp;gt;&#039;&#039;&#039;,&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|2D&amp;lt;br&amp;gt;&#039;&#039;&#039;-&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|2E&amp;lt;br&amp;gt;&#039;&#039;&#039;.&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|2F&amp;lt;br&amp;gt;&#039;&#039;&#039;/&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
!3…&lt;br /&gt;
|align=&#039;center&#039;|30&amp;lt;br&amp;gt;&#039;&#039;&#039;0&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|31&amp;lt;br&amp;gt;&#039;&#039;&#039;1&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|32&amp;lt;br&amp;gt;&#039;&#039;&#039;2&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|33&amp;lt;br&amp;gt;&#039;&#039;&#039;3&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|34&amp;lt;br&amp;gt;&#039;&#039;&#039;4&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|35&amp;lt;br&amp;gt;&#039;&#039;&#039;5&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|36&amp;lt;br&amp;gt;&#039;&#039;&#039;6&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|37&amp;lt;br&amp;gt;&#039;&#039;&#039;7&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|38&amp;lt;br&amp;gt;&#039;&#039;&#039;8&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|39&amp;lt;br&amp;gt;&#039;&#039;&#039;9&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|3A&amp;lt;br&amp;gt;&#039;&#039;&#039;:&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|3B&amp;lt;br&amp;gt;&#039;&#039;&#039;;&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|3C&amp;lt;br&amp;gt;&#039;&#039;&#039;&amp;lt;&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|3D&amp;lt;br&amp;gt;&#039;&#039;&#039;=&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|3E&amp;lt;br&amp;gt;&#039;&#039;&#039;&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|3F&amp;lt;br&amp;gt;&#039;&#039;&#039;?&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
!4…&lt;br /&gt;
|align=&#039;center&#039;|40&amp;lt;br&amp;gt;&#039;&#039;&#039;@&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|41&amp;lt;br&amp;gt;&#039;&#039;&#039;A&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|42&amp;lt;br&amp;gt;&#039;&#039;&#039;B&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|43&amp;lt;br&amp;gt;&#039;&#039;&#039;C&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|44&amp;lt;br&amp;gt;&#039;&#039;&#039;D&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|45&amp;lt;br&amp;gt;&#039;&#039;&#039;E&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|46&amp;lt;br&amp;gt;&#039;&#039;&#039;F&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|47&amp;lt;br&amp;gt;&#039;&#039;&#039;G&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|48&amp;lt;br&amp;gt;&#039;&#039;&#039;H&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|49&amp;lt;br&amp;gt;&#039;&#039;&#039;I&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|4A&amp;lt;br&amp;gt;&#039;&#039;&#039;J&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|4B&amp;lt;br&amp;gt;&#039;&#039;&#039;K&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|4C&amp;lt;br&amp;gt;&#039;&#039;&#039;L&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|4D&amp;lt;br&amp;gt;&#039;&#039;&#039;M&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|4E&amp;lt;br&amp;gt;&#039;&#039;&#039;N&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|4F&amp;lt;br&amp;gt;&#039;&#039;&#039;O&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
!5…&lt;br /&gt;
|align=&#039;center&#039;|50&amp;lt;br&amp;gt;&#039;&#039;&#039;P&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|51&amp;lt;br&amp;gt;&#039;&#039;&#039;Q&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|52&amp;lt;br&amp;gt;&#039;&#039;&#039;R&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|53&amp;lt;br&amp;gt;&#039;&#039;&#039;S&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|54&amp;lt;br&amp;gt;&#039;&#039;&#039;T&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|55&amp;lt;br&amp;gt;&#039;&#039;&#039;U&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|56&amp;lt;br&amp;gt;&#039;&#039;&#039;V&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|57&amp;lt;br&amp;gt;&#039;&#039;&#039;W&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|58&amp;lt;br&amp;gt;&#039;&#039;&#039;X&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|59&amp;lt;br&amp;gt;&#039;&#039;&#039;Y&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|5A&amp;lt;br&amp;gt;&#039;&#039;&#039;Z&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|5B&amp;lt;br&amp;gt;&#039;&#039;&#039;[&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|5C&amp;lt;br&amp;gt;&#039;&#039;&#039;\&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|5D&amp;lt;br&amp;gt;&#039;&#039;&#039;]&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|5E&amp;lt;br&amp;gt;&#039;&#039;&#039;^&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|5F&amp;lt;br&amp;gt;&#039;&#039;&#039;_&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
!6…&lt;br /&gt;
|align=&#039;center&#039;|60&amp;lt;br&amp;gt;&#039;&#039;&#039;`&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|61&amp;lt;br&amp;gt;&#039;&#039;&#039;a&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|62&amp;lt;br&amp;gt;&#039;&#039;&#039;b&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|63&amp;lt;br&amp;gt;&#039;&#039;&#039;c&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|64&amp;lt;br&amp;gt;&#039;&#039;&#039;d&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|65&amp;lt;br&amp;gt;&#039;&#039;&#039;e&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|66&amp;lt;br&amp;gt;&#039;&#039;&#039;f&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|67&amp;lt;br&amp;gt;&#039;&#039;&#039;g&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|68&amp;lt;br&amp;gt;&#039;&#039;&#039;h&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|69&amp;lt;br&amp;gt;&#039;&#039;&#039;i&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|6A&amp;lt;br&amp;gt;&#039;&#039;&#039;j&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|6B&amp;lt;br&amp;gt;&#039;&#039;&#039;k&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|6C&amp;lt;br&amp;gt;&#039;&#039;&#039;l&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|6D&amp;lt;br&amp;gt;&#039;&#039;&#039;m&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|6E&amp;lt;br&amp;gt;&#039;&#039;&#039;n&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|6F&amp;lt;br&amp;gt;&#039;&#039;&#039;o&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
!7…&lt;br /&gt;
|align=&#039;center&#039;|70&amp;lt;br&amp;gt;&#039;&#039;&#039;p&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|71&amp;lt;br&amp;gt;&#039;&#039;&#039;q&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|72&amp;lt;br&amp;gt;&#039;&#039;&#039;r&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|73&amp;lt;br&amp;gt;&#039;&#039;&#039;s&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|74&amp;lt;br&amp;gt;&#039;&#039;&#039;t&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|75&amp;lt;br&amp;gt;&#039;&#039;&#039;u&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|76&amp;lt;br&amp;gt;&#039;&#039;&#039;v&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|77&amp;lt;br&amp;gt;&#039;&#039;&#039;w&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|78&amp;lt;br&amp;gt;&#039;&#039;&#039;x&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|79&amp;lt;br&amp;gt;&#039;&#039;&#039;y&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|7A&amp;lt;br&amp;gt;&#039;&#039;&#039;z&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|7B&amp;lt;br&amp;gt;&#039;&#039;&#039;{&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|7C&amp;lt;br&amp;gt;&#039;&#039;&#039;|&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|7D&amp;lt;br&amp;gt;&#039;&#039;&#039;}&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|7E&amp;lt;br&amp;gt;&#039;&#039;&#039;~&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #d0e0d0&#039;|7F&amp;lt;br&amp;gt;&#039;&#039;&#039;�&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
!8…&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #c0ffc0&#039;|80&amp;lt;br&amp;gt;&#039;&#039;&#039;Ň&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #c0ffc0&#039;|81&amp;lt;br&amp;gt;&#039;&#039;&#039;Ś&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #c0ffc0&#039;|82&amp;lt;br&amp;gt;&#039;&#039;&#039;Ć&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #c0ffc0&#039;|83&amp;lt;br&amp;gt;&#039;&#039;&#039;Ż&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #c0ffc0&#039;|84&amp;lt;br&amp;gt;&#039;&#039;&#039;Ź&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #c0ffc0&#039;|85&amp;lt;br&amp;gt;&#039;&#039;&#039;Ŝ&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #c0ffc0&#039;|86&amp;lt;br&amp;gt;&#039;&#039;&#039;Ĉ&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #c0ffc0&#039;|87&amp;lt;br&amp;gt;&#039;&#039;&#039;Ẑ&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #c0ffc0&#039;|88&amp;lt;br&amp;gt;&#039;&#039;&#039;Ô&#039;&#039;&#039; [1]&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #c0ffc0&#039;|89&amp;lt;br&amp;gt;&#039;&#039;&#039;Ŕ&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #c0ffc0&#039;|8A&amp;lt;br&amp;gt;&#039;&#039;&#039;Ǔ&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #c0ffc0&#039;|8B&amp;lt;br&amp;gt;&#039;&#039;&#039;Ă&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #c0ffc0&#039;|8C&amp;lt;br&amp;gt;&#039;&#039;&#039;Ń&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #80f080&#039;|8D&amp;lt;br&amp;gt;&#039;&#039;&#039;Ș&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #80f080&#039;|8E&amp;lt;br&amp;gt;&#039;&#039;&#039;Ț&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #d0e0d0&#039;|8F&amp;lt;br&amp;gt;&#039;&#039;&#039;�&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
!9…&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #80f080&#039;|90&amp;lt;br&amp;gt;&#039;&#039;&#039;đ&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #c0ffc0&#039;|91&amp;lt;br&amp;gt;&#039;&#039;&#039;ś&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #c0ffc0&#039;|92&amp;lt;br&amp;gt;&#039;&#039;&#039;ć&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #c0ffc0&#039;|93&amp;lt;br&amp;gt;&#039;&#039;&#039;ż&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #c0ffc0&#039;|94&amp;lt;br&amp;gt;&#039;&#039;&#039;ź&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #c0ffc0&#039;|95&amp;lt;br&amp;gt;&#039;&#039;&#039;ŝ&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #c0ffc0&#039;|96&amp;lt;br&amp;gt;&#039;&#039;&#039;ĉ&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #c0ffc0&#039;|97&amp;lt;br&amp;gt;&#039;&#039;&#039;ẑ&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #c0ffc0&#039;|98&amp;lt;br&amp;gt;&#039;&#039;&#039;ô&#039;&#039;&#039; [1]&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #c0ffc0&#039;|99&amp;lt;br&amp;gt;&#039;&#039;&#039;ŕ&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #c0ffc0&#039;|9A&amp;lt;br&amp;gt;&#039;&#039;&#039;ǔ&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #c0ffc0&#039;|9B&amp;lt;br&amp;gt;&#039;&#039;&#039;ă&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #c0ffc0&#039;|9C&amp;lt;br&amp;gt;&#039;&#039;&#039;ń&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #80f080&#039;|9D&amp;lt;br&amp;gt;&#039;&#039;&#039;ș&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #80f080&#039;|9E&amp;lt;br&amp;gt;&#039;&#039;&#039;ț&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #d0e0d0&#039;|9F&amp;lt;br&amp;gt;&#039;&#039;&#039;�&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
!A…&lt;br /&gt;
|align=&#039;center&#039;|A0&amp;lt;br&amp;gt;&#039;&#039;&#039;[https://secure.wikimedia.org/wikipedia/en/wiki/Non-breaking_space NBSP]&#039;&#039;&#039;&amp;lt;br&amp;gt;[2]&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #d0d0f0&#039;|A1&amp;lt;br&amp;gt;&#039;&#039;&#039;ň&#039;&#039;&#039;&amp;lt;br&amp;gt;(¡)&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #d0d0f0&#039;|A2&amp;lt;br&amp;gt;&#039;&#039;&#039;Ű&#039;&#039;&#039;&amp;lt;br&amp;gt;(¢)&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #d0d0f0&#039;|A3&amp;lt;br&amp;gt;&#039;&#039;&#039;ě&#039;&#039;&#039;&amp;lt;br&amp;gt;(£)&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #d0d0f0&#039;|A4&amp;lt;br&amp;gt;&#039;&#039;&#039;ű&#039;&#039;&#039;&amp;lt;br&amp;gt;(¤)&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #d0d0f0&#039;|A5&amp;lt;br&amp;gt;&#039;&#039;&#039;Ě&#039;&#039;&#039;&amp;lt;br&amp;gt;(¥)&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #d0d0f0&#039;|A6&amp;lt;br&amp;gt;&#039;&#039;&#039;Š&#039;&#039;&#039;&amp;lt;br&amp;gt;(¦)&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|A7&amp;lt;br&amp;gt;&#039;&#039;&#039;§&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #d0d0f0&#039;|A8&amp;lt;br&amp;gt;&#039;&#039;&#039;š&#039;&#039;&#039;&amp;lt;br&amp;gt;(¨)&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #d0d0f0&#039;|A9&amp;lt;br&amp;gt;&#039;&#039;&#039;Ů&#039;&#039;&#039;&amp;lt;br&amp;gt;(©)&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #d0d0f0&#039;|AA&amp;lt;br&amp;gt;&#039;&#039;&#039;Ą&#039;&#039;&#039;&amp;lt;br&amp;gt;(ª)&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #d0d0f0&#039;|AB&amp;lt;br&amp;gt;&#039;&#039;&#039;Ę&#039;&#039;&#039;&amp;lt;br&amp;gt;(«)&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #d0d0f0&#039;|AC&amp;lt;br&amp;gt;&#039;&#039;&#039;Č&#039;&#039;&#039;&amp;lt;br&amp;gt;(¬)&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|AD&amp;lt;br&amp;gt;&#039;&#039;&#039;[https://secure.wikimedia.org/wikipedia/en/wiki/Soft_hyphen SHY]&#039;&#039;&#039;&amp;lt;br&amp;gt;[2]&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #d0d0f0&#039;|AE&amp;lt;br&amp;gt;&#039;&#039;&#039;č&#039;&#039;&#039;&amp;lt;br&amp;gt;(®)&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #d0d0f0&#039;|AF&amp;lt;br&amp;gt;&#039;&#039;&#039;ů&#039;&#039;&#039;&amp;lt;br&amp;gt;(¯)&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
!B…&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #d0d0f0&#039;|B0&amp;lt;br&amp;gt;&#039;&#039;&#039;Ő&#039;&#039;&#039;&amp;lt;br&amp;gt;(°)&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #d0d0f0&#039;|B1&amp;lt;br&amp;gt;&#039;&#039;&#039;Ł&#039;&#039;&#039;&amp;lt;br&amp;gt;(±)&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #d0d0f0&#039;|B2&amp;lt;br&amp;gt;&#039;&#039;&#039;Ť&#039;&#039;&#039;&amp;lt;br&amp;gt;(²)&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #d0d0f0&#039;|B3&amp;lt;br&amp;gt;&#039;&#039;&#039;Ď&#039;&#039;&#039;&amp;lt;br&amp;gt;(³)&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #d0d0f0&#039;|B4&amp;lt;br&amp;gt;&#039;&#039;&#039;Ž&#039;&#039;&#039;&amp;lt;br&amp;gt;(´)&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #d0d0f0&#039;|B5&amp;lt;br&amp;gt;&#039;&#039;&#039;ł&#039;&#039;&#039;&amp;lt;br&amp;gt;(µ)&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #d0d0f0&#039;|B6&amp;lt;br&amp;gt;&#039;&#039;&#039;ť&#039;&#039;&#039;&amp;lt;br&amp;gt;(¶)&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #d0d0f0&#039;|B7&amp;lt;br&amp;gt;&#039;&#039;&#039;ď&#039;&#039;&#039;&amp;lt;br&amp;gt;(·)&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #d0d0f0&#039;|B8&amp;lt;br&amp;gt;&#039;&#039;&#039;ž&#039;&#039;&#039;&amp;lt;br&amp;gt;(¸)&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #d0d0f0&#039;|B9&amp;lt;br&amp;gt;&#039;&#039;&#039;ő&#039;&#039;&#039;&amp;lt;br&amp;gt;(¹)&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #d0d0f0&#039;|BA&amp;lt;br&amp;gt;&#039;&#039;&#039;ą&#039;&#039;&#039;&amp;lt;br&amp;gt;(º)&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #d0d0f0&#039;|BB&amp;lt;br&amp;gt;&#039;&#039;&#039;ę&#039;&#039;&#039;&amp;lt;br&amp;gt;(»)&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #d0d0f0&#039;|BC&amp;lt;br&amp;gt;&#039;&#039;&#039;Œ&#039;&#039;&#039;&amp;lt;br&amp;gt;(¼)&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #d0d0f0&#039;|BD&amp;lt;br&amp;gt;&#039;&#039;&#039;œ&#039;&#039;&#039;&amp;lt;br&amp;gt;(½)&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #d0d0f0&#039;|BE&amp;lt;br&amp;gt;&#039;&#039;&#039;Ÿ&#039;&#039;&#039;&amp;lt;br&amp;gt;(¾)&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|BF&amp;lt;br&amp;gt;&#039;&#039;&#039;¿&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
!C…&lt;br /&gt;
|align=&#039;center&#039;|C0&amp;lt;br&amp;gt;&#039;&#039;&#039;À&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|C1&amp;lt;br&amp;gt;&#039;&#039;&#039;Á&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|C2&amp;lt;br&amp;gt;&#039;&#039;&#039;Â&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|C3&amp;lt;br&amp;gt;&#039;&#039;&#039;Ã&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|C4&amp;lt;br&amp;gt;&#039;&#039;&#039;Ä&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|C5&amp;lt;br&amp;gt;&#039;&#039;&#039;Å&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|C6&amp;lt;br&amp;gt;&#039;&#039;&#039;Æ&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|C7&amp;lt;br&amp;gt;&#039;&#039;&#039;Ç&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|C8&amp;lt;br&amp;gt;&#039;&#039;&#039;È&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|C9&amp;lt;br&amp;gt;&#039;&#039;&#039;É&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|CA&amp;lt;br&amp;gt;&#039;&#039;&#039;Ê&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|CB&amp;lt;br&amp;gt;&#039;&#039;&#039;Ë&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|CC&amp;lt;br&amp;gt;&#039;&#039;&#039;Ì&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|CD&amp;lt;br&amp;gt;&#039;&#039;&#039;Í&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|CE&amp;lt;br&amp;gt;&#039;&#039;&#039;Î&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|CF&amp;lt;br&amp;gt;&#039;&#039;&#039;Ï&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
!D…&lt;br /&gt;
|align=&#039;center&#039;|D0&amp;lt;br&amp;gt;&#039;&#039;&#039;Ð&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|D1&amp;lt;br&amp;gt;&#039;&#039;&#039;Ñ&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|D2&amp;lt;br&amp;gt;&#039;&#039;&#039;Ò&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|D3&amp;lt;br&amp;gt;&#039;&#039;&#039;Ó&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|D4&amp;lt;br&amp;gt;&#039;&#039;&#039;Ô&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|D5&amp;lt;br&amp;gt;&#039;&#039;&#039;Õ&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|D6&amp;lt;br&amp;gt;&#039;&#039;&#039;Ö&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #d0d0f0&#039;|D7&amp;lt;br&amp;gt;&#039;&#039;&#039;Ř&#039;&#039;&#039;&amp;lt;br&amp;gt;(×)&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|D8&amp;lt;br&amp;gt;&#039;&#039;&#039;Ø&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|D9&amp;lt;br&amp;gt;&#039;&#039;&#039;Ù&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|DA&amp;lt;br&amp;gt;&#039;&#039;&#039;Ú&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|DB&amp;lt;br&amp;gt;&#039;&#039;&#039;Û&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|DC&amp;lt;br&amp;gt;&#039;&#039;&#039;Ü&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|DD&amp;lt;br&amp;gt;&#039;&#039;&#039;Ý&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|DE&amp;lt;br&amp;gt;&#039;&#039;&#039;Þ&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|DF&amp;lt;br&amp;gt;&#039;&#039;&#039;ß&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
!E…&lt;br /&gt;
|align=&#039;center&#039;|E0&amp;lt;br&amp;gt;&#039;&#039;&#039;à&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|E1&amp;lt;br&amp;gt;&#039;&#039;&#039;á&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|E2&amp;lt;br&amp;gt;&#039;&#039;&#039;â&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|E3&amp;lt;br&amp;gt;&#039;&#039;&#039;ã&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|E4&amp;lt;br&amp;gt;&#039;&#039;&#039;ä&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|E5&amp;lt;br&amp;gt;&#039;&#039;&#039;å&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|E6&amp;lt;br&amp;gt;&#039;&#039;&#039;æ&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|E7&amp;lt;br&amp;gt;&#039;&#039;&#039;ç&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|E8&amp;lt;br&amp;gt;&#039;&#039;&#039;è&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|E9&amp;lt;br&amp;gt;&#039;&#039;&#039;é&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|EA&amp;lt;br&amp;gt;&#039;&#039;&#039;ê&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|EB&amp;lt;br&amp;gt;&#039;&#039;&#039;ë&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|EC&amp;lt;br&amp;gt;&#039;&#039;&#039;ì&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|ED&amp;lt;br&amp;gt;&#039;&#039;&#039;í&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|EE&amp;lt;br&amp;gt;&#039;&#039;&#039;î&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|EF&amp;lt;br&amp;gt;&#039;&#039;&#039;ï&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
!F…&lt;br /&gt;
|align=&#039;center&#039;|F0&amp;lt;br&amp;gt;&#039;&#039;&#039;ð&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|F1&amp;lt;br&amp;gt;&#039;&#039;&#039;ñ&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|F2&amp;lt;br&amp;gt;&#039;&#039;&#039;ò&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|F3&amp;lt;br&amp;gt;&#039;&#039;&#039;ó&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|F4&amp;lt;br&amp;gt;&#039;&#039;&#039;ô&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|F5&amp;lt;br&amp;gt;&#039;&#039;&#039;õ&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|F6&amp;lt;br&amp;gt;&#039;&#039;&#039;ö&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #d0d0f0&#039;|F7&amp;lt;br&amp;gt;&#039;&#039;&#039;ř&#039;&#039;&#039;&amp;lt;br&amp;gt;(÷)&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|F8&amp;lt;br&amp;gt;&#039;&#039;&#039;ø&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|F9&amp;lt;br&amp;gt;&#039;&#039;&#039;ù&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|FA&amp;lt;br&amp;gt;&#039;&#039;&#039;ú&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|FB&amp;lt;br&amp;gt;&#039;&#039;&#039;û&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|FC&amp;lt;br&amp;gt;&#039;&#039;&#039;ü&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|FD&amp;lt;br&amp;gt;&#039;&#039;&#039;ý&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|FE&amp;lt;br&amp;gt;&#039;&#039;&#039;þ&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|FF&amp;lt;br&amp;gt;&#039;&#039;&#039;ÿ&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Table Notes ====&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;[1]&#039;&#039;&#039; As discussed [https://forums.thedarkmod.com/index.php?/topic/22427-analysis-of-212-tdm-fonts/&amp;amp;do=findComment&amp;amp;comment=494855 here], the TDM char set has a redundant treatment of 2 characters:&lt;br /&gt;
&lt;br /&gt;
* Ô appears at 0x88 and 0xD4&lt;br /&gt;
* ô appears at 0x98 and 0xF4&lt;br /&gt;
&lt;br /&gt;
Starting with TDM 2.13, the redundancy can be removed and these new characters (from ISO-8859-3) introduced:&lt;br /&gt;
&lt;br /&gt;
* Ğ appears at 0x88&lt;br /&gt;
* ğ appears at 0x98&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;[2]&#039;&#039;&#039; Avoid using the non-breaking space (NBSP, 0xA0) and the soft hyphen (SHY, 0xAD) in your strings. The TDM engine has no code to respect these during word wrap. Font maintainers: probably map NBSP to the &amp;lt;space&amp;gt; glyph, SHY to undefined/hollow box or zero-sized box.&lt;br /&gt;
&lt;br /&gt;
==== Corresponding Unicode ====&lt;br /&gt;
&lt;br /&gt;
For a mapping of these 256 codepoints to Unicode U+NNNN values and formal names, download &#039;TDM 8859-Style Font Map to Unicode-16.txt&#039;: &lt;br /&gt;
&lt;br /&gt;
* [https://drive.google.com/file/d/1wLEtuFvnrZ-WHK8ign8i3diIXZdriZ4F/view?usp=sharing for TDM 2.13]&lt;br /&gt;
* [https://drive.google.com/file/d/1UAz9jSZpT_j33STP3So_Re8JWa8QuAmz/view?usp=sharing for TDM 2.12 and earlier]&lt;br /&gt;
&lt;br /&gt;
Each of these files (by Geep, 2024) is in a standardized format so that it can also be imported into font design programs like FontForge as a custom 256-position map. In the comments, there is additional information about:&lt;br /&gt;
* ISO 8859-x sourcing of each character.&lt;br /&gt;
* alternative representations of some European and control characters.&lt;br /&gt;
&lt;br /&gt;
=== Russian ===&lt;br /&gt;
&lt;br /&gt;
Characters conform to the [https://en.wikipedia.org/wiki/Win-1251 WIN-1251 native encoding, shown in the Wikipedia article]. Exception: the character &#039;&#039;&#039;0xFF&#039;&#039;&#039; (я) is mapped to &#039;&#039;&#039;0xB6&#039;&#039;&#039; upon loading. Therefore any Russian font must contain я at the place 0xB6.&lt;br /&gt;
&lt;br /&gt;
Within any given font, character overage may be incomplete. A 2025 effort extended the Mason 48pt font to all 256 codepoints.&lt;br /&gt;
&lt;br /&gt;
=== Asian Languages (Korean, Chinese, Japanese) ===&lt;br /&gt;
&lt;br /&gt;
The original D3 had support for these languages, so it might be possible to add them to TDM, too. At the moment, however, we lack the fonts and translators. Also, writing from right-to-left (Hebrew) or top-down (Japanese) might be tricky or outright impossible in our GUI without more work in the C++ code. Plus, these languages use more than 256 different characters, and an 8 bit table will not hold these.&lt;br /&gt;
&lt;br /&gt;
== European Character Implementation ==&lt;br /&gt;
=== Priority Early-On - the &amp;quot;Top 50&amp;quot; ===&lt;br /&gt;
&lt;br /&gt;
Some of the special characters are used more often than others. Here is a statistic over the entire string set of the TDM core, from TDM v1.08, showing the top 50 most-used characters (excluding a-z, 0-9 and russian characters):&lt;br /&gt;
&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot; border=1 style=&amp;quot;border-collapse: collapse; font-size: 85%&amp;quot; cellspacing=0 cellpadding=2&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|Rank&lt;br /&gt;
|Occurances&lt;br /&gt;
|Letter&lt;br /&gt;
|Remarks&lt;br /&gt;
|Rank&lt;br /&gt;
|Occurances&lt;br /&gt;
|Letter&lt;br /&gt;
|Remarks&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|1&lt;br /&gt;
|í&lt;br /&gt;
|715&lt;br /&gt;
|&lt;br /&gt;
|25&lt;br /&gt;
|ć&lt;br /&gt;
|67&lt;br /&gt;
|&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|2&lt;br /&gt;
|é&lt;br /&gt;
|674&lt;br /&gt;
|&lt;br /&gt;
|26&lt;br /&gt;
|è&lt;br /&gt;
|65&lt;br /&gt;
|&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|3&lt;br /&gt;
|á&lt;br /&gt;
|524&lt;br /&gt;
|&lt;br /&gt;
|27&lt;br /&gt;
|ú&lt;br /&gt;
|56&lt;br /&gt;
|&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|4&lt;br /&gt;
|ø&lt;br /&gt;
|303&lt;br /&gt;
|Danish&lt;br /&gt;
|28&lt;br /&gt;
|ê&lt;br /&gt;
|52&lt;br /&gt;
|&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|5&lt;br /&gt;
|č&lt;br /&gt;
|288&lt;br /&gt;
|&lt;br /&gt;
|29&lt;br /&gt;
|ö&lt;br /&gt;
|48&lt;br /&gt;
|German&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|6&lt;br /&gt;
|ó&lt;br /&gt;
|283&lt;br /&gt;
|&lt;br /&gt;
|30&lt;br /&gt;
|É&lt;br /&gt;
|46&lt;br /&gt;
|&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|7&lt;br /&gt;
|ü&lt;br /&gt;
|270&lt;br /&gt;
|German&lt;br /&gt;
|31&lt;br /&gt;
|ñ&lt;br /&gt;
|37&lt;br /&gt;
|&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|8&lt;br /&gt;
|ł&lt;br /&gt;
|203&lt;br /&gt;
|Polish&lt;br /&gt;
|32&lt;br /&gt;
|õ&lt;br /&gt;
|32&lt;br /&gt;
|&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|9&lt;br /&gt;
|æ&lt;br /&gt;
|200&lt;br /&gt;
|Danish&lt;br /&gt;
|33&lt;br /&gt;
|ń&lt;br /&gt;
|26&lt;br /&gt;
|&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|10&lt;br /&gt;
|ě&lt;br /&gt;
|182&lt;br /&gt;
|&lt;br /&gt;
|34&lt;br /&gt;
|Ł&lt;br /&gt;
|24&lt;br /&gt;
|&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|11&lt;br /&gt;
|ř&lt;br /&gt;
|175&lt;br /&gt;
|Czech&lt;br /&gt;
|35&lt;br /&gt;
|Š&lt;br /&gt;
|21&lt;br /&gt;
|&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|12&lt;br /&gt;
|ã&lt;br /&gt;
|168&lt;br /&gt;
|&lt;br /&gt;
|36&lt;br /&gt;
|â&lt;br /&gt;
|21&lt;br /&gt;
|&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|13&lt;br /&gt;
|ž&lt;br /&gt;
|148&lt;br /&gt;
|Czech&lt;br /&gt;
|37&lt;br /&gt;
|ź&lt;br /&gt;
|20&lt;br /&gt;
|&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|14&lt;br /&gt;
|ý&lt;br /&gt;
|142&lt;br /&gt;
|&lt;br /&gt;
|38&lt;br /&gt;
|ß&lt;br /&gt;
|18&lt;br /&gt;
|German&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|15&lt;br /&gt;
|ę&lt;br /&gt;
|141&lt;br /&gt;
|&lt;br /&gt;
|39&lt;br /&gt;
|Ó&lt;br /&gt;
|18&lt;br /&gt;
|&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|16&lt;br /&gt;
|ą&lt;br /&gt;
|140&lt;br /&gt;
|&lt;br /&gt;
|40&lt;br /&gt;
|ň&lt;br /&gt;
|15&lt;br /&gt;
|&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|17&lt;br /&gt;
|ż&lt;br /&gt;
|119&lt;br /&gt;
|&lt;br /&gt;
|41&lt;br /&gt;
|Ú&lt;br /&gt;
|15&lt;br /&gt;
|&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|18&lt;br /&gt;
|å&lt;br /&gt;
|109&lt;br /&gt;
|Danish&lt;br /&gt;
|42&lt;br /&gt;
|Á&lt;br /&gt;
|13&lt;br /&gt;
|&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|19&lt;br /&gt;
|š&lt;br /&gt;
|99&lt;br /&gt;
|&lt;br /&gt;
|43&lt;br /&gt;
|î&lt;br /&gt;
|12&lt;br /&gt;
|&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|20&lt;br /&gt;
|ś&lt;br /&gt;
|97&lt;br /&gt;
|&lt;br /&gt;
|44&lt;br /&gt;
|ť&lt;br /&gt;
|11&lt;br /&gt;
|&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|21&lt;br /&gt;
|ç&lt;br /&gt;
|91&lt;br /&gt;
|&lt;br /&gt;
|45&lt;br /&gt;
|ô&lt;br /&gt;
|9&lt;br /&gt;
|&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|22&lt;br /&gt;
|ä&lt;br /&gt;
|86&lt;br /&gt;
|German&lt;br /&gt;
|46&lt;br /&gt;
|Ž&lt;br /&gt;
|8&lt;br /&gt;
|&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|23&lt;br /&gt;
|à&lt;br /&gt;
|83&lt;br /&gt;
|&lt;br /&gt;
|47&lt;br /&gt;
|Ż&lt;br /&gt;
|7&lt;br /&gt;
|&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|24&lt;br /&gt;
|ů&lt;br /&gt;
|77&lt;br /&gt;
|&lt;br /&gt;
|48&lt;br /&gt;
|Č&lt;br /&gt;
|7&lt;br /&gt;
|&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|25&lt;br /&gt;
|ć&lt;br /&gt;
|67&lt;br /&gt;
|&lt;br /&gt;
|49&lt;br /&gt;
|ù&lt;br /&gt;
|6&lt;br /&gt;
|&lt;br /&gt;
&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Although ö, ä and ü do not appear that often, with only these and Ü, Ö, Ä and ß, the entire German language works. So adding these letters to the fonts is quite important. &lt;br /&gt;
&lt;br /&gt;
Preferably, all foreign letters would be added to the fonts (see [[Font Patcher]] or [[Refont]]). However, if time permits only adding a few, &#039;&#039;&#039;í&#039;&#039;&#039; would be more important than, say, &#039;&#039;&#039;ô&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
It is commonplace for missing accented letters to be redirected in the .dat file to the corresponding unaccented base letter.&lt;br /&gt;
&lt;br /&gt;
=== Coverage Expansion &amp;amp; Remaining Limitations ===&lt;br /&gt;
&lt;br /&gt;
By 2014, all the system (e.g., main menu) fonts (Carleton, Carleton_condensed, Stone in sizes 24pt and 48pt; Mason and Mason_glow in 48pt) had good coverage of the &amp;quot;Top 50&amp;quot; and beyond, although not all 256 codepoints. &lt;br /&gt;
This was confirmed more specifically in 2024, as part of an [https://forums.thedarkmod.com/index.php?/topic/22427-analysis-of-212-tdm-fonts/ Analysis of 2.12 Fonts]. This analysis indicated that, unlike the system fonts, the FM fonts generally did not provide specific glyphs beyond ASCII.&lt;br /&gt;
&lt;br /&gt;
In 2024, Stone 24pt, important for subtitles and a number of readables, was further extended to cover all 256 codepoints. This was tested with TDM 2.13[betas] and released with 2.14. Similar Stone 48pt and Carleton 24pt improvements are planned for TDM 2.15.&lt;br /&gt;
&lt;br /&gt;
[[Category:Fonts]]&lt;br /&gt;
&lt;br /&gt;
{{i18n}}&lt;/div&gt;</summary>
		<author><name>Geep</name></author>
	</entry>
	<entry>
		<id>https://wiki.thedarkmod.com/index.php?title=I18N_-_Charset&amp;diff=34443</id>
		<title>I18N - Charset</title>
		<link rel="alternate" type="text/html" href="https://wiki.thedarkmod.com/index.php?title=I18N_-_Charset&amp;diff=34443"/>
		<updated>2026-03-15T20:58:07Z</updated>

		<summary type="html">&lt;p&gt;Geep: Added note 2 about avoiding non-breaking space &amp;amp; soft hyphen&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction ==&lt;br /&gt;
&lt;br /&gt;
The D3 code that handles the GUI bitmap font can only load a specific range of bytes as characters. To get the most out of the available entries, special charsets are used. The fonts (Carleton for the menu f.i.) are build/patched so that the right characters appear in the right place.&lt;br /&gt;
&lt;br /&gt;
== Encodings ==&lt;br /&gt;
&lt;br /&gt;
=== all.lang ===&lt;br /&gt;
&lt;br /&gt;
This file is in &#039;&#039;&#039;UTF-8&#039;&#039;&#039;, and converted with the help of the script &#039;&#039;&#039;devel/gen_lang.pl&#039;&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
 perl devel/gen_lang.pl&lt;br /&gt;
&lt;br /&gt;
This ensures that the generated language files are in their proper encodings (see below).&lt;br /&gt;
&lt;br /&gt;
=== All other language files ===&lt;br /&gt;
&lt;br /&gt;
Note that the language files (f.i. &#039;&#039;&#039;strings/german.lang&#039;&#039;&#039;) as well as the readables and the FM dictionariaries are expected to be in the following encodings:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Czech&#039;&#039;&#039;, &#039;&#039;&#039;Hungarian&#039;&#039;&#039;, &#039;&#039;&#039;Slovak&#039;&#039;&#039;, &#039;&#039;&#039;Polish:&#039;&#039;&#039; [https://secure.wikimedia.org/wikipedia/en/wiki/ISO/IEC_8859-2 ISO-8859-2] (&#039;&#039;&#039;not WIN-1250!)&lt;br /&gt;
* &#039;&#039;&#039;Russian:&#039;&#039;&#039; [https://secure.wikimedia.org/wikipedia/en/wiki/Win-1251 WIN-1251]&lt;br /&gt;
* &#039;&#039;&#039;French:&#039;&#039;&#039; [https://secure.wikimedia.org/wikipedia/en/wiki/ISO/IEC_8859-15 ISO-8859-15]&lt;br /&gt;
* &#039;&#039;&#039;Romanian:&#039;&#039;&#039; [https://secure.wikimedia.org/wikipedia/en/wiki/ISO/IEC_8859-16 ISO-8859-16] &lt;br /&gt;
* &#039;&#039;&#039;All other languages:&#039;&#039;&#039; [https://secure.wikimedia.org/wikipedia/en/wiki/ISO/IEC_8859-1 ISO-8859-1] (German, Dutch, Danish, Swedish, Portuguese, etc.)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{{infobox|The core dictionaries are automatically generated in the right encoding, but make sure that you use the right encoding for the FM dictionary, too!}}&lt;br /&gt;
&lt;br /&gt;
== Character remapping ==&lt;br /&gt;
&lt;br /&gt;
The characters are remapped upon loading the dictionary/readable, from their native encoding to the special one that TDM uses and that is described here.  Responsible for the remapping are [[I18N - Character mapping|mapping files]], f.i. &amp;quot;strings/czech.map&amp;quot;. If a map file for a specific language is not found, &amp;quot;strings/default.map&amp;quot; is used instead, if this is not found, no remapping takes place.&lt;br /&gt;
&lt;br /&gt;
See &#039;&#039;&#039;[[I18N - Character mapping|Character mapping]]&#039;&#039;&#039; for more information.&lt;br /&gt;
&lt;br /&gt;
=== European Languages ===&lt;br /&gt;
&lt;br /&gt;
This mapping is used for European languages, f.i. &#039;&#039;&#039;Czech&#039;&#039;&#039;, &#039;&#039;&#039;French&#039;&#039;&#039;, &#039;&#039;&#039;German&#039;&#039;&#039;, &#039;&#039;&#039;Spanish&#039;&#039;&#039;, &#039;&#039;&#039;Portuguese&#039;&#039;&#039;, &#039;&#039;&#039;Polish&#039;&#039;&#039;. Note that the double accented characters in Hungarian &#039;&#039;&#039;Ő, ő, Ű and ű&#039;&#039;&#039; look a bit different from &#039;&#039;&#039;Ö, ö, Ü and ü&#039;&#039;&#039;!&lt;br /&gt;
&lt;br /&gt;
In the table below, the original ISO 8859-1 characters are given in &#039;&#039;()&#039;&#039; below the TDM character.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Color code:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
{{box|#f0d0d0|Character not usable by TDM|Unusable}}{{box|#d0e0d0|Character not yet used in TDM|Unused}}{{box|#c0ffc0|Character displayed in v1.08 or newer|Usable in v1.08}}{{box|#80f080|Character displayed in v2.03 or newer|Usable in v2.03}}{{box|#d0d0f0|Changed from the ISO-8859-1 default, usable by TDM 1.0 or newer|Changed from ISO 8859-1}}&lt;br /&gt;
&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot; border=1 style=&amp;quot;border-collapse: collapse; font-size: 95%&amp;quot; cellspacing=0 cellpadding=2 width=100%&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
!&lt;br /&gt;
!…0&lt;br /&gt;
!…1&lt;br /&gt;
!…2&lt;br /&gt;
!…3&lt;br /&gt;
!…4&lt;br /&gt;
!…5&lt;br /&gt;
!…6&lt;br /&gt;
!…7&lt;br /&gt;
!…8&lt;br /&gt;
!…9&lt;br /&gt;
!…A&lt;br /&gt;
!…B&lt;br /&gt;
!…C&lt;br /&gt;
!…D&lt;br /&gt;
!…E&lt;br /&gt;
!…F&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
!0…&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #f0d0d0&#039;|00&amp;lt;br&amp;gt;&#039;&#039;&#039;–&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #f0d0d0&#039;|01&amp;lt;br&amp;gt;&#039;&#039;&#039;–&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #f0d0d0&#039;|02&amp;lt;br&amp;gt;&#039;&#039;&#039;–&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #f0d0d0&#039;|03&amp;lt;br&amp;gt;&#039;&#039;&#039;–&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #f0d0d0&#039;|04&amp;lt;br&amp;gt;&#039;&#039;&#039;–&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #f0d0d0&#039;|05&amp;lt;br&amp;gt;&#039;&#039;&#039;–&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #f0d0d0&#039;|06&amp;lt;br&amp;gt;&#039;&#039;&#039;–&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #f0d0d0&#039;|07&amp;lt;br&amp;gt;&#039;&#039;&#039;–&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #f0d0d0&#039;|08&amp;lt;br&amp;gt;&#039;&#039;&#039;–&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #f0d0d0&#039;|09&amp;lt;br&amp;gt;&#039;&#039;&#039;–&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #f0d0d0&#039;|0A&amp;lt;br&amp;gt;&#039;&#039;&#039;–&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #f0d0d0&#039;|0B&amp;lt;br&amp;gt;&#039;&#039;&#039;–&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #f0d0d0&#039;|0C&amp;lt;br&amp;gt;&#039;&#039;&#039;–&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #f0d0d0&#039;|0D&amp;lt;br&amp;gt;&#039;&#039;&#039;–&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #f0d0d0&#039;|0E&amp;lt;br&amp;gt;&#039;&#039;&#039;–&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #f0d0d0&#039;|0F&amp;lt;br&amp;gt;&#039;&#039;&#039;–&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
!1…&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #f0d0d0&#039;|10&amp;lt;br&amp;gt;&#039;&#039;&#039;–&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #f0d0d0&#039;|11&amp;lt;br&amp;gt;&#039;&#039;&#039;–&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #f0d0d0&#039;|12&amp;lt;br&amp;gt;&#039;&#039;&#039;–&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #f0d0d0&#039;|13&amp;lt;br&amp;gt;&#039;&#039;&#039;–&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #f0d0d0&#039;|14&amp;lt;br&amp;gt;&#039;&#039;&#039;–&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #f0d0d0&#039;|15&amp;lt;br&amp;gt;&#039;&#039;&#039;–&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #f0d0d0&#039;|16&amp;lt;br&amp;gt;&#039;&#039;&#039;–&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #f0d0d0&#039;|17&amp;lt;br&amp;gt;&#039;&#039;&#039;–&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #f0d0d0&#039;|18&amp;lt;br&amp;gt;&#039;&#039;&#039;–&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #f0d0d0&#039;|19&amp;lt;br&amp;gt;&#039;&#039;&#039;–&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #f0d0d0&#039;|1A&amp;lt;br&amp;gt;&#039;&#039;&#039;–&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #f0d0d0&#039;|1B&amp;lt;br&amp;gt;&#039;&#039;&#039;–&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #f0d0d0&#039;|1C&amp;lt;br&amp;gt;&#039;&#039;&#039;–&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #f0d0d0&#039;|1D&amp;lt;br&amp;gt;&#039;&#039;&#039;–&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #f0d0d0&#039;|1E&amp;lt;br&amp;gt;&#039;&#039;&#039;–&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #f0d0d0&#039;|1F&amp;lt;br&amp;gt;&#039;&#039;&#039;–&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
!2…&lt;br /&gt;
|align=&#039;center&#039;|20&amp;lt;br&amp;gt;&#039;&#039;&#039;&amp;amp;nbsp;&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|21&amp;lt;br&amp;gt;&#039;&#039;&#039;!&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|22&amp;lt;br&amp;gt;&#039;&#039;&#039;&amp;quot;&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|23&amp;lt;br&amp;gt;&#039;&#039;&#039;#&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|24&amp;lt;br&amp;gt;&#039;&#039;&#039;$&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|25&amp;lt;br&amp;gt;&#039;&#039;&#039;%&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|26&amp;lt;br&amp;gt;&#039;&#039;&#039;&amp;amp;&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|27&amp;lt;br&amp;gt;&#039;&#039;&#039;&#039;&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|28&amp;lt;br&amp;gt;&#039;&#039;&#039;(&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|29&amp;lt;br&amp;gt;&#039;&#039;&#039;)&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|2A&amp;lt;br&amp;gt;&#039;&#039;&#039;*&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|2B&amp;lt;br&amp;gt;&#039;&#039;&#039;+&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|2C&amp;lt;br&amp;gt;&#039;&#039;&#039;,&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|2D&amp;lt;br&amp;gt;&#039;&#039;&#039;-&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|2E&amp;lt;br&amp;gt;&#039;&#039;&#039;.&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|2F&amp;lt;br&amp;gt;&#039;&#039;&#039;/&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
!3…&lt;br /&gt;
|align=&#039;center&#039;|30&amp;lt;br&amp;gt;&#039;&#039;&#039;0&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|31&amp;lt;br&amp;gt;&#039;&#039;&#039;1&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|32&amp;lt;br&amp;gt;&#039;&#039;&#039;2&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|33&amp;lt;br&amp;gt;&#039;&#039;&#039;3&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|34&amp;lt;br&amp;gt;&#039;&#039;&#039;4&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|35&amp;lt;br&amp;gt;&#039;&#039;&#039;5&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|36&amp;lt;br&amp;gt;&#039;&#039;&#039;6&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|37&amp;lt;br&amp;gt;&#039;&#039;&#039;7&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|38&amp;lt;br&amp;gt;&#039;&#039;&#039;8&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|39&amp;lt;br&amp;gt;&#039;&#039;&#039;9&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|3A&amp;lt;br&amp;gt;&#039;&#039;&#039;:&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|3B&amp;lt;br&amp;gt;&#039;&#039;&#039;;&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|3C&amp;lt;br&amp;gt;&#039;&#039;&#039;&amp;lt;&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|3D&amp;lt;br&amp;gt;&#039;&#039;&#039;=&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|3E&amp;lt;br&amp;gt;&#039;&#039;&#039;&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|3F&amp;lt;br&amp;gt;&#039;&#039;&#039;?&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
!4…&lt;br /&gt;
|align=&#039;center&#039;|40&amp;lt;br&amp;gt;&#039;&#039;&#039;@&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|41&amp;lt;br&amp;gt;&#039;&#039;&#039;A&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|42&amp;lt;br&amp;gt;&#039;&#039;&#039;B&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|43&amp;lt;br&amp;gt;&#039;&#039;&#039;C&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|44&amp;lt;br&amp;gt;&#039;&#039;&#039;D&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|45&amp;lt;br&amp;gt;&#039;&#039;&#039;E&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|46&amp;lt;br&amp;gt;&#039;&#039;&#039;F&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|47&amp;lt;br&amp;gt;&#039;&#039;&#039;G&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|48&amp;lt;br&amp;gt;&#039;&#039;&#039;H&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|49&amp;lt;br&amp;gt;&#039;&#039;&#039;I&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|4A&amp;lt;br&amp;gt;&#039;&#039;&#039;J&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|4B&amp;lt;br&amp;gt;&#039;&#039;&#039;K&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|4C&amp;lt;br&amp;gt;&#039;&#039;&#039;L&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|4D&amp;lt;br&amp;gt;&#039;&#039;&#039;M&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|4E&amp;lt;br&amp;gt;&#039;&#039;&#039;N&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|4F&amp;lt;br&amp;gt;&#039;&#039;&#039;O&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
!5…&lt;br /&gt;
|align=&#039;center&#039;|50&amp;lt;br&amp;gt;&#039;&#039;&#039;P&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|51&amp;lt;br&amp;gt;&#039;&#039;&#039;Q&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|52&amp;lt;br&amp;gt;&#039;&#039;&#039;R&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|53&amp;lt;br&amp;gt;&#039;&#039;&#039;S&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|54&amp;lt;br&amp;gt;&#039;&#039;&#039;T&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|55&amp;lt;br&amp;gt;&#039;&#039;&#039;U&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|56&amp;lt;br&amp;gt;&#039;&#039;&#039;V&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|57&amp;lt;br&amp;gt;&#039;&#039;&#039;W&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|58&amp;lt;br&amp;gt;&#039;&#039;&#039;X&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|59&amp;lt;br&amp;gt;&#039;&#039;&#039;Y&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|5A&amp;lt;br&amp;gt;&#039;&#039;&#039;Z&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|5B&amp;lt;br&amp;gt;&#039;&#039;&#039;[&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|5C&amp;lt;br&amp;gt;&#039;&#039;&#039;\&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|5D&amp;lt;br&amp;gt;&#039;&#039;&#039;]&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|5E&amp;lt;br&amp;gt;&#039;&#039;&#039;^&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|5F&amp;lt;br&amp;gt;&#039;&#039;&#039;_&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
!6…&lt;br /&gt;
|align=&#039;center&#039;|60&amp;lt;br&amp;gt;&#039;&#039;&#039;`&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|61&amp;lt;br&amp;gt;&#039;&#039;&#039;a&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|62&amp;lt;br&amp;gt;&#039;&#039;&#039;b&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|63&amp;lt;br&amp;gt;&#039;&#039;&#039;c&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|64&amp;lt;br&amp;gt;&#039;&#039;&#039;d&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|65&amp;lt;br&amp;gt;&#039;&#039;&#039;e&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|66&amp;lt;br&amp;gt;&#039;&#039;&#039;f&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|67&amp;lt;br&amp;gt;&#039;&#039;&#039;g&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|68&amp;lt;br&amp;gt;&#039;&#039;&#039;h&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|69&amp;lt;br&amp;gt;&#039;&#039;&#039;i&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|6A&amp;lt;br&amp;gt;&#039;&#039;&#039;j&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|6B&amp;lt;br&amp;gt;&#039;&#039;&#039;k&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|6C&amp;lt;br&amp;gt;&#039;&#039;&#039;l&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|6D&amp;lt;br&amp;gt;&#039;&#039;&#039;m&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|6E&amp;lt;br&amp;gt;&#039;&#039;&#039;n&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|6F&amp;lt;br&amp;gt;&#039;&#039;&#039;o&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
!7…&lt;br /&gt;
|align=&#039;center&#039;|70&amp;lt;br&amp;gt;&#039;&#039;&#039;p&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|71&amp;lt;br&amp;gt;&#039;&#039;&#039;q&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|72&amp;lt;br&amp;gt;&#039;&#039;&#039;r&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|73&amp;lt;br&amp;gt;&#039;&#039;&#039;s&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|74&amp;lt;br&amp;gt;&#039;&#039;&#039;t&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|75&amp;lt;br&amp;gt;&#039;&#039;&#039;u&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|76&amp;lt;br&amp;gt;&#039;&#039;&#039;v&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|77&amp;lt;br&amp;gt;&#039;&#039;&#039;w&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|78&amp;lt;br&amp;gt;&#039;&#039;&#039;x&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|79&amp;lt;br&amp;gt;&#039;&#039;&#039;y&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|7A&amp;lt;br&amp;gt;&#039;&#039;&#039;z&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|7B&amp;lt;br&amp;gt;&#039;&#039;&#039;{&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|7C&amp;lt;br&amp;gt;&#039;&#039;&#039;|&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|7D&amp;lt;br&amp;gt;&#039;&#039;&#039;}&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|7E&amp;lt;br&amp;gt;&#039;&#039;&#039;~&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #d0e0d0&#039;|7F&amp;lt;br&amp;gt;&#039;&#039;&#039;�&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
!8…&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #c0ffc0&#039;|80&amp;lt;br&amp;gt;&#039;&#039;&#039;Ň&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #c0ffc0&#039;|81&amp;lt;br&amp;gt;&#039;&#039;&#039;Ś&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #c0ffc0&#039;|82&amp;lt;br&amp;gt;&#039;&#039;&#039;Ć&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #c0ffc0&#039;|83&amp;lt;br&amp;gt;&#039;&#039;&#039;Ż&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #c0ffc0&#039;|84&amp;lt;br&amp;gt;&#039;&#039;&#039;Ź&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #c0ffc0&#039;|85&amp;lt;br&amp;gt;&#039;&#039;&#039;Ŝ&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #c0ffc0&#039;|86&amp;lt;br&amp;gt;&#039;&#039;&#039;Ĉ&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #c0ffc0&#039;|87&amp;lt;br&amp;gt;&#039;&#039;&#039;Ẑ&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #c0ffc0&#039;|88&amp;lt;br&amp;gt;&#039;&#039;&#039;Ô&#039;&#039;&#039; [1]&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #c0ffc0&#039;|89&amp;lt;br&amp;gt;&#039;&#039;&#039;Ŕ&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #c0ffc0&#039;|8A&amp;lt;br&amp;gt;&#039;&#039;&#039;Ǔ&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #c0ffc0&#039;|8B&amp;lt;br&amp;gt;&#039;&#039;&#039;Ă&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #c0ffc0&#039;|8C&amp;lt;br&amp;gt;&#039;&#039;&#039;Ń&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #80f080&#039;|8D&amp;lt;br&amp;gt;&#039;&#039;&#039;Ș&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #80f080&#039;|8E&amp;lt;br&amp;gt;&#039;&#039;&#039;Ț&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #d0e0d0&#039;|8F&amp;lt;br&amp;gt;&#039;&#039;&#039;�&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
!9…&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #80f080&#039;|90&amp;lt;br&amp;gt;&#039;&#039;&#039;đ&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #c0ffc0&#039;|91&amp;lt;br&amp;gt;&#039;&#039;&#039;ś&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #c0ffc0&#039;|92&amp;lt;br&amp;gt;&#039;&#039;&#039;ć&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #c0ffc0&#039;|93&amp;lt;br&amp;gt;&#039;&#039;&#039;ż&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #c0ffc0&#039;|94&amp;lt;br&amp;gt;&#039;&#039;&#039;ź&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #c0ffc0&#039;|95&amp;lt;br&amp;gt;&#039;&#039;&#039;ŝ&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #c0ffc0&#039;|96&amp;lt;br&amp;gt;&#039;&#039;&#039;ĉ&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #c0ffc0&#039;|97&amp;lt;br&amp;gt;&#039;&#039;&#039;ẑ&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #c0ffc0&#039;|98&amp;lt;br&amp;gt;&#039;&#039;&#039;ô&#039;&#039;&#039; [1]&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #c0ffc0&#039;|99&amp;lt;br&amp;gt;&#039;&#039;&#039;ŕ&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #c0ffc0&#039;|9A&amp;lt;br&amp;gt;&#039;&#039;&#039;ǔ&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #c0ffc0&#039;|9B&amp;lt;br&amp;gt;&#039;&#039;&#039;ă&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #c0ffc0&#039;|9C&amp;lt;br&amp;gt;&#039;&#039;&#039;ń&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #80f080&#039;|9D&amp;lt;br&amp;gt;&#039;&#039;&#039;ș&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #80f080&#039;|9E&amp;lt;br&amp;gt;&#039;&#039;&#039;ț&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #d0e0d0&#039;|9F&amp;lt;br&amp;gt;&#039;&#039;&#039;�&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
!A…&lt;br /&gt;
|align=&#039;center&#039;|A0&amp;lt;br&amp;gt;&#039;&#039;&#039;[https://secure.wikimedia.org/wikipedia/en/wiki/Non-breaking_space NBSP]&#039;&#039;&#039;&amp;lt;br&amp;gt;[2]&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #d0d0f0&#039;|A1&amp;lt;br&amp;gt;&#039;&#039;&#039;ň&#039;&#039;&#039;&amp;lt;br&amp;gt;(¡)&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #d0d0f0&#039;|A2&amp;lt;br&amp;gt;&#039;&#039;&#039;Ű&#039;&#039;&#039;&amp;lt;br&amp;gt;(¢)&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #d0d0f0&#039;|A3&amp;lt;br&amp;gt;&#039;&#039;&#039;ě&#039;&#039;&#039;&amp;lt;br&amp;gt;(£)&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #d0d0f0&#039;|A4&amp;lt;br&amp;gt;&#039;&#039;&#039;ű&#039;&#039;&#039;&amp;lt;br&amp;gt;(¤)&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #d0d0f0&#039;|A5&amp;lt;br&amp;gt;&#039;&#039;&#039;Ě&#039;&#039;&#039;&amp;lt;br&amp;gt;(¥)&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #d0d0f0&#039;|A6&amp;lt;br&amp;gt;&#039;&#039;&#039;Š&#039;&#039;&#039;&amp;lt;br&amp;gt;(¦)&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|A7&amp;lt;br&amp;gt;&#039;&#039;&#039;§&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #d0d0f0&#039;|A8&amp;lt;br&amp;gt;&#039;&#039;&#039;š&#039;&#039;&#039;&amp;lt;br&amp;gt;(¨)&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #d0d0f0&#039;|A9&amp;lt;br&amp;gt;&#039;&#039;&#039;Ů&#039;&#039;&#039;&amp;lt;br&amp;gt;(©)&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #d0d0f0&#039;|AA&amp;lt;br&amp;gt;&#039;&#039;&#039;Ą&#039;&#039;&#039;&amp;lt;br&amp;gt;(ª)&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #d0d0f0&#039;|AB&amp;lt;br&amp;gt;&#039;&#039;&#039;Ę&#039;&#039;&#039;&amp;lt;br&amp;gt;(«)&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #d0d0f0&#039;|AC&amp;lt;br&amp;gt;&#039;&#039;&#039;Č&#039;&#039;&#039;&amp;lt;br&amp;gt;(¬)&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|AD&amp;lt;br&amp;gt;&#039;&#039;&#039;[https://secure.wikimedia.org/wikipedia/en/wiki/Soft_hyphen SHY]&#039;&#039;&#039;&amp;lt;br&amp;gt;[2]&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #d0d0f0&#039;|AE&amp;lt;br&amp;gt;&#039;&#039;&#039;č&#039;&#039;&#039;&amp;lt;br&amp;gt;(®)&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #d0d0f0&#039;|AF&amp;lt;br&amp;gt;&#039;&#039;&#039;ů&#039;&#039;&#039;&amp;lt;br&amp;gt;(¯)&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
!B…&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #d0d0f0&#039;|B0&amp;lt;br&amp;gt;&#039;&#039;&#039;Ő&#039;&#039;&#039;&amp;lt;br&amp;gt;(°)&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #d0d0f0&#039;|B1&amp;lt;br&amp;gt;&#039;&#039;&#039;Ł&#039;&#039;&#039;&amp;lt;br&amp;gt;(±)&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #d0d0f0&#039;|B2&amp;lt;br&amp;gt;&#039;&#039;&#039;Ť&#039;&#039;&#039;&amp;lt;br&amp;gt;(²)&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #d0d0f0&#039;|B3&amp;lt;br&amp;gt;&#039;&#039;&#039;Ď&#039;&#039;&#039;&amp;lt;br&amp;gt;(³)&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #d0d0f0&#039;|B4&amp;lt;br&amp;gt;&#039;&#039;&#039;Ž&#039;&#039;&#039;&amp;lt;br&amp;gt;(´)&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #d0d0f0&#039;|B5&amp;lt;br&amp;gt;&#039;&#039;&#039;ł&#039;&#039;&#039;&amp;lt;br&amp;gt;(µ)&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #d0d0f0&#039;|B6&amp;lt;br&amp;gt;&#039;&#039;&#039;ť&#039;&#039;&#039;&amp;lt;br&amp;gt;(¶)&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #d0d0f0&#039;|B7&amp;lt;br&amp;gt;&#039;&#039;&#039;ď&#039;&#039;&#039;&amp;lt;br&amp;gt;(·)&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #d0d0f0&#039;|B8&amp;lt;br&amp;gt;&#039;&#039;&#039;ž&#039;&#039;&#039;&amp;lt;br&amp;gt;(¸)&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #d0d0f0&#039;|B9&amp;lt;br&amp;gt;&#039;&#039;&#039;ő&#039;&#039;&#039;&amp;lt;br&amp;gt;(¹)&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #d0d0f0&#039;|BA&amp;lt;br&amp;gt;&#039;&#039;&#039;ą&#039;&#039;&#039;&amp;lt;br&amp;gt;(º)&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #d0d0f0&#039;|BB&amp;lt;br&amp;gt;&#039;&#039;&#039;ę&#039;&#039;&#039;&amp;lt;br&amp;gt;(»)&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #d0d0f0&#039;|BC&amp;lt;br&amp;gt;&#039;&#039;&#039;Œ&#039;&#039;&#039;&amp;lt;br&amp;gt;(¼)&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #d0d0f0&#039;|BD&amp;lt;br&amp;gt;&#039;&#039;&#039;œ&#039;&#039;&#039;&amp;lt;br&amp;gt;(½)&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #d0d0f0&#039;|BE&amp;lt;br&amp;gt;&#039;&#039;&#039;Ÿ&#039;&#039;&#039;&amp;lt;br&amp;gt;(¾)&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|BF&amp;lt;br&amp;gt;&#039;&#039;&#039;¿&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
!C…&lt;br /&gt;
|align=&#039;center&#039;|C0&amp;lt;br&amp;gt;&#039;&#039;&#039;À&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|C1&amp;lt;br&amp;gt;&#039;&#039;&#039;Á&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|C2&amp;lt;br&amp;gt;&#039;&#039;&#039;Â&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|C3&amp;lt;br&amp;gt;&#039;&#039;&#039;Ã&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|C4&amp;lt;br&amp;gt;&#039;&#039;&#039;Ä&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|C5&amp;lt;br&amp;gt;&#039;&#039;&#039;Å&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|C6&amp;lt;br&amp;gt;&#039;&#039;&#039;Æ&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|C7&amp;lt;br&amp;gt;&#039;&#039;&#039;Ç&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|C8&amp;lt;br&amp;gt;&#039;&#039;&#039;È&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|C9&amp;lt;br&amp;gt;&#039;&#039;&#039;É&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|CA&amp;lt;br&amp;gt;&#039;&#039;&#039;Ê&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|CB&amp;lt;br&amp;gt;&#039;&#039;&#039;Ë&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|CC&amp;lt;br&amp;gt;&#039;&#039;&#039;Ì&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|CD&amp;lt;br&amp;gt;&#039;&#039;&#039;Í&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|CE&amp;lt;br&amp;gt;&#039;&#039;&#039;Î&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|CF&amp;lt;br&amp;gt;&#039;&#039;&#039;Ï&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
!D…&lt;br /&gt;
|align=&#039;center&#039;|D0&amp;lt;br&amp;gt;&#039;&#039;&#039;Ð&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|D1&amp;lt;br&amp;gt;&#039;&#039;&#039;Ñ&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|D2&amp;lt;br&amp;gt;&#039;&#039;&#039;Ò&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|D3&amp;lt;br&amp;gt;&#039;&#039;&#039;Ó&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|D4&amp;lt;br&amp;gt;&#039;&#039;&#039;Ô&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|D5&amp;lt;br&amp;gt;&#039;&#039;&#039;Õ&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|D6&amp;lt;br&amp;gt;&#039;&#039;&#039;Ö&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #d0d0f0&#039;|D7&amp;lt;br&amp;gt;&#039;&#039;&#039;Ř&#039;&#039;&#039;&amp;lt;br&amp;gt;(×)&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|D8&amp;lt;br&amp;gt;&#039;&#039;&#039;Ø&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|D9&amp;lt;br&amp;gt;&#039;&#039;&#039;Ù&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|DA&amp;lt;br&amp;gt;&#039;&#039;&#039;Ú&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|DB&amp;lt;br&amp;gt;&#039;&#039;&#039;Û&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|DC&amp;lt;br&amp;gt;&#039;&#039;&#039;Ü&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|DD&amp;lt;br&amp;gt;&#039;&#039;&#039;Ý&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|DE&amp;lt;br&amp;gt;&#039;&#039;&#039;Þ&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|DF&amp;lt;br&amp;gt;&#039;&#039;&#039;ß&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
!E…&lt;br /&gt;
|align=&#039;center&#039;|E0&amp;lt;br&amp;gt;&#039;&#039;&#039;à&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|E1&amp;lt;br&amp;gt;&#039;&#039;&#039;á&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|E2&amp;lt;br&amp;gt;&#039;&#039;&#039;â&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|E3&amp;lt;br&amp;gt;&#039;&#039;&#039;ã&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|E4&amp;lt;br&amp;gt;&#039;&#039;&#039;ä&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|E5&amp;lt;br&amp;gt;&#039;&#039;&#039;å&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|E6&amp;lt;br&amp;gt;&#039;&#039;&#039;æ&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|E7&amp;lt;br&amp;gt;&#039;&#039;&#039;ç&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|E8&amp;lt;br&amp;gt;&#039;&#039;&#039;è&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|E9&amp;lt;br&amp;gt;&#039;&#039;&#039;é&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|EA&amp;lt;br&amp;gt;&#039;&#039;&#039;ê&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|EB&amp;lt;br&amp;gt;&#039;&#039;&#039;ë&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|EC&amp;lt;br&amp;gt;&#039;&#039;&#039;ì&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|ED&amp;lt;br&amp;gt;&#039;&#039;&#039;í&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|EE&amp;lt;br&amp;gt;&#039;&#039;&#039;î&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|EF&amp;lt;br&amp;gt;&#039;&#039;&#039;ï&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
!F…&lt;br /&gt;
|align=&#039;center&#039;|F0&amp;lt;br&amp;gt;&#039;&#039;&#039;ð&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|F1&amp;lt;br&amp;gt;&#039;&#039;&#039;ñ&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|F2&amp;lt;br&amp;gt;&#039;&#039;&#039;ò&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|F3&amp;lt;br&amp;gt;&#039;&#039;&#039;ó&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|F4&amp;lt;br&amp;gt;&#039;&#039;&#039;ô&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|F5&amp;lt;br&amp;gt;&#039;&#039;&#039;õ&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|F6&amp;lt;br&amp;gt;&#039;&#039;&#039;ö&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #d0d0f0&#039;|F7&amp;lt;br&amp;gt;&#039;&#039;&#039;ř&#039;&#039;&#039;&amp;lt;br&amp;gt;(÷)&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|F8&amp;lt;br&amp;gt;&#039;&#039;&#039;ø&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|F9&amp;lt;br&amp;gt;&#039;&#039;&#039;ù&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|FA&amp;lt;br&amp;gt;&#039;&#039;&#039;ú&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|FB&amp;lt;br&amp;gt;&#039;&#039;&#039;û&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|FC&amp;lt;br&amp;gt;&#039;&#039;&#039;ü&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|FD&amp;lt;br&amp;gt;&#039;&#039;&#039;ý&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|FE&amp;lt;br&amp;gt;&#039;&#039;&#039;þ&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|FF&amp;lt;br&amp;gt;&#039;&#039;&#039;ÿ&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Notes ====&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;[1]&#039;&#039;&#039; As discussed [https://forums.thedarkmod.com/index.php?/topic/22427-analysis-of-212-tdm-fonts/&amp;amp;do=findComment&amp;amp;comment=494855 here], the TDM char set has a redundant treatment of 2 characters:&lt;br /&gt;
&lt;br /&gt;
* Ô appears at 0x88 and 0xD4&lt;br /&gt;
* ô appears at 0x98 and 0xF4&lt;br /&gt;
&lt;br /&gt;
Starting with TDM 2.13, the redundancy can be removed and these new characters (from ISO-8859-3) introduced:&lt;br /&gt;
&lt;br /&gt;
* Ğ appears at 0x88&lt;br /&gt;
* ğ appears at 0x98&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;[2]&#039;&#039;&#039; Avoid using the non-breaking space (NBSP, 0xA0) and the soft hyphen (SHY, 0xAD) in your strings. The TDM engine has no code to respect these during word wrap. Font maintainers: probably map NBSP to the &amp;lt;space&amp;gt; glyph, SHY to undefined/hollow box or zero-sized box.&lt;br /&gt;
&lt;br /&gt;
==== Corresponding Unicode ====&lt;br /&gt;
&lt;br /&gt;
For a mapping of these 256 codepoints to Unicode U+NNNN values and formal names, download &#039;TDM 8859-Style Font Map to Unicode-16.txt&#039;: &lt;br /&gt;
&lt;br /&gt;
* [https://drive.google.com/file/d/1wLEtuFvnrZ-WHK8ign8i3diIXZdriZ4F/view?usp=sharing for TDM 2.13]&lt;br /&gt;
* [https://drive.google.com/file/d/1UAz9jSZpT_j33STP3So_Re8JWa8QuAmz/view?usp=sharing for TDM 2.12 and earlier]&lt;br /&gt;
&lt;br /&gt;
Each of these files (by Geep, 2024) is in a standardized format so that it can also be imported into font design programs like FontForge as a custom 256-position map. In the comments, there is additional information about:&lt;br /&gt;
* ISO 8859-x sourcing of each character.&lt;br /&gt;
* alternative representations of some European and control characters.&lt;br /&gt;
&lt;br /&gt;
=== Russian ===&lt;br /&gt;
&lt;br /&gt;
Characters conform to the [https://en.wikipedia.org/wiki/Win-1251 WIN-1251 native encoding, shown in the Wikipedia article]. Exception: the character &#039;&#039;&#039;0xFF&#039;&#039;&#039; (я) is mapped to &#039;&#039;&#039;0xB6&#039;&#039;&#039; upon loading. Therefore any Russian font must contain я at the place 0xB6.&lt;br /&gt;
&lt;br /&gt;
Within any given font, character overage may be incomplete. A 2025 effort extended the Mason 48pt font to all 256 codepoints.&lt;br /&gt;
&lt;br /&gt;
=== Asian Languages (Korean, Chinese, Japanese) ===&lt;br /&gt;
&lt;br /&gt;
The original D3 had support for these languages, so it might be possible to add them to TDM, too. At the moment, however, we lack the fonts and translators. Also, writing from right-to-left (Hebrew) or top-down (Japanese) might be tricky or outright impossible in our GUI without more work in the C++ code. Plus, these languages use more than 256 different characters, and an 8 bit table will not hold these.&lt;br /&gt;
&lt;br /&gt;
== European Character Implementation ==&lt;br /&gt;
=== Priority Early-On - the &amp;quot;Top 50&amp;quot; ===&lt;br /&gt;
&lt;br /&gt;
Some of the special characters are used more often than others. Here is a statistic over the entire string set of the TDM core, from TDM v1.08, showing the top 50 most-used characters (excluding a-z, 0-9 and russian characters):&lt;br /&gt;
&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot; border=1 style=&amp;quot;border-collapse: collapse; font-size: 85%&amp;quot; cellspacing=0 cellpadding=2&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|Rank&lt;br /&gt;
|Occurances&lt;br /&gt;
|Letter&lt;br /&gt;
|Remarks&lt;br /&gt;
|Rank&lt;br /&gt;
|Occurances&lt;br /&gt;
|Letter&lt;br /&gt;
|Remarks&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|1&lt;br /&gt;
|í&lt;br /&gt;
|715&lt;br /&gt;
|&lt;br /&gt;
|25&lt;br /&gt;
|ć&lt;br /&gt;
|67&lt;br /&gt;
|&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|2&lt;br /&gt;
|é&lt;br /&gt;
|674&lt;br /&gt;
|&lt;br /&gt;
|26&lt;br /&gt;
|è&lt;br /&gt;
|65&lt;br /&gt;
|&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|3&lt;br /&gt;
|á&lt;br /&gt;
|524&lt;br /&gt;
|&lt;br /&gt;
|27&lt;br /&gt;
|ú&lt;br /&gt;
|56&lt;br /&gt;
|&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|4&lt;br /&gt;
|ø&lt;br /&gt;
|303&lt;br /&gt;
|Danish&lt;br /&gt;
|28&lt;br /&gt;
|ê&lt;br /&gt;
|52&lt;br /&gt;
|&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|5&lt;br /&gt;
|č&lt;br /&gt;
|288&lt;br /&gt;
|&lt;br /&gt;
|29&lt;br /&gt;
|ö&lt;br /&gt;
|48&lt;br /&gt;
|German&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|6&lt;br /&gt;
|ó&lt;br /&gt;
|283&lt;br /&gt;
|&lt;br /&gt;
|30&lt;br /&gt;
|É&lt;br /&gt;
|46&lt;br /&gt;
|&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|7&lt;br /&gt;
|ü&lt;br /&gt;
|270&lt;br /&gt;
|German&lt;br /&gt;
|31&lt;br /&gt;
|ñ&lt;br /&gt;
|37&lt;br /&gt;
|&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|8&lt;br /&gt;
|ł&lt;br /&gt;
|203&lt;br /&gt;
|Polish&lt;br /&gt;
|32&lt;br /&gt;
|õ&lt;br /&gt;
|32&lt;br /&gt;
|&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|9&lt;br /&gt;
|æ&lt;br /&gt;
|200&lt;br /&gt;
|Danish&lt;br /&gt;
|33&lt;br /&gt;
|ń&lt;br /&gt;
|26&lt;br /&gt;
|&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|10&lt;br /&gt;
|ě&lt;br /&gt;
|182&lt;br /&gt;
|&lt;br /&gt;
|34&lt;br /&gt;
|Ł&lt;br /&gt;
|24&lt;br /&gt;
|&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|11&lt;br /&gt;
|ř&lt;br /&gt;
|175&lt;br /&gt;
|Czech&lt;br /&gt;
|35&lt;br /&gt;
|Š&lt;br /&gt;
|21&lt;br /&gt;
|&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|12&lt;br /&gt;
|ã&lt;br /&gt;
|168&lt;br /&gt;
|&lt;br /&gt;
|36&lt;br /&gt;
|â&lt;br /&gt;
|21&lt;br /&gt;
|&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|13&lt;br /&gt;
|ž&lt;br /&gt;
|148&lt;br /&gt;
|Czech&lt;br /&gt;
|37&lt;br /&gt;
|ź&lt;br /&gt;
|20&lt;br /&gt;
|&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|14&lt;br /&gt;
|ý&lt;br /&gt;
|142&lt;br /&gt;
|&lt;br /&gt;
|38&lt;br /&gt;
|ß&lt;br /&gt;
|18&lt;br /&gt;
|German&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|15&lt;br /&gt;
|ę&lt;br /&gt;
|141&lt;br /&gt;
|&lt;br /&gt;
|39&lt;br /&gt;
|Ó&lt;br /&gt;
|18&lt;br /&gt;
|&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|16&lt;br /&gt;
|ą&lt;br /&gt;
|140&lt;br /&gt;
|&lt;br /&gt;
|40&lt;br /&gt;
|ň&lt;br /&gt;
|15&lt;br /&gt;
|&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|17&lt;br /&gt;
|ż&lt;br /&gt;
|119&lt;br /&gt;
|&lt;br /&gt;
|41&lt;br /&gt;
|Ú&lt;br /&gt;
|15&lt;br /&gt;
|&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|18&lt;br /&gt;
|å&lt;br /&gt;
|109&lt;br /&gt;
|Danish&lt;br /&gt;
|42&lt;br /&gt;
|Á&lt;br /&gt;
|13&lt;br /&gt;
|&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|19&lt;br /&gt;
|š&lt;br /&gt;
|99&lt;br /&gt;
|&lt;br /&gt;
|43&lt;br /&gt;
|î&lt;br /&gt;
|12&lt;br /&gt;
|&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|20&lt;br /&gt;
|ś&lt;br /&gt;
|97&lt;br /&gt;
|&lt;br /&gt;
|44&lt;br /&gt;
|ť&lt;br /&gt;
|11&lt;br /&gt;
|&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|21&lt;br /&gt;
|ç&lt;br /&gt;
|91&lt;br /&gt;
|&lt;br /&gt;
|45&lt;br /&gt;
|ô&lt;br /&gt;
|9&lt;br /&gt;
|&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|22&lt;br /&gt;
|ä&lt;br /&gt;
|86&lt;br /&gt;
|German&lt;br /&gt;
|46&lt;br /&gt;
|Ž&lt;br /&gt;
|8&lt;br /&gt;
|&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|23&lt;br /&gt;
|à&lt;br /&gt;
|83&lt;br /&gt;
|&lt;br /&gt;
|47&lt;br /&gt;
|Ż&lt;br /&gt;
|7&lt;br /&gt;
|&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|24&lt;br /&gt;
|ů&lt;br /&gt;
|77&lt;br /&gt;
|&lt;br /&gt;
|48&lt;br /&gt;
|Č&lt;br /&gt;
|7&lt;br /&gt;
|&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|25&lt;br /&gt;
|ć&lt;br /&gt;
|67&lt;br /&gt;
|&lt;br /&gt;
|49&lt;br /&gt;
|ù&lt;br /&gt;
|6&lt;br /&gt;
|&lt;br /&gt;
&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Although ö, ä and ü do not appear that often, with only these and Ü, Ö, Ä and ß, the entire German language works. So adding these letters to the fonts is quite important. &lt;br /&gt;
&lt;br /&gt;
Preferably, all foreign letters would be added to the fonts (see [[Font Patcher]] or [[Refont]]). However, if time permits only adding a few, &#039;&#039;&#039;í&#039;&#039;&#039; would be more important than, say, &#039;&#039;&#039;ô&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
It is commonplace for missing accented letters to be redirected in the .dat file to the corresponding unaccented base letter.&lt;br /&gt;
&lt;br /&gt;
=== Coverage Expansion &amp;amp; Remaining Limitations ===&lt;br /&gt;
&lt;br /&gt;
By 2014, all the system (e.g., main menu) fonts (Carleton, Carleton_condensed, Stone in sizes 24pt and 48pt; Mason and Mason_glow in 48pt) had good coverage of the &amp;quot;Top 50&amp;quot; and beyond, although not all 256 codepoints. &lt;br /&gt;
This was confirmed more specifically in 2024, as part of an [https://forums.thedarkmod.com/index.php?/topic/22427-analysis-of-212-tdm-fonts/ Analysis of 2.12 Fonts]. This analysis indicated that, unlike the system fonts, the FM fonts generally did not provide specific glyphs beyond ASCII.&lt;br /&gt;
&lt;br /&gt;
In 2024, Stone 24pt, important for subtitles and a number of readables, was further extended to cover all 256 codepoints. This was tested with TDM 2.13[betas] and released with 2.14. Similar Stone 48pt and Carleton 24pt improvements are planned for TDM 2.15.&lt;br /&gt;
&lt;br /&gt;
[[Category:Fonts]]&lt;br /&gt;
&lt;br /&gt;
{{i18n}}&lt;/div&gt;</summary>
		<author><name>Geep</name></author>
	</entry>
	<entry>
		<id>https://wiki.thedarkmod.com/index.php?title=ExportUnicodeFontToDoom3&amp;diff=34439</id>
		<title>ExportUnicodeFontToDoom3</title>
		<link rel="alternate" type="text/html" href="https://wiki.thedarkmod.com/index.php?title=ExportUnicodeFontToDoom3&amp;diff=34439"/>
		<updated>2026-03-03T21:57:54Z</updated>

		<summary type="html">&lt;p&gt;Geep: /* Downloads */ Add 1.1 links. Also fix 1.0 source project link&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;By Geep, 2025&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
== Introduction ==&lt;br /&gt;
&lt;br /&gt;
In 2025, kalinovka in [https://forums.thedarkmod.com/index.php?/topic/22736-font-localization Font localization] sought to extend TDM’s Mason 48pt font, used in the main menu, to include missing Cyrillic glyphs. This would allow this font to be used in an FM and still support a Russian translation.&lt;br /&gt;
&lt;br /&gt;
This offshoot of [https://wiki.thedarkmod.com/index.php?title=ExportFontToDoom3 ExportFontToDoom3All256] is a generalized response to that. The main idea to select an input TTF font that includes not just ASCII or ANSI, but offers additional Unicode characters, like Cyrillic. The program still limits output to a maximum of 256 characters, consistent with the DAT format.&lt;br /&gt;
&lt;br /&gt;
To achieve this, it reads in an external human-readable &amp;quot;unicodeMap&amp;quot; file, in Unicode.org’s &amp;quot;Format A&amp;quot;. This format provides a mapping from the traditional 8-bit encoding that TDM uses to the corresponding UCS (Unicode 16-bit) value. Unicode.org provides stock files for standard ISO and Windows 8-bit encodings. Of specific interest here is [https://www.unicode.org/Public/MAPPINGS/VENDORS/MICSFT/WINDOWS/CP1251.TXT cp1251.txt for Cyrillic]. This requires just trivial editing for [https://wiki.thedarkmod.com/index.php?title=I18N_-_Charset TDM-specific codepoints]. As discussed below, you can further edit a unicodeMap file in advance, if you want to generate just a subset of glyphs.&lt;br /&gt;
&lt;br /&gt;
More broadly, this program supersedes ExportFontToDoom3 and ExportFontToDoom3All256.&lt;br /&gt;
&lt;br /&gt;
== New Command Line Arguments ==&lt;br /&gt;
&lt;br /&gt;
These are in-addition to those of [https://wiki.thedarkmod.com/index.php?title=ExportFontToDoom3 ExportFontToDoom3All256].&lt;br /&gt;
&lt;br /&gt;
=== unicodeMap &amp;lt;file&amp;gt; ===&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
 -unicodeMap &amp;quot;./Test/cp1251.txt&amp;quot;&lt;br /&gt;
&lt;br /&gt;
You can edit the unicodeMap file in advance, to specify which particular glyphs you want to generate by suppressing unwanted glyphs, either by:&lt;br /&gt;
&lt;br /&gt;
* Deleting an unwanted line (or block of lines) entirely, or&lt;br /&gt;
* Prepending a &amp;quot;#&amp;quot; to comment-out the line.&lt;br /&gt;
&lt;br /&gt;
Also, this file format allows the Unicode value (e.g., &amp;quot;0x1234&amp;quot;) to be replaced by 6 space characters, when the ISO or Windows standard leaves that character undefined.&lt;br /&gt;
&lt;br /&gt;
In all 3 of those cases, every suppressed character in the output DAT file will be represented by the glyph that the font uses for U+0000. A hollow box is common.&lt;br /&gt;
&lt;br /&gt;
=== startFileNumber &amp;lt;n&amp;gt; ===&lt;br /&gt;
When a set of TGA/DDS files are generated for a particular font size, by default the first file&#039;s name contains _0_, which increments for additional files. You can optionally specify a different 1- or 2-digit start number, e.g., &amp;quot;-startFileNumber 7&amp;quot;. Why? Because...&lt;br /&gt;
&lt;br /&gt;
* the file(s) you are generating are supplemental to, not replacements for, existing TGA/DDS files; and&lt;br /&gt;
* in this run, you are generating just one of the 3 possible font sizes (assuming each size has a different count of existing TGA/DDS files).&lt;br /&gt;
&lt;br /&gt;
When you generate a supplemental set, the new DAT file has no knowledge of what&#039;s in the original set and its DAT file. You will have to interleave-edit the old and new DAT files (e.g., with reFont&#039;s REF files) to create a single DAT file spanning old and new glyphs. There may be a redundant NULL glyph in your new TGA set; just ignore it.&lt;br /&gt;
&lt;br /&gt;
=== awayFromEdge &amp;lt;n&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
Allows specifying in positive integer pixels (e.g., &amp;quot;-awayFromEdge 2&amp;quot;) a small extra boundary at the top and left edges of the overall bitmap. This is for fonts like Mason where extra space (typically 2 pixels) is needed around every character to create a &amp;quot;glow variant&amp;quot;. Routine glyph layout provides usually enough space for this except at the top and (arguably) left edges. See also the &amp;quot;compact&amp;quot; parameter.&lt;br /&gt;
&lt;br /&gt;
Note: The spacing value is relative to 256x256 bitmaps. If you specify &amp;quot;hirez&amp;quot;, then for proportionality, your specified value is doubled internally when laying out the 512x512 bitmaps.&lt;br /&gt;
&lt;br /&gt;
=== compact ===&lt;br /&gt;
If specified (i.e, &amp;quot;-compact&amp;quot;), packs the character glyphs more closely together. Particularly recommended for 48pt fonts; it will generate roughly half the files.&lt;br /&gt;
&lt;br /&gt;
Whether &amp;quot;compact&amp;quot; is specified or not, packing is controlled by simply &amp;quot;padding&amp;quot; each glyph’s bounding box. Specifically, this doesn’t change the bounding box, but adds pixel &amp;quot;padding&amp;quot; to just the right and bottom of the bounding box, a simple though asymmetric process. One reason for padding was given ExportFontToDoom3 author Grant Davies in code comments:&lt;br /&gt;
&lt;br /&gt;
&amp;quot;Because of the way Doom 3 Indexes the texture page (using floating point numbers), it is unable to reference exact pixels – there is error. How much error, I don’t know. For this reason, the rectangles needs to be padded out.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Geep suspects that such error with the TDM engine is not really a problem. Likely some error in the past was due to editing with Q3Font and its low floating-point precision. Nevertheless, some padding is good because:&lt;br /&gt;
&lt;br /&gt;
* For the Mason font, 2 pixels around each glyph are needed for &amp;quot;glow&amp;quot; effects (either done as a separate smudge font for /english/ or as a bidirection offset effect for /russian/.)&lt;br /&gt;
* Keeping glyphs separated improves visualization of boundaries with datBounds, and makes editing tweaks easier.&lt;br /&gt;
&lt;br /&gt;
The &amp;quot;compact&amp;quot; setting restores Grant Davies&#039; first algorithm, which just pads the bounding box by 5 pixels to the right and 5 pixels below.&lt;br /&gt;
&lt;br /&gt;
Without &amp;quot;compact&amp;quot;, the default is Grant Davies&#039; second algorithm found in ExportFontToDoom3 v1.02. This likewise first pads each bounding box by 5 pixels to the right and 5 pixels below. It then further pads to make both the width and height a factor of 2; this makes 48pt quite sparse.  (It is possible this improved rendering performance in 2005; not important now. Also, in practice for major fonts, much of this &amp;quot;factor of 2&amp;quot; spacing was overridden by subsequent Font Patcher work.)&lt;br /&gt;
&lt;br /&gt;
=== hirez or hires ===&lt;br /&gt;
&#039;&#039;Added with v1.1, March 2026&#039;&#039; &lt;br /&gt;
&lt;br /&gt;
Instead of 256x256 bitmaps (and associated DAT), this exports double-sized 512x512 bitmaps with larger, thus potentially-crisper glyphs. (TDM has had a few such 512x512 bitmaps for redrawn fonts since 2014.) Specifically, it: &lt;br /&gt;
* outputs requested 512x512 TGAs and their DAT(s).&lt;br /&gt;
* internally, doubles the pointsize requested of the TTF, resulting in 2x character glyph sizes. Because both the container bitmap and each glyph is (nominally) doubled in size, the [0...1] s, s2, t, t2 values stored in the DAT would be very similar to those for a 256x256 bitmap.&lt;br /&gt;
* Other DAT layout metrics remain as if scaled to a 256x256 layout:&lt;br /&gt;
** imageHeight&lt;br /&gt;
** imageWidth&lt;br /&gt;
** skip&lt;br /&gt;
** top (with bottom ignored as usual)&lt;br /&gt;
** pitch&lt;br /&gt;
&lt;br /&gt;
For example, if you request –hirez with a carleton font in just 24pt type, it will create 512x512 files with usual names like carleton_0_24.tga, etc., and fontimage_24.dat, with the console showing “Exporting carleton 24pt”.&lt;br /&gt;
But internally, 48pt characters are drawn on the bitmaps. The imageHeight and imageWidth metrics will be as if the requested 24pt size was generated, so in effect causing the game engine to scale down by a factor of 2 from the 48pt glyph.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;TIPS on Using a HiRez DAT file&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
If subsequently using Refont to make a REF file from this DAT, add the “scaling_ok” option, to suppress otherwise voluminous console warnings about per-character scaling.&lt;br /&gt;
&lt;br /&gt;
If you further plan to generate bounds visualizations with datBounds:&lt;br /&gt;
* For 512x512 bitmaps, you must generate from the REF file, not directly from DAT.&lt;br /&gt;
* Be sure to first edit the REF to add headers of the form:&lt;br /&gt;
&lt;br /&gt;
 # bitmap_&amp;lt;n&amp;gt;_size=512&lt;br /&gt;
 &lt;br /&gt;
  , where &amp;lt;n&amp;gt; is 0 to 9, and refers to shaders present in the REF file with names like, e.g., carleton_3_48.tga; n would be 3 for this.&lt;br /&gt;
&lt;br /&gt;
* datBounds also has a worthwhile “scaling_ok” option.&lt;br /&gt;
* Uncommonly, the raw_metrics option may be of interest.&lt;br /&gt;
&lt;br /&gt;
=== bolding &amp;lt;n&amp;gt; ===&lt;br /&gt;
&#039;&#039;Added with v1.1, March 2026&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Sometimes, a TTF font does not offer a “bold” variant, or, more generally, a font’s overall stroke thickness is not ideal. It is possible to alter character outlines, then render those as bitmap glyphs.&lt;br /&gt;
The result is usually better than post-bitmap thickening or thinning. The FreeType library offers an embolding function for outline alteration, used here.&lt;br /&gt;
&lt;br /&gt;
The integer parameter &amp;lt;n&amp;gt; is in units of 1/64th pixel. A positive value adjusts the outline to embolden the character. Negative thins. The change affects both the overall height and width of the outline.&lt;br /&gt;
You may think of the left and bottom character borders as unchanged. The allowed range of &amp;lt;n&amp;gt; is from -128 (i.e., -2 pixels) to 256 (4 pixels). The -2 limit is arbitrary, but for sanity. The 4 limit is the maximum FreeType permits.&lt;br /&gt;
&lt;br /&gt;
Caution: The adjustment algorithm moves the outline controls points, but doesn&#039;t change the number of such points;&lt;br /&gt;
this means that certain situations like acute angles or intersections are sometimes handled incorrectly.&lt;br /&gt;
&lt;br /&gt;
== Changed Behavior for Font Title from ExportFontToDoom3All256 ==&lt;br /&gt;
In ExportFontToDoom3All256, if the font title was more that 20 characters long, it would truncate it to fit in the DAT file as part of the shader names (i.e., paths to TGA files). But this threshold was wrong. Now, truncation and a warning happens if the font title is more that 17 characters long (or 16 if generated TGAs include any with a 2-digit count instead of 1-digit). If truncation occurs, the user is asked to consider using or revising the -name argument.&lt;br /&gt;
&lt;br /&gt;
== Downloads ==&lt;br /&gt;
Release v1.1 of 2025-03-03:&lt;br /&gt;
* [https://drive.google.com/file/d/1f3Jj53qtJGIp0_mz7Riing9Fi8ESFDr5/view?usp=sharing ExportUnicodeFontToDoom3_release_1_1_exe.zip] . Windows binary and required archived versions of FreeType and DevIL DLLs.&lt;br /&gt;
* [https://drive.google.com/file/d/1nutMBfcIWw63wNTUdnlnzP397tGVpnpd/view?usp=sharing ExportUnicodeFontToDoom3_release_1_1_source_project.zip] . The C++ project file with source code, including source &amp;amp; build project of archived library.&lt;br /&gt;
&lt;br /&gt;
Release 1 of 2024-09-10:&lt;br /&gt;
* [https://drive.google.com/file/d/1MqoOfhc5-ovoxoHfRquYAcIEdHEOJAQV/view?usp=sharing ExportUnicodeFontToDoom3_release_1_exe.zip]&lt;br /&gt;
* [https://drive.google.com/file/d/1Frk_byfdtCcMqdr27ulw1XyuFj8vYp9x/view?usp=sharing ExportUnicodeFontToDoom3_release_1_source_project.zip]&lt;br /&gt;
&lt;br /&gt;
== See Also ==&lt;br /&gt;
The Cyrillic coverage of Lora Regular TTF font, projected to used as Russian Mason supplement in TDM 2.14, may be viewed and font downloaded [https://www.fontsquirrel.com/fonts/lora?filter%5Bclassifications%5D%5B0%5D=serif&amp;amp;filter%5Blanguages%5D%5B0%5D=cyrillic#eula here].&lt;/div&gt;</summary>
		<author><name>Geep</name></author>
	</entry>
	<entry>
		<id>https://wiki.thedarkmod.com/index.php?title=ExportUnicodeFontToDoom3&amp;diff=34438</id>
		<title>ExportUnicodeFontToDoom3</title>
		<link rel="alternate" type="text/html" href="https://wiki.thedarkmod.com/index.php?title=ExportUnicodeFontToDoom3&amp;diff=34438"/>
		<updated>2026-03-02T21:01:07Z</updated>

		<summary type="html">&lt;p&gt;Geep: Added 512x512 for awayFromEdge, hirez, bolding&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;By Geep, 2025&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
== Introduction ==&lt;br /&gt;
&lt;br /&gt;
In 2025, kalinovka in [https://forums.thedarkmod.com/index.php?/topic/22736-font-localization Font localization] sought to extend TDM’s Mason 48pt font, used in the main menu, to include missing Cyrillic glyphs. This would allow this font to be used in an FM and still support a Russian translation.&lt;br /&gt;
&lt;br /&gt;
This offshoot of [https://wiki.thedarkmod.com/index.php?title=ExportFontToDoom3 ExportFontToDoom3All256] is a generalized response to that. The main idea to select an input TTF font that includes not just ASCII or ANSI, but offers additional Unicode characters, like Cyrillic. The program still limits output to a maximum of 256 characters, consistent with the DAT format.&lt;br /&gt;
&lt;br /&gt;
To achieve this, it reads in an external human-readable &amp;quot;unicodeMap&amp;quot; file, in Unicode.org’s &amp;quot;Format A&amp;quot;. This format provides a mapping from the traditional 8-bit encoding that TDM uses to the corresponding UCS (Unicode 16-bit) value. Unicode.org provides stock files for standard ISO and Windows 8-bit encodings. Of specific interest here is [https://www.unicode.org/Public/MAPPINGS/VENDORS/MICSFT/WINDOWS/CP1251.TXT cp1251.txt for Cyrillic]. This requires just trivial editing for [https://wiki.thedarkmod.com/index.php?title=I18N_-_Charset TDM-specific codepoints]. As discussed below, you can further edit a unicodeMap file in advance, if you want to generate just a subset of glyphs.&lt;br /&gt;
&lt;br /&gt;
More broadly, this program supersedes ExportFontToDoom3 and ExportFontToDoom3All256.&lt;br /&gt;
&lt;br /&gt;
== New Command Line Arguments ==&lt;br /&gt;
&lt;br /&gt;
These are in-addition to those of [https://wiki.thedarkmod.com/index.php?title=ExportFontToDoom3 ExportFontToDoom3All256].&lt;br /&gt;
&lt;br /&gt;
=== unicodeMap &amp;lt;file&amp;gt; ===&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
 -unicodeMap &amp;quot;./Test/cp1251.txt&amp;quot;&lt;br /&gt;
&lt;br /&gt;
You can edit the unicodeMap file in advance, to specify which particular glyphs you want to generate by suppressing unwanted glyphs, either by:&lt;br /&gt;
&lt;br /&gt;
* Deleting an unwanted line (or block of lines) entirely, or&lt;br /&gt;
* Prepending a &amp;quot;#&amp;quot; to comment-out the line.&lt;br /&gt;
&lt;br /&gt;
Also, this file format allows the Unicode value (e.g., &amp;quot;0x1234&amp;quot;) to be replaced by 6 space characters, when the ISO or Windows standard leaves that character undefined.&lt;br /&gt;
&lt;br /&gt;
In all 3 of those cases, every suppressed character in the output DAT file will be represented by the glyph that the font uses for U+0000. A hollow box is common.&lt;br /&gt;
&lt;br /&gt;
=== startFileNumber &amp;lt;n&amp;gt; ===&lt;br /&gt;
When a set of TGA/DDS files are generated for a particular font size, by default the first file&#039;s name contains _0_, which increments for additional files. You can optionally specify a different 1- or 2-digit start number, e.g., &amp;quot;-startFileNumber 7&amp;quot;. Why? Because...&lt;br /&gt;
&lt;br /&gt;
* the file(s) you are generating are supplemental to, not replacements for, existing TGA/DDS files; and&lt;br /&gt;
* in this run, you are generating just one of the 3 possible font sizes (assuming each size has a different count of existing TGA/DDS files).&lt;br /&gt;
&lt;br /&gt;
When you generate a supplemental set, the new DAT file has no knowledge of what&#039;s in the original set and its DAT file. You will have to interleave-edit the old and new DAT files (e.g., with reFont&#039;s REF files) to create a single DAT file spanning old and new glyphs. There may be a redundant NULL glyph in your new TGA set; just ignore it.&lt;br /&gt;
&lt;br /&gt;
=== awayFromEdge &amp;lt;n&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
Allows specifying in positive integer pixels (e.g., &amp;quot;-awayFromEdge 2&amp;quot;) a small extra boundary at the top and left edges of the overall bitmap. This is for fonts like Mason where extra space (typically 2 pixels) is needed around every character to create a &amp;quot;glow variant&amp;quot;. Routine glyph layout provides usually enough space for this except at the top and (arguably) left edges. See also the &amp;quot;compact&amp;quot; parameter.&lt;br /&gt;
&lt;br /&gt;
Note: The spacing value is relative to 256x256 bitmaps. If you specify &amp;quot;hirez&amp;quot;, then for proportionality, your specified value is doubled internally when laying out the 512x512 bitmaps.&lt;br /&gt;
&lt;br /&gt;
=== compact ===&lt;br /&gt;
If specified (i.e, &amp;quot;-compact&amp;quot;), packs the character glyphs more closely together. Particularly recommended for 48pt fonts; it will generate roughly half the files.&lt;br /&gt;
&lt;br /&gt;
Whether &amp;quot;compact&amp;quot; is specified or not, packing is controlled by simply &amp;quot;padding&amp;quot; each glyph’s bounding box. Specifically, this doesn’t change the bounding box, but adds pixel &amp;quot;padding&amp;quot; to just the right and bottom of the bounding box, a simple though asymmetric process. One reason for padding was given ExportFontToDoom3 author Grant Davies in code comments:&lt;br /&gt;
&lt;br /&gt;
&amp;quot;Because of the way Doom 3 Indexes the texture page (using floating point numbers), it is unable to reference exact pixels – there is error. How much error, I don’t know. For this reason, the rectangles needs to be padded out.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Geep suspects that such error with the TDM engine is not really a problem. Likely some error in the past was due to editing with Q3Font and its low floating-point precision. Nevertheless, some padding is good because:&lt;br /&gt;
&lt;br /&gt;
* For the Mason font, 2 pixels around each glyph are needed for &amp;quot;glow&amp;quot; effects (either done as a separate smudge font for /english/ or as a bidirection offset effect for /russian/.)&lt;br /&gt;
* Keeping glyphs separated improves visualization of boundaries with datBounds, and makes editing tweaks easier.&lt;br /&gt;
&lt;br /&gt;
The &amp;quot;compact&amp;quot; setting restores Grant Davies&#039; first algorithm, which just pads the bounding box by 5 pixels to the right and 5 pixels below.&lt;br /&gt;
&lt;br /&gt;
Without &amp;quot;compact&amp;quot;, the default is Grant Davies&#039; second algorithm found in ExportFontToDoom3 v1.02. This likewise first pads each bounding box by 5 pixels to the right and 5 pixels below. It then further pads to make both the width and height a factor of 2; this makes 48pt quite sparse.  (It is possible this improved rendering performance in 2005; not important now. Also, in practice for major fonts, much of this &amp;quot;factor of 2&amp;quot; spacing was overridden by subsequent Font Patcher work.)&lt;br /&gt;
&lt;br /&gt;
=== hirez or hires ===&lt;br /&gt;
&#039;&#039;Added with v1.1, March 2026&#039;&#039; &lt;br /&gt;
&lt;br /&gt;
Instead of 256x256 bitmaps (and associated DAT), this exports double-sized 512x512 bitmaps with larger, thus potentially-crisper glyphs. (TDM has had a few such 512x512 bitmaps for redrawn fonts since 2014.) Specifically, it: &lt;br /&gt;
* outputs requested 512x512 TGAs and their DAT(s).&lt;br /&gt;
* internally, doubles the pointsize requested of the TTF, resulting in 2x character glyph sizes. Because both the container bitmap and each glyph is (nominally) doubled in size, the [0...1] s, s2, t, t2 values stored in the DAT would be very similar to those for a 256x256 bitmap.&lt;br /&gt;
* Other DAT layout metrics remain as if scaled to a 256x256 layout:&lt;br /&gt;
** imageHeight&lt;br /&gt;
** imageWidth&lt;br /&gt;
** skip&lt;br /&gt;
** top (with bottom ignored as usual)&lt;br /&gt;
** pitch&lt;br /&gt;
&lt;br /&gt;
For example, if you request –hirez with a carleton font in just 24pt type, it will create 512x512 files with usual names like carleton_0_24.tga, etc., and fontimage_24.dat, with the console showing “Exporting carleton 24pt”.&lt;br /&gt;
But internally, 48pt characters are drawn on the bitmaps. The imageHeight and imageWidth metrics will be as if the requested 24pt size was generated, so in effect causing the game engine to scale down by a factor of 2 from the 48pt glyph.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;TIPS on Using a HiRez DAT file&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
If subsequently using Refont to make a REF file from this DAT, add the “scaling_ok” option, to suppress otherwise voluminous console warnings about per-character scaling.&lt;br /&gt;
&lt;br /&gt;
If you further plan to generate bounds visualizations with datBounds:&lt;br /&gt;
* For 512x512 bitmaps, you must generate from the REF file, not directly from DAT.&lt;br /&gt;
* Be sure to first edit the REF to add headers of the form:&lt;br /&gt;
&lt;br /&gt;
 # bitmap_&amp;lt;n&amp;gt;_size=512&lt;br /&gt;
 &lt;br /&gt;
  , where &amp;lt;n&amp;gt; is 0 to 9, and refers to shaders present in the REF file with names like, e.g., carleton_3_48.tga; n would be 3 for this.&lt;br /&gt;
&lt;br /&gt;
* datBounds also has a worthwhile “scaling_ok” option.&lt;br /&gt;
* Uncommonly, the raw_metrics option may be of interest.&lt;br /&gt;
&lt;br /&gt;
=== bolding &amp;lt;n&amp;gt; ===&lt;br /&gt;
&#039;&#039;Added with v1.1, March 2026&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Sometimes, a TTF font does not offer a “bold” variant, or, more generally, a font’s overall stroke thickness is not ideal. It is possible to alter character outlines, then render those as bitmap glyphs.&lt;br /&gt;
The result is usually better than post-bitmap thickening or thinning. The FreeType library offers an embolding function for outline alteration, used here.&lt;br /&gt;
&lt;br /&gt;
The integer parameter &amp;lt;n&amp;gt; is in units of 1/64th pixel. A positive value adjusts the outline to embolden the character. Negative thins. The change affects both the overall height and width of the outline.&lt;br /&gt;
You may think of the left and bottom character borders as unchanged. The allowed range of &amp;lt;n&amp;gt; is from -128 (i.e., -2 pixels) to 256 (4 pixels). The -2 limit is arbitrary, but for sanity. The 4 limit is the maximum FreeType permits.&lt;br /&gt;
&lt;br /&gt;
Caution: The adjustment algorithm moves the outline controls points, but doesn&#039;t change the number of such points;&lt;br /&gt;
this means that certain situations like acute angles or intersections are sometimes handled incorrectly.&lt;br /&gt;
&lt;br /&gt;
== Changed Behavior for Font Title from ExportFontToDoom3All256 ==&lt;br /&gt;
In ExportFontToDoom3All256, if the font title was more that 20 characters long, it would truncate it to fit in the DAT file as part of the shader names (i.e., paths to TGA files). But this threshold was wrong. Now, truncation and a warning happens if the font title is more that 17 characters long (or 16 if generated TGAs include any with a 2-digit count instead of 1-digit). If truncation occurs, the user is asked to consider using or revising the -name argument.&lt;br /&gt;
&lt;br /&gt;
== Downloads ==&lt;br /&gt;
[COMING SOON - v1.1]&lt;br /&gt;
&lt;br /&gt;
Release 1 of 2024-09-10:&lt;br /&gt;
* [https://drive.google.com/file/d/1MqoOfhc5-ovoxoHfRquYAcIEdHEOJAQV/view?usp=sharing ExportUnicodeFontToDoom3_release_1_exe.zip] . Windows binary and required archived versions of FreeType and DevIL DLLs.&lt;br /&gt;
* [https://drive.google.com/file/d/1Frk_byfdtCcMqdr27ulw1XyuFj8vYp9x/view?usp=sharing ExportUnicodeFontToDoom3_release_1_source_project.zip] . The C++ project file with source code, including source &amp;amp; build project of archived library.&lt;br /&gt;
&lt;br /&gt;
The Cyrillic coverage of Lora Regular TTF font, projected to used as Russian Mason supplement in TDM 2.14, may be viewed and font downloaded [https://www.fontsquirrel.com/fonts/lora?filter%5Bclassifications%5D%5B0%5D=serif&amp;amp;filter%5Blanguages%5D%5B0%5D=cyrillic#eula here].&lt;/div&gt;</summary>
		<author><name>Geep</name></author>
	</entry>
	<entry>
		<id>https://wiki.thedarkmod.com/index.php?title=Rebuild_all_lang_Program&amp;diff=34430</id>
		<title>Rebuild all lang Program</title>
		<link rel="alternate" type="text/html" href="https://wiki.thedarkmod.com/index.php?title=Rebuild_all_lang_Program&amp;diff=34430"/>
		<updated>2026-02-14T16:15:29Z</updated>

		<summary type="html">&lt;p&gt;Geep: /* Downloads */ Update contents of rebuilt_all_lang.zip to include LICENSE.txt&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;by Geep, 2026&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
==== Introduction ====&lt;br /&gt;
Ordinarily, an FM that has been internationalized has a UTF8 &amp;quot;all.lang&amp;quot; text file, from which &amp;quot;*.lang&amp;quot; files in various 8-bit ISO-8859-x (or Windows) encodings were generated and distributed within the &amp;quot;strings&amp;quot; folder.&lt;br /&gt;
&lt;br /&gt;
Sometimes, an attempt is made to improve translations, or extend them to additional languages. The ideal way is to alter content in all.lang, then regenerate the *.lang files (e.g., with gen_lang_plus). This regeneration could be for every language section specified in all.lang, or more selectively, just the ones for languages newly added or with changed content.&lt;br /&gt;
&lt;br /&gt;
Suppose &amp;quot;all.lang&amp;quot; was not distributed with the FM. The original FM author may be able to provide it, or you can ask about it being in some TDM SVN repo.&lt;br /&gt;
&lt;br /&gt;
If those routes fail, you can fabricate a replacement all.lang from the *.lang files. Note that the latter are stripped of most helpful comments, including grouping header lines, often found in the original all.lang. So this approach is driven by necessity.&lt;br /&gt;
&lt;br /&gt;
One way that fabrication can be done is first make a new partial all.lang from the existing english.lang file (which being in ASCII, can be viewed as also UTF8), Then add new language sections in UTF8 form. Regenerate just those *.lang files, while retaining older unchanged *.lang files. Each new UTF8 language section can be -&lt;br /&gt;
* typed from scratch, while consulting the ISO-8859-x version.&lt;br /&gt;
* possibly generated using some third-party ISO to UTF8 translator tool.&lt;br /&gt;
&lt;br /&gt;
Or, as a convenience, use &#039;&#039;&#039;rebuild_all_lang&#039;&#039;&#039;. When run from within a give folder (e.g., &amp;quot;strings&amp;quot;), it will take every *.lang it finds (starting with english.lang), convert it from that language&#039;s ISO to UTF8, and basically glue them together into the required form.&lt;br /&gt;
&lt;br /&gt;
==== Usage and Example ====&lt;br /&gt;
The Windows command-line program rebuild_all_lang is a simple C++ utility that takes no parameters, and if successful generates &amp;quot;all.lang&amp;quot; in the current directory. Control it by -&lt;br /&gt;
* deciding in advance which *.lang files are the current directory&lt;br /&gt;
* if you want the generated file to embed a preamble, you can provide it as a file named &amp;quot;preamble_utf8.txt&amp;quot; in the same directory. This is optional. As examples, the program distribution includes 2 typical stock preambles.&lt;br /&gt;
&lt;br /&gt;
A typical output to console is:&lt;br /&gt;
&lt;br /&gt;
 Running rebuild_all_lang, v. 1.0&lt;br /&gt;
 Note: Did not find an optional preamble file preamble_utf8.txt&lt;br /&gt;
 Processing...&lt;br /&gt;
 English&lt;br /&gt;
 German&lt;br /&gt;
 French&lt;br /&gt;
 Italian&lt;br /&gt;
 Spanish&lt;br /&gt;
 Polish&lt;br /&gt;
 Romanian&lt;br /&gt;
 Russian&lt;br /&gt;
 Portuguese&lt;br /&gt;
 Czech&lt;br /&gt;
 Hungarian&lt;br /&gt;
 Slovak&lt;br /&gt;
 Swedish&lt;br /&gt;
 Danish&lt;br /&gt;
 Dutch&lt;br /&gt;
 Turkish&lt;br /&gt;
 Catalan&lt;br /&gt;
 Contents of *.lang files were converted successfully to UTF-8 and merged into new &#039;all.lang&#039;.&lt;br /&gt;
&lt;br /&gt;
Languages are &#039;&#039;always&#039;&#039; processed in the order shown. If a particular *.lang is missing, that is merely mentioned to the console, and that section is not added to all.lang.&lt;br /&gt;
&lt;br /&gt;
At the start of all.lang, typical text is...&lt;br /&gt;
&lt;br /&gt;
 // Rebuilt all.lang file - created by rebuild_all_lang v. 1.0&lt;br /&gt;
 // Strings in each section in same order as in *.lang, but converted from various iso-8859s encodings to UTF8.&lt;br /&gt;
 &lt;br /&gt;
 // Note - did not find an optional file preamble_utf8.txt with preamble comments to place here.&lt;br /&gt;
 &lt;br /&gt;
 {&lt;br /&gt;
 [English]&lt;br /&gt;
 // Sourced from english.lang of 2025-07-16T16:08:26+00:00, whose first line was...&lt;br /&gt;
 // String table - english (iso-8859-1) - created on 2025-07-16T16:08:26Z with gen_lang_plus v. 1.1&lt;br /&gt;
 	&amp;quot;#str_fm_airpocket_xd_sheet_appointment_to_service_pg1__title&amp;quot;	&amp;quot;Appointment to Service\n&amp;quot;&lt;br /&gt;
 	....&lt;br /&gt;
&lt;br /&gt;
Within each language section - like [English] here - some variant of the first two commented lines are always generated. As you see, the &amp;quot;// Sourced from...&amp;quot; line is followed by the first line copied from the *.lang file. In this example, the comments show the external file modification datetime, and then the datetime written at generation time. The latter will not always be present, depending upon creation method.&lt;br /&gt;
&lt;br /&gt;
==== Details ====&lt;br /&gt;
As required, the generated all.lang text file has Linux linebreaks (e.g., LF instead of CRFL), independent of linebreak form in input files *.lang or preamble_UTF8.txt&lt;br /&gt;
&lt;br /&gt;
If all.lang already exists, you will see...&lt;br /&gt;
&lt;br /&gt;
 Running rebuild_all_lang, v. 1.0&lt;br /&gt;
 File &#039;all.lang&#039; already exists.&lt;br /&gt;
 Continue and overwrite it? [y/n]&lt;br /&gt;
&lt;br /&gt;
If you indicate &amp;quot;n&amp;quot; for &amp;quot;no&amp;quot;, the program quits with message &amp;quot;Bye&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
This program has some minimal file I/O and conversion error checking, with reporting to console. It is not thought necessary to do character-level checking of the UTF8 results against characters supported by TDM&#039;s character map... such checking is better done elsewhere. This is a simple program. (One could imagine a more elaborate version that would, say, allow english.lang to be annotated with comments (e.g., to group lines into subsections). And then reorder lines within the non-English language sections to match, embedding those same annotations.)&lt;br /&gt;
&lt;br /&gt;
Within each of the source *.lang files, comments take only two forms:&lt;br /&gt;
* as a preamble; as discussed above, the first line is harvested, the rest ignored.&lt;br /&gt;
* as trailing &amp;quot;// ...&amp;quot; at the ends of lines. These will be propagated to the corresponding lines of the rebuilt all.lang. (These will be treated as in the same 8-bit language encoding as the rest of the text in the block. Because all supported encodings include ASCII, English comments will be preserved.)&lt;br /&gt;
&lt;br /&gt;
==== Downloads ====&lt;br /&gt;
v 1.1 [Recommended]. This upgrades to a non-deprecated interface to Windows 10/11&#039;s built-in encoding support, and adds custom code to fix 1.0&#039;s problem with [Romanian]. It was roundtrip tested against AirPocket&#039;s new all.lang. See the release notes in the .cpp file for details.&lt;br /&gt;
* [https://drive.google.com/file/d/1j7941Sjy969XZvKEkHuHxs2Ikz5DVp46/view?usp=sharing Windows executable rebuild_all_lang.exe]&lt;br /&gt;
* [https://drive.google.com/file/d/178UsLBFpPPce6N-LPwSrG84VRGeLO35i/view?usp=sharing rebuilt_all_lang_1_1.zip - source code: a .cpp and .sln file]&lt;br /&gt;
&lt;br /&gt;
v 1.0 Source Code: This C++ v20 program was developed under Windows 11 with VS 2022 Community Edition (updated through 2025).&lt;br /&gt;
* [https://drive.google.com/file/d/1kKunDZfVcolZgU4xMsYIpWc5VQgjd3-_/view?usp=sharing Windows executable rebuild_all_lang.exe]&lt;br /&gt;
* [https://drive.google.com/file/d/1sNbWZRznhmgUeGJR8GXK6uiMGAstTusY/view?usp=sharing rebuilt_all_lang.zip - source code], consisting of a .cpp, .sln, and open-source license file.&lt;br /&gt;
&lt;br /&gt;
Example preamble files (rename to preamble_utf8.txt to use):&lt;br /&gt;
* [https://drive.google.com/file/d/1bOWXv8Ju1DktaNYe2M8Bo-V7zAg2bNJ9/view?usp=sharing preamble_utf8[traditional&amp;lt;nowiki&amp;gt;]&amp;lt;/nowiki&amp;gt;.txt]&lt;br /&gt;
* [https://drive.google.com/file/d/1QKJvG6FoAzuI7njO5fnOQCgwbXQdWqQe/view?usp=sharing preamble_utf8[modern for FM&amp;lt;nowiki&amp;gt;]&amp;lt;/nowiki&amp;gt;.txt]&lt;br /&gt;
&lt;br /&gt;
==== See Also ====&lt;br /&gt;
* [[Gen_Lang_Programs]]&lt;br /&gt;
&lt;br /&gt;
{{i18n}} {{editing}}&lt;/div&gt;</summary>
		<author><name>Geep</name></author>
	</entry>
	<entry>
		<id>https://wiki.thedarkmod.com/index.php?title=Rebuild_all_lang_Program&amp;diff=34426</id>
		<title>Rebuild all lang Program</title>
		<link rel="alternate" type="text/html" href="https://wiki.thedarkmod.com/index.php?title=Rebuild_all_lang_Program&amp;diff=34426"/>
		<updated>2026-02-01T20:42:37Z</updated>

		<summary type="html">&lt;p&gt;Geep: /* Downloads */ links to 1.1 distribution&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;by Geep, 2026&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
==== Introduction ====&lt;br /&gt;
Ordinarily, an FM that has been internationalized has a UTF8 &amp;quot;all.lang&amp;quot; text file, from which &amp;quot;*.lang&amp;quot; files in various 8-bit ISO-8859-x (or Windows) encodings were generated and distributed within the &amp;quot;strings&amp;quot; folder.&lt;br /&gt;
&lt;br /&gt;
Sometimes, an attempt is made to improve translations, or extend them to additional languages. The ideal way is to alter content in all.lang, then regenerate the *.lang files (e.g., with gen_lang_plus). This regeneration could be for every language section specified in all.lang, or more selectively, just the ones for languages newly added or with changed content.&lt;br /&gt;
&lt;br /&gt;
Suppose &amp;quot;all.lang&amp;quot; was not distributed with the FM. The original FM author may be able to provide it, or you can ask about it being in some TDM SVN repo.&lt;br /&gt;
&lt;br /&gt;
If those routes fail, you can fabricate a replacement all.lang from the *.lang files. Note that the latter are stripped of most helpful comments, including grouping header lines, often found in the original all.lang. So this approach is driven by necessity.&lt;br /&gt;
&lt;br /&gt;
One way that fabrication can be done is first make a new partial all.lang from the existing english.lang file (which being in ASCII, can be viewed as also UTF8), Then add new language sections in UTF8 form. Regenerate just those *.lang files, while retaining older unchanged *.lang files. Each new UTF8 language section can be -&lt;br /&gt;
* typed from scratch, while consulting the ISO-8859-x version.&lt;br /&gt;
* possibly generated using some third-party ISO to UTF8 translator tool.&lt;br /&gt;
&lt;br /&gt;
Or, as a convenience, use &#039;&#039;&#039;rebuild_all_lang&#039;&#039;&#039;. When run from within a give folder (e.g., &amp;quot;strings&amp;quot;), it will take every *.lang it finds (starting with english.lang), convert it from that language&#039;s ISO to UTF8, and basically glue them together into the required form.&lt;br /&gt;
&lt;br /&gt;
==== Usage and Example ====&lt;br /&gt;
The Windows command-line program rebuild_all_lang is a simple C++ utility that takes no parameters, and if successful generates &amp;quot;all.lang&amp;quot; in the current directory. Control it by -&lt;br /&gt;
* deciding in advance which *.lang files are the current directory&lt;br /&gt;
* if you want the generated file to embed a preamble, you can provide it as a file named &amp;quot;preamble_utf8.txt&amp;quot; in the same directory. This is optional. As examples, the program distribution includes 2 typical stock preambles.&lt;br /&gt;
&lt;br /&gt;
A typical output to console is:&lt;br /&gt;
&lt;br /&gt;
 Running rebuild_all_lang, v. 1.0&lt;br /&gt;
 Note: Did not find an optional preamble file preamble_utf8.txt&lt;br /&gt;
 Processing...&lt;br /&gt;
 English&lt;br /&gt;
 German&lt;br /&gt;
 French&lt;br /&gt;
 Italian&lt;br /&gt;
 Spanish&lt;br /&gt;
 Polish&lt;br /&gt;
 Romanian&lt;br /&gt;
 Russian&lt;br /&gt;
 Portuguese&lt;br /&gt;
 Czech&lt;br /&gt;
 Hungarian&lt;br /&gt;
 Slovak&lt;br /&gt;
 Swedish&lt;br /&gt;
 Danish&lt;br /&gt;
 Dutch&lt;br /&gt;
 Turkish&lt;br /&gt;
 Catalan&lt;br /&gt;
 Contents of *.lang files were converted successfully to UTF-8 and merged into new &#039;all.lang&#039;.&lt;br /&gt;
&lt;br /&gt;
Languages are &#039;&#039;always&#039;&#039; processed in the order shown. If a particular *.lang is missing, that is merely mentioned to the console, and that section is not added to all.lang.&lt;br /&gt;
&lt;br /&gt;
At the start of all.lang, typical text is...&lt;br /&gt;
&lt;br /&gt;
 // Rebuilt all.lang file - created by rebuild_all_lang v. 1.0&lt;br /&gt;
 // Strings in each section in same order as in *.lang, but converted from various iso-8859s encodings to UTF8.&lt;br /&gt;
 &lt;br /&gt;
 // Note - did not find an optional file preamble_utf8.txt with preamble comments to place here.&lt;br /&gt;
 &lt;br /&gt;
 {&lt;br /&gt;
 [English]&lt;br /&gt;
 // Sourced from english.lang of 2025-07-16T16:08:26+00:00, whose first line was...&lt;br /&gt;
 // String table - english (iso-8859-1) - created on 2025-07-16T16:08:26Z with gen_lang_plus v. 1.1&lt;br /&gt;
 	&amp;quot;#str_fm_airpocket_xd_sheet_appointment_to_service_pg1__title&amp;quot;	&amp;quot;Appointment to Service\n&amp;quot;&lt;br /&gt;
 	....&lt;br /&gt;
&lt;br /&gt;
Within each language section - like [English] here - some variant of the first two commented lines are always generated. As you see, the &amp;quot;// Sourced from...&amp;quot; line is followed by the first line copied from the *.lang file. In this example, the comments show the external file modification datetime, and then the datetime written at generation time. The latter will not always be present, depending upon creation method.&lt;br /&gt;
&lt;br /&gt;
==== Details ====&lt;br /&gt;
As required, the generated all.lang text file has Linux linebreaks (e.g., LF instead of CRFL), independent of linebreak form in input files *.lang or preamble_UTF8.txt&lt;br /&gt;
&lt;br /&gt;
If all.lang already exists, you will see...&lt;br /&gt;
&lt;br /&gt;
 Running rebuild_all_lang, v. 1.0&lt;br /&gt;
 File &#039;all.lang&#039; already exists.&lt;br /&gt;
 Continue and overwrite it? [y/n]&lt;br /&gt;
&lt;br /&gt;
If you indicate &amp;quot;n&amp;quot; for &amp;quot;no&amp;quot;, the program quits with message &amp;quot;Bye&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
This program has some minimal file I/O and conversion error checking, with reporting to console. It is not thought necessary to do character-level checking of the UTF8 results against characters supported by TDM&#039;s character map... such checking is better done elsewhere. This is a simple program. (One could imagine a more elaborate version that would, say, allow english.lang to be annotated with comments (e.g., to group lines into subsections). And then reorder lines within the non-English language sections to match, embedding those same annotations.)&lt;br /&gt;
&lt;br /&gt;
Within each of the source *.lang files, comments take only two forms:&lt;br /&gt;
* as a preamble; as discussed above, the first line is harvested, the rest ignored.&lt;br /&gt;
* as trailing &amp;quot;// ...&amp;quot; at the ends of lines. These will be propagated to the corresponding lines of the rebuilt all.lang. (These will be treated as in the same 8-bit language encoding as the rest of the text in the block. Because all supported encodings include ASCII, English comments will be preserved.)&lt;br /&gt;
&lt;br /&gt;
==== Downloads ====&lt;br /&gt;
v 1.1 [Recommended]. This upgrades to a non-deprecated interface to Windows 10/11&#039;s built-in encoding support, and adds custom code to fix 1.0&#039;s problem with [Romanian]. It was roundtrip tested against AirPocket&#039;s new all.lang. See the release notes in the .cpp file for details.&lt;br /&gt;
* [https://drive.google.com/file/d/1j7941Sjy969XZvKEkHuHxs2Ikz5DVp46/view?usp=sharing Windows executable rebuild_all_lang.exe]&lt;br /&gt;
* [https://drive.google.com/file/d/178UsLBFpPPce6N-LPwSrG84VRGeLO35i/view?usp=sharing rebuilt_all_lang_1_1.zip - source code: a .cpp and .sln file]&lt;br /&gt;
&lt;br /&gt;
v 1.0 Source Code: This C++ v20 program was developed under Windows 11 with VS 2022 Community Edition (updated through 2025).&lt;br /&gt;
* [https://drive.google.com/file/d/1kKunDZfVcolZgU4xMsYIpWc5VQgjd3-_/view?usp=sharing Windows executable rebuild_all_lang.exe]&lt;br /&gt;
* [https://drive.google.com/file/d/1sNbWZRznhmgUeGJR8GXK6uiMGAstTusY/view?usp=sharing rebuilt_all_lang.zip - source code: a .cpp and .sln file]&lt;br /&gt;
&lt;br /&gt;
Example preamble files (rename to preamble_utf8.txt to use):&lt;br /&gt;
* [https://drive.google.com/file/d/1bOWXv8Ju1DktaNYe2M8Bo-V7zAg2bNJ9/view?usp=sharing preamble_utf8[traditional&amp;lt;nowiki&amp;gt;]&amp;lt;/nowiki&amp;gt;.txt]&lt;br /&gt;
* [https://drive.google.com/file/d/1QKJvG6FoAzuI7njO5fnOQCgwbXQdWqQe/view?usp=sharing preamble_utf8[modern for FM&amp;lt;nowiki&amp;gt;]&amp;lt;/nowiki&amp;gt;.txt]&lt;br /&gt;
&lt;br /&gt;
==== See Also ====&lt;br /&gt;
* [[Gen_Lang_Programs]]&lt;br /&gt;
&lt;br /&gt;
{{i18n}} {{editing}}&lt;/div&gt;</summary>
		<author><name>Geep</name></author>
	</entry>
	<entry>
		<id>https://wiki.thedarkmod.com/index.php?title=Rebuild_all_lang_Program&amp;diff=34425</id>
		<title>Rebuild all lang Program</title>
		<link rel="alternate" type="text/html" href="https://wiki.thedarkmod.com/index.php?title=Rebuild_all_lang_Program&amp;diff=34425"/>
		<updated>2026-02-01T20:38:54Z</updated>

		<summary type="html">&lt;p&gt;Geep: Update for v 1.1&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;by Geep, 2026&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
==== Introduction ====&lt;br /&gt;
Ordinarily, an FM that has been internationalized has a UTF8 &amp;quot;all.lang&amp;quot; text file, from which &amp;quot;*.lang&amp;quot; files in various 8-bit ISO-8859-x (or Windows) encodings were generated and distributed within the &amp;quot;strings&amp;quot; folder.&lt;br /&gt;
&lt;br /&gt;
Sometimes, an attempt is made to improve translations, or extend them to additional languages. The ideal way is to alter content in all.lang, then regenerate the *.lang files (e.g., with gen_lang_plus). This regeneration could be for every language section specified in all.lang, or more selectively, just the ones for languages newly added or with changed content.&lt;br /&gt;
&lt;br /&gt;
Suppose &amp;quot;all.lang&amp;quot; was not distributed with the FM. The original FM author may be able to provide it, or you can ask about it being in some TDM SVN repo.&lt;br /&gt;
&lt;br /&gt;
If those routes fail, you can fabricate a replacement all.lang from the *.lang files. Note that the latter are stripped of most helpful comments, including grouping header lines, often found in the original all.lang. So this approach is driven by necessity.&lt;br /&gt;
&lt;br /&gt;
One way that fabrication can be done is first make a new partial all.lang from the existing english.lang file (which being in ASCII, can be viewed as also UTF8), Then add new language sections in UTF8 form. Regenerate just those *.lang files, while retaining older unchanged *.lang files. Each new UTF8 language section can be -&lt;br /&gt;
* typed from scratch, while consulting the ISO-8859-x version.&lt;br /&gt;
* possibly generated using some third-party ISO to UTF8 translator tool.&lt;br /&gt;
&lt;br /&gt;
Or, as a convenience, use &#039;&#039;&#039;rebuild_all_lang&#039;&#039;&#039;. When run from within a give folder (e.g., &amp;quot;strings&amp;quot;), it will take every *.lang it finds (starting with english.lang), convert it from that language&#039;s ISO to UTF8, and basically glue them together into the required form.&lt;br /&gt;
&lt;br /&gt;
==== Usage and Example ====&lt;br /&gt;
The Windows command-line program rebuild_all_lang is a simple C++ utility that takes no parameters, and if successful generates &amp;quot;all.lang&amp;quot; in the current directory. Control it by -&lt;br /&gt;
* deciding in advance which *.lang files are the current directory&lt;br /&gt;
* if you want the generated file to embed a preamble, you can provide it as a file named &amp;quot;preamble_utf8.txt&amp;quot; in the same directory. This is optional. As examples, the program distribution includes 2 typical stock preambles.&lt;br /&gt;
&lt;br /&gt;
A typical output to console is:&lt;br /&gt;
&lt;br /&gt;
 Running rebuild_all_lang, v. 1.0&lt;br /&gt;
 Note: Did not find an optional preamble file preamble_utf8.txt&lt;br /&gt;
 Processing...&lt;br /&gt;
 English&lt;br /&gt;
 German&lt;br /&gt;
 French&lt;br /&gt;
 Italian&lt;br /&gt;
 Spanish&lt;br /&gt;
 Polish&lt;br /&gt;
 Romanian&lt;br /&gt;
 Russian&lt;br /&gt;
 Portuguese&lt;br /&gt;
 Czech&lt;br /&gt;
 Hungarian&lt;br /&gt;
 Slovak&lt;br /&gt;
 Swedish&lt;br /&gt;
 Danish&lt;br /&gt;
 Dutch&lt;br /&gt;
 Turkish&lt;br /&gt;
 Catalan&lt;br /&gt;
 Contents of *.lang files were converted successfully to UTF-8 and merged into new &#039;all.lang&#039;.&lt;br /&gt;
&lt;br /&gt;
Languages are &#039;&#039;always&#039;&#039; processed in the order shown. If a particular *.lang is missing, that is merely mentioned to the console, and that section is not added to all.lang.&lt;br /&gt;
&lt;br /&gt;
At the start of all.lang, typical text is...&lt;br /&gt;
&lt;br /&gt;
 // Rebuilt all.lang file - created by rebuild_all_lang v. 1.0&lt;br /&gt;
 // Strings in each section in same order as in *.lang, but converted from various iso-8859s encodings to UTF8.&lt;br /&gt;
 &lt;br /&gt;
 // Note - did not find an optional file preamble_utf8.txt with preamble comments to place here.&lt;br /&gt;
 &lt;br /&gt;
 {&lt;br /&gt;
 [English]&lt;br /&gt;
 // Sourced from english.lang of 2025-07-16T16:08:26+00:00, whose first line was...&lt;br /&gt;
 // String table - english (iso-8859-1) - created on 2025-07-16T16:08:26Z with gen_lang_plus v. 1.1&lt;br /&gt;
 	&amp;quot;#str_fm_airpocket_xd_sheet_appointment_to_service_pg1__title&amp;quot;	&amp;quot;Appointment to Service\n&amp;quot;&lt;br /&gt;
 	....&lt;br /&gt;
&lt;br /&gt;
Within each language section - like [English] here - some variant of the first two commented lines are always generated. As you see, the &amp;quot;// Sourced from...&amp;quot; line is followed by the first line copied from the *.lang file. In this example, the comments show the external file modification datetime, and then the datetime written at generation time. The latter will not always be present, depending upon creation method.&lt;br /&gt;
&lt;br /&gt;
==== Details ====&lt;br /&gt;
As required, the generated all.lang text file has Linux linebreaks (e.g., LF instead of CRFL), independent of linebreak form in input files *.lang or preamble_UTF8.txt&lt;br /&gt;
&lt;br /&gt;
If all.lang already exists, you will see...&lt;br /&gt;
&lt;br /&gt;
 Running rebuild_all_lang, v. 1.0&lt;br /&gt;
 File &#039;all.lang&#039; already exists.&lt;br /&gt;
 Continue and overwrite it? [y/n]&lt;br /&gt;
&lt;br /&gt;
If you indicate &amp;quot;n&amp;quot; for &amp;quot;no&amp;quot;, the program quits with message &amp;quot;Bye&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
This program has some minimal file I/O and conversion error checking, with reporting to console. It is not thought necessary to do character-level checking of the UTF8 results against characters supported by TDM&#039;s character map... such checking is better done elsewhere. This is a simple program. (One could imagine a more elaborate version that would, say, allow english.lang to be annotated with comments (e.g., to group lines into subsections). And then reorder lines within the non-English language sections to match, embedding those same annotations.)&lt;br /&gt;
&lt;br /&gt;
Within each of the source *.lang files, comments take only two forms:&lt;br /&gt;
* as a preamble; as discussed above, the first line is harvested, the rest ignored.&lt;br /&gt;
* as trailing &amp;quot;// ...&amp;quot; at the ends of lines. These will be propagated to the corresponding lines of the rebuilt all.lang. (These will be treated as in the same 8-bit language encoding as the rest of the text in the block. Because all supported encodings include ASCII, English comments will be preserved.)&lt;br /&gt;
&lt;br /&gt;
==== Downloads ====&lt;br /&gt;
v 1.1 [Recommended]. This upgrades to a non-deprecated interface to Windows 10/11&#039;s built-in encoding support, and adds custom code to fix 1.0&#039;s problem with [Romanian]. It was roundtrip tested against AirPocket&#039;s new all.lang. See the release notes in the .cpp file for details.&lt;br /&gt;
* [https://drive.google.com/file/d/1kKunDZfVcolZgU4xMsYIpWc5VQgjd3-_/view?usp=sharing Windows executable rebuild_all_lang.exe]&lt;br /&gt;
* [https://drive.google.com/file/d/1sNbWZRznhmgUeGJR8GXK6uiMGAstTusY/view?usp=sharing rebuilt_all_lang.zip - source code: a .cpp and .sln file]&lt;br /&gt;
&lt;br /&gt;
v 1.0 Source Code: This C++ v20 program was developed under Windows 11 with VS 2022 Community Edition (updated through 2025).&lt;br /&gt;
* [https://drive.google.com/file/d/1kKunDZfVcolZgU4xMsYIpWc5VQgjd3-_/view?usp=sharing Windows executable rebuild_all_lang.exe]&lt;br /&gt;
* [https://drive.google.com/file/d/1sNbWZRznhmgUeGJR8GXK6uiMGAstTusY/view?usp=sharing rebuilt_all_lang.zip - source code: a .cpp and .sln file]&lt;br /&gt;
&lt;br /&gt;
Example preamble files (rename to preamble_utf8.txt to use):&lt;br /&gt;
* [https://drive.google.com/file/d/1bOWXv8Ju1DktaNYe2M8Bo-V7zAg2bNJ9/view?usp=sharing preamble_utf8[traditional&amp;lt;nowiki&amp;gt;]&amp;lt;/nowiki&amp;gt;.txt]&lt;br /&gt;
* [https://drive.google.com/file/d/1QKJvG6FoAzuI7njO5fnOQCgwbXQdWqQe/view?usp=sharing preamble_utf8[modern for FM&amp;lt;nowiki&amp;gt;]&amp;lt;/nowiki&amp;gt;.txt]&lt;br /&gt;
==== See Also ====&lt;br /&gt;
* [[Gen_Lang_Programs]]&lt;br /&gt;
&lt;br /&gt;
{{i18n}} {{editing}}&lt;/div&gt;</summary>
		<author><name>Geep</name></author>
	</entry>
	<entry>
		<id>https://wiki.thedarkmod.com/index.php?title=CBinaryFrobMover&amp;diff=34423</id>
		<title>CBinaryFrobMover</title>
		<link rel="alternate" type="text/html" href="https://wiki.thedarkmod.com/index.php?title=CBinaryFrobMover&amp;diff=34423"/>
		<updated>2026-01-27T16:08:20Z</updated>

		<summary type="html">&lt;p&gt;Geep: /* Spawnargs */ lock_picktype can&amp;#039;t use *&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== CBinaryFrobMover ==&lt;br /&gt;
The corresponding entityDef is &#039;&#039;&#039;atdm:mover_binarymover_base&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This is the base class for all kind of TDM movers like doors, levers and buttons. The class is designed for movers with two final states, namely open and closed. &amp;quot;Open&amp;quot; and &amp;quot;closed&amp;quot; are abstract definitions and just refer to the &amp;quot;one&amp;quot; and the &amp;quot;other&amp;quot; state of the mover. All movers are considered to spawn &amp;quot;closed&amp;quot;, until specifically specified otherwise. &lt;br /&gt;
&lt;br /&gt;
The class provides a set of virtual C++ methods which can be specialised by their subclasses to implement the correct behaviour. It also supports a number if spawnargs which allow for easy customisation right in the editor.&lt;br /&gt;
&lt;br /&gt;
=== Spawnargs ===&lt;br /&gt;
* &#039;&#039;&#039;rotate&#039;&#039;&#039;: (angles) Describes the angles (pitch, yaw, roll) the mover will rotate from its closed to its open position (default is: &amp;quot;90 0 0&amp;quot;).&lt;br /&gt;
* &#039;&#039;&#039;translate&#039;&#039;&#039;: (vector) Describes the relative movement of the origin from the closed position to the open position (default is &amp;quot;0 0 0&amp;quot; = no movement). &lt;br /&gt;
* &#039;&#039;&#039;translate_speed&#039;&#039;&#039;: (float) Is the linear velocity in units per second (defaults to &amp;quot;0&amp;quot;, which means that the idMover&#039;s &amp;quot;move_time&amp;quot; value is in effect).&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;open&#039;&#039;&#039;: (1/0) Specifies whether this frobmover spawns at the open position. Can be used to let doors be open right at map start (default is &amp;quot;0&amp;quot;).&lt;br /&gt;
* &#039;&#039;&#039;locked&#039;&#039;&#039;: (1/0) Specifies whether this frobmover is locked (default is &amp;quot;0&amp;quot;).&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;pickable&#039;&#039;&#039; (1/0) If set to 1, is pickable by the player&#039;s lockpicks.&lt;br /&gt;
* &#039;&#039;&#039;lock_picktype&#039;&#039;&#039; (string) This is a sequence of characters defining the lockpick types which need to be used on this door. For instance, &#039;ts&#039; means that the player must use the &amp;quot;triangle&amp;quot; lockpick (&#039;t&#039;) and the &amp;quot;snake&amp;quot; lockpick (&#039;s&#039;) - in this order - to pick this lock. [At one time, it was said that it&#039;s also possible to define a star &amp;quot;*&amp;quot;, which matches all lockpick types. Doesn&#039;t work now.]&lt;br /&gt;
* &#039;&#039;&#039;lock_pins&#039;&#039;&#039; (string) Defines the number of samples per pin to be created for this lock, example: &amp;quot;56&amp;quot; will create two patterns, one with 5 samples, the other with 6 samples. The minimum is 5.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;open_on_unlock&#039;&#039;&#039;: (1/0) When set to 1, the mover will automatically open when unlocked.&lt;br /&gt;
* &#039;&#039;&#039;interruptable&#039;&#039;&#039;: (1/0) When set to 1, the mover can be stopped by frobbing it while moving. Doors are interruptable by default, whereas levers are not.&lt;br /&gt;
* &#039;&#039;&#039;stop_when_blocked&#039;&#039;&#039;: (1/0) Set stop_when_blocked to 0 to let this entity keep moving after the blocking entity is out of the way. Default is &amp;quot;1&amp;quot;.&lt;br /&gt;
* &#039;&#039;&#039;push_player&#039;&#039;&#039;: (1/0) Set this to 1 to let this entity push the player (default is 0). Note: belongs to idMover class.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;start_rotate&#039;&#039;&#039;: (Angles) Defines the angles (pitch, yaw, roll) the mover should have at spawn time (to let the mover start out half-open, for instance). Defaults to &amp;quot;0 0 0&amp;quot;.&lt;br /&gt;
* &amp;quot;start_position&amp;quot;: (Vector) Defines the position the mover should have at spawn time (to let the mover start out open, for instance). Defaults to &amp;quot;0 0 0&amp;quot;.&lt;br /&gt;
* &#039;&#039;&#039;first_frob_open&#039;&#039;&#039;: (1/0) This helps to disambiguate the behaviour when a mover starts at a half-open position. When this is set to &amp;quot;1&amp;quot; the first frob will make the mover open. Defaults to &amp;quot;0&amp;quot;, which means that half-open doors will close on first frob by default.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;snd_open&#039;&#039;&#039; (Soundshader) The sound to be played when the door starts to open after being fully closed.&lt;br /&gt;
* &#039;&#039;&#039;snd_close&#039;&#039;&#039; (Soundshader) The sound to be played when the door reaches its fully closed position.&lt;br /&gt;
* &#039;&#039;&#039;snd_locked&#039;&#039;&#039; (Soundshader)  The sound to be played when the mover becomes locked.&lt;br /&gt;
* &#039;&#039;&#039;snd_unlock&#039;&#039;&#039; (Soundshader)  The sound to be played when the mover unlocks.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;snd_lockpick_pin_NN&#039;&#039;&#039; (soundshader) Defines the sample sound for the pin with NN being in the range 00..14. The number must have a leading zero in it (e.g. &#039;02&#039;).&lt;br /&gt;
* &#039;&#039;&#039;snd_lockpick_pin_sweetspot&#039;&#039;&#039; (soundshader) Defines the sweet spot sound to be inserted into a pattern.&lt;br /&gt;
* &#039;&#039;&#039;snd_lockpick_lock_picked&#039;&#039;&#039; (soundshader) Is played when the entire lock is successfully picked.&lt;br /&gt;
* &#039;&#039;&#039;snd_lockpick_pin_success&#039;&#039;&#039; (soundshader) Is played when a single pin is successfully picked.&lt;br /&gt;
* &#039;&#039;&#039;snd_lockpick_pin_fail&#039;&#039;&#039; (soundshader) Is played when the player fails to pick a pin.&lt;br /&gt;
* &#039;&#039;&#039;snd_lockpick_pick_wrong&#039;&#039;&#039; (soundshader) Is played when the user either attempts to use the wrong lockpick type or the door is not locked or already picked.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;trigger_on_open&#039;&#039;&#039;: (1/0) If set to &amp;quot;1&amp;quot;, this binary mover will trigger its targets when it starts out completely closed and is opened. Default is &amp;quot;0&amp;quot;.&lt;br /&gt;
* &#039;&#039;&#039;trigger_on_close&#039;&#039;&#039;: (1/0)	If set to 1, this binary mover will trigger its targets when it completely closes after being open. Default is &amp;quot;0&amp;quot;.&lt;br /&gt;
* &#039;&#039;&#039;trigger_when_opened&#039;&#039;&#039;: (1/0) If set to 1, this binary mover will trigger its targets when it is completely opened. Default is &amp;quot;0&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;auto_close_time&#039;&#039;&#039;: (float) Set this to something &amp;gt;= 0 to let the mover automatically close (again) after this time when being fully opened (measured in seconds). Defaults to -1, which means &#039;do not autoclose&#039;. The event is also activated when the mover starts at the open position at map start.&lt;br /&gt;
* &#039;&#039;&#039;auto_open_time&#039;&#039;&#039;: (float) Set this to something &amp;gt;= 0 to let the mover automatically open (again) after this time when being fully closed (measured in seconds). Defaults to -1, which means &#039;do not autoopen&#039;. The event is also activated when the mover starts at the closed position at map start.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;impulse_thresh_open&#039;&#039;&#039;: (float) Defines the minimum impulse which needs to be applied to this door before it starts to open. If 0, no open impulse is defined. Default is &amp;quot;0&amp;quot;.&lt;br /&gt;
* &#039;&#039;&#039;impulse_thresh_close&#039;&#039;&#039;: (float) Defines the minimum impulse which needs to be applied to this door before it starts to close. If 0, no close impulse is defined. Default is &amp;quot;0&amp;quot;.&lt;br /&gt;
* &#039;&#039;&#039;impulse_dir_open&#039;&#039;&#039;: (vector) Defines the direction the open impulse needs to be applied in. Default is &#039;0 0 0&#039;.&lt;br /&gt;
* &#039;&#039;&#039;impulse_dir_close&#039;&#039;&#039;: (vector) Defines the direction the close impulse needs to be applied in. Default is &#039;0 0 0&#039;.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;state_change_callback&#039;&#039;&#039;: (script function) Defines the (global) script function which gets called when the mover changes its state. Function signature is: &#039;&#039;&#039;void statChangeCallback(entity self, bool open, bool locked, bool interrupted);&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
=== Script Events ===&lt;br /&gt;
&lt;br /&gt;
;scriptEvent	void 	Open();&lt;br /&gt;
: Opens the frobmover, regardless of its previous state. The mover will not move when it&#039;s locked.&lt;br /&gt;
&lt;br /&gt;
;scriptEvent	void 	Close();&lt;br /&gt;
: Closes the frobmover, regardless of its previous state.&lt;br /&gt;
&lt;br /&gt;
;scriptEvent	void 	ToggleOpen();&lt;br /&gt;
: Toggles the mover state. Closes when fully open, opens when fully closed. If the mover is &amp;quot;interrupted&amp;quot; (e.g. when the player frobbed the mover in between), the move direction depends on the state of the internal &amp;quot;intent_open&amp;quot; flag.&lt;br /&gt;
&lt;br /&gt;
; scriptEvent	float 	IsOpen();&lt;br /&gt;
: Returns true (nonzero) if the mover is open, which is basically the same as &amp;quot;not closed&amp;quot;. A mover is considered closed when it is at its close position.&lt;br /&gt;
&lt;br /&gt;
;scriptEvent	void 	Lock();&lt;br /&gt;
: Locks the mover. Calls to Open() will not succeed after this call.&lt;br /&gt;
;scriptEvent	void 	Unlock();&lt;br /&gt;
: Unlocks the mover. Calls to Open() will succeed after this call. Depending on the value of the spawnarg &amp;quot;open_on_unlock&amp;quot; the mover might automatically open after this call.&lt;br /&gt;
; scriptEvent	void 	ToggleLock();&lt;br /&gt;
: Toggles the lock state. Unlocked movers will be locked and vice versa. The notes above concerning Unlock() still apply if this call unlocks the mover.&lt;br /&gt;
; scriptEvent	float 	IsLocked();&lt;br /&gt;
: Returns true (nonzero) if the mover is currently locked.&lt;br /&gt;
; scriptEvent	float 	IsPickable();&lt;br /&gt;
: Returns true (nonzero) if this mover is pickable.&lt;br /&gt;
&lt;br /&gt;
=== C++ Methods and Events ===&lt;br /&gt;
The class declaration can be found in &#039;&#039;DarkMod/BinaryFrobMover.h&#039;&#039;. Apart from the mandatory Spawn/Save/Restore triple, a set of virtual functions are defined, which can be overridden by the subclasses to specialise the mover.&lt;br /&gt;
&lt;br /&gt;
Note: This is just an abstract. A detailed description of these events can be found in the BinaryFrobMover.h header itself.&lt;br /&gt;
&lt;br /&gt;
As many spawnargs refer to other entities, most of the setup work can be performed after all entities have been spawned. This is why the FrobMover base class provides a virtual PostSpawn() method which can be overridden by the subclasses to do work after all map entities have been spawned. Note: don&#039;t forget to call the base class!&lt;br /&gt;
 // Gets called 16 ms after all entities have been spawned&lt;br /&gt;
 virtual void PostSpawn();&lt;br /&gt;
&lt;br /&gt;
The class provides a few virtual &amp;quot;interceptor&amp;quot; methods, which can be used to prevent the mover from changing its state. These are:&lt;br /&gt;
 virtual bool PreOpen();&lt;br /&gt;
 virtual bool PreClose();&lt;br /&gt;
 virtual bool PreInterrupt();&lt;br /&gt;
 virtual bool PreLock(bool bMaster);&lt;br /&gt;
 virtual bool PreUnlock(bool bMaster);&lt;br /&gt;
These functions are called when the mover is about to perform the respective action. If these are returning TRUE, the mover has green light and it will start to open/close/lock/unlock/get interrupted. Returning FALSE will prevent the calling method from continuing. An example of such a use case is the CBinaryFrobMover::PreOpen() routine, which returns FALSE when the mover is locked. It also playes the &amp;quot;I&#039;m locked&amp;quot; sound before returning.&lt;br /&gt;
&lt;br /&gt;
There are a couple of &amp;quot;state change events&amp;quot;, which get invoked when the mover has reached a certain state:&lt;br /&gt;
 // Gets called when the mover actually starts to move, regardless what the state was beforehand. &lt;br /&gt;
 // The boolean tells which state the mover is heading towards.&lt;br /&gt;
 virtual void OnMoveStart(bool open);&lt;br /&gt;
 &lt;br /&gt;
 // Gets called when the mover is about to move towards its &amp;quot;open&amp;quot; and &amp;quot;closed&amp;quot; position, resp..&lt;br /&gt;
 virtual void OnStartOpen(bool wasClosed, bool bMaster);&lt;br /&gt;
 virtual void OnStartClose(bool wasOpen, bool bMaster);&lt;br /&gt;
 &lt;br /&gt;
 // Gets called when the mover has just reached its fully open/closed position. Does not get called when the mover didn&#039;t move.&lt;br /&gt;
 virtual void OnOpenPositionReached();&lt;br /&gt;
 virtual void OnClosedPositionReached();&lt;br /&gt;
 &lt;br /&gt;
 // Gets called when the mover has just been interrupted.&lt;br /&gt;
 virtual void OnInterrupt();&lt;br /&gt;
 &lt;br /&gt;
 // Is called when the mover has just been locked/unlocked.&lt;br /&gt;
 virtual void OnLock(bool bMaster);&lt;br /&gt;
 virtual void OnUnlock(bool bMaster);&lt;br /&gt;
&lt;br /&gt;
General note on overriding these events: Althought most default implementations are empty, it&#039;s still advisable to call the base class from the overriding function. Default behaviour might be changed in the future, so always call the base class, unless you really need to prevent the default action from being executed.&lt;br /&gt;
&lt;br /&gt;
{{coding}} {{editing}}&lt;/div&gt;</summary>
		<author><name>Geep</name></author>
	</entry>
	<entry>
		<id>https://wiki.thedarkmod.com/index.php?title=Rebuild_all_lang_Program&amp;diff=34417</id>
		<title>Rebuild all lang Program</title>
		<link rel="alternate" type="text/html" href="https://wiki.thedarkmod.com/index.php?title=Rebuild_all_lang_Program&amp;diff=34417"/>
		<updated>2026-01-23T18:15:07Z</updated>

		<summary type="html">&lt;p&gt;Geep: /* Usage and Example */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;by Geep, 2026&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;HOLD OFF ON USING THIS! Further round-trip testing indicates a problem needing more work.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
==== Introduction ====&lt;br /&gt;
Ordinarily, an FM that has been internationalized has a UTF8 &amp;quot;all.lang&amp;quot; text file, from which &amp;quot;*.lang&amp;quot; files in various 8-bit ISO-8859-x (or Windows) encodings were generated and distributed within the &amp;quot;strings&amp;quot; folder.&lt;br /&gt;
&lt;br /&gt;
Sometimes, an attempt is made to improve translations, or extend them to additional languages. The ideal way is to alter content in all.lang, then regenerate the *.lang files (e.g., with gen_lang_plus). This regeneration could be for every language section specified in all.lang, or more selectively, just the ones for languages newly added or with changed content.&lt;br /&gt;
&lt;br /&gt;
Suppose &amp;quot;all.lang&amp;quot; was not distributed with the FM. The original FM author may be able to provide it, or you can ask about it being in some TDM SVN repo.&lt;br /&gt;
&lt;br /&gt;
If those routes fail, you can fabricate a replacement all.lang from the *.lang files. Note that the latter are stripped of helpful comments, including grouping header lines, often found in the original all.lang. So this approach is driven by necessity.&lt;br /&gt;
&lt;br /&gt;
One way that fabrication can be done is first make a new partial all.lang from the existing english.lang file (which being in ASCII, can be viewed as also UTF8), Then add new language sections in UTF8 form. Regenerate just those *.lang files, while retaining older unchanged *.lang files. Each new UTF8 language section can be -&lt;br /&gt;
* typed from scratch, while consulting the ISO-8859-x version.&lt;br /&gt;
* possibly generated using some third-party ISO to UTF8 translator tool.&lt;br /&gt;
&lt;br /&gt;
Or, as a convenience, use &#039;&#039;&#039;rebuild_all_lang&#039;&#039;&#039;. When run from within a give folder (e.g., &amp;quot;strings&amp;quot;), it will take every *.lang it finds (starting with english.lang), convert it from that language&#039;s ISO to UTF8, and basically glue them together into the required form.&lt;br /&gt;
&lt;br /&gt;
==== Usage and Example ====&lt;br /&gt;
The Windows command-line program rebuild_all_lang is a simple C++ utility that takes no parameters, and if successful generates &amp;quot;all.lang&amp;quot; in the current directory. Control it by -&lt;br /&gt;
* deciding in advance which *.lang files are the current directory&lt;br /&gt;
* if you want the generated file to embed a preamble, you can provide it as a file named &amp;quot;preamble_utf8.txt&amp;quot; in the same directory. This is optional. As an example, the program distribution includes a typical stock preamble.&lt;br /&gt;
&lt;br /&gt;
A typical output to console is:&lt;br /&gt;
&lt;br /&gt;
 Running rebuild_all_lang, v. 1.0&lt;br /&gt;
 Note: Did not find an optional preamble file preamble_utf8.txt&lt;br /&gt;
 Processing...&lt;br /&gt;
 English&lt;br /&gt;
 German&lt;br /&gt;
 French&lt;br /&gt;
 Italian&lt;br /&gt;
 Spanish&lt;br /&gt;
 Polish&lt;br /&gt;
 Romanian&lt;br /&gt;
 Russian&lt;br /&gt;
 Portuguese&lt;br /&gt;
 Czech&lt;br /&gt;
 Hungarian&lt;br /&gt;
 Slovak&lt;br /&gt;
 Swedish&lt;br /&gt;
 Danish&lt;br /&gt;
 Dutch&lt;br /&gt;
 Turkish&lt;br /&gt;
 Catalan&lt;br /&gt;
 Contents of *.lang files were converted successfully to UTF-8 and merged into new &#039;all.lang&#039;.&lt;br /&gt;
&lt;br /&gt;
Languages are always processed in the order shown. If a particular *.lang is missing, that is handled quietly, and that section is not added to all.lang.&lt;br /&gt;
&lt;br /&gt;
At the start of all.lang, typical text is...&lt;br /&gt;
&lt;br /&gt;
 // Rebuilt all.lang file - created by rebuild_all_lang v. 1.0&lt;br /&gt;
 // Strings in each section in same order as in *.lang, but converted from various iso-8859s encodings to UTF8.&lt;br /&gt;
 &lt;br /&gt;
 // Note - did not find an optional file preamble_utf8.txt with preamble comments to place here.&lt;br /&gt;
 &lt;br /&gt;
 {&lt;br /&gt;
 [English]&lt;br /&gt;
 // Sourced from english.lang of 2025-07-16T16:08:26+00:00, whose first line was...&lt;br /&gt;
 // String table - english (iso-8859-1) - created on 2025-07-16T16:08:26Z with gen_lang_plus v. 1.1&lt;br /&gt;
 	&amp;quot;#str_fm_airpocket_xd_sheet_appointment_to_service_pg1__title&amp;quot;	&amp;quot;Appointment to Service\n&amp;quot;&lt;br /&gt;
 	....&lt;br /&gt;
&lt;br /&gt;
Within each language section - like [English] here - some variant of the first two commented lines are always generated. As you see, the &amp;quot;// Sourced from...&amp;quot; line is followed by the first line copied from the *.lang file. In this example, the comments show the external file modification datetime, and then the datetime written at generation time. The latter will not always be present, depending upon creation method.&lt;br /&gt;
&lt;br /&gt;
==== Details ====&lt;br /&gt;
As required, the generated all.lang text file has Linux linebreaks (e.g., LF instead of CRFL), independent of linebreak form in input files *.lang or preamble_UTF8.txt&lt;br /&gt;
&lt;br /&gt;
If all.lang already exists, you will see...&lt;br /&gt;
&lt;br /&gt;
 Running rebuild_all_lang, v. 1.0&lt;br /&gt;
 File &#039;all.lang&#039; already exists.&lt;br /&gt;
 Continue and overwrite it? [y/n]&lt;br /&gt;
&lt;br /&gt;
If you indicate &amp;quot;n&amp;quot; for &amp;quot;no&amp;quot;, the program quits with message &amp;quot;Bye&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
This program has some minimal file I/O and conversion error checking, with reporting to console. It is not thought necessary to do character-level checking of the UTF8 results against characters supported by TDM&#039;s character map... such checking is better done elsewhere. This is a simple program. (One could imagine a more elaborate version that would, say, allow english.lang to be annotated with comments (e.g., to group lines into subsections). And then reorder lines within the non-English language sections to match, embedding those same annotations.)&lt;br /&gt;
&lt;br /&gt;
==== Downloads ====&lt;br /&gt;
v 1.0 Source Code: This C++ v20 program was developed under Windows 11 with VS 2022 Community Edition (updated through 2025).&lt;br /&gt;
* [https://drive.google.com/file/d/1kKunDZfVcolZgU4xMsYIpWc5VQgjd3-_/view?usp=sharing Windows executable rebuild_all_lang.exe]&lt;br /&gt;
* [https://drive.google.com/file/d/1sNbWZRznhmgUeGJR8GXK6uiMGAstTusY/view?usp=sharing rebuilt_all_lang.zip - source code: a .cpp and .sln file]&lt;br /&gt;
&lt;br /&gt;
Example preamble files (rename to preamble_utf8.txt to use):&lt;br /&gt;
* [https://drive.google.com/file/d/1bOWXv8Ju1DktaNYe2M8Bo-V7zAg2bNJ9/view?usp=sharing preamble_utf8[traditional&amp;lt;nowiki&amp;gt;]&amp;lt;/nowiki&amp;gt;.txt]&lt;br /&gt;
* [https://drive.google.com/file/d/1QKJvG6FoAzuI7njO5fnOQCgwbXQdWqQe/view?usp=sharing preamble_utf8[modern for FM&amp;lt;nowiki&amp;gt;]&amp;lt;/nowiki&amp;gt;.txt]&lt;br /&gt;
==== See Also ====&lt;br /&gt;
* [[Gen_Lang_Programs]]&lt;br /&gt;
&lt;br /&gt;
{{i18n}} {{editing}}&lt;/div&gt;</summary>
		<author><name>Geep</name></author>
	</entry>
	<entry>
		<id>https://wiki.thedarkmod.com/index.php?title=Rebuild_all_lang_Program&amp;diff=34416</id>
		<title>Rebuild all lang Program</title>
		<link rel="alternate" type="text/html" href="https://wiki.thedarkmod.com/index.php?title=Rebuild_all_lang_Program&amp;diff=34416"/>
		<updated>2026-01-23T18:07:16Z</updated>

		<summary type="html">&lt;p&gt;Geep: HOLD OFF ON USING THIS warning added&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;by Geep, 2026&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;HOLD OFF ON USING THIS! Further round-trip testing indicates a problem needing more work.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
==== Introduction ====&lt;br /&gt;
Ordinarily, an FM that has been internationalized has a UTF8 &amp;quot;all.lang&amp;quot; text file, from which &amp;quot;*.lang&amp;quot; files in various 8-bit ISO-8859-x (or Windows) encodings were generated and distributed within the &amp;quot;strings&amp;quot; folder.&lt;br /&gt;
&lt;br /&gt;
Sometimes, an attempt is made to improve translations, or extend them to additional languages. The ideal way is to alter content in all.lang, then regenerate the *.lang files (e.g., with gen_lang_plus). This regeneration could be for every language section specified in all.lang, or more selectively, just the ones for languages newly added or with changed content.&lt;br /&gt;
&lt;br /&gt;
Suppose &amp;quot;all.lang&amp;quot; was not distributed with the FM. The original FM author may be able to provide it, or you can ask about it being in some TDM SVN repo.&lt;br /&gt;
&lt;br /&gt;
If those routes fail, you can fabricate a replacement all.lang from the *.lang files. Note that the latter are stripped of helpful comments, including grouping header lines, often found in the original all.lang. So this approach is driven by necessity.&lt;br /&gt;
&lt;br /&gt;
One way that fabrication can be done is first make a new partial all.lang from the existing english.lang file (which being in ASCII, can be viewed as also UTF8), Then add new language sections in UTF8 form. Regenerate just those *.lang files, while retaining older unchanged *.lang files. Each new UTF8 language section can be -&lt;br /&gt;
* typed from scratch, while consulting the ISO-8859-x version.&lt;br /&gt;
* possibly generated using some third-party ISO to UTF8 translator tool.&lt;br /&gt;
&lt;br /&gt;
Or, as a convenience, use &#039;&#039;&#039;rebuild_all_lang&#039;&#039;&#039;. When run from within a give folder (e.g., &amp;quot;strings&amp;quot;), it will take every *.lang it finds (starting with english.lang), convert it from that language&#039;s ISO to UTF8, and basically glue them together into the required form.&lt;br /&gt;
&lt;br /&gt;
==== Usage and Example ====&lt;br /&gt;
The Windows command-line program rebuild_all_lang is a simple C++ utility that takes no parameters, and if successful generates &amp;quot;all.lang&amp;quot; in the current directory. Control it by -&lt;br /&gt;
- deciding in advance which *.lang files are the current directory&lt;br /&gt;
- if you want the generated file to embed a preamble, you can provide it as a file named &amp;quot;preamble_utf8.txt&amp;quot; in the same directory. This is optional. As an example, the program distribution includes a typical stock preamble.&lt;br /&gt;
&lt;br /&gt;
A typical output to console is:&lt;br /&gt;
&lt;br /&gt;
 Running rebuild_all_lang, v. 1.0&lt;br /&gt;
 Note: Did not find an optional preamble file preamble_utf8.txt&lt;br /&gt;
 Processing...&lt;br /&gt;
 English&lt;br /&gt;
 German&lt;br /&gt;
 French&lt;br /&gt;
 Italian&lt;br /&gt;
 Spanish&lt;br /&gt;
 Polish&lt;br /&gt;
 Romanian&lt;br /&gt;
 Russian&lt;br /&gt;
 Portuguese&lt;br /&gt;
 Czech&lt;br /&gt;
 Hungarian&lt;br /&gt;
 Slovak&lt;br /&gt;
 Swedish&lt;br /&gt;
 Danish&lt;br /&gt;
 Dutch&lt;br /&gt;
 Turkish&lt;br /&gt;
 Catalan&lt;br /&gt;
 Contents of *.lang files were converted successfully to UTF-8 and merged into new &#039;all.lang&#039;.&lt;br /&gt;
&lt;br /&gt;
Languages are always processed in the order shown. If a particular *.lang is missing, that is handled quietly, and that section is not added to all.lang.&lt;br /&gt;
&lt;br /&gt;
At the start of all.lang, typical text is...&lt;br /&gt;
&lt;br /&gt;
 // Rebuilt all.lang file - created by rebuild_all_lang v. 1.0&lt;br /&gt;
 // Strings in each section in same order as in *.lang, but converted from various iso-8859s encodings to UTF8.&lt;br /&gt;
 &lt;br /&gt;
 // Note - did not find an optional file preamble_utf8.txt with preamble comments to place here.&lt;br /&gt;
 &lt;br /&gt;
 {&lt;br /&gt;
 [English]&lt;br /&gt;
 // Sourced from english.lang of 2025-07-16T16:08:26+00:00, whose first line was...&lt;br /&gt;
 // String table - english (iso-8859-1) - created on 2025-07-16T16:08:26Z with gen_lang_plus v. 1.1&lt;br /&gt;
 	&amp;quot;#str_fm_airpocket_xd_sheet_appointment_to_service_pg1__title&amp;quot;	&amp;quot;Appointment to Service\n&amp;quot;&lt;br /&gt;
 	....&lt;br /&gt;
&lt;br /&gt;
Within each language section - like [English] here - some variant of the first two commented lines are always generated. As you see, the &amp;quot;// Sourced from...&amp;quot; line is followed by the first line copied from the *.lang file. In this example, the comments show the external file modification datetime, and then the datetime written at generation time. The latter will not always be present, depending upon creation method.&lt;br /&gt;
&lt;br /&gt;
==== Details ====&lt;br /&gt;
As required, the generated all.lang text file has Linux linebreaks (e.g., LF instead of CRFL), independent of linebreak form in input files *.lang or preamble_UTF8.txt&lt;br /&gt;
&lt;br /&gt;
If all.lang already exists, you will see...&lt;br /&gt;
&lt;br /&gt;
 Running rebuild_all_lang, v. 1.0&lt;br /&gt;
 File &#039;all.lang&#039; already exists.&lt;br /&gt;
 Continue and overwrite it? [y/n]&lt;br /&gt;
&lt;br /&gt;
If you indicate &amp;quot;n&amp;quot; for &amp;quot;no&amp;quot;, the program quits with message &amp;quot;Bye&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
This program has some minimal file I/O and conversion error checking, with reporting to console. It is not thought necessary to do character-level checking of the UTF8 results against characters supported by TDM&#039;s character map... such checking is better done elsewhere. This is a simple program. (One could imagine a more elaborate version that would, say, allow english.lang to be annotated with comments (e.g., to group lines into subsections). And then reorder lines within the non-English language sections to match, embedding those same annotations.)&lt;br /&gt;
&lt;br /&gt;
==== Downloads ====&lt;br /&gt;
v 1.0 Source Code: This C++ v20 program was developed under Windows 11 with VS 2022 Community Edition (updated through 2025).&lt;br /&gt;
* [https://drive.google.com/file/d/1kKunDZfVcolZgU4xMsYIpWc5VQgjd3-_/view?usp=sharing Windows executable rebuild_all_lang.exe]&lt;br /&gt;
* [https://drive.google.com/file/d/1sNbWZRznhmgUeGJR8GXK6uiMGAstTusY/view?usp=sharing rebuilt_all_lang.zip - source code: a .cpp and .sln file]&lt;br /&gt;
&lt;br /&gt;
Example preamble files (rename to preamble_utf8.txt to use):&lt;br /&gt;
* [https://drive.google.com/file/d/1bOWXv8Ju1DktaNYe2M8Bo-V7zAg2bNJ9/view?usp=sharing preamble_utf8[traditional&amp;lt;nowiki&amp;gt;]&amp;lt;/nowiki&amp;gt;.txt]&lt;br /&gt;
* [https://drive.google.com/file/d/1QKJvG6FoAzuI7njO5fnOQCgwbXQdWqQe/view?usp=sharing preamble_utf8[modern for FM&amp;lt;nowiki&amp;gt;]&amp;lt;/nowiki&amp;gt;.txt]&lt;br /&gt;
==== See Also ====&lt;br /&gt;
* [[Gen_Lang_Programs]]&lt;br /&gt;
&lt;br /&gt;
{{i18n}} {{editing}}&lt;/div&gt;</summary>
		<author><name>Geep</name></author>
	</entry>
	<entry>
		<id>https://wiki.thedarkmod.com/index.php?title=I18N_-_Charset&amp;diff=34414</id>
		<title>I18N - Charset</title>
		<link rel="alternate" type="text/html" href="https://wiki.thedarkmod.com/index.php?title=I18N_-_Charset&amp;diff=34414"/>
		<updated>2026-01-21T20:26:23Z</updated>

		<summary type="html">&lt;p&gt;Geep: /* Russian */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction ==&lt;br /&gt;
&lt;br /&gt;
The D3 code that handles the GUI bitmap font can only load a specific range of bytes as characters. To get the most out of the available entries, special charsets are used. The fonts (Carleton for the menu f.i.) are build/patched so that the right characters appear in the right place.&lt;br /&gt;
&lt;br /&gt;
== Encodings ==&lt;br /&gt;
&lt;br /&gt;
=== all.lang ===&lt;br /&gt;
&lt;br /&gt;
This file is in &#039;&#039;&#039;UTF-8&#039;&#039;&#039;, and converted with the help of the script &#039;&#039;&#039;devel/gen_lang.pl&#039;&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
 perl devel/gen_lang.pl&lt;br /&gt;
&lt;br /&gt;
This ensures that the generated language files are in their proper encodings (see below).&lt;br /&gt;
&lt;br /&gt;
=== All other language files ===&lt;br /&gt;
&lt;br /&gt;
Note that the language files (f.i. &#039;&#039;&#039;strings/german.lang&#039;&#039;&#039;) as well as the readables and the FM dictionariaries are expected to be in the following encodings:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Czech&#039;&#039;&#039;, &#039;&#039;&#039;Hungarian&#039;&#039;&#039;, &#039;&#039;&#039;Slovak&#039;&#039;&#039;, &#039;&#039;&#039;Polish:&#039;&#039;&#039; [https://secure.wikimedia.org/wikipedia/en/wiki/ISO/IEC_8859-2 ISO-8859-2] (&#039;&#039;&#039;not WIN-1250!)&lt;br /&gt;
* &#039;&#039;&#039;Russian:&#039;&#039;&#039; [https://secure.wikimedia.org/wikipedia/en/wiki/Win-1251 WIN-1251]&lt;br /&gt;
* &#039;&#039;&#039;French:&#039;&#039;&#039; [https://secure.wikimedia.org/wikipedia/en/wiki/ISO/IEC_8859-15 ISO-8859-15]&lt;br /&gt;
* &#039;&#039;&#039;Romanian:&#039;&#039;&#039; [https://secure.wikimedia.org/wikipedia/en/wiki/ISO/IEC_8859-16 ISO-8859-16] &lt;br /&gt;
* &#039;&#039;&#039;All other languages:&#039;&#039;&#039; [https://secure.wikimedia.org/wikipedia/en/wiki/ISO/IEC_8859-1 ISO-8859-1] (German, Dutch, Danish, Swedish, Portuguese, etc.)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{{infobox|The core dictionaries are automatically generated in the right encoding, but make sure that you use the right encoding for the FM dictionary, too!}}&lt;br /&gt;
&lt;br /&gt;
== Character remapping ==&lt;br /&gt;
&lt;br /&gt;
The characters are remapped upon loading the dictionary/readable, from their native encoding to the special one that TDM uses and that is described here.  Responsible for the remapping are [[I18N - Character mapping|mapping files]], f.i. &amp;quot;strings/czech.map&amp;quot;. If a map file for a specific language is not found, &amp;quot;strings/default.map&amp;quot; is used instead, if this is not found, no remapping takes place.&lt;br /&gt;
&lt;br /&gt;
See &#039;&#039;&#039;[[I18N - Character mapping|Character mapping]]&#039;&#039;&#039; for more information.&lt;br /&gt;
&lt;br /&gt;
=== European Languages ===&lt;br /&gt;
&lt;br /&gt;
This mapping is used for European languages, f.i. &#039;&#039;&#039;Czech&#039;&#039;&#039;, &#039;&#039;&#039;French&#039;&#039;&#039;, &#039;&#039;&#039;German&#039;&#039;&#039;, &#039;&#039;&#039;Spanish&#039;&#039;&#039;, &#039;&#039;&#039;Portuguese&#039;&#039;&#039;, &#039;&#039;&#039;Polish&#039;&#039;&#039;. Note that the double accented characters in Hungarian &#039;&#039;&#039;Ő, ő, Ű and ű&#039;&#039;&#039; look a bit different from &#039;&#039;&#039;Ö, ö, Ü and ü&#039;&#039;&#039;!&lt;br /&gt;
&lt;br /&gt;
In the table below, the original ISO 8859-1 characters are given in &#039;&#039;()&#039;&#039; below the TDM character.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Color code:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
{{box|#f0d0d0|Character not usable by TDM|Unusable}}{{box|#d0e0d0|Character not yet used in TDM|Unused}}{{box|#c0ffc0|Character displayed in v1.08 or newer|Usable in v1.08}}{{box|#80f080|Character displayed in v2.03 or newer|Usable in v2.03}}{{box|#d0d0f0|Changed from the ISO-8859-1 default, usable by TDM 1.0 or newer|Changed from ISO 8859-1}}&lt;br /&gt;
&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot; border=1 style=&amp;quot;border-collapse: collapse; font-size: 95%&amp;quot; cellspacing=0 cellpadding=2 width=100%&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
!&lt;br /&gt;
!…0&lt;br /&gt;
!…1&lt;br /&gt;
!…2&lt;br /&gt;
!…3&lt;br /&gt;
!…4&lt;br /&gt;
!…5&lt;br /&gt;
!…6&lt;br /&gt;
!…7&lt;br /&gt;
!…8&lt;br /&gt;
!…9&lt;br /&gt;
!…A&lt;br /&gt;
!…B&lt;br /&gt;
!…C&lt;br /&gt;
!…D&lt;br /&gt;
!…E&lt;br /&gt;
!…F&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
!0…&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #f0d0d0&#039;|00&amp;lt;br&amp;gt;&#039;&#039;&#039;–&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #f0d0d0&#039;|01&amp;lt;br&amp;gt;&#039;&#039;&#039;–&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #f0d0d0&#039;|02&amp;lt;br&amp;gt;&#039;&#039;&#039;–&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #f0d0d0&#039;|03&amp;lt;br&amp;gt;&#039;&#039;&#039;–&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #f0d0d0&#039;|04&amp;lt;br&amp;gt;&#039;&#039;&#039;–&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #f0d0d0&#039;|05&amp;lt;br&amp;gt;&#039;&#039;&#039;–&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #f0d0d0&#039;|06&amp;lt;br&amp;gt;&#039;&#039;&#039;–&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #f0d0d0&#039;|07&amp;lt;br&amp;gt;&#039;&#039;&#039;–&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #f0d0d0&#039;|08&amp;lt;br&amp;gt;&#039;&#039;&#039;–&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #f0d0d0&#039;|09&amp;lt;br&amp;gt;&#039;&#039;&#039;–&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #f0d0d0&#039;|0A&amp;lt;br&amp;gt;&#039;&#039;&#039;–&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #f0d0d0&#039;|0B&amp;lt;br&amp;gt;&#039;&#039;&#039;–&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #f0d0d0&#039;|0C&amp;lt;br&amp;gt;&#039;&#039;&#039;–&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #f0d0d0&#039;|0D&amp;lt;br&amp;gt;&#039;&#039;&#039;–&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #f0d0d0&#039;|0E&amp;lt;br&amp;gt;&#039;&#039;&#039;–&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #f0d0d0&#039;|0F&amp;lt;br&amp;gt;&#039;&#039;&#039;–&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
!1…&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #f0d0d0&#039;|10&amp;lt;br&amp;gt;&#039;&#039;&#039;–&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #f0d0d0&#039;|11&amp;lt;br&amp;gt;&#039;&#039;&#039;–&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #f0d0d0&#039;|12&amp;lt;br&amp;gt;&#039;&#039;&#039;–&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #f0d0d0&#039;|13&amp;lt;br&amp;gt;&#039;&#039;&#039;–&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #f0d0d0&#039;|14&amp;lt;br&amp;gt;&#039;&#039;&#039;–&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #f0d0d0&#039;|15&amp;lt;br&amp;gt;&#039;&#039;&#039;–&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #f0d0d0&#039;|16&amp;lt;br&amp;gt;&#039;&#039;&#039;–&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #f0d0d0&#039;|17&amp;lt;br&amp;gt;&#039;&#039;&#039;–&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #f0d0d0&#039;|18&amp;lt;br&amp;gt;&#039;&#039;&#039;–&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #f0d0d0&#039;|19&amp;lt;br&amp;gt;&#039;&#039;&#039;–&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #f0d0d0&#039;|1A&amp;lt;br&amp;gt;&#039;&#039;&#039;–&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #f0d0d0&#039;|1B&amp;lt;br&amp;gt;&#039;&#039;&#039;–&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #f0d0d0&#039;|1C&amp;lt;br&amp;gt;&#039;&#039;&#039;–&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #f0d0d0&#039;|1D&amp;lt;br&amp;gt;&#039;&#039;&#039;–&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #f0d0d0&#039;|1E&amp;lt;br&amp;gt;&#039;&#039;&#039;–&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #f0d0d0&#039;|1F&amp;lt;br&amp;gt;&#039;&#039;&#039;–&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
!2…&lt;br /&gt;
|align=&#039;center&#039;|20&amp;lt;br&amp;gt;&#039;&#039;&#039;&amp;amp;nbsp;&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|21&amp;lt;br&amp;gt;&#039;&#039;&#039;!&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|22&amp;lt;br&amp;gt;&#039;&#039;&#039;&amp;quot;&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|23&amp;lt;br&amp;gt;&#039;&#039;&#039;#&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|24&amp;lt;br&amp;gt;&#039;&#039;&#039;$&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|25&amp;lt;br&amp;gt;&#039;&#039;&#039;%&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|26&amp;lt;br&amp;gt;&#039;&#039;&#039;&amp;amp;&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|27&amp;lt;br&amp;gt;&#039;&#039;&#039;&#039;&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|28&amp;lt;br&amp;gt;&#039;&#039;&#039;(&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|29&amp;lt;br&amp;gt;&#039;&#039;&#039;)&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|2A&amp;lt;br&amp;gt;&#039;&#039;&#039;*&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|2B&amp;lt;br&amp;gt;&#039;&#039;&#039;+&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|2C&amp;lt;br&amp;gt;&#039;&#039;&#039;,&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|2D&amp;lt;br&amp;gt;&#039;&#039;&#039;-&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|2E&amp;lt;br&amp;gt;&#039;&#039;&#039;.&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|2F&amp;lt;br&amp;gt;&#039;&#039;&#039;/&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
!3…&lt;br /&gt;
|align=&#039;center&#039;|30&amp;lt;br&amp;gt;&#039;&#039;&#039;0&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|31&amp;lt;br&amp;gt;&#039;&#039;&#039;1&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|32&amp;lt;br&amp;gt;&#039;&#039;&#039;2&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|33&amp;lt;br&amp;gt;&#039;&#039;&#039;3&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|34&amp;lt;br&amp;gt;&#039;&#039;&#039;4&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|35&amp;lt;br&amp;gt;&#039;&#039;&#039;5&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|36&amp;lt;br&amp;gt;&#039;&#039;&#039;6&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|37&amp;lt;br&amp;gt;&#039;&#039;&#039;7&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|38&amp;lt;br&amp;gt;&#039;&#039;&#039;8&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|39&amp;lt;br&amp;gt;&#039;&#039;&#039;9&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|3A&amp;lt;br&amp;gt;&#039;&#039;&#039;:&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|3B&amp;lt;br&amp;gt;&#039;&#039;&#039;;&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|3C&amp;lt;br&amp;gt;&#039;&#039;&#039;&amp;lt;&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|3D&amp;lt;br&amp;gt;&#039;&#039;&#039;=&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|3E&amp;lt;br&amp;gt;&#039;&#039;&#039;&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|3F&amp;lt;br&amp;gt;&#039;&#039;&#039;?&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
!4…&lt;br /&gt;
|align=&#039;center&#039;|40&amp;lt;br&amp;gt;&#039;&#039;&#039;@&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|41&amp;lt;br&amp;gt;&#039;&#039;&#039;A&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|42&amp;lt;br&amp;gt;&#039;&#039;&#039;B&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|43&amp;lt;br&amp;gt;&#039;&#039;&#039;C&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|44&amp;lt;br&amp;gt;&#039;&#039;&#039;D&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|45&amp;lt;br&amp;gt;&#039;&#039;&#039;E&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|46&amp;lt;br&amp;gt;&#039;&#039;&#039;F&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|47&amp;lt;br&amp;gt;&#039;&#039;&#039;G&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|48&amp;lt;br&amp;gt;&#039;&#039;&#039;H&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|49&amp;lt;br&amp;gt;&#039;&#039;&#039;I&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|4A&amp;lt;br&amp;gt;&#039;&#039;&#039;J&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|4B&amp;lt;br&amp;gt;&#039;&#039;&#039;K&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|4C&amp;lt;br&amp;gt;&#039;&#039;&#039;L&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|4D&amp;lt;br&amp;gt;&#039;&#039;&#039;M&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|4E&amp;lt;br&amp;gt;&#039;&#039;&#039;N&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|4F&amp;lt;br&amp;gt;&#039;&#039;&#039;O&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
!5…&lt;br /&gt;
|align=&#039;center&#039;|50&amp;lt;br&amp;gt;&#039;&#039;&#039;P&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|51&amp;lt;br&amp;gt;&#039;&#039;&#039;Q&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|52&amp;lt;br&amp;gt;&#039;&#039;&#039;R&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|53&amp;lt;br&amp;gt;&#039;&#039;&#039;S&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|54&amp;lt;br&amp;gt;&#039;&#039;&#039;T&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|55&amp;lt;br&amp;gt;&#039;&#039;&#039;U&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|56&amp;lt;br&amp;gt;&#039;&#039;&#039;V&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|57&amp;lt;br&amp;gt;&#039;&#039;&#039;W&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|58&amp;lt;br&amp;gt;&#039;&#039;&#039;X&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|59&amp;lt;br&amp;gt;&#039;&#039;&#039;Y&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|5A&amp;lt;br&amp;gt;&#039;&#039;&#039;Z&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|5B&amp;lt;br&amp;gt;&#039;&#039;&#039;[&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|5C&amp;lt;br&amp;gt;&#039;&#039;&#039;\&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|5D&amp;lt;br&amp;gt;&#039;&#039;&#039;]&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|5E&amp;lt;br&amp;gt;&#039;&#039;&#039;^&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|5F&amp;lt;br&amp;gt;&#039;&#039;&#039;_&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
!6…&lt;br /&gt;
|align=&#039;center&#039;|60&amp;lt;br&amp;gt;&#039;&#039;&#039;`&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|61&amp;lt;br&amp;gt;&#039;&#039;&#039;a&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|62&amp;lt;br&amp;gt;&#039;&#039;&#039;b&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|63&amp;lt;br&amp;gt;&#039;&#039;&#039;c&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|64&amp;lt;br&amp;gt;&#039;&#039;&#039;d&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|65&amp;lt;br&amp;gt;&#039;&#039;&#039;e&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|66&amp;lt;br&amp;gt;&#039;&#039;&#039;f&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|67&amp;lt;br&amp;gt;&#039;&#039;&#039;g&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|68&amp;lt;br&amp;gt;&#039;&#039;&#039;h&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|69&amp;lt;br&amp;gt;&#039;&#039;&#039;i&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|6A&amp;lt;br&amp;gt;&#039;&#039;&#039;j&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|6B&amp;lt;br&amp;gt;&#039;&#039;&#039;k&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|6C&amp;lt;br&amp;gt;&#039;&#039;&#039;l&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|6D&amp;lt;br&amp;gt;&#039;&#039;&#039;m&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|6E&amp;lt;br&amp;gt;&#039;&#039;&#039;n&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|6F&amp;lt;br&amp;gt;&#039;&#039;&#039;o&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
!7…&lt;br /&gt;
|align=&#039;center&#039;|70&amp;lt;br&amp;gt;&#039;&#039;&#039;p&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|71&amp;lt;br&amp;gt;&#039;&#039;&#039;q&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|72&amp;lt;br&amp;gt;&#039;&#039;&#039;r&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|73&amp;lt;br&amp;gt;&#039;&#039;&#039;s&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|74&amp;lt;br&amp;gt;&#039;&#039;&#039;t&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|75&amp;lt;br&amp;gt;&#039;&#039;&#039;u&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|76&amp;lt;br&amp;gt;&#039;&#039;&#039;v&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|77&amp;lt;br&amp;gt;&#039;&#039;&#039;w&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|78&amp;lt;br&amp;gt;&#039;&#039;&#039;x&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|79&amp;lt;br&amp;gt;&#039;&#039;&#039;y&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|7A&amp;lt;br&amp;gt;&#039;&#039;&#039;z&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|7B&amp;lt;br&amp;gt;&#039;&#039;&#039;{&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|7C&amp;lt;br&amp;gt;&#039;&#039;&#039;|&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|7D&amp;lt;br&amp;gt;&#039;&#039;&#039;}&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|7E&amp;lt;br&amp;gt;&#039;&#039;&#039;~&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #d0e0d0&#039;|7F&amp;lt;br&amp;gt;&#039;&#039;&#039;�&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
!8…&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #c0ffc0&#039;|80&amp;lt;br&amp;gt;&#039;&#039;&#039;Ň&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #c0ffc0&#039;|81&amp;lt;br&amp;gt;&#039;&#039;&#039;Ś&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #c0ffc0&#039;|82&amp;lt;br&amp;gt;&#039;&#039;&#039;Ć&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #c0ffc0&#039;|83&amp;lt;br&amp;gt;&#039;&#039;&#039;Ż&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #c0ffc0&#039;|84&amp;lt;br&amp;gt;&#039;&#039;&#039;Ź&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #c0ffc0&#039;|85&amp;lt;br&amp;gt;&#039;&#039;&#039;Ŝ&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #c0ffc0&#039;|86&amp;lt;br&amp;gt;&#039;&#039;&#039;Ĉ&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #c0ffc0&#039;|87&amp;lt;br&amp;gt;&#039;&#039;&#039;Ẑ&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #c0ffc0&#039;|88&amp;lt;br&amp;gt;&#039;&#039;&#039;Ô&#039;&#039;&#039; [note]&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #c0ffc0&#039;|89&amp;lt;br&amp;gt;&#039;&#039;&#039;Ŕ&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #c0ffc0&#039;|8A&amp;lt;br&amp;gt;&#039;&#039;&#039;Ǔ&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #c0ffc0&#039;|8B&amp;lt;br&amp;gt;&#039;&#039;&#039;Ă&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #c0ffc0&#039;|8C&amp;lt;br&amp;gt;&#039;&#039;&#039;Ń&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #80f080&#039;|8D&amp;lt;br&amp;gt;&#039;&#039;&#039;Ș&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #80f080&#039;|8E&amp;lt;br&amp;gt;&#039;&#039;&#039;Ț&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #d0e0d0&#039;|8F&amp;lt;br&amp;gt;&#039;&#039;&#039;�&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
!9…&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #80f080&#039;|90&amp;lt;br&amp;gt;&#039;&#039;&#039;đ&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #c0ffc0&#039;|91&amp;lt;br&amp;gt;&#039;&#039;&#039;ś&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #c0ffc0&#039;|92&amp;lt;br&amp;gt;&#039;&#039;&#039;ć&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #c0ffc0&#039;|93&amp;lt;br&amp;gt;&#039;&#039;&#039;ż&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #c0ffc0&#039;|94&amp;lt;br&amp;gt;&#039;&#039;&#039;ź&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #c0ffc0&#039;|95&amp;lt;br&amp;gt;&#039;&#039;&#039;ŝ&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #c0ffc0&#039;|96&amp;lt;br&amp;gt;&#039;&#039;&#039;ĉ&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #c0ffc0&#039;|97&amp;lt;br&amp;gt;&#039;&#039;&#039;ẑ&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #c0ffc0&#039;|98&amp;lt;br&amp;gt;&#039;&#039;&#039;ô&#039;&#039;&#039; [note]&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #c0ffc0&#039;|99&amp;lt;br&amp;gt;&#039;&#039;&#039;ŕ&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #c0ffc0&#039;|9A&amp;lt;br&amp;gt;&#039;&#039;&#039;ǔ&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #c0ffc0&#039;|9B&amp;lt;br&amp;gt;&#039;&#039;&#039;ă&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #c0ffc0&#039;|9C&amp;lt;br&amp;gt;&#039;&#039;&#039;ń&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #80f080&#039;|9D&amp;lt;br&amp;gt;&#039;&#039;&#039;ș&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #80f080&#039;|9E&amp;lt;br&amp;gt;&#039;&#039;&#039;ț&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #d0e0d0&#039;|9F&amp;lt;br&amp;gt;&#039;&#039;&#039;�&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
!A…&lt;br /&gt;
|align=&#039;center&#039;|A0&amp;lt;br&amp;gt;&#039;&#039;&#039;[https://secure.wikimedia.org/wikipedia/en/wiki/Non-breaking_space NBSP]&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #d0d0f0&#039;|A1&amp;lt;br&amp;gt;&#039;&#039;&#039;ň&#039;&#039;&#039;&amp;lt;br&amp;gt;(¡)&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #d0d0f0&#039;|A2&amp;lt;br&amp;gt;&#039;&#039;&#039;Ű&#039;&#039;&#039;&amp;lt;br&amp;gt;(¢)&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #d0d0f0&#039;|A3&amp;lt;br&amp;gt;&#039;&#039;&#039;ě&#039;&#039;&#039;&amp;lt;br&amp;gt;(£)&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #d0d0f0&#039;|A4&amp;lt;br&amp;gt;&#039;&#039;&#039;ű&#039;&#039;&#039;&amp;lt;br&amp;gt;(¤)&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #d0d0f0&#039;|A5&amp;lt;br&amp;gt;&#039;&#039;&#039;Ě&#039;&#039;&#039;&amp;lt;br&amp;gt;(¥)&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #d0d0f0&#039;|A6&amp;lt;br&amp;gt;&#039;&#039;&#039;Š&#039;&#039;&#039;&amp;lt;br&amp;gt;(¦)&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|A7&amp;lt;br&amp;gt;&#039;&#039;&#039;§&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #d0d0f0&#039;|A8&amp;lt;br&amp;gt;&#039;&#039;&#039;š&#039;&#039;&#039;&amp;lt;br&amp;gt;(¨)&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #d0d0f0&#039;|A9&amp;lt;br&amp;gt;&#039;&#039;&#039;Ů&#039;&#039;&#039;&amp;lt;br&amp;gt;(©)&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #d0d0f0&#039;|AA&amp;lt;br&amp;gt;&#039;&#039;&#039;Ą&#039;&#039;&#039;&amp;lt;br&amp;gt;(ª)&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #d0d0f0&#039;|AB&amp;lt;br&amp;gt;&#039;&#039;&#039;Ę&#039;&#039;&#039;&amp;lt;br&amp;gt;(«)&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #d0d0f0&#039;|AC&amp;lt;br&amp;gt;&#039;&#039;&#039;Č&#039;&#039;&#039;&amp;lt;br&amp;gt;(¬)&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|AD&amp;lt;br&amp;gt;&#039;&#039;&#039;[https://secure.wikimedia.org/wikipedia/en/wiki/Soft_hyphen SHY]&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #d0d0f0&#039;|AE&amp;lt;br&amp;gt;&#039;&#039;&#039;č&#039;&#039;&#039;&amp;lt;br&amp;gt;(®)&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #d0d0f0&#039;|AF&amp;lt;br&amp;gt;&#039;&#039;&#039;ů&#039;&#039;&#039;&amp;lt;br&amp;gt;(¯)&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
!B…&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #d0d0f0&#039;|B0&amp;lt;br&amp;gt;&#039;&#039;&#039;Ő&#039;&#039;&#039;&amp;lt;br&amp;gt;(°)&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #d0d0f0&#039;|B1&amp;lt;br&amp;gt;&#039;&#039;&#039;Ł&#039;&#039;&#039;&amp;lt;br&amp;gt;(±)&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #d0d0f0&#039;|B2&amp;lt;br&amp;gt;&#039;&#039;&#039;Ť&#039;&#039;&#039;&amp;lt;br&amp;gt;(²)&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #d0d0f0&#039;|B3&amp;lt;br&amp;gt;&#039;&#039;&#039;Ď&#039;&#039;&#039;&amp;lt;br&amp;gt;(³)&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #d0d0f0&#039;|B4&amp;lt;br&amp;gt;&#039;&#039;&#039;Ž&#039;&#039;&#039;&amp;lt;br&amp;gt;(´)&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #d0d0f0&#039;|B5&amp;lt;br&amp;gt;&#039;&#039;&#039;ł&#039;&#039;&#039;&amp;lt;br&amp;gt;(µ)&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #d0d0f0&#039;|B6&amp;lt;br&amp;gt;&#039;&#039;&#039;ť&#039;&#039;&#039;&amp;lt;br&amp;gt;(¶)&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #d0d0f0&#039;|B7&amp;lt;br&amp;gt;&#039;&#039;&#039;ď&#039;&#039;&#039;&amp;lt;br&amp;gt;(·)&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #d0d0f0&#039;|B8&amp;lt;br&amp;gt;&#039;&#039;&#039;ž&#039;&#039;&#039;&amp;lt;br&amp;gt;(¸)&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #d0d0f0&#039;|B9&amp;lt;br&amp;gt;&#039;&#039;&#039;ő&#039;&#039;&#039;&amp;lt;br&amp;gt;(¹)&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #d0d0f0&#039;|BA&amp;lt;br&amp;gt;&#039;&#039;&#039;ą&#039;&#039;&#039;&amp;lt;br&amp;gt;(º)&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #d0d0f0&#039;|BB&amp;lt;br&amp;gt;&#039;&#039;&#039;ę&#039;&#039;&#039;&amp;lt;br&amp;gt;(»)&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #d0d0f0&#039;|BC&amp;lt;br&amp;gt;&#039;&#039;&#039;Œ&#039;&#039;&#039;&amp;lt;br&amp;gt;(¼)&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #d0d0f0&#039;|BD&amp;lt;br&amp;gt;&#039;&#039;&#039;œ&#039;&#039;&#039;&amp;lt;br&amp;gt;(½)&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #d0d0f0&#039;|BE&amp;lt;br&amp;gt;&#039;&#039;&#039;Ÿ&#039;&#039;&#039;&amp;lt;br&amp;gt;(¾)&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|BF&amp;lt;br&amp;gt;&#039;&#039;&#039;¿&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
!C…&lt;br /&gt;
|align=&#039;center&#039;|C0&amp;lt;br&amp;gt;&#039;&#039;&#039;À&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|C1&amp;lt;br&amp;gt;&#039;&#039;&#039;Á&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|C2&amp;lt;br&amp;gt;&#039;&#039;&#039;Â&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|C3&amp;lt;br&amp;gt;&#039;&#039;&#039;Ã&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|C4&amp;lt;br&amp;gt;&#039;&#039;&#039;Ä&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|C5&amp;lt;br&amp;gt;&#039;&#039;&#039;Å&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|C6&amp;lt;br&amp;gt;&#039;&#039;&#039;Æ&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|C7&amp;lt;br&amp;gt;&#039;&#039;&#039;Ç&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|C8&amp;lt;br&amp;gt;&#039;&#039;&#039;È&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|C9&amp;lt;br&amp;gt;&#039;&#039;&#039;É&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|CA&amp;lt;br&amp;gt;&#039;&#039;&#039;Ê&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|CB&amp;lt;br&amp;gt;&#039;&#039;&#039;Ë&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|CC&amp;lt;br&amp;gt;&#039;&#039;&#039;Ì&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|CD&amp;lt;br&amp;gt;&#039;&#039;&#039;Í&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|CE&amp;lt;br&amp;gt;&#039;&#039;&#039;Î&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|CF&amp;lt;br&amp;gt;&#039;&#039;&#039;Ï&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
!D…&lt;br /&gt;
|align=&#039;center&#039;|D0&amp;lt;br&amp;gt;&#039;&#039;&#039;Ð&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|D1&amp;lt;br&amp;gt;&#039;&#039;&#039;Ñ&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|D2&amp;lt;br&amp;gt;&#039;&#039;&#039;Ò&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|D3&amp;lt;br&amp;gt;&#039;&#039;&#039;Ó&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|D4&amp;lt;br&amp;gt;&#039;&#039;&#039;Ô&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|D5&amp;lt;br&amp;gt;&#039;&#039;&#039;Õ&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|D6&amp;lt;br&amp;gt;&#039;&#039;&#039;Ö&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #d0d0f0&#039;|D7&amp;lt;br&amp;gt;&#039;&#039;&#039;Ř&#039;&#039;&#039;&amp;lt;br&amp;gt;(×)&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|D8&amp;lt;br&amp;gt;&#039;&#039;&#039;Ø&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|D9&amp;lt;br&amp;gt;&#039;&#039;&#039;Ù&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|DA&amp;lt;br&amp;gt;&#039;&#039;&#039;Ú&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|DB&amp;lt;br&amp;gt;&#039;&#039;&#039;Û&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|DC&amp;lt;br&amp;gt;&#039;&#039;&#039;Ü&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|DD&amp;lt;br&amp;gt;&#039;&#039;&#039;Ý&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|DE&amp;lt;br&amp;gt;&#039;&#039;&#039;Þ&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|DF&amp;lt;br&amp;gt;&#039;&#039;&#039;ß&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
!E…&lt;br /&gt;
|align=&#039;center&#039;|E0&amp;lt;br&amp;gt;&#039;&#039;&#039;à&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|E1&amp;lt;br&amp;gt;&#039;&#039;&#039;á&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|E2&amp;lt;br&amp;gt;&#039;&#039;&#039;â&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|E3&amp;lt;br&amp;gt;&#039;&#039;&#039;ã&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|E4&amp;lt;br&amp;gt;&#039;&#039;&#039;ä&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|E5&amp;lt;br&amp;gt;&#039;&#039;&#039;å&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|E6&amp;lt;br&amp;gt;&#039;&#039;&#039;æ&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|E7&amp;lt;br&amp;gt;&#039;&#039;&#039;ç&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|E8&amp;lt;br&amp;gt;&#039;&#039;&#039;è&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|E9&amp;lt;br&amp;gt;&#039;&#039;&#039;é&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|EA&amp;lt;br&amp;gt;&#039;&#039;&#039;ê&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|EB&amp;lt;br&amp;gt;&#039;&#039;&#039;ë&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|EC&amp;lt;br&amp;gt;&#039;&#039;&#039;ì&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|ED&amp;lt;br&amp;gt;&#039;&#039;&#039;í&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|EE&amp;lt;br&amp;gt;&#039;&#039;&#039;î&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|EF&amp;lt;br&amp;gt;&#039;&#039;&#039;ï&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
!F…&lt;br /&gt;
|align=&#039;center&#039;|F0&amp;lt;br&amp;gt;&#039;&#039;&#039;ð&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|F1&amp;lt;br&amp;gt;&#039;&#039;&#039;ñ&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|F2&amp;lt;br&amp;gt;&#039;&#039;&#039;ò&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|F3&amp;lt;br&amp;gt;&#039;&#039;&#039;ó&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|F4&amp;lt;br&amp;gt;&#039;&#039;&#039;ô&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|F5&amp;lt;br&amp;gt;&#039;&#039;&#039;õ&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|F6&amp;lt;br&amp;gt;&#039;&#039;&#039;ö&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #d0d0f0&#039;|F7&amp;lt;br&amp;gt;&#039;&#039;&#039;ř&#039;&#039;&#039;&amp;lt;br&amp;gt;(÷)&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|F8&amp;lt;br&amp;gt;&#039;&#039;&#039;ø&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|F9&amp;lt;br&amp;gt;&#039;&#039;&#039;ù&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|FA&amp;lt;br&amp;gt;&#039;&#039;&#039;ú&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|FB&amp;lt;br&amp;gt;&#039;&#039;&#039;û&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|FC&amp;lt;br&amp;gt;&#039;&#039;&#039;ü&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|FD&amp;lt;br&amp;gt;&#039;&#039;&#039;ý&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|FE&amp;lt;br&amp;gt;&#039;&#039;&#039;þ&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|FF&amp;lt;br&amp;gt;&#039;&#039;&#039;ÿ&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
[note] As discussed [https://forums.thedarkmod.com/index.php?/topic/22427-analysis-of-212-tdm-fonts/&amp;amp;do=findComment&amp;amp;comment=494855 here], the TDM char set has a redundant treatment of 2 characters:&lt;br /&gt;
&lt;br /&gt;
* Ô appears at 0x88 and 0xD4&lt;br /&gt;
* ô appears at 0x98 and 0xF4&lt;br /&gt;
&lt;br /&gt;
Planned for TDM 2.13, the redundancy can be removed and these new characters (from ISO-8859-3) introduced:&lt;br /&gt;
&lt;br /&gt;
* Ğ appears at 0x88&lt;br /&gt;
* ğ appears at 0x98&lt;br /&gt;
&lt;br /&gt;
For a mapping of these 256 codepoints to Unicode U+NNNN values and formal names, download &#039;TDM 8859-Style Font Map to Unicode-16.txt&#039;: &lt;br /&gt;
&lt;br /&gt;
* [https://drive.google.com/file/d/1wLEtuFvnrZ-WHK8ign8i3diIXZdriZ4F/view?usp=sharing for TDM 2.13]&lt;br /&gt;
* [https://drive.google.com/file/d/1UAz9jSZpT_j33STP3So_Re8JWa8QuAmz/view?usp=sharing for TDM 2.12 and earlier]&lt;br /&gt;
&lt;br /&gt;
Each of these files (by Geep, 2024) is in a standardized format so that it can also be imported into font design programs like FontForge as a custom 256-position map. In the comments, there is additional information about:&lt;br /&gt;
* ISO 8859-x sourcing of each character.&lt;br /&gt;
* alternative representations of some European and control characters.&lt;br /&gt;
&lt;br /&gt;
=== Russian ===&lt;br /&gt;
&lt;br /&gt;
Characters conform to the [https://en.wikipedia.org/wiki/Win-1251 WIN-1251 native encoding, shown in the Wikipedia article]. Exception: the character &#039;&#039;&#039;0xFF&#039;&#039;&#039; (я) is mapped to &#039;&#039;&#039;0xB6&#039;&#039;&#039; upon loading. Therefore any Russian font must contain я at the place 0xB6.&lt;br /&gt;
&lt;br /&gt;
Within any given font, character overage may be incomplete. A 2025 effort extended the Mason 48pt font to all 256 codepoints.&lt;br /&gt;
&lt;br /&gt;
=== Asian Languages (Korean, Chinese, Japanese) ===&lt;br /&gt;
&lt;br /&gt;
The original D3 had support for these languages, so it might be possible to add them to TDM, too. At the moment, however, we lack the fonts and translators. Also, writing from right-to-left (Hebrew) or top-down (Japanese) might be tricky or outright impossible in our GUI without more work in the C++ code. Plus, these languages use more than 256 different characters, and an 8 bit table will not hold these.&lt;br /&gt;
&lt;br /&gt;
== European Character Implementation ==&lt;br /&gt;
=== Priority Early-On - the &amp;quot;Top 50&amp;quot; ===&lt;br /&gt;
&lt;br /&gt;
Some of the special characters are used more often than others. Here is a statistic over the entire string set of the TDM core, from TDM v1.08, showing the top 50 most-used characters (excluding a-z, 0-9 and russian characters):&lt;br /&gt;
&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot; border=1 style=&amp;quot;border-collapse: collapse; font-size: 85%&amp;quot; cellspacing=0 cellpadding=2&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|Rank&lt;br /&gt;
|Occurances&lt;br /&gt;
|Letter&lt;br /&gt;
|Remarks&lt;br /&gt;
|Rank&lt;br /&gt;
|Occurances&lt;br /&gt;
|Letter&lt;br /&gt;
|Remarks&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|1&lt;br /&gt;
|í&lt;br /&gt;
|715&lt;br /&gt;
|&lt;br /&gt;
|25&lt;br /&gt;
|ć&lt;br /&gt;
|67&lt;br /&gt;
|&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|2&lt;br /&gt;
|é&lt;br /&gt;
|674&lt;br /&gt;
|&lt;br /&gt;
|26&lt;br /&gt;
|è&lt;br /&gt;
|65&lt;br /&gt;
|&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|3&lt;br /&gt;
|á&lt;br /&gt;
|524&lt;br /&gt;
|&lt;br /&gt;
|27&lt;br /&gt;
|ú&lt;br /&gt;
|56&lt;br /&gt;
|&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|4&lt;br /&gt;
|ø&lt;br /&gt;
|303&lt;br /&gt;
|Danish&lt;br /&gt;
|28&lt;br /&gt;
|ê&lt;br /&gt;
|52&lt;br /&gt;
|&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|5&lt;br /&gt;
|č&lt;br /&gt;
|288&lt;br /&gt;
|&lt;br /&gt;
|29&lt;br /&gt;
|ö&lt;br /&gt;
|48&lt;br /&gt;
|German&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|6&lt;br /&gt;
|ó&lt;br /&gt;
|283&lt;br /&gt;
|&lt;br /&gt;
|30&lt;br /&gt;
|É&lt;br /&gt;
|46&lt;br /&gt;
|&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|7&lt;br /&gt;
|ü&lt;br /&gt;
|270&lt;br /&gt;
|German&lt;br /&gt;
|31&lt;br /&gt;
|ñ&lt;br /&gt;
|37&lt;br /&gt;
|&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|8&lt;br /&gt;
|ł&lt;br /&gt;
|203&lt;br /&gt;
|Polish&lt;br /&gt;
|32&lt;br /&gt;
|õ&lt;br /&gt;
|32&lt;br /&gt;
|&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|9&lt;br /&gt;
|æ&lt;br /&gt;
|200&lt;br /&gt;
|Danish&lt;br /&gt;
|33&lt;br /&gt;
|ń&lt;br /&gt;
|26&lt;br /&gt;
|&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|10&lt;br /&gt;
|ě&lt;br /&gt;
|182&lt;br /&gt;
|&lt;br /&gt;
|34&lt;br /&gt;
|Ł&lt;br /&gt;
|24&lt;br /&gt;
|&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|11&lt;br /&gt;
|ř&lt;br /&gt;
|175&lt;br /&gt;
|Czech&lt;br /&gt;
|35&lt;br /&gt;
|Š&lt;br /&gt;
|21&lt;br /&gt;
|&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|12&lt;br /&gt;
|ã&lt;br /&gt;
|168&lt;br /&gt;
|&lt;br /&gt;
|36&lt;br /&gt;
|â&lt;br /&gt;
|21&lt;br /&gt;
|&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|13&lt;br /&gt;
|ž&lt;br /&gt;
|148&lt;br /&gt;
|Czech&lt;br /&gt;
|37&lt;br /&gt;
|ź&lt;br /&gt;
|20&lt;br /&gt;
|&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|14&lt;br /&gt;
|ý&lt;br /&gt;
|142&lt;br /&gt;
|&lt;br /&gt;
|38&lt;br /&gt;
|ß&lt;br /&gt;
|18&lt;br /&gt;
|German&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|15&lt;br /&gt;
|ę&lt;br /&gt;
|141&lt;br /&gt;
|&lt;br /&gt;
|39&lt;br /&gt;
|Ó&lt;br /&gt;
|18&lt;br /&gt;
|&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|16&lt;br /&gt;
|ą&lt;br /&gt;
|140&lt;br /&gt;
|&lt;br /&gt;
|40&lt;br /&gt;
|ň&lt;br /&gt;
|15&lt;br /&gt;
|&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|17&lt;br /&gt;
|ż&lt;br /&gt;
|119&lt;br /&gt;
|&lt;br /&gt;
|41&lt;br /&gt;
|Ú&lt;br /&gt;
|15&lt;br /&gt;
|&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|18&lt;br /&gt;
|å&lt;br /&gt;
|109&lt;br /&gt;
|Danish&lt;br /&gt;
|42&lt;br /&gt;
|Á&lt;br /&gt;
|13&lt;br /&gt;
|&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|19&lt;br /&gt;
|š&lt;br /&gt;
|99&lt;br /&gt;
|&lt;br /&gt;
|43&lt;br /&gt;
|î&lt;br /&gt;
|12&lt;br /&gt;
|&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|20&lt;br /&gt;
|ś&lt;br /&gt;
|97&lt;br /&gt;
|&lt;br /&gt;
|44&lt;br /&gt;
|ť&lt;br /&gt;
|11&lt;br /&gt;
|&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|21&lt;br /&gt;
|ç&lt;br /&gt;
|91&lt;br /&gt;
|&lt;br /&gt;
|45&lt;br /&gt;
|ô&lt;br /&gt;
|9&lt;br /&gt;
|&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|22&lt;br /&gt;
|ä&lt;br /&gt;
|86&lt;br /&gt;
|German&lt;br /&gt;
|46&lt;br /&gt;
|Ž&lt;br /&gt;
|8&lt;br /&gt;
|&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|23&lt;br /&gt;
|à&lt;br /&gt;
|83&lt;br /&gt;
|&lt;br /&gt;
|47&lt;br /&gt;
|Ż&lt;br /&gt;
|7&lt;br /&gt;
|&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|24&lt;br /&gt;
|ů&lt;br /&gt;
|77&lt;br /&gt;
|&lt;br /&gt;
|48&lt;br /&gt;
|Č&lt;br /&gt;
|7&lt;br /&gt;
|&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|25&lt;br /&gt;
|ć&lt;br /&gt;
|67&lt;br /&gt;
|&lt;br /&gt;
|49&lt;br /&gt;
|ù&lt;br /&gt;
|6&lt;br /&gt;
|&lt;br /&gt;
&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Although ö, ä and ü do not appear that often, with only these and Ü, Ö, Ä and ß, the entire German language works. So adding these letters to the fonts is quite important. &lt;br /&gt;
&lt;br /&gt;
Preferably, all foreign letters would be added to the fonts (see [[Font Patcher]] or [[Refont]]). However, if time permits only adding a few, &#039;&#039;&#039;í&#039;&#039;&#039; would be more important than, say, &#039;&#039;&#039;ô&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
It is commonplace for missing accented letters to be redirected in the .dat file to the corresponding unaccented base letter.&lt;br /&gt;
&lt;br /&gt;
=== Coverage Expansion &amp;amp; Remaining Limitations ===&lt;br /&gt;
&lt;br /&gt;
By 2014, all the system (e.g., main menu) fonts (Carleton, Carleton_condensed, Stone in sizes 24pt and 48pt; Mason and Mason_glow in 48pt) had good coverage of the &amp;quot;Top 50&amp;quot; and beyond, although not all 256 codepoints. &lt;br /&gt;
This was confirmed more specifically in 2024, as part of an [https://forums.thedarkmod.com/index.php?/topic/22427-analysis-of-212-tdm-fonts/ Analysis of 2.12 Fonts]. This analysis indicated that, unlike the system fonts, the FM fonts generally did not provide specific glyphs beyond ASCII.&lt;br /&gt;
&lt;br /&gt;
In 2024, Stone 24pt, important for subtitles and a number of readables, was further extended to cover all 256 codepoints. This was tested with TDM 2.13[betas] and released with 2.14. Similar Stone 48pt and Carleton 24pt improvements are planned for TDM 2.15.&lt;br /&gt;
&lt;br /&gt;
[[Category:Fonts]]&lt;br /&gt;
&lt;br /&gt;
{{i18n}}&lt;/div&gt;</summary>
		<author><name>Geep</name></author>
	</entry>
	<entry>
		<id>https://wiki.thedarkmod.com/index.php?title=I18N_-_Charset&amp;diff=34413</id>
		<title>I18N - Charset</title>
		<link rel="alternate" type="text/html" href="https://wiki.thedarkmod.com/index.php?title=I18N_-_Charset&amp;diff=34413"/>
		<updated>2026-01-21T20:09:12Z</updated>

		<summary type="html">&lt;p&gt;Geep: /* European Character Implementation */ subsection headers, minor updates&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction ==&lt;br /&gt;
&lt;br /&gt;
The D3 code that handles the GUI bitmap font can only load a specific range of bytes as characters. To get the most out of the available entries, special charsets are used. The fonts (Carleton for the menu f.i.) are build/patched so that the right characters appear in the right place.&lt;br /&gt;
&lt;br /&gt;
== Encodings ==&lt;br /&gt;
&lt;br /&gt;
=== all.lang ===&lt;br /&gt;
&lt;br /&gt;
This file is in &#039;&#039;&#039;UTF-8&#039;&#039;&#039;, and converted with the help of the script &#039;&#039;&#039;devel/gen_lang.pl&#039;&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
 perl devel/gen_lang.pl&lt;br /&gt;
&lt;br /&gt;
This ensures that the generated language files are in their proper encodings (see below).&lt;br /&gt;
&lt;br /&gt;
=== All other language files ===&lt;br /&gt;
&lt;br /&gt;
Note that the language files (f.i. &#039;&#039;&#039;strings/german.lang&#039;&#039;&#039;) as well as the readables and the FM dictionariaries are expected to be in the following encodings:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Czech&#039;&#039;&#039;, &#039;&#039;&#039;Hungarian&#039;&#039;&#039;, &#039;&#039;&#039;Slovak&#039;&#039;&#039;, &#039;&#039;&#039;Polish:&#039;&#039;&#039; [https://secure.wikimedia.org/wikipedia/en/wiki/ISO/IEC_8859-2 ISO-8859-2] (&#039;&#039;&#039;not WIN-1250!)&lt;br /&gt;
* &#039;&#039;&#039;Russian:&#039;&#039;&#039; [https://secure.wikimedia.org/wikipedia/en/wiki/Win-1251 WIN-1251]&lt;br /&gt;
* &#039;&#039;&#039;French:&#039;&#039;&#039; [https://secure.wikimedia.org/wikipedia/en/wiki/ISO/IEC_8859-15 ISO-8859-15]&lt;br /&gt;
* &#039;&#039;&#039;Romanian:&#039;&#039;&#039; [https://secure.wikimedia.org/wikipedia/en/wiki/ISO/IEC_8859-16 ISO-8859-16] &lt;br /&gt;
* &#039;&#039;&#039;All other languages:&#039;&#039;&#039; [https://secure.wikimedia.org/wikipedia/en/wiki/ISO/IEC_8859-1 ISO-8859-1] (German, Dutch, Danish, Swedish, Portuguese, etc.)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{{infobox|The core dictionaries are automatically generated in the right encoding, but make sure that you use the right encoding for the FM dictionary, too!}}&lt;br /&gt;
&lt;br /&gt;
== Character remapping ==&lt;br /&gt;
&lt;br /&gt;
The characters are remapped upon loading the dictionary/readable, from their native encoding to the special one that TDM uses and that is described here.  Responsible for the remapping are [[I18N - Character mapping|mapping files]], f.i. &amp;quot;strings/czech.map&amp;quot;. If a map file for a specific language is not found, &amp;quot;strings/default.map&amp;quot; is used instead, if this is not found, no remapping takes place.&lt;br /&gt;
&lt;br /&gt;
See &#039;&#039;&#039;[[I18N - Character mapping|Character mapping]]&#039;&#039;&#039; for more information.&lt;br /&gt;
&lt;br /&gt;
=== European Languages ===&lt;br /&gt;
&lt;br /&gt;
This mapping is used for European languages, f.i. &#039;&#039;&#039;Czech&#039;&#039;&#039;, &#039;&#039;&#039;French&#039;&#039;&#039;, &#039;&#039;&#039;German&#039;&#039;&#039;, &#039;&#039;&#039;Spanish&#039;&#039;&#039;, &#039;&#039;&#039;Portuguese&#039;&#039;&#039;, &#039;&#039;&#039;Polish&#039;&#039;&#039;. Note that the double accented characters in Hungarian &#039;&#039;&#039;Ő, ő, Ű and ű&#039;&#039;&#039; look a bit different from &#039;&#039;&#039;Ö, ö, Ü and ü&#039;&#039;&#039;!&lt;br /&gt;
&lt;br /&gt;
In the table below, the original ISO 8859-1 characters are given in &#039;&#039;()&#039;&#039; below the TDM character.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Color code:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
{{box|#f0d0d0|Character not usable by TDM|Unusable}}{{box|#d0e0d0|Character not yet used in TDM|Unused}}{{box|#c0ffc0|Character displayed in v1.08 or newer|Usable in v1.08}}{{box|#80f080|Character displayed in v2.03 or newer|Usable in v2.03}}{{box|#d0d0f0|Changed from the ISO-8859-1 default, usable by TDM 1.0 or newer|Changed from ISO 8859-1}}&lt;br /&gt;
&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot; border=1 style=&amp;quot;border-collapse: collapse; font-size: 95%&amp;quot; cellspacing=0 cellpadding=2 width=100%&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
!&lt;br /&gt;
!…0&lt;br /&gt;
!…1&lt;br /&gt;
!…2&lt;br /&gt;
!…3&lt;br /&gt;
!…4&lt;br /&gt;
!…5&lt;br /&gt;
!…6&lt;br /&gt;
!…7&lt;br /&gt;
!…8&lt;br /&gt;
!…9&lt;br /&gt;
!…A&lt;br /&gt;
!…B&lt;br /&gt;
!…C&lt;br /&gt;
!…D&lt;br /&gt;
!…E&lt;br /&gt;
!…F&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
!0…&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #f0d0d0&#039;|00&amp;lt;br&amp;gt;&#039;&#039;&#039;–&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #f0d0d0&#039;|01&amp;lt;br&amp;gt;&#039;&#039;&#039;–&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #f0d0d0&#039;|02&amp;lt;br&amp;gt;&#039;&#039;&#039;–&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #f0d0d0&#039;|03&amp;lt;br&amp;gt;&#039;&#039;&#039;–&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #f0d0d0&#039;|04&amp;lt;br&amp;gt;&#039;&#039;&#039;–&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #f0d0d0&#039;|05&amp;lt;br&amp;gt;&#039;&#039;&#039;–&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #f0d0d0&#039;|06&amp;lt;br&amp;gt;&#039;&#039;&#039;–&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #f0d0d0&#039;|07&amp;lt;br&amp;gt;&#039;&#039;&#039;–&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #f0d0d0&#039;|08&amp;lt;br&amp;gt;&#039;&#039;&#039;–&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #f0d0d0&#039;|09&amp;lt;br&amp;gt;&#039;&#039;&#039;–&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #f0d0d0&#039;|0A&amp;lt;br&amp;gt;&#039;&#039;&#039;–&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #f0d0d0&#039;|0B&amp;lt;br&amp;gt;&#039;&#039;&#039;–&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #f0d0d0&#039;|0C&amp;lt;br&amp;gt;&#039;&#039;&#039;–&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #f0d0d0&#039;|0D&amp;lt;br&amp;gt;&#039;&#039;&#039;–&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #f0d0d0&#039;|0E&amp;lt;br&amp;gt;&#039;&#039;&#039;–&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #f0d0d0&#039;|0F&amp;lt;br&amp;gt;&#039;&#039;&#039;–&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
!1…&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #f0d0d0&#039;|10&amp;lt;br&amp;gt;&#039;&#039;&#039;–&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #f0d0d0&#039;|11&amp;lt;br&amp;gt;&#039;&#039;&#039;–&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #f0d0d0&#039;|12&amp;lt;br&amp;gt;&#039;&#039;&#039;–&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #f0d0d0&#039;|13&amp;lt;br&amp;gt;&#039;&#039;&#039;–&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #f0d0d0&#039;|14&amp;lt;br&amp;gt;&#039;&#039;&#039;–&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #f0d0d0&#039;|15&amp;lt;br&amp;gt;&#039;&#039;&#039;–&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #f0d0d0&#039;|16&amp;lt;br&amp;gt;&#039;&#039;&#039;–&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #f0d0d0&#039;|17&amp;lt;br&amp;gt;&#039;&#039;&#039;–&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #f0d0d0&#039;|18&amp;lt;br&amp;gt;&#039;&#039;&#039;–&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #f0d0d0&#039;|19&amp;lt;br&amp;gt;&#039;&#039;&#039;–&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #f0d0d0&#039;|1A&amp;lt;br&amp;gt;&#039;&#039;&#039;–&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #f0d0d0&#039;|1B&amp;lt;br&amp;gt;&#039;&#039;&#039;–&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #f0d0d0&#039;|1C&amp;lt;br&amp;gt;&#039;&#039;&#039;–&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #f0d0d0&#039;|1D&amp;lt;br&amp;gt;&#039;&#039;&#039;–&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #f0d0d0&#039;|1E&amp;lt;br&amp;gt;&#039;&#039;&#039;–&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #f0d0d0&#039;|1F&amp;lt;br&amp;gt;&#039;&#039;&#039;–&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
!2…&lt;br /&gt;
|align=&#039;center&#039;|20&amp;lt;br&amp;gt;&#039;&#039;&#039;&amp;amp;nbsp;&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|21&amp;lt;br&amp;gt;&#039;&#039;&#039;!&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|22&amp;lt;br&amp;gt;&#039;&#039;&#039;&amp;quot;&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|23&amp;lt;br&amp;gt;&#039;&#039;&#039;#&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|24&amp;lt;br&amp;gt;&#039;&#039;&#039;$&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|25&amp;lt;br&amp;gt;&#039;&#039;&#039;%&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|26&amp;lt;br&amp;gt;&#039;&#039;&#039;&amp;amp;&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|27&amp;lt;br&amp;gt;&#039;&#039;&#039;&#039;&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|28&amp;lt;br&amp;gt;&#039;&#039;&#039;(&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|29&amp;lt;br&amp;gt;&#039;&#039;&#039;)&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|2A&amp;lt;br&amp;gt;&#039;&#039;&#039;*&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|2B&amp;lt;br&amp;gt;&#039;&#039;&#039;+&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|2C&amp;lt;br&amp;gt;&#039;&#039;&#039;,&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|2D&amp;lt;br&amp;gt;&#039;&#039;&#039;-&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|2E&amp;lt;br&amp;gt;&#039;&#039;&#039;.&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|2F&amp;lt;br&amp;gt;&#039;&#039;&#039;/&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
!3…&lt;br /&gt;
|align=&#039;center&#039;|30&amp;lt;br&amp;gt;&#039;&#039;&#039;0&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|31&amp;lt;br&amp;gt;&#039;&#039;&#039;1&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|32&amp;lt;br&amp;gt;&#039;&#039;&#039;2&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|33&amp;lt;br&amp;gt;&#039;&#039;&#039;3&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|34&amp;lt;br&amp;gt;&#039;&#039;&#039;4&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|35&amp;lt;br&amp;gt;&#039;&#039;&#039;5&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|36&amp;lt;br&amp;gt;&#039;&#039;&#039;6&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|37&amp;lt;br&amp;gt;&#039;&#039;&#039;7&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|38&amp;lt;br&amp;gt;&#039;&#039;&#039;8&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|39&amp;lt;br&amp;gt;&#039;&#039;&#039;9&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|3A&amp;lt;br&amp;gt;&#039;&#039;&#039;:&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|3B&amp;lt;br&amp;gt;&#039;&#039;&#039;;&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|3C&amp;lt;br&amp;gt;&#039;&#039;&#039;&amp;lt;&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|3D&amp;lt;br&amp;gt;&#039;&#039;&#039;=&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|3E&amp;lt;br&amp;gt;&#039;&#039;&#039;&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|3F&amp;lt;br&amp;gt;&#039;&#039;&#039;?&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
!4…&lt;br /&gt;
|align=&#039;center&#039;|40&amp;lt;br&amp;gt;&#039;&#039;&#039;@&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|41&amp;lt;br&amp;gt;&#039;&#039;&#039;A&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|42&amp;lt;br&amp;gt;&#039;&#039;&#039;B&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|43&amp;lt;br&amp;gt;&#039;&#039;&#039;C&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|44&amp;lt;br&amp;gt;&#039;&#039;&#039;D&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|45&amp;lt;br&amp;gt;&#039;&#039;&#039;E&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|46&amp;lt;br&amp;gt;&#039;&#039;&#039;F&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|47&amp;lt;br&amp;gt;&#039;&#039;&#039;G&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|48&amp;lt;br&amp;gt;&#039;&#039;&#039;H&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|49&amp;lt;br&amp;gt;&#039;&#039;&#039;I&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|4A&amp;lt;br&amp;gt;&#039;&#039;&#039;J&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|4B&amp;lt;br&amp;gt;&#039;&#039;&#039;K&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|4C&amp;lt;br&amp;gt;&#039;&#039;&#039;L&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|4D&amp;lt;br&amp;gt;&#039;&#039;&#039;M&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|4E&amp;lt;br&amp;gt;&#039;&#039;&#039;N&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|4F&amp;lt;br&amp;gt;&#039;&#039;&#039;O&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
!5…&lt;br /&gt;
|align=&#039;center&#039;|50&amp;lt;br&amp;gt;&#039;&#039;&#039;P&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|51&amp;lt;br&amp;gt;&#039;&#039;&#039;Q&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|52&amp;lt;br&amp;gt;&#039;&#039;&#039;R&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|53&amp;lt;br&amp;gt;&#039;&#039;&#039;S&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|54&amp;lt;br&amp;gt;&#039;&#039;&#039;T&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|55&amp;lt;br&amp;gt;&#039;&#039;&#039;U&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|56&amp;lt;br&amp;gt;&#039;&#039;&#039;V&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|57&amp;lt;br&amp;gt;&#039;&#039;&#039;W&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|58&amp;lt;br&amp;gt;&#039;&#039;&#039;X&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|59&amp;lt;br&amp;gt;&#039;&#039;&#039;Y&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|5A&amp;lt;br&amp;gt;&#039;&#039;&#039;Z&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|5B&amp;lt;br&amp;gt;&#039;&#039;&#039;[&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|5C&amp;lt;br&amp;gt;&#039;&#039;&#039;\&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|5D&amp;lt;br&amp;gt;&#039;&#039;&#039;]&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|5E&amp;lt;br&amp;gt;&#039;&#039;&#039;^&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|5F&amp;lt;br&amp;gt;&#039;&#039;&#039;_&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
!6…&lt;br /&gt;
|align=&#039;center&#039;|60&amp;lt;br&amp;gt;&#039;&#039;&#039;`&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|61&amp;lt;br&amp;gt;&#039;&#039;&#039;a&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|62&amp;lt;br&amp;gt;&#039;&#039;&#039;b&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|63&amp;lt;br&amp;gt;&#039;&#039;&#039;c&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|64&amp;lt;br&amp;gt;&#039;&#039;&#039;d&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|65&amp;lt;br&amp;gt;&#039;&#039;&#039;e&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|66&amp;lt;br&amp;gt;&#039;&#039;&#039;f&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|67&amp;lt;br&amp;gt;&#039;&#039;&#039;g&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|68&amp;lt;br&amp;gt;&#039;&#039;&#039;h&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|69&amp;lt;br&amp;gt;&#039;&#039;&#039;i&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|6A&amp;lt;br&amp;gt;&#039;&#039;&#039;j&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|6B&amp;lt;br&amp;gt;&#039;&#039;&#039;k&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|6C&amp;lt;br&amp;gt;&#039;&#039;&#039;l&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|6D&amp;lt;br&amp;gt;&#039;&#039;&#039;m&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|6E&amp;lt;br&amp;gt;&#039;&#039;&#039;n&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|6F&amp;lt;br&amp;gt;&#039;&#039;&#039;o&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
!7…&lt;br /&gt;
|align=&#039;center&#039;|70&amp;lt;br&amp;gt;&#039;&#039;&#039;p&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|71&amp;lt;br&amp;gt;&#039;&#039;&#039;q&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|72&amp;lt;br&amp;gt;&#039;&#039;&#039;r&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|73&amp;lt;br&amp;gt;&#039;&#039;&#039;s&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|74&amp;lt;br&amp;gt;&#039;&#039;&#039;t&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|75&amp;lt;br&amp;gt;&#039;&#039;&#039;u&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|76&amp;lt;br&amp;gt;&#039;&#039;&#039;v&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|77&amp;lt;br&amp;gt;&#039;&#039;&#039;w&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|78&amp;lt;br&amp;gt;&#039;&#039;&#039;x&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|79&amp;lt;br&amp;gt;&#039;&#039;&#039;y&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|7A&amp;lt;br&amp;gt;&#039;&#039;&#039;z&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|7B&amp;lt;br&amp;gt;&#039;&#039;&#039;{&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|7C&amp;lt;br&amp;gt;&#039;&#039;&#039;|&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|7D&amp;lt;br&amp;gt;&#039;&#039;&#039;}&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|7E&amp;lt;br&amp;gt;&#039;&#039;&#039;~&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #d0e0d0&#039;|7F&amp;lt;br&amp;gt;&#039;&#039;&#039;�&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
!8…&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #c0ffc0&#039;|80&amp;lt;br&amp;gt;&#039;&#039;&#039;Ň&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #c0ffc0&#039;|81&amp;lt;br&amp;gt;&#039;&#039;&#039;Ś&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #c0ffc0&#039;|82&amp;lt;br&amp;gt;&#039;&#039;&#039;Ć&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #c0ffc0&#039;|83&amp;lt;br&amp;gt;&#039;&#039;&#039;Ż&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #c0ffc0&#039;|84&amp;lt;br&amp;gt;&#039;&#039;&#039;Ź&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #c0ffc0&#039;|85&amp;lt;br&amp;gt;&#039;&#039;&#039;Ŝ&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #c0ffc0&#039;|86&amp;lt;br&amp;gt;&#039;&#039;&#039;Ĉ&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #c0ffc0&#039;|87&amp;lt;br&amp;gt;&#039;&#039;&#039;Ẑ&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #c0ffc0&#039;|88&amp;lt;br&amp;gt;&#039;&#039;&#039;Ô&#039;&#039;&#039; [note]&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #c0ffc0&#039;|89&amp;lt;br&amp;gt;&#039;&#039;&#039;Ŕ&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #c0ffc0&#039;|8A&amp;lt;br&amp;gt;&#039;&#039;&#039;Ǔ&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #c0ffc0&#039;|8B&amp;lt;br&amp;gt;&#039;&#039;&#039;Ă&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #c0ffc0&#039;|8C&amp;lt;br&amp;gt;&#039;&#039;&#039;Ń&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #80f080&#039;|8D&amp;lt;br&amp;gt;&#039;&#039;&#039;Ș&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #80f080&#039;|8E&amp;lt;br&amp;gt;&#039;&#039;&#039;Ț&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #d0e0d0&#039;|8F&amp;lt;br&amp;gt;&#039;&#039;&#039;�&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
!9…&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #80f080&#039;|90&amp;lt;br&amp;gt;&#039;&#039;&#039;đ&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #c0ffc0&#039;|91&amp;lt;br&amp;gt;&#039;&#039;&#039;ś&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #c0ffc0&#039;|92&amp;lt;br&amp;gt;&#039;&#039;&#039;ć&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #c0ffc0&#039;|93&amp;lt;br&amp;gt;&#039;&#039;&#039;ż&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #c0ffc0&#039;|94&amp;lt;br&amp;gt;&#039;&#039;&#039;ź&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #c0ffc0&#039;|95&amp;lt;br&amp;gt;&#039;&#039;&#039;ŝ&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #c0ffc0&#039;|96&amp;lt;br&amp;gt;&#039;&#039;&#039;ĉ&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #c0ffc0&#039;|97&amp;lt;br&amp;gt;&#039;&#039;&#039;ẑ&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #c0ffc0&#039;|98&amp;lt;br&amp;gt;&#039;&#039;&#039;ô&#039;&#039;&#039; [note]&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #c0ffc0&#039;|99&amp;lt;br&amp;gt;&#039;&#039;&#039;ŕ&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #c0ffc0&#039;|9A&amp;lt;br&amp;gt;&#039;&#039;&#039;ǔ&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #c0ffc0&#039;|9B&amp;lt;br&amp;gt;&#039;&#039;&#039;ă&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #c0ffc0&#039;|9C&amp;lt;br&amp;gt;&#039;&#039;&#039;ń&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #80f080&#039;|9D&amp;lt;br&amp;gt;&#039;&#039;&#039;ș&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #80f080&#039;|9E&amp;lt;br&amp;gt;&#039;&#039;&#039;ț&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #d0e0d0&#039;|9F&amp;lt;br&amp;gt;&#039;&#039;&#039;�&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
!A…&lt;br /&gt;
|align=&#039;center&#039;|A0&amp;lt;br&amp;gt;&#039;&#039;&#039;[https://secure.wikimedia.org/wikipedia/en/wiki/Non-breaking_space NBSP]&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #d0d0f0&#039;|A1&amp;lt;br&amp;gt;&#039;&#039;&#039;ň&#039;&#039;&#039;&amp;lt;br&amp;gt;(¡)&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #d0d0f0&#039;|A2&amp;lt;br&amp;gt;&#039;&#039;&#039;Ű&#039;&#039;&#039;&amp;lt;br&amp;gt;(¢)&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #d0d0f0&#039;|A3&amp;lt;br&amp;gt;&#039;&#039;&#039;ě&#039;&#039;&#039;&amp;lt;br&amp;gt;(£)&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #d0d0f0&#039;|A4&amp;lt;br&amp;gt;&#039;&#039;&#039;ű&#039;&#039;&#039;&amp;lt;br&amp;gt;(¤)&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #d0d0f0&#039;|A5&amp;lt;br&amp;gt;&#039;&#039;&#039;Ě&#039;&#039;&#039;&amp;lt;br&amp;gt;(¥)&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #d0d0f0&#039;|A6&amp;lt;br&amp;gt;&#039;&#039;&#039;Š&#039;&#039;&#039;&amp;lt;br&amp;gt;(¦)&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|A7&amp;lt;br&amp;gt;&#039;&#039;&#039;§&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #d0d0f0&#039;|A8&amp;lt;br&amp;gt;&#039;&#039;&#039;š&#039;&#039;&#039;&amp;lt;br&amp;gt;(¨)&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #d0d0f0&#039;|A9&amp;lt;br&amp;gt;&#039;&#039;&#039;Ů&#039;&#039;&#039;&amp;lt;br&amp;gt;(©)&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #d0d0f0&#039;|AA&amp;lt;br&amp;gt;&#039;&#039;&#039;Ą&#039;&#039;&#039;&amp;lt;br&amp;gt;(ª)&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #d0d0f0&#039;|AB&amp;lt;br&amp;gt;&#039;&#039;&#039;Ę&#039;&#039;&#039;&amp;lt;br&amp;gt;(«)&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #d0d0f0&#039;|AC&amp;lt;br&amp;gt;&#039;&#039;&#039;Č&#039;&#039;&#039;&amp;lt;br&amp;gt;(¬)&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|AD&amp;lt;br&amp;gt;&#039;&#039;&#039;[https://secure.wikimedia.org/wikipedia/en/wiki/Soft_hyphen SHY]&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #d0d0f0&#039;|AE&amp;lt;br&amp;gt;&#039;&#039;&#039;č&#039;&#039;&#039;&amp;lt;br&amp;gt;(®)&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #d0d0f0&#039;|AF&amp;lt;br&amp;gt;&#039;&#039;&#039;ů&#039;&#039;&#039;&amp;lt;br&amp;gt;(¯)&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
!B…&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #d0d0f0&#039;|B0&amp;lt;br&amp;gt;&#039;&#039;&#039;Ő&#039;&#039;&#039;&amp;lt;br&amp;gt;(°)&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #d0d0f0&#039;|B1&amp;lt;br&amp;gt;&#039;&#039;&#039;Ł&#039;&#039;&#039;&amp;lt;br&amp;gt;(±)&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #d0d0f0&#039;|B2&amp;lt;br&amp;gt;&#039;&#039;&#039;Ť&#039;&#039;&#039;&amp;lt;br&amp;gt;(²)&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #d0d0f0&#039;|B3&amp;lt;br&amp;gt;&#039;&#039;&#039;Ď&#039;&#039;&#039;&amp;lt;br&amp;gt;(³)&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #d0d0f0&#039;|B4&amp;lt;br&amp;gt;&#039;&#039;&#039;Ž&#039;&#039;&#039;&amp;lt;br&amp;gt;(´)&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #d0d0f0&#039;|B5&amp;lt;br&amp;gt;&#039;&#039;&#039;ł&#039;&#039;&#039;&amp;lt;br&amp;gt;(µ)&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #d0d0f0&#039;|B6&amp;lt;br&amp;gt;&#039;&#039;&#039;ť&#039;&#039;&#039;&amp;lt;br&amp;gt;(¶)&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #d0d0f0&#039;|B7&amp;lt;br&amp;gt;&#039;&#039;&#039;ď&#039;&#039;&#039;&amp;lt;br&amp;gt;(·)&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #d0d0f0&#039;|B8&amp;lt;br&amp;gt;&#039;&#039;&#039;ž&#039;&#039;&#039;&amp;lt;br&amp;gt;(¸)&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #d0d0f0&#039;|B9&amp;lt;br&amp;gt;&#039;&#039;&#039;ő&#039;&#039;&#039;&amp;lt;br&amp;gt;(¹)&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #d0d0f0&#039;|BA&amp;lt;br&amp;gt;&#039;&#039;&#039;ą&#039;&#039;&#039;&amp;lt;br&amp;gt;(º)&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #d0d0f0&#039;|BB&amp;lt;br&amp;gt;&#039;&#039;&#039;ę&#039;&#039;&#039;&amp;lt;br&amp;gt;(»)&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #d0d0f0&#039;|BC&amp;lt;br&amp;gt;&#039;&#039;&#039;Œ&#039;&#039;&#039;&amp;lt;br&amp;gt;(¼)&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #d0d0f0&#039;|BD&amp;lt;br&amp;gt;&#039;&#039;&#039;œ&#039;&#039;&#039;&amp;lt;br&amp;gt;(½)&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #d0d0f0&#039;|BE&amp;lt;br&amp;gt;&#039;&#039;&#039;Ÿ&#039;&#039;&#039;&amp;lt;br&amp;gt;(¾)&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|BF&amp;lt;br&amp;gt;&#039;&#039;&#039;¿&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
!C…&lt;br /&gt;
|align=&#039;center&#039;|C0&amp;lt;br&amp;gt;&#039;&#039;&#039;À&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|C1&amp;lt;br&amp;gt;&#039;&#039;&#039;Á&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|C2&amp;lt;br&amp;gt;&#039;&#039;&#039;Â&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|C3&amp;lt;br&amp;gt;&#039;&#039;&#039;Ã&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|C4&amp;lt;br&amp;gt;&#039;&#039;&#039;Ä&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|C5&amp;lt;br&amp;gt;&#039;&#039;&#039;Å&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|C6&amp;lt;br&amp;gt;&#039;&#039;&#039;Æ&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|C7&amp;lt;br&amp;gt;&#039;&#039;&#039;Ç&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|C8&amp;lt;br&amp;gt;&#039;&#039;&#039;È&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|C9&amp;lt;br&amp;gt;&#039;&#039;&#039;É&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|CA&amp;lt;br&amp;gt;&#039;&#039;&#039;Ê&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|CB&amp;lt;br&amp;gt;&#039;&#039;&#039;Ë&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|CC&amp;lt;br&amp;gt;&#039;&#039;&#039;Ì&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|CD&amp;lt;br&amp;gt;&#039;&#039;&#039;Í&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|CE&amp;lt;br&amp;gt;&#039;&#039;&#039;Î&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|CF&amp;lt;br&amp;gt;&#039;&#039;&#039;Ï&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
!D…&lt;br /&gt;
|align=&#039;center&#039;|D0&amp;lt;br&amp;gt;&#039;&#039;&#039;Ð&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|D1&amp;lt;br&amp;gt;&#039;&#039;&#039;Ñ&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|D2&amp;lt;br&amp;gt;&#039;&#039;&#039;Ò&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|D3&amp;lt;br&amp;gt;&#039;&#039;&#039;Ó&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|D4&amp;lt;br&amp;gt;&#039;&#039;&#039;Ô&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|D5&amp;lt;br&amp;gt;&#039;&#039;&#039;Õ&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|D6&amp;lt;br&amp;gt;&#039;&#039;&#039;Ö&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #d0d0f0&#039;|D7&amp;lt;br&amp;gt;&#039;&#039;&#039;Ř&#039;&#039;&#039;&amp;lt;br&amp;gt;(×)&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|D8&amp;lt;br&amp;gt;&#039;&#039;&#039;Ø&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|D9&amp;lt;br&amp;gt;&#039;&#039;&#039;Ù&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|DA&amp;lt;br&amp;gt;&#039;&#039;&#039;Ú&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|DB&amp;lt;br&amp;gt;&#039;&#039;&#039;Û&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|DC&amp;lt;br&amp;gt;&#039;&#039;&#039;Ü&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|DD&amp;lt;br&amp;gt;&#039;&#039;&#039;Ý&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|DE&amp;lt;br&amp;gt;&#039;&#039;&#039;Þ&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|DF&amp;lt;br&amp;gt;&#039;&#039;&#039;ß&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
!E…&lt;br /&gt;
|align=&#039;center&#039;|E0&amp;lt;br&amp;gt;&#039;&#039;&#039;à&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|E1&amp;lt;br&amp;gt;&#039;&#039;&#039;á&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|E2&amp;lt;br&amp;gt;&#039;&#039;&#039;â&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|E3&amp;lt;br&amp;gt;&#039;&#039;&#039;ã&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|E4&amp;lt;br&amp;gt;&#039;&#039;&#039;ä&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|E5&amp;lt;br&amp;gt;&#039;&#039;&#039;å&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|E6&amp;lt;br&amp;gt;&#039;&#039;&#039;æ&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|E7&amp;lt;br&amp;gt;&#039;&#039;&#039;ç&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|E8&amp;lt;br&amp;gt;&#039;&#039;&#039;è&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|E9&amp;lt;br&amp;gt;&#039;&#039;&#039;é&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|EA&amp;lt;br&amp;gt;&#039;&#039;&#039;ê&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|EB&amp;lt;br&amp;gt;&#039;&#039;&#039;ë&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|EC&amp;lt;br&amp;gt;&#039;&#039;&#039;ì&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|ED&amp;lt;br&amp;gt;&#039;&#039;&#039;í&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|EE&amp;lt;br&amp;gt;&#039;&#039;&#039;î&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|EF&amp;lt;br&amp;gt;&#039;&#039;&#039;ï&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
!F…&lt;br /&gt;
|align=&#039;center&#039;|F0&amp;lt;br&amp;gt;&#039;&#039;&#039;ð&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|F1&amp;lt;br&amp;gt;&#039;&#039;&#039;ñ&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|F2&amp;lt;br&amp;gt;&#039;&#039;&#039;ò&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|F3&amp;lt;br&amp;gt;&#039;&#039;&#039;ó&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|F4&amp;lt;br&amp;gt;&#039;&#039;&#039;ô&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|F5&amp;lt;br&amp;gt;&#039;&#039;&#039;õ&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|F6&amp;lt;br&amp;gt;&#039;&#039;&#039;ö&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039; style=&#039;background: #d0d0f0&#039;|F7&amp;lt;br&amp;gt;&#039;&#039;&#039;ř&#039;&#039;&#039;&amp;lt;br&amp;gt;(÷)&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|F8&amp;lt;br&amp;gt;&#039;&#039;&#039;ø&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|F9&amp;lt;br&amp;gt;&#039;&#039;&#039;ù&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|FA&amp;lt;br&amp;gt;&#039;&#039;&#039;ú&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|FB&amp;lt;br&amp;gt;&#039;&#039;&#039;û&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|FC&amp;lt;br&amp;gt;&#039;&#039;&#039;ü&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|FD&amp;lt;br&amp;gt;&#039;&#039;&#039;ý&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|FE&amp;lt;br&amp;gt;&#039;&#039;&#039;þ&#039;&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|FF&amp;lt;br&amp;gt;&#039;&#039;&#039;ÿ&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
[note] As discussed [https://forums.thedarkmod.com/index.php?/topic/22427-analysis-of-212-tdm-fonts/&amp;amp;do=findComment&amp;amp;comment=494855 here], the TDM char set has a redundant treatment of 2 characters:&lt;br /&gt;
&lt;br /&gt;
* Ô appears at 0x88 and 0xD4&lt;br /&gt;
* ô appears at 0x98 and 0xF4&lt;br /&gt;
&lt;br /&gt;
Planned for TDM 2.13, the redundancy can be removed and these new characters (from ISO-8859-3) introduced:&lt;br /&gt;
&lt;br /&gt;
* Ğ appears at 0x88&lt;br /&gt;
* ğ appears at 0x98&lt;br /&gt;
&lt;br /&gt;
For a mapping of these 256 codepoints to Unicode U+NNNN values and formal names, download &#039;TDM 8859-Style Font Map to Unicode-16.txt&#039;: &lt;br /&gt;
&lt;br /&gt;
* [https://drive.google.com/file/d/1wLEtuFvnrZ-WHK8ign8i3diIXZdriZ4F/view?usp=sharing for TDM 2.13]&lt;br /&gt;
* [https://drive.google.com/file/d/1UAz9jSZpT_j33STP3So_Re8JWa8QuAmz/view?usp=sharing for TDM 2.12 and earlier]&lt;br /&gt;
&lt;br /&gt;
Each of these files (by Geep, 2024) is in a standardized format so that it can also be imported into font design programs like FontForge as a custom 256-position map. In the comments, there is additional information about:&lt;br /&gt;
* ISO 8859-x sourcing of each character.&lt;br /&gt;
* alternative representations of some European and control characters.&lt;br /&gt;
&lt;br /&gt;
=== Russian ===&lt;br /&gt;
&lt;br /&gt;
Characters conform to the [https://en.wikipedia.org/wiki/Win-1251 WIN-1251 native encoding, shown in the Wikipedia article]. Exception: the character &#039;&#039;&#039;0xFF&#039;&#039;&#039; (я) is mapped to &#039;&#039;&#039;0xB6&#039;&#039;&#039; upon loading. Therefore any Russian font must contain я at the place 0xB6.&lt;br /&gt;
&lt;br /&gt;
=== Asian Languages (Korean, Chinese, Japanese) ===&lt;br /&gt;
&lt;br /&gt;
The original D3 had support for these languages, so it might be possible to add them to TDM, too. At the moment, however, we lack the fonts and translators. Also, writing from right-to-left (Hebrew) or top-down (Japanese) might be tricky or outright impossible in our GUI without more work in the C++ code. Plus, these languages use more than 256 different characters, and an 8 bit table will not hold these.&lt;br /&gt;
&lt;br /&gt;
== European Character Implementation ==&lt;br /&gt;
=== Priority Early-On - the &amp;quot;Top 50&amp;quot; ===&lt;br /&gt;
&lt;br /&gt;
Some of the special characters are used more often than others. Here is a statistic over the entire string set of the TDM core, from TDM v1.08, showing the top 50 most-used characters (excluding a-z, 0-9 and russian characters):&lt;br /&gt;
&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot; border=1 style=&amp;quot;border-collapse: collapse; font-size: 85%&amp;quot; cellspacing=0 cellpadding=2&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|Rank&lt;br /&gt;
|Occurances&lt;br /&gt;
|Letter&lt;br /&gt;
|Remarks&lt;br /&gt;
|Rank&lt;br /&gt;
|Occurances&lt;br /&gt;
|Letter&lt;br /&gt;
|Remarks&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|1&lt;br /&gt;
|í&lt;br /&gt;
|715&lt;br /&gt;
|&lt;br /&gt;
|25&lt;br /&gt;
|ć&lt;br /&gt;
|67&lt;br /&gt;
|&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|2&lt;br /&gt;
|é&lt;br /&gt;
|674&lt;br /&gt;
|&lt;br /&gt;
|26&lt;br /&gt;
|è&lt;br /&gt;
|65&lt;br /&gt;
|&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|3&lt;br /&gt;
|á&lt;br /&gt;
|524&lt;br /&gt;
|&lt;br /&gt;
|27&lt;br /&gt;
|ú&lt;br /&gt;
|56&lt;br /&gt;
|&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|4&lt;br /&gt;
|ø&lt;br /&gt;
|303&lt;br /&gt;
|Danish&lt;br /&gt;
|28&lt;br /&gt;
|ê&lt;br /&gt;
|52&lt;br /&gt;
|&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|5&lt;br /&gt;
|č&lt;br /&gt;
|288&lt;br /&gt;
|&lt;br /&gt;
|29&lt;br /&gt;
|ö&lt;br /&gt;
|48&lt;br /&gt;
|German&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|6&lt;br /&gt;
|ó&lt;br /&gt;
|283&lt;br /&gt;
|&lt;br /&gt;
|30&lt;br /&gt;
|É&lt;br /&gt;
|46&lt;br /&gt;
|&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|7&lt;br /&gt;
|ü&lt;br /&gt;
|270&lt;br /&gt;
|German&lt;br /&gt;
|31&lt;br /&gt;
|ñ&lt;br /&gt;
|37&lt;br /&gt;
|&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|8&lt;br /&gt;
|ł&lt;br /&gt;
|203&lt;br /&gt;
|Polish&lt;br /&gt;
|32&lt;br /&gt;
|õ&lt;br /&gt;
|32&lt;br /&gt;
|&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|9&lt;br /&gt;
|æ&lt;br /&gt;
|200&lt;br /&gt;
|Danish&lt;br /&gt;
|33&lt;br /&gt;
|ń&lt;br /&gt;
|26&lt;br /&gt;
|&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|10&lt;br /&gt;
|ě&lt;br /&gt;
|182&lt;br /&gt;
|&lt;br /&gt;
|34&lt;br /&gt;
|Ł&lt;br /&gt;
|24&lt;br /&gt;
|&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|11&lt;br /&gt;
|ř&lt;br /&gt;
|175&lt;br /&gt;
|Czech&lt;br /&gt;
|35&lt;br /&gt;
|Š&lt;br /&gt;
|21&lt;br /&gt;
|&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|12&lt;br /&gt;
|ã&lt;br /&gt;
|168&lt;br /&gt;
|&lt;br /&gt;
|36&lt;br /&gt;
|â&lt;br /&gt;
|21&lt;br /&gt;
|&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|13&lt;br /&gt;
|ž&lt;br /&gt;
|148&lt;br /&gt;
|Czech&lt;br /&gt;
|37&lt;br /&gt;
|ź&lt;br /&gt;
|20&lt;br /&gt;
|&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|14&lt;br /&gt;
|ý&lt;br /&gt;
|142&lt;br /&gt;
|&lt;br /&gt;
|38&lt;br /&gt;
|ß&lt;br /&gt;
|18&lt;br /&gt;
|German&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|15&lt;br /&gt;
|ę&lt;br /&gt;
|141&lt;br /&gt;
|&lt;br /&gt;
|39&lt;br /&gt;
|Ó&lt;br /&gt;
|18&lt;br /&gt;
|&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|16&lt;br /&gt;
|ą&lt;br /&gt;
|140&lt;br /&gt;
|&lt;br /&gt;
|40&lt;br /&gt;
|ň&lt;br /&gt;
|15&lt;br /&gt;
|&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|17&lt;br /&gt;
|ż&lt;br /&gt;
|119&lt;br /&gt;
|&lt;br /&gt;
|41&lt;br /&gt;
|Ú&lt;br /&gt;
|15&lt;br /&gt;
|&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|18&lt;br /&gt;
|å&lt;br /&gt;
|109&lt;br /&gt;
|Danish&lt;br /&gt;
|42&lt;br /&gt;
|Á&lt;br /&gt;
|13&lt;br /&gt;
|&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|19&lt;br /&gt;
|š&lt;br /&gt;
|99&lt;br /&gt;
|&lt;br /&gt;
|43&lt;br /&gt;
|î&lt;br /&gt;
|12&lt;br /&gt;
|&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|20&lt;br /&gt;
|ś&lt;br /&gt;
|97&lt;br /&gt;
|&lt;br /&gt;
|44&lt;br /&gt;
|ť&lt;br /&gt;
|11&lt;br /&gt;
|&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|21&lt;br /&gt;
|ç&lt;br /&gt;
|91&lt;br /&gt;
|&lt;br /&gt;
|45&lt;br /&gt;
|ô&lt;br /&gt;
|9&lt;br /&gt;
|&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|22&lt;br /&gt;
|ä&lt;br /&gt;
|86&lt;br /&gt;
|German&lt;br /&gt;
|46&lt;br /&gt;
|Ž&lt;br /&gt;
|8&lt;br /&gt;
|&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|23&lt;br /&gt;
|à&lt;br /&gt;
|83&lt;br /&gt;
|&lt;br /&gt;
|47&lt;br /&gt;
|Ż&lt;br /&gt;
|7&lt;br /&gt;
|&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|24&lt;br /&gt;
|ů&lt;br /&gt;
|77&lt;br /&gt;
|&lt;br /&gt;
|48&lt;br /&gt;
|Č&lt;br /&gt;
|7&lt;br /&gt;
|&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|25&lt;br /&gt;
|ć&lt;br /&gt;
|67&lt;br /&gt;
|&lt;br /&gt;
|49&lt;br /&gt;
|ù&lt;br /&gt;
|6&lt;br /&gt;
|&lt;br /&gt;
&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Although ö, ä and ü do not appear that often, with only these and Ü, Ö, Ä and ß, the entire German language works. So adding these letters to the fonts is quite important. &lt;br /&gt;
&lt;br /&gt;
Preferably, all foreign letters would be added to the fonts (see [[Font Patcher]] or [[Refont]]). However, if time permits only adding a few, &#039;&#039;&#039;í&#039;&#039;&#039; would be more important than, say, &#039;&#039;&#039;ô&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
It is commonplace for missing accented letters to be redirected in the .dat file to the corresponding unaccented base letter.&lt;br /&gt;
&lt;br /&gt;
=== Coverage Expansion &amp;amp; Remaining Limitations ===&lt;br /&gt;
&lt;br /&gt;
By 2014, all the system (e.g., main menu) fonts (Carleton, Carleton_condensed, Stone in sizes 24pt and 48pt; Mason and Mason_glow in 48pt) had good coverage of the &amp;quot;Top 50&amp;quot; and beyond, although not all 256 codepoints. &lt;br /&gt;
This was confirmed more specifically in 2024, as part of an [https://forums.thedarkmod.com/index.php?/topic/22427-analysis-of-212-tdm-fonts/ Analysis of 2.12 Fonts]. This analysis indicated that, unlike the system fonts, the FM fonts generally did not provide specific glyphs beyond ASCII.&lt;br /&gt;
&lt;br /&gt;
In 2024, Stone 24pt, important for subtitles and a number of readables, was further extended to cover all 256 codepoints. This was tested with TDM 2.13[betas] and released with 2.14. Similar Stone 48pt and Carleton 24pt improvements are planned for TDM 2.15.&lt;br /&gt;
&lt;br /&gt;
[[Category:Fonts]]&lt;br /&gt;
&lt;br /&gt;
{{i18n}}&lt;/div&gt;</summary>
		<author><name>Geep</name></author>
	</entry>
	<entry>
		<id>https://wiki.thedarkmod.com/index.php?title=Rebuild_all_lang_Program&amp;diff=34412</id>
		<title>Rebuild all lang Program</title>
		<link rel="alternate" type="text/html" href="https://wiki.thedarkmod.com/index.php?title=Rebuild_all_lang_Program&amp;diff=34412"/>
		<updated>2026-01-21T19:29:52Z</updated>

		<summary type="html">&lt;p&gt;Geep: Add ending tags&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;by Geep, 2026&#039;&#039;&lt;br /&gt;
==== Introduction ====&lt;br /&gt;
Ordinarily, an FM that has been internationalized has a UTF8 &amp;quot;all.lang&amp;quot; text file, from which &amp;quot;*.lang&amp;quot; files in various 8-bit ISO-8859-x (or Windows) encodings were generated and distributed within the &amp;quot;strings&amp;quot; folder.&lt;br /&gt;
&lt;br /&gt;
Sometimes, an attempt is made to improve translations, or extend them to additional languages. The ideal way is to alter content in all.lang, then regenerate the *.lang files (e.g., with gen_lang_plus). This regeneration could be for every language section specified in all.lang, or more selectively, just the ones for languages newly added or with changed content.&lt;br /&gt;
&lt;br /&gt;
Suppose &amp;quot;all.lang&amp;quot; was not distributed with the FM. The original FM author may be able to provide it, or you can ask about it being in some TDM SVN repo.&lt;br /&gt;
&lt;br /&gt;
If those routes fail, you can fabricate a replacement all.lang from the *.lang files. Note that the latter are stripped of helpful comments, including grouping header lines, often found in the original all.lang. So this approach is driven by necessity.&lt;br /&gt;
&lt;br /&gt;
One way that fabrication can be done is first make a new partial all.lang from the existing english.lang file (which being in ASCII, can be viewed as also UTF8), Then add new language sections in UTF8 form. Regenerate just those *.lang files, while retaining older unchanged *.lang files. Each new UTF8 language section can be -&lt;br /&gt;
* typed from scratch, while consulting the ISO-8859-x version.&lt;br /&gt;
* possibly generated using some third-party ISO to UTF8 translator tool.&lt;br /&gt;
&lt;br /&gt;
Or, as a convenience, use &#039;&#039;&#039;rebuild_all_lang&#039;&#039;&#039;. When run from within a give folder (e.g., &amp;quot;strings&amp;quot;), it will take every *.lang it finds (starting with english.lang), convert it from that language&#039;s ISO to UTF8, and basically glue them together into the required form.&lt;br /&gt;
&lt;br /&gt;
==== Usage and Example ====&lt;br /&gt;
The Windows command-line program rebuild_all_lang is a simple C++ utility that takes no parameters, and if successful generates &amp;quot;all.lang&amp;quot; in the current directory. Control it by -&lt;br /&gt;
- deciding in advance which *.lang files are the current directory&lt;br /&gt;
- if you want the generated file to embed a preamble, you can provide it as a file named &amp;quot;preamble_utf8.txt&amp;quot; in the same directory. This is optional. As an example, the program distribution includes a typical stock preamble.&lt;br /&gt;
&lt;br /&gt;
A typical output to console is:&lt;br /&gt;
&lt;br /&gt;
 Running rebuild_all_lang, v. 1.0&lt;br /&gt;
 Note: Did not find an optional preamble file preamble_utf8.txt&lt;br /&gt;
 Processing...&lt;br /&gt;
 English&lt;br /&gt;
 German&lt;br /&gt;
 French&lt;br /&gt;
 Italian&lt;br /&gt;
 Spanish&lt;br /&gt;
 Polish&lt;br /&gt;
 Romanian&lt;br /&gt;
 Russian&lt;br /&gt;
 Portuguese&lt;br /&gt;
 Czech&lt;br /&gt;
 Hungarian&lt;br /&gt;
 Slovak&lt;br /&gt;
 Swedish&lt;br /&gt;
 Danish&lt;br /&gt;
 Dutch&lt;br /&gt;
 Turkish&lt;br /&gt;
 Catalan&lt;br /&gt;
 Contents of *.lang files were converted successfully to UTF-8 and merged into new &#039;all.lang&#039;.&lt;br /&gt;
&lt;br /&gt;
Languages are always processed in the order shown. If a particular *.lang is missing, that is handled quietly, and that section is not added to all.lang.&lt;br /&gt;
&lt;br /&gt;
At the start of all.lang, typical text is...&lt;br /&gt;
&lt;br /&gt;
 // Rebuilt all.lang file - created by rebuild_all_lang v. 1.0&lt;br /&gt;
 // Strings in each section in same order as in *.lang, but converted from various iso-8859s encodings to UTF8.&lt;br /&gt;
 &lt;br /&gt;
 // Note - did not find an optional file preamble_utf8.txt with preamble comments to place here.&lt;br /&gt;
 &lt;br /&gt;
 {&lt;br /&gt;
 [English]&lt;br /&gt;
 // Sourced from english.lang of 2025-07-16T16:08:26+00:00, whose first line was...&lt;br /&gt;
 // String table - english (iso-8859-1) - created on 2025-07-16T16:08:26Z with gen_lang_plus v. 1.1&lt;br /&gt;
 	&amp;quot;#str_fm_airpocket_xd_sheet_appointment_to_service_pg1__title&amp;quot;	&amp;quot;Appointment to Service\n&amp;quot;&lt;br /&gt;
 	....&lt;br /&gt;
&lt;br /&gt;
Within each language section - like [English] here - some variant of the first two commented lines are always generated. As you see, the &amp;quot;// Sourced from...&amp;quot; line is followed by the first line copied from the *.lang file. In this example, the comments show the external file modification datetime, and then the datetime written at generation time. The latter will not always be present, depending upon creation method.&lt;br /&gt;
&lt;br /&gt;
==== Details ====&lt;br /&gt;
As required, the generated all.lang text file has Linux linebreaks (e.g., LF instead of CRFL), independent of linebreak form in input files *.lang or preamble_UTF8.txt&lt;br /&gt;
&lt;br /&gt;
If all.lang already exists, you will see...&lt;br /&gt;
&lt;br /&gt;
 Running rebuild_all_lang, v. 1.0&lt;br /&gt;
 File &#039;all.lang&#039; already exists.&lt;br /&gt;
 Continue and overwrite it? [y/n]&lt;br /&gt;
&lt;br /&gt;
If you indicate &amp;quot;n&amp;quot; for &amp;quot;no&amp;quot;, the program quits with message &amp;quot;Bye&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
This program has some minimal file I/O and conversion error checking, with reporting to console. It is not thought necessary to do character-level checking of the UTF8 results against characters supported by TDM&#039;s character map... such checking is better done elsewhere. This is a simple program. (One could imagine a more elaborate version that would, say, allow english.lang to be annotated with comments (e.g., to group lines into subsections). And then reorder lines within the non-English language sections to match, embedding those same annotations.)&lt;br /&gt;
&lt;br /&gt;
==== Downloads ====&lt;br /&gt;
v 1.0 Source Code: This C++ v20 program was developed under Windows 11 with VS 2022 Community Edition (updated through 2025).&lt;br /&gt;
* [https://drive.google.com/file/d/1kKunDZfVcolZgU4xMsYIpWc5VQgjd3-_/view?usp=sharing Windows executable rebuild_all_lang.exe]&lt;br /&gt;
* [https://drive.google.com/file/d/1sNbWZRznhmgUeGJR8GXK6uiMGAstTusY/view?usp=sharing rebuilt_all_lang.zip - source code: a .cpp and .sln file]&lt;br /&gt;
&lt;br /&gt;
Example preamble files (rename to preamble_utf8.txt to use):&lt;br /&gt;
* [https://drive.google.com/file/d/1bOWXv8Ju1DktaNYe2M8Bo-V7zAg2bNJ9/view?usp=sharing preamble_utf8[traditional&amp;lt;nowiki&amp;gt;]&amp;lt;/nowiki&amp;gt;.txt]&lt;br /&gt;
* [https://drive.google.com/file/d/1QKJvG6FoAzuI7njO5fnOQCgwbXQdWqQe/view?usp=sharing preamble_utf8[modern for FM&amp;lt;nowiki&amp;gt;]&amp;lt;/nowiki&amp;gt;.txt]&lt;br /&gt;
==== See Also ====&lt;br /&gt;
* [[Gen_Lang_Programs]]&lt;br /&gt;
&lt;br /&gt;
{{i18n}} {{editing}}&lt;/div&gt;</summary>
		<author><name>Geep</name></author>
	</entry>
	<entry>
		<id>https://wiki.thedarkmod.com/index.php?title=Rebuild_all_lang_Program&amp;diff=34411</id>
		<title>Rebuild all lang Program</title>
		<link rel="alternate" type="text/html" href="https://wiki.thedarkmod.com/index.php?title=Rebuild_all_lang_Program&amp;diff=34411"/>
		<updated>2026-01-21T19:27:08Z</updated>

		<summary type="html">&lt;p&gt;Geep: Tweak &amp;quot;Downloads&amp;quot; &amp;amp; &amp;quot;See Also&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;by Geep, 2026&#039;&#039;&lt;br /&gt;
==== Introduction ====&lt;br /&gt;
Ordinarily, an FM that has been internationalized has a UTF8 &amp;quot;all.lang&amp;quot; text file, from which &amp;quot;*.lang&amp;quot; files in various 8-bit ISO-8859-x (or Windows) encodings were generated and distributed within the &amp;quot;strings&amp;quot; folder.&lt;br /&gt;
&lt;br /&gt;
Sometimes, an attempt is made to improve translations, or extend them to additional languages. The ideal way is to alter content in all.lang, then regenerate the *.lang files (e.g., with gen_lang_plus). This regeneration could be for every language section specified in all.lang, or more selectively, just the ones for languages newly added or with changed content.&lt;br /&gt;
&lt;br /&gt;
Suppose &amp;quot;all.lang&amp;quot; was not distributed with the FM. The original FM author may be able to provide it, or you can ask about it being in some TDM SVN repo.&lt;br /&gt;
&lt;br /&gt;
If those routes fail, you can fabricate a replacement all.lang from the *.lang files. Note that the latter are stripped of helpful comments, including grouping header lines, often found in the original all.lang. So this approach is driven by necessity.&lt;br /&gt;
&lt;br /&gt;
One way that fabrication can be done is first make a new partial all.lang from the existing english.lang file (which being in ASCII, can be viewed as also UTF8), Then add new language sections in UTF8 form. Regenerate just those *.lang files, while retaining older unchanged *.lang files. Each new UTF8 language section can be -&lt;br /&gt;
* typed from scratch, while consulting the ISO-8859-x version.&lt;br /&gt;
* possibly generated using some third-party ISO to UTF8 translator tool.&lt;br /&gt;
&lt;br /&gt;
Or, as a convenience, use &#039;&#039;&#039;rebuild_all_lang&#039;&#039;&#039;. When run from within a give folder (e.g., &amp;quot;strings&amp;quot;), it will take every *.lang it finds (starting with english.lang), convert it from that language&#039;s ISO to UTF8, and basically glue them together into the required form.&lt;br /&gt;
&lt;br /&gt;
==== Usage and Example ====&lt;br /&gt;
The Windows command-line program rebuild_all_lang is a simple C++ utility that takes no parameters, and if successful generates &amp;quot;all.lang&amp;quot; in the current directory. Control it by -&lt;br /&gt;
- deciding in advance which *.lang files are the current directory&lt;br /&gt;
- if you want the generated file to embed a preamble, you can provide it as a file named &amp;quot;preamble_utf8.txt&amp;quot; in the same directory. This is optional. As an example, the program distribution includes a typical stock preamble.&lt;br /&gt;
&lt;br /&gt;
A typical output to console is:&lt;br /&gt;
&lt;br /&gt;
 Running rebuild_all_lang, v. 1.0&lt;br /&gt;
 Note: Did not find an optional preamble file preamble_utf8.txt&lt;br /&gt;
 Processing...&lt;br /&gt;
 English&lt;br /&gt;
 German&lt;br /&gt;
 French&lt;br /&gt;
 Italian&lt;br /&gt;
 Spanish&lt;br /&gt;
 Polish&lt;br /&gt;
 Romanian&lt;br /&gt;
 Russian&lt;br /&gt;
 Portuguese&lt;br /&gt;
 Czech&lt;br /&gt;
 Hungarian&lt;br /&gt;
 Slovak&lt;br /&gt;
 Swedish&lt;br /&gt;
 Danish&lt;br /&gt;
 Dutch&lt;br /&gt;
 Turkish&lt;br /&gt;
 Catalan&lt;br /&gt;
 Contents of *.lang files were converted successfully to UTF-8 and merged into new &#039;all.lang&#039;.&lt;br /&gt;
&lt;br /&gt;
Languages are always processed in the order shown. If a particular *.lang is missing, that is handled quietly, and that section is not added to all.lang.&lt;br /&gt;
&lt;br /&gt;
At the start of all.lang, typical text is...&lt;br /&gt;
&lt;br /&gt;
 // Rebuilt all.lang file - created by rebuild_all_lang v. 1.0&lt;br /&gt;
 // Strings in each section in same order as in *.lang, but converted from various iso-8859s encodings to UTF8.&lt;br /&gt;
 &lt;br /&gt;
 // Note - did not find an optional file preamble_utf8.txt with preamble comments to place here.&lt;br /&gt;
 &lt;br /&gt;
 {&lt;br /&gt;
 [English]&lt;br /&gt;
 // Sourced from english.lang of 2025-07-16T16:08:26+00:00, whose first line was...&lt;br /&gt;
 // String table - english (iso-8859-1) - created on 2025-07-16T16:08:26Z with gen_lang_plus v. 1.1&lt;br /&gt;
 	&amp;quot;#str_fm_airpocket_xd_sheet_appointment_to_service_pg1__title&amp;quot;	&amp;quot;Appointment to Service\n&amp;quot;&lt;br /&gt;
 	....&lt;br /&gt;
&lt;br /&gt;
Within each language section - like [English] here - some variant of the first two commented lines are always generated. As you see, the &amp;quot;// Sourced from...&amp;quot; line is followed by the first line copied from the *.lang file. In this example, the comments show the external file modification datetime, and then the datetime written at generation time. The latter will not always be present, depending upon creation method.&lt;br /&gt;
&lt;br /&gt;
==== Details ====&lt;br /&gt;
As required, the generated all.lang text file has Linux linebreaks (e.g., LF instead of CRFL), independent of linebreak form in input files *.lang or preamble_UTF8.txt&lt;br /&gt;
&lt;br /&gt;
If all.lang already exists, you will see...&lt;br /&gt;
&lt;br /&gt;
 Running rebuild_all_lang, v. 1.0&lt;br /&gt;
 File &#039;all.lang&#039; already exists.&lt;br /&gt;
 Continue and overwrite it? [y/n]&lt;br /&gt;
&lt;br /&gt;
If you indicate &amp;quot;n&amp;quot; for &amp;quot;no&amp;quot;, the program quits with message &amp;quot;Bye&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
This program has some minimal file I/O and conversion error checking, with reporting to console. It is not thought necessary to do character-level checking of the UTF8 results against characters supported by TDM&#039;s character map... such checking is better done elsewhere. This is a simple program. (One could imagine a more elaborate version that would, say, allow english.lang to be annotated with comments (e.g., to group lines into subsections). And then reorder lines within the non-English language sections to match, embedding those same annotations.)&lt;br /&gt;
&lt;br /&gt;
==== Downloads ====&lt;br /&gt;
v 1.0 Source Code: This C++ v20 program was developed under Windows 11 with VS 2022 Community Edition (updated through 2025).&lt;br /&gt;
* [https://drive.google.com/file/d/1kKunDZfVcolZgU4xMsYIpWc5VQgjd3-_/view?usp=sharing Windows executable rebuild_all_lang.exe]&lt;br /&gt;
* [https://drive.google.com/file/d/1sNbWZRznhmgUeGJR8GXK6uiMGAstTusY/view?usp=sharing rebuilt_all_lang.zip - source code: a .cpp and .sln file]&lt;br /&gt;
&lt;br /&gt;
Example preamble files (rename to preamble_utf8.txt to use):&lt;br /&gt;
* [https://drive.google.com/file/d/1bOWXv8Ju1DktaNYe2M8Bo-V7zAg2bNJ9/view?usp=sharing preamble_utf8[traditional&amp;lt;nowiki&amp;gt;]&amp;lt;/nowiki&amp;gt;.txt]&lt;br /&gt;
* [https://drive.google.com/file/d/1QKJvG6FoAzuI7njO5fnOQCgwbXQdWqQe/view?usp=sharing preamble_utf8[modern for FM&amp;lt;nowiki&amp;gt;]&amp;lt;/nowiki&amp;gt;.txt]&lt;br /&gt;
==== See Also ====&lt;br /&gt;
* [[Gen_Lang_Programs]]&lt;/div&gt;</summary>
		<author><name>Geep</name></author>
	</entry>
	<entry>
		<id>https://wiki.thedarkmod.com/index.php?title=Rebuild_all_lang_Program&amp;diff=34410</id>
		<title>Rebuild all lang Program</title>
		<link rel="alternate" type="text/html" href="https://wiki.thedarkmod.com/index.php?title=Rebuild_all_lang_Program&amp;diff=34410"/>
		<updated>2026-01-21T19:19:33Z</updated>

		<summary type="html">&lt;p&gt;Geep: /* Downloads */ added links&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;by Geep, 2026&#039;&#039;&lt;br /&gt;
==== Introduction ====&lt;br /&gt;
Ordinarily, an FM that has been internationalized has a UTF8 &amp;quot;all.lang&amp;quot; text file, from which &amp;quot;*.lang&amp;quot; files in various 8-bit ISO-8859-x (or Windows) encodings were generated and distributed within the &amp;quot;strings&amp;quot; folder.&lt;br /&gt;
&lt;br /&gt;
Sometimes, an attempt is made to improve translations, or extend them to additional languages. The ideal way is to alter content in all.lang, then regenerate the *.lang files (e.g., with gen_lang_plus). This regeneration could be for every language section specified in all.lang, or more selectively, just the ones for languages newly added or with changed content.&lt;br /&gt;
&lt;br /&gt;
Suppose &amp;quot;all.lang&amp;quot; was not distributed with the FM. The original FM author may be able to provide it, or you can ask about it being in some TDM SVN repo.&lt;br /&gt;
&lt;br /&gt;
If those routes fail, you can fabricate a replacement all.lang from the *.lang files. Note that the latter are stripped of helpful comments, including grouping header lines, often found in the original all.lang. So this approach is driven by necessity.&lt;br /&gt;
&lt;br /&gt;
One way that fabrication can be done is first make a new partial all.lang from the existing english.lang file (which being in ASCII, can be viewed as also UTF8), Then add new language sections in UTF8 form. Regenerate just those *.lang files, while retaining older unchanged *.lang files. Each new UTF8 language section can be -&lt;br /&gt;
* typed from scratch, while consulting the ISO-8859-x version.&lt;br /&gt;
* possibly generated using some third-party ISO to UTF8 translator tool.&lt;br /&gt;
&lt;br /&gt;
Or, as a convenience, use &#039;&#039;&#039;rebuild_all_lang&#039;&#039;&#039;. When run from within a give folder (e.g., &amp;quot;strings&amp;quot;), it will take every *.lang it finds (starting with english.lang), convert it from that language&#039;s ISO to UTF8, and basically glue them together into the required form.&lt;br /&gt;
&lt;br /&gt;
==== Usage and Example ====&lt;br /&gt;
The Windows command-line program rebuild_all_lang is a simple C++ utility that takes no parameters, and if successful generates &amp;quot;all.lang&amp;quot; in the current directory. Control it by -&lt;br /&gt;
- deciding in advance which *.lang files are the current directory&lt;br /&gt;
- if you want the generated file to embed a preamble, you can provide it as a file named &amp;quot;preamble_utf8.txt&amp;quot; in the same directory. This is optional. As an example, the program distribution includes a typical stock preamble.&lt;br /&gt;
&lt;br /&gt;
A typical output to console is:&lt;br /&gt;
&lt;br /&gt;
 Running rebuild_all_lang, v. 1.0&lt;br /&gt;
 Note: Did not find an optional preamble file preamble_utf8.txt&lt;br /&gt;
 Processing...&lt;br /&gt;
 English&lt;br /&gt;
 German&lt;br /&gt;
 French&lt;br /&gt;
 Italian&lt;br /&gt;
 Spanish&lt;br /&gt;
 Polish&lt;br /&gt;
 Romanian&lt;br /&gt;
 Russian&lt;br /&gt;
 Portuguese&lt;br /&gt;
 Czech&lt;br /&gt;
 Hungarian&lt;br /&gt;
 Slovak&lt;br /&gt;
 Swedish&lt;br /&gt;
 Danish&lt;br /&gt;
 Dutch&lt;br /&gt;
 Turkish&lt;br /&gt;
 Catalan&lt;br /&gt;
 Contents of *.lang files were converted successfully to UTF-8 and merged into new &#039;all.lang&#039;.&lt;br /&gt;
&lt;br /&gt;
Languages are always processed in the order shown. If a particular *.lang is missing, that is handled quietly, and that section is not added to all.lang.&lt;br /&gt;
&lt;br /&gt;
At the start of all.lang, typical text is...&lt;br /&gt;
&lt;br /&gt;
 // Rebuilt all.lang file - created by rebuild_all_lang v. 1.0&lt;br /&gt;
 // Strings in each section in same order as in *.lang, but converted from various iso-8859s encodings to UTF8.&lt;br /&gt;
 &lt;br /&gt;
 // Note - did not find an optional file preamble_utf8.txt with preamble comments to place here.&lt;br /&gt;
 &lt;br /&gt;
 {&lt;br /&gt;
 [English]&lt;br /&gt;
 // Sourced from english.lang of 2025-07-16T16:08:26+00:00, whose first line was...&lt;br /&gt;
 // String table - english (iso-8859-1) - created on 2025-07-16T16:08:26Z with gen_lang_plus v. 1.1&lt;br /&gt;
 	&amp;quot;#str_fm_airpocket_xd_sheet_appointment_to_service_pg1__title&amp;quot;	&amp;quot;Appointment to Service\n&amp;quot;&lt;br /&gt;
 	....&lt;br /&gt;
&lt;br /&gt;
Within each language section - like [English] here - some variant of the first two commented lines are always generated. As you see, the &amp;quot;// Sourced from...&amp;quot; line is followed by the first line copied from the *.lang file. In this example, the comments show the external file modification datetime, and then the datetime written at generation time. The latter will not always be present, depending upon creation method.&lt;br /&gt;
&lt;br /&gt;
==== Details ====&lt;br /&gt;
As required, the generated all.lang text file has Linux linebreaks (e.g., LF instead of CRFL), independent of linebreak form in input files *.lang or preamble_UTF8.txt&lt;br /&gt;
&lt;br /&gt;
If all.lang already exists, you will see...&lt;br /&gt;
&lt;br /&gt;
 Running rebuild_all_lang, v. 1.0&lt;br /&gt;
 File &#039;all.lang&#039; already exists.&lt;br /&gt;
 Continue and overwrite it? [y/n]&lt;br /&gt;
&lt;br /&gt;
If you indicate &amp;quot;n&amp;quot; for &amp;quot;no&amp;quot;, the program quits with message &amp;quot;Bye&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
This program has some minimal file I/O and conversion error checking, with reporting to console. It is not thought necessary to do character-level checking of the UTF8 results against characters supported by TDM&#039;s character map... such checking is better done elsewhere. This is a simple program. (One could imagine a more elaborate version that would, say, allow english.lang to be annotated with comments (e.g., to group lines into subsections). And then reorder lines within the non-English language sections to match, embedding those same annotations.)&lt;br /&gt;
&lt;br /&gt;
==== Downloads ====&lt;br /&gt;
Source code: This C++ v20 program was developed under Windows 11 with VS 2022 Community Edition (updated through 2025).&lt;br /&gt;
* [https://drive.google.com/file/d/1kKunDZfVcolZgU4xMsYIpWc5VQgjd3-_/view?usp=sharing Windows executable rebuild_all_lang.exe]&lt;br /&gt;
* [https://drive.google.com/file/d/1sNbWZRznhmgUeGJR8GXK6uiMGAstTusY/view?usp=sharing rebuilt_all_lang.zip - source code: a .cpp and .sln file]&lt;br /&gt;
&lt;br /&gt;
Example preamble files (rename to preamble_utf8.txt to use):&lt;br /&gt;
* [https://drive.google.com/file/d/1bOWXv8Ju1DktaNYe2M8Bo-V7zAg2bNJ9/view?usp=sharing preamble_utf8[traditional&amp;lt;nowiki&amp;gt;]&amp;lt;/nowiki&amp;gt;.txt]&lt;br /&gt;
* [https://drive.google.com/file/d/1QKJvG6FoAzuI7njO5fnOQCgwbXQdWqQe/view?usp=sharing preamble_utf8[modern for FM&amp;lt;nowiki&amp;gt;]&amp;lt;/nowiki&amp;gt;.txt]&lt;br /&gt;
==== See Also ====&lt;br /&gt;
[COMING SOON]&lt;/div&gt;</summary>
		<author><name>Geep</name></author>
	</entry>
	<entry>
		<id>https://wiki.thedarkmod.com/index.php?title=Rebuild_all_lang_Program&amp;diff=34409</id>
		<title>Rebuild all lang Program</title>
		<link rel="alternate" type="text/html" href="https://wiki.thedarkmod.com/index.php?title=Rebuild_all_lang_Program&amp;diff=34409"/>
		<updated>2026-01-20T18:55:36Z</updated>

		<summary type="html">&lt;p&gt;Geep: create article&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;by Geep, 2026&#039;&#039;&lt;br /&gt;
==== Introduction ====&lt;br /&gt;
Ordinarily, an FM that has been internationalized has a UTF8 &amp;quot;all.lang&amp;quot; text file, from which &amp;quot;*.lang&amp;quot; files in various 8-bit ISO-8859-x (or Windows) encodings were generated and distributed within the &amp;quot;strings&amp;quot; folder.&lt;br /&gt;
&lt;br /&gt;
Sometimes, an attempt is made to improve translations, or extend them to additional languages. The ideal way is to alter content in all.lang, then regenerate the *.lang files (e.g., with gen_lang_plus). This regeneration could be for every language section specified in all.lang, or more selectively, just the ones for languages newly added or with changed content.&lt;br /&gt;
&lt;br /&gt;
Suppose &amp;quot;all.lang&amp;quot; was not distributed with the FM. The original FM author may be able to provide it, or you can ask about it being in some TDM SVN repo.&lt;br /&gt;
&lt;br /&gt;
If those routes fail, you can fabricate a replacement all.lang from the *.lang files. Note that the latter are stripped of helpful comments, including grouping header lines, often found in the original all.lang. So this approach is driven by necessity.&lt;br /&gt;
&lt;br /&gt;
One way that fabrication can be done is first make a new partial all.lang from the existing english.lang file (which being in ASCII, can be viewed as also UTF8), Then add new language sections in UTF8 form. Regenerate just those *.lang files, while retaining older unchanged *.lang files. Each new UTF8 language section can be -&lt;br /&gt;
* typed from scratch, while consulting the ISO-8859-x version.&lt;br /&gt;
* possibly generated using some third-party ISO to UTF8 translator tool.&lt;br /&gt;
&lt;br /&gt;
Or, as a convenience, use rebuild_all_lang. When run from within a give folder (e.g., &amp;quot;strings&amp;quot;), it will take every *.lang it finds (starting with english.lang), convert it from that language&#039;s ISO to UTF8, and basically glue them together into the required form.&lt;br /&gt;
&lt;br /&gt;
==== Usage and Example ====&lt;br /&gt;
The Windows command-line program rebuild_all_lang is a simple C++ utility that takes no parameters, and if successful generates &amp;quot;all.lang&amp;quot; in the current directory. Control it by -&lt;br /&gt;
- deciding in advance which *.lang files are the current directory&lt;br /&gt;
- if you want the generated file to embed a preamble, you can provide it as a file named &amp;quot;preamble_utf8.txt&amp;quot; in the same directory. This is optional. As an example, the program distribution includes a typical stock preamble.&lt;br /&gt;
&lt;br /&gt;
A typical output to console is:&lt;br /&gt;
&lt;br /&gt;
 Running rebuild_all_lang, v. 1.0&lt;br /&gt;
 Note: Did not find an optional preamble file preamble_utf8.txt&lt;br /&gt;
 Processing...&lt;br /&gt;
 English&lt;br /&gt;
 German&lt;br /&gt;
 French&lt;br /&gt;
 Italian&lt;br /&gt;
 Spanish&lt;br /&gt;
 Polish&lt;br /&gt;
 Romanian&lt;br /&gt;
 Russian&lt;br /&gt;
 Portuguese&lt;br /&gt;
 Czech&lt;br /&gt;
 Hungarian&lt;br /&gt;
 Slovak&lt;br /&gt;
 Swedish&lt;br /&gt;
 Danish&lt;br /&gt;
 Dutch&lt;br /&gt;
 Turkish&lt;br /&gt;
 Catalan&lt;br /&gt;
 Contents of *.lang files were converted successfully to UTF-8 and merged into new &#039;all.lang&#039;.&lt;br /&gt;
&lt;br /&gt;
Languages are always processed in the order shown. If a particular *.lang is missing, that is handled quietly, and that section is not added to all.lang.&lt;br /&gt;
&lt;br /&gt;
At the start of all.lang, typical text is...&lt;br /&gt;
&lt;br /&gt;
 // Rebuilt all.lang file - created by rebuild_all_lang v. 1.0&lt;br /&gt;
 // Strings in each section in same order as in *.lang, but converted from various iso-8859s encodings to UTF8.&lt;br /&gt;
 &lt;br /&gt;
 // Note - did not find an optional file preamble_utf8.txt with preamble comments to place here.&lt;br /&gt;
 &lt;br /&gt;
 {&lt;br /&gt;
 [English]&lt;br /&gt;
 // Sourced from english.lang of 2025-07-16T16:08:26+00:00, whose first line was...&lt;br /&gt;
 // String table - english (iso-8859-1) - created on 2025-07-16T16:08:26Z with gen_lang_plus v. 1.1&lt;br /&gt;
 	&amp;quot;#str_fm_airpocket_xd_sheet_appointment_to_service_pg1__title&amp;quot;	&amp;quot;Appointment to Service\n&amp;quot;&lt;br /&gt;
 	....&lt;br /&gt;
&lt;br /&gt;
Within each language section - like [English] here - some variant of the first two commented lines are always generated. As you see, the &amp;quot;// Sourced from...&amp;quot; line is followed by the first line copied from the *.lang file. In this example, the comments show the external file modification datetime, and then the datetime written at generation time. The latter will not always be present, depending upon creation method.&lt;br /&gt;
&lt;br /&gt;
==== Details ====&lt;br /&gt;
As required, the generated all.lang text file has Linux linebreaks (e.g., LF instead of CRFL), independent of linebreak form in input files *.lang or preamble_UTF8.txt&lt;br /&gt;
&lt;br /&gt;
If all.lang already exists, you will see...&lt;br /&gt;
&lt;br /&gt;
 Running rebuild_all_lang, v. 1.0&lt;br /&gt;
 File &#039;all.lang&#039; already exists.&lt;br /&gt;
 Continue and overwrite it? [y/n]&lt;br /&gt;
&lt;br /&gt;
If you indicate &amp;quot;n&amp;quot; for &amp;quot;no&amp;quot;, the program quits with message &amp;quot;Bye&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
This program has some minimal file I/O and conversion error checking, with reporting to console. It is not thought necessary to do character-level checking of the UTF8 results against characters supported by TDM&#039;s character map... such checking is better done elsewhere. This is a simple program. (One could imagine a more elaborate version that would, say, allow english.lang to be annotated with comments (e.g., to group lines into subsections). And then reorder lines within the non-English language sections to match, embedding those same annotations.)&lt;br /&gt;
&lt;br /&gt;
==== Download ====&lt;br /&gt;
[COMING SOON]&lt;br /&gt;
The distribution includes an example stock &amp;quot;preamble_utf8.txt&amp;quot; file.&lt;br /&gt;
Source code: This C++ v20 program was developed under Windows 11 with VS 2022 Community Edition (updated through 2025).&lt;br /&gt;
==== See Also ====&lt;br /&gt;
[COMING SOON]&lt;/div&gt;</summary>
		<author><name>Geep</name></author>
	</entry>
	<entry>
		<id>https://wiki.thedarkmod.com/index.php?title=Subtitles&amp;diff=34366</id>
		<title>Subtitles</title>
		<link rel="alternate" type="text/html" href="https://wiki.thedarkmod.com/index.php?title=Subtitles&amp;diff=34366"/>
		<updated>2026-01-17T18:20:01Z</updated>

		<summary type="html">&lt;p&gt;Geep: /* internationalization */ section added&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Support for subtitles (or closed captions) was added in TDM 2.10.&lt;br /&gt;
&lt;br /&gt;
=== What the player sees ===&lt;br /&gt;
In 2.10+, the player can control subtitle visualization under Settings/Audio/Subtitles, which takes one of these values:&lt;br /&gt;
* Story - display only story-related subtitles&lt;br /&gt;
* On - display subtitles for all speech&lt;br /&gt;
* Off - disable subtitles&lt;br /&gt;
&amp;quot;Story&amp;quot; is the default. If &amp;quot;On&amp;quot; is chosen, story and non-story speech subtitles (like for AI &amp;quot;barks&amp;quot;) appear.&lt;br /&gt;
&lt;br /&gt;
Each subtitle has an implicit or explicit start and end time relative to its audio clip. To handle multiple overlapping sounds, the text is not interwoven; instead, there are 3 separate, non-overlapping fields, stacked in the lower part of the screen. When a subtitle is shown, it is as white text on a translucent field-rectangle background. A text line that is too long is wrapped to two lines.&lt;br /&gt;
&lt;br /&gt;
One immediate purpose for TDM&#039;s subtitles is to provide English captions for English audio. This will assist understanding of accented dialog for those who are hearing-impaired or whose English is less fluent. (In theory, subtitles could be relied upon to play an FM silently, but the lack of audio positional and distance cues, e.g., for footsteps, would be detrimental.)&lt;br /&gt;
&lt;br /&gt;
As for translation, i.e., subtitles shown in other TDM-supported languages, the current system provides an important and usable building block.  An FM author could employ it to provide &amp;quot;story&amp;quot; subtitles in a particular language other than English. Furthermore, a non-TDM site for a specific non-English audience - one that hosts full ports of TDM and its FMs - could create its own subtitle files in the target language. Other ideas for future capabilities, such as easy switching among multiple subtitle languages, are [https://forums.thedarkmod.com/index.php?/topic/21741-subtitles-possibilities-beyond-211/ under discussion].&lt;br /&gt;
&lt;br /&gt;
=== Rollout so far ===&lt;br /&gt;
&#039;&#039;As of 2.11&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
The &amp;quot;Subtitles&amp;quot; setting affects the CVar &amp;quot;cv_tdm_subtitles&amp;quot;, as follows:&lt;br /&gt;
* Story --&amp;gt;  1 --- show only story-relevant&lt;br /&gt;
* On    --&amp;gt;  2 --- show all speech&lt;br /&gt;
* Off   --&amp;gt;  0 --- hide all&lt;br /&gt;
&lt;br /&gt;
There is an additional cv_tdm_subtitles value, 3. It means &amp;quot;show everything&amp;quot;, including additional subtitles for sound effects. No core sound effect subtitles are provided yet.&lt;br /&gt;
&lt;br /&gt;
Subtitles are not generated on the fly. They are pre-encoded into game files (as detailed below), and this will take human effort over time. &amp;quot;Story&amp;quot; subtitles are chiefly associated with custom sound files and typically the responsibility of the FM author. Conversely, subtitles for AI standard speech phrases (as well as standard sound effects) are seen as mainly core resources.  &lt;br /&gt;
&lt;br /&gt;
For the FMs included in the standard distribution, &amp;quot;Tears of Saint Lucia&amp;quot; (in 2.10) and &amp;quot;A New Job&amp;quot; (planned in 2.11) have &amp;quot;Story&amp;quot; speech English subtitles.&lt;br /&gt;
&lt;br /&gt;
Non-story speech (as of 2.10) is limited to a dozen phrases of the &amp;quot;Cynic&amp;quot; voice, used by some attacking guards. Since this is part of the core distribution, these English subtitles become available to existing games automatically. [https://forums.thedarkmod.com/index.php?/topic/21740-english-subtitles-for-ai-barks/ A project to expand this coverage for 2.12] has been started.&lt;br /&gt;
&lt;br /&gt;
See also the section &amp;quot;displaying text with extended duration (new for 2.12)&amp;quot; below.&lt;br /&gt;
&lt;br /&gt;
=== How it works ===&lt;br /&gt;
&lt;br /&gt;
Subtitles work on a very low level: where the engine manages sound samples and sound channels.&lt;br /&gt;
This approach allows to reliably add subtitles for sounds of any kind, but has some downsides too: the system does &#039;&#039;&#039;not&#039;&#039;&#039; know anything at all about entities, spawnargs, scripts, and other gameplay stuff.&lt;br /&gt;
The system allows to assign chunks of text directly to sound samples (which are usually .ogg and .wav files), so that when a sound sample is played, the assigned text is shown on the screen.&lt;br /&gt;
&lt;br /&gt;
=== Subtitles decls ===&lt;br /&gt;
&lt;br /&gt;
The assignment of text to sound samples is specified in a new type of decl files. These files must:&lt;br /&gt;
# be in &#039;&#039;&#039;subtitles&#039;&#039;&#039; directory,&lt;br /&gt;
# have &#039;&#039;&#039;.subs&#039;&#039;&#039; extension,&lt;br /&gt;
# contain declarations of type &#039;&#039;&#039;subtitles&#039;&#039;&#039;.&lt;br /&gt;
For comparison, materials are another type of decls, which must be in &amp;lt;tt&amp;gt;materials&amp;lt;/tt&amp;gt; directory, in files with &amp;lt;tt&amp;gt;.mtr&amp;lt;/tt&amp;gt; extension, and be of type &amp;lt;tt&amp;gt;material&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
To avoid any conflicts between core game and missions, FM authors should follow the conventions:&lt;br /&gt;
# Names of subtitles decl files must start with &#039;&#039;&#039;fm_&#039;&#039;&#039;, e.g.: &amp;lt;tt&amp;gt;fm_conversations.subs&amp;lt;/tt&amp;gt;&lt;br /&gt;
# Names of declarations must start with &#039;&#039;&#039;fm_&#039;&#039;&#039; too, e.g.: &amp;lt;tt&amp;gt;fm_paul_intro_convo&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Here is an example of &amp;lt;tt&amp;gt;fm_conversations.subs&amp;lt;/tt&amp;gt; contents:&lt;br /&gt;
&lt;br /&gt;
 //note: comments work as they normally do&lt;br /&gt;
 &lt;br /&gt;
 subtitles fm_intro_convo {&lt;br /&gt;
     verbosity story&lt;br /&gt;
     inline &amp;quot;sound/voices/paul/sound1.ogg&amp;quot; &amp;quot;My name is Paul, and I&#039;m a city guard.&amp;quot;&lt;br /&gt;
     inline &amp;quot;sound/voices/bjorn/sound2.ogg&amp;quot; &amp;quot;Welcome to Anonymous City Guards! Call me Bjorn.&amp;quot;&lt;br /&gt;
     inline &amp;quot;sound/voices/paul/sound3.ogg&amp;quot; &amp;quot;I started cutting thieves&#039; throats when I was 17...&amp;quot;&lt;br /&gt;
     inline &amp;quot;sound/voices/paul/sound4.ogg&amp;quot; &amp;quot;... and now I cannot stop doing that!&amp;quot;&lt;br /&gt;
 &lt;br /&gt;
     verbosity effect&lt;br /&gt;
     inline &amp;quot;sound/voices/paul/sound5.ogg&amp;quot; &amp;quot;(starts weeping)&amp;quot;&lt;br /&gt;
 &lt;br /&gt;
     verbosity story&lt;br /&gt;
     inline &amp;quot;sound/voices/bjorn/sound6.ogg&amp;quot; &amp;quot;Calm down, Paul! We all were in your shoes!&amp;quot;&lt;br /&gt;
     inline &amp;quot;sound/voices/bjorn/sound7.ogg&amp;quot; &amp;quot;Let us first watch an educational video about the harm from cutting throats.&amp;quot;&lt;br /&gt;
 &lt;br /&gt;
     srt &amp;quot;sound/voices/bjorn/sound8_long.ogg&amp;quot; &amp;quot;sound/voices/bjorn/sound8_long.srt&amp;quot;&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 subtitles fm_briefing {&lt;br /&gt;
     verbosity story&lt;br /&gt;
     srt &amp;quot;fromVideo video/sts_briefing_intro&amp;quot; &amp;quot;video/briefing/briefing.srt&amp;quot;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
==== displayed text ====&lt;br /&gt;
&lt;br /&gt;
There are two ways to specify subtitle text: inline and srt-based.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;inline&#039;&#039;&#039; command is followed by a name of sound sample and the text to be displayed while it is being played.&lt;br /&gt;
In this case, the text is written straight in the decl file, and it is displayed for the whole duration of the sound sample.&lt;br /&gt;
This way is convenient for short sounds, which are the majority of sound samples, including phrases of a conversation. A &amp;quot;\n&amp;quot; can be embedded in the text to force a line break.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;srt&#039;&#039;&#039; command is followed by paths to a sound sample and its .srt file, typically with matching filenames. This method, while more complicated than inline, has the flexibility to support a long sound file that needs multiple sequential subtitles, such as the sound sample of a briefing video. An .srt file, in &amp;quot;SubRip&amp;quot; format, is usually placed either with its sound file or in a &amp;quot;subtitles&amp;quot; folder. It contains a sequence of text messages to show during the sound sample, each with start and end HH:MM:SS,sss timestamps within the sample&#039;s timeline. For example:&lt;br /&gt;
 1&lt;br /&gt;
 00:00:03,612 --&amp;gt; 00:00:10,376&lt;br /&gt;
 Bugger me!&lt;br /&gt;
 Something&#039;s wrong with this crystal ball.&lt;br /&gt;
 &lt;br /&gt;
 2&lt;br /&gt;
 00:00:25,336 --&amp;gt; 00:00:28,167&lt;br /&gt;
 Ah! Here we go. &lt;br /&gt;
Creating .srt files is best done with third-party AV software, not writing them manually. For TDM, files must be in engine-native encoding (internationalization is not supported yet anyway) and have no BOM mark. While implementations of the [https://en.wikipedia.org/wiki/Subrip#SubRip_file_format &amp;quot;SubRip&amp;quot; file format] often include HTML-style markups for font attributes like bold or italics, these are not possible for TDM. What TDM &#039;&#039;does&#039;&#039; have is limited primary-color font markup, applicable to inline and srt subtitles; see [[Text_Decals_for_Signs_etc.#Signs_with_Illuminated_Colored_Letters | Signs_with_Illuminated_Colored_Letters]] for details.&lt;br /&gt;
&lt;br /&gt;
==== displaying text with extended duration (new for 2.12) ====&lt;br /&gt;
&lt;br /&gt;
A TDM inline subtitle appears on screen at the start of its audio clip. By convention, this is true for srt as well; the first message starts at time 00:00:00,000.&lt;br /&gt;
&lt;br /&gt;
Under 2.10/2.11, a subtitle goes away when its audio clip ends. For srt, this is true even if a timestamp specifies a value beyond the audio clip duration.&lt;br /&gt;
&lt;br /&gt;
Starting with 2.12, both automatic and manual extensions are provided.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;For inline subtitles.&#039;&#039;&#039; Automatically, durations are extended by 0.2 seconds  past the clip end. This matches the 0.2 second pause automatically put in between each voice clip in the Conversation object, so as to show such subtitles without a visual gap. This degree of extension is considered imperceptable. In addition, 1.0 second is now the minimum duration of an inline subtitle, as widely recommended for captioning. (These extensions apply to all subtitles, not just Conversation.)&lt;br /&gt;
&lt;br /&gt;
For any particular &amp;quot;inline&amp;quot; command, the 0.2 second value can be overridden (e.g., with a larger value) by an additional trailing parameter, with syntax of either:&lt;br /&gt;
&lt;br /&gt;
 -durationExtend &#039;&#039;&amp;lt;positive value&amp;gt;&#039;&#039;&lt;br /&gt;
 -dx &#039;&#039;&amp;lt;positive value&amp;gt;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
     inline &amp;quot;sound/voices/bjorn/sound7.ogg&amp;quot; &amp;quot;Let us first watch an educational video about the harm from cutting throats.&amp;quot; -dx 0.45&lt;br /&gt;
Manual extension may be needed with particularly fast talking (i.e., high presentation rate, as expressed in characters-per-second or words-per-minute).  Conversely, to avoid irritating the reader with noticeably lagging subtitles, use manual extension sparingly. In particular, don&#039;t be keen to go longer than 1/2 second.&lt;br /&gt;
&lt;br /&gt;
There is a sanity upper limit of 5.0 seconds on the extension. So overall, the calculated duration is:&lt;br /&gt;
 duration =     max(c + 0.2, 1.0)           &#039;&#039;if x not defined&#039;&#039;&lt;br /&gt;
 duration = min(max(c +   x, 1.0), c + 5.0) &#039;&#039;if x defined&#039;&#039;&lt;br /&gt;
where c is the clip length, and x is the -dx value&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;For srt subtitles.&#039;&#039;&#039; The automatic extensions provided for inline do not apply to srt. Instead, the srt timestamp values can now extend beyond the clip end.&lt;br /&gt;
&lt;br /&gt;
It is the srt author&#039;s responsibility to apply best-practices such as:&lt;br /&gt;
* Start the first message at time 0&lt;br /&gt;
* Avoid messages less than 1 second duration&lt;br /&gt;
* Try to cut messages between sentences, or at other vocal pauses&lt;br /&gt;
* Don&#039;t overlap messages in time&lt;br /&gt;
* Usually, messages are abutted; sometimes, significant time gaps are appropriate&lt;br /&gt;
* Avoid ending the last message much beyond the clip length (analogous to -dx considerations)&lt;br /&gt;
* While such a duration extension directly benefits the final message, it is sometimes possible to &amp;quot;distribute the benefit&amp;quot; to an earlier message by small shifts in message breaks.&lt;br /&gt;
&lt;br /&gt;
==== internationalization ====&lt;br /&gt;
&lt;br /&gt;
As mentioned above, a mechanism for support of translations, e.g., use of #str IDs, has not been developed. As of TDM 2.14 [alpha], one pre-requisite for European languages exists: build-out of the font used for subtitles, &amp;quot;english&amp;quot; Stone 24pt, to include complete coverage of all 256 characters in the TDM character map.&lt;br /&gt;
&lt;br /&gt;
==== sound sample ====&lt;br /&gt;
&lt;br /&gt;
In order to specify sound sample, write path to the file the same way you do e.g. in sound shaders.&lt;br /&gt;
&lt;br /&gt;
One complicated case is when you have an [[Cutscene_video_with_FFmpeg#Play_video_with_sound|FFmpeg-based video with embedded sound]].&lt;br /&gt;
In this case write material name, prepended with &#039;&#039;&#039;fromVideo&#039;&#039;&#039; keyword and space, just like you do in the sound shader.&lt;br /&gt;
See &amp;lt;tt&amp;gt;fm_briefing&amp;lt;/tt&amp;gt; in the example above.&lt;br /&gt;
&lt;br /&gt;
==== verbosity ====&lt;br /&gt;
&lt;br /&gt;
Currently there are three verbosity levels for subtitles:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;story&#039;&#039;&#039;: This level should be applied to all story-related subtitles, everything that player should absolutely notice and understand.&lt;br /&gt;
* &#039;&#039;&#039;speech&#039;&#039;&#039;: This is for subtitles of speech which is usually of little interest to the player, or is repeated too often. For instance, regular AI barks (e.g. &amp;quot;I&#039;ll get ya!&amp;quot;) belong here.&lt;br /&gt;
* &#039;&#039;&#039;effect&#039;&#039;&#039;: This level is reserved for non-speech subtitles which have little interest to the player, like &amp;quot;(bang)&amp;quot; or &amp;quot;(ding)&amp;quot;, etc.&lt;br /&gt;
&lt;br /&gt;
It is not yet clear how exactly these levels will be used in the long term. For now:&lt;br /&gt;
&lt;br /&gt;
# By default, players only see &amp;lt;tt&amp;gt;story&amp;lt;/tt&amp;gt;-level subtitles, although they can enable the other two categories in settings, or disable subtitles entirely.&lt;br /&gt;
# It is expected that almost all FM-specific subtitles get into &amp;lt;tt&amp;gt;story&amp;lt;/tt&amp;gt; category. The other two exist mostly for core TDM sounds, which include a lot of AI barks (&amp;lt;tt&amp;gt;speech&amp;lt;/tt&amp;gt; level) and trivial sound effects like arrow hit (&amp;lt;tt&amp;gt;effect&amp;lt;/tt&amp;gt; level).&lt;br /&gt;
&lt;br /&gt;
Every subtitles declaration must start with &#039;&#039;&#039;verbosity&#039;&#039;&#039; command.&lt;br /&gt;
This command applies to all the subsequent commands, until the other &amp;lt;tt&amp;gt;verbosity&amp;lt;/tt&amp;gt; is met or declaration ends (whichever happens first).&lt;br /&gt;
For instance, all subtitles have &amp;lt;tt&amp;gt;story&amp;lt;/tt&amp;gt; verbosity level in the example above, except for the &amp;quot;(starts weeping)&amp;quot; text, which has &amp;lt;tt&amp;gt;effect&amp;lt;/tt&amp;gt; verbosity.&lt;br /&gt;
&lt;br /&gt;
==== include ====&lt;br /&gt;
&lt;br /&gt;
While the engine parses all declarations that are present in the files, the subtitles system only uses one subtitles decl named &amp;lt;tt&amp;gt;tdm_root&amp;lt;/tt&amp;gt;. &#039;&#039;Include&#039;&#039; commands are used in order to put other subtitle decls into it.  (The &amp;lt;tt&amp;gt;tdm_root&amp;lt;/tt&amp;gt; decl is in file &amp;lt;tt&amp;gt;tdm_root.subs&amp;lt;/tt&amp;gt;. As of TDM 2.11, this file, and all core non-game-specific tdm_*.subs, can be found in tdm_sound_vocals_decls01.pk4/subtitles/. An &#039;&#039;fm_root.subs&#039;&#039; file exists there, whose stub fm_root decl is over-ridden by your FM&#039;s fm_root as described next.)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;include&#039;&#039;&#039; command has one argument: the name of the subtitles decl to be included. Note that it is the name of the decl, not the name of the file which contains it! Included decl can in turn include other decls.&lt;br /&gt;
&lt;br /&gt;
FM-specific subtitles are always included from the decl named &#039;&#039;&#039;fm_root&#039;&#039;&#039;, which must be in the &#039;&#039;&#039;fm_root.subs&#039;&#039;&#039; file. For instance, the contents of the &amp;lt;tt&amp;gt;fm_conversations.subs&amp;lt;/tt&amp;gt; file from the example above will have no effect until we add the file &amp;lt;tt&amp;gt;fm_root.subs&amp;lt;/tt&amp;gt; with contents:&lt;br /&gt;
&lt;br /&gt;
 /**&lt;br /&gt;
  * This file should be overridden in order to provide mission-specific subtitles.&lt;br /&gt;
  * When doing so, please follow the conventions:&lt;br /&gt;
  *   1) The root decl is called &amp;quot;fm_root&amp;quot; and is located in file &amp;quot;fm_root.subs&amp;quot;.&lt;br /&gt;
  *   2) All other subtitle decls start with &amp;quot;fm_&amp;quot; prefix and are located in files starting with &amp;quot;fm_&amp;quot;.&lt;br /&gt;
  */&lt;br /&gt;
 &lt;br /&gt;
 subtitles fm_root {&lt;br /&gt;
     include &amp;quot;fm_intro_convo&amp;quot;&lt;br /&gt;
     include &amp;quot;fm_briefing&amp;quot;&lt;br /&gt;
     include &amp;quot;fm_much_later&amp;quot; // points to the decl below&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 // Decls and their &amp;quot;inline&amp;quot;/&amp;quot;srt&amp;quot; commands can be in the fm_root.subs file, not just in other .subs files:&lt;br /&gt;
 subtitles fm_much_later { &lt;br /&gt;
    verbosity story&lt;br /&gt;
    inline &amp;quot;sound/voices/paul/sound14.ogg&amp;quot; &amp;quot;Where did I put that knife sharpener?&amp;quot;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
Notice that one decl can be used to do any number of subtitle assignments, so it is not necessary to have many decls and decl files. The easiest way to do FM-specific subtitles is to have one &amp;lt;tt&amp;gt;fm_root.subs&amp;lt;/tt&amp;gt; file with one &amp;lt;tt&amp;gt;fm_root&amp;lt;/tt&amp;gt; decl, and specify all your subtitles right there. Splitting subtitles across decls and files is entirely optional and can be used for grouping subtitles. It was added mainly for core TDM sounds: there are several thousands of them, so keeping all subtitles in a single file can become a headache quickly.&lt;br /&gt;
&lt;br /&gt;
=== Output ===&lt;br /&gt;
&lt;br /&gt;
The subtitles which should be displayed right now are provided to GUI code as &#039;&#039;&#039;gui::subtitleN&#039;&#039;&#039; variables, where N ranges from 0 to 3 (although only 0 to 2 will be made visible by the standard GUI scripting described next).&lt;br /&gt;
GUI scripts display these variables as non-overlapping text messages. Given a logical screen height of 480, each of the 3 fields is 45 units high. N = 0 is the lowest, at Y-origin 400; 1 at 350; 2 at 300.&lt;br /&gt;
The responsible code is located in &amp;lt;tt&amp;gt;tdm_subtitles_common.gui&amp;lt;/tt&amp;gt; file, and is already used in several places:&lt;br /&gt;
* in the following states of the main menu: briefing, briefing video, and debriefing video&lt;br /&gt;
* in the always-on GUI overlay during gameplay&lt;br /&gt;
&lt;br /&gt;
For example, here is how it is used in &amp;lt;tt&amp;gt;mainmenu_briefing.gui&amp;lt;/tt&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
 //note: each include of tdm_subtitles_common must have different name prefix!&lt;br /&gt;
 #define SUBTITLES_NAMEPREFIX Briefing&lt;br /&gt;
 #include &amp;quot;guis/tdm_subtitles_common.gui&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Usually, you don&#039;t need to do anything about it. However, this information can be relevant if you write some custom GUI and want to see subtitles there.&lt;br /&gt;
&lt;br /&gt;
Note: it is not clear yet which kind of customization is necessary for the subtitles GUI.&lt;br /&gt;
If you have any ideas, please share them on [https://forums.thedarkmod.com/index.php?/topic/21741-subtitles-possibilities-beyond-211/ forums].&lt;br /&gt;
&lt;br /&gt;
{{GUI}}&lt;/div&gt;</summary>
		<author><name>Geep</name></author>
	</entry>
	<entry>
		<id>https://wiki.thedarkmod.com/index.php?title=Mason_Font&amp;diff=34096</id>
		<title>Mason Font</title>
		<link rel="alternate" type="text/html" href="https://wiki.thedarkmod.com/index.php?title=Mason_Font&amp;diff=34096"/>
		<updated>2025-10-21T22:05:06Z</updated>

		<summary type="html">&lt;p&gt;Geep: Add new section: 2025 Improvements to Russian [Proposed for TDM 2.14]&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;By Geep, 2024&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
== Introduction ==&lt;br /&gt;
Mason is a highly stylized font found in the large headlines at the top of the main menu pages. In English these read as:&lt;br /&gt;
* The Dark Mod &#039;&#039;(on main page)&#039;&#039;&lt;br /&gt;
* Missions List&lt;br /&gt;
* Online Mission Archive &#039;&#039;(with Online rendered smaller)&#039;&#039;&lt;br /&gt;
* Download Status&lt;br /&gt;
* Mission Details &#039;&#039;(and subheadings Description and Screenshots)&#039;&#039;&lt;br /&gt;
* Settings&lt;br /&gt;
* Load + Save&lt;br /&gt;
&lt;br /&gt;
Headline characters are rendered in black, surrounded by a static golden-white &amp;quot;glow&amp;quot; (or a different effect if Russian). The styling features top-alignment of characters, achieved by giving capital letters a higher-than-normal baseline. As a TDM font, provided in English (including Latin/European) and Russian, only the 48pt size is supplied, not 24pt or 12pt. That&#039;s because this font is not positioned for general use in FMs. &lt;br /&gt;
&lt;br /&gt;
The information here will be of most interest to anyone seeking to extend or manipulate this font. Historical context hopefully sheds light on current complexities.&lt;br /&gt;
&lt;br /&gt;
== Origins ==&lt;br /&gt;
Back when the founders created TDM, the main menu headlines (including glow) were burnt into the parchment backgrounds of main pages. This was no doubt done with a font (likely Adobe&#039;s &amp;quot;Mason Alternate Serif&amp;quot;) available within a graphics editor. And presumably with different page images for English and Russian, the two initial languages. [Please expand/refine this section if you were around then.]&lt;br /&gt;
&lt;br /&gt;
== 2010-14 Era - A New Font to Support Translations ==&lt;br /&gt;
&#039;&#039;Drawing from Springheel&#039;s [https://forums.thedarkmod.com/index.php?/topic/13825-menu-concerns-for-108/ &amp;quot;Menu concerns for 1.08&amp;quot;] and Tels&#039; &amp;quot;Translating the TDM GUI&amp;quot; thread, particularly [https://forums.thedarkmod.com/index.php?/topic/12863-translating-the-tdm-gui/page/14/#findComment-274467 here].&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
When it came time to expand main menu headlines of that time to European languages (an effort Springheel and Tels led in 2010-14), the original method was replaced by a more flexible one: blank parchment backgrounds overlaid by a text font, plus the glow.&lt;br /&gt;
&lt;br /&gt;
=== TTF Manipulation and Conversion ===&lt;br /&gt;
The starting point for that font [one assumes] was some Mason-like TTF font. It was likely Jonathan Barnbrook&#039;s 1992 &amp;quot;Mason Alternate&amp;quot;, which has no separately styled lower case characters; lower-case is just a smaller version of upper-case.&lt;br /&gt;
&lt;br /&gt;
Doom-era tools existed to programmatically convert a TTF file into a starting version of a TDM font, namely, a DAT file and a set of TGA (and ultimately DDS) images. (12pt and 24pt sizes were also generated, but only 48pt was pursued.) Furthermore, Tels reported working with graphics apps GIMP and Paintshop, that work directly with TTF fonts as well as TGA image files.&lt;br /&gt;
&lt;br /&gt;
=== Bitmap Tweaking and Character Set Extension ===&lt;br /&gt;
The 48pt font was then further adapted to &amp;quot;TDM style&amp;quot; (internally, &amp;quot;MasonAlternate&amp;quot;), with some characters morphed to look more like their burned-in TDM predecessors. Substantial additional bitmap editing added Cyrillic and the full panoply of accented Latin characters. The result was a duplicated set of (initially) seven 256x256 bitmaps that would cover English, European, and Russian languages. While the bitmaps were &amp;quot;shared&amp;quot; (by duplication - unlike the case with other TDM fonts), the metadata DAT files for English+European and for Russian had different content (i.e., diverging in their included glyphs and codepoint mapping), and were generated by separate [[Font Patcher]] scripts. (Subsequently, the sharing became partial; see &amp;quot;Further Changes...&amp;quot; below.)&lt;br /&gt;
&lt;br /&gt;
=== Enlarging Upper-Case Character of the New Font ===&lt;br /&gt;
Font Patcher scripting, as it generates a new, modified DAT file from an old one, can be asked to apply a scaling factor to specific characters. This does not affect the bitmap glyphs in any way, but instructs the TDM engine to scale at render-time. (See elsewhere for more about scaling within DAT files.)&lt;br /&gt;
&lt;br /&gt;
Recall the starting Mason TTF font had lower case-letters that were the same as upper-case, except for size difference. But that difference seemed insufficient. After experimentation, it was decided to make the upper-case letter nominally 20% larger, by applying a scaling factor of 1.20 to them. (Actual scaling ratios recalculated from resulting DAT values will vary due to rounding-to-integer quantification.)&lt;br /&gt;
This was applied to A-Z, as well as accented uppercase characters at codepoints 0x80-84, a2, a5, a6, a9-ac, b0, b2-b4, bc, be, and c0-dd.&lt;br /&gt;
&lt;br /&gt;
=== Finalizing Russian ===&lt;br /&gt;
At this point, the /russian/ versions of the seven bitmap shaders were frozen, and remain unchanged to the current day (unless DarkFate independently has made further alterations; beyond our scope here). [There was a 2021 touch of all font file dates... was anything changed then?]&lt;br /&gt;
&lt;br /&gt;
While a Russian &amp;quot;mason_glow&amp;quot; font was created and shipped, it is merely a placeholder: an exact duplicate of &amp;quot;mason&amp;quot;, in regard to the content of their DAT files and their sets of DDS files. Instead, the Russian deployment provides a substitute visual effect by rendering each character twice.&lt;br /&gt;
&lt;br /&gt;
=== Further Changes to English+European Mason During 2010-14 ===&lt;br /&gt;
==== Bitmap Consolation ====&lt;br /&gt;
While /russian/ kept 7 bitmaps, as discussed, the /english/ set was compacted to 6, by combining characters from Masonalternate_5_48.dds and Masonalternate_6_48.dds into the former alone. The DAT file was appropriated adjusted.&lt;br /&gt;
&lt;br /&gt;
Be aware that the compacted &amp;quot;english&amp;quot; set and the uncompacted &amp;quot;russian&amp;quot; set still encompass the same character glyphs; as before, their DAT files differ in what they expose.&lt;br /&gt;
&lt;br /&gt;
==== Introducing Glow ====&lt;br /&gt;
TDM&#039;s Mason (as well as Carleton) supports a &amp;quot;glow&amp;quot; around each character. As deployed with the /english/ version of Mason, the glow is a static yellowish-white halo around each black character; it does not vary with mouse-over. Indeed, TDM&#039;s Mason headlines (as opposed to Carleton) are not mouse-selectable. The glow is not done with special engine coding, but rather by using the GUI system and separate bitmap sets for the base characters (&amp;quot;mason&amp;quot;) and their glows (&amp;quot;mason_glow&amp;quot;). Each pair of base and glow characters will be aligned at render time, so must have compatible DAT metrics. (More about this below in a modern context.)&lt;br /&gt;
&lt;br /&gt;
To accommodate the extra spacing needed for a glow, some glyphs were moved further away from a shader edge, where they had been placed by the programmatic conversion. Significant adjustments for glow spacing:&lt;br /&gt;
* Masonalternate_0_48.dds. No change.&lt;br /&gt;
* Masonalternate_1_48.dds. Top row english moved down.&lt;br /&gt;
* Masonalternate_2_48.dds. Top row english moved down.&lt;br /&gt;
* Masonalternate_3_48.dds. No change.&lt;br /&gt;
* Masonalternate_4_48.dds. Top row accented moved down. Left column accented moved right.&lt;br /&gt;
* Masonalternate_5_48.dds. (combines russian 5 &amp;amp; 6) Top row accented moved down.&lt;br /&gt;
&lt;br /&gt;
The general GIMP method of creating a glow font bitmap from a copy of a base font bitmap is described &lt;br /&gt;
[https://forums.thedarkmod.com/index.php?/topic/12863-translating-the-tdm-gui/page/5/#findComment-262661 here].&lt;br /&gt;
&lt;br /&gt;
This results in paired base and glow bitmaps having the same character positioning, which while not required, is best practice and simplifies understanding when viewing in GIMP.&lt;br /&gt;
&lt;br /&gt;
Be aware that though paired DDS files in /english/mason/ and /english/mason_glow/ have identical filenames, the content is different. For example, mason/masonalternative_0_48.dds and mason_glow/masonalternative_0_48.dds have respectively base content and glow content.&lt;br /&gt;
&lt;br /&gt;
==== Resulting Bitmaps within GIMP, as Source ====&lt;br /&gt;
This discusses masonalternate_48.xcf, available...&lt;br /&gt;
* with filedate of May 26, 2012, unversioned in TDM SVN&lt;br /&gt;
* with filedate of March 28, 2014, within Tels&#039; [http://bloodgate.com/mirrors/tdm/pub/tdm_i18n.zip bloodgate archive of translated FMs]. Font Patcher scripts (as .txt files) are found here too.&lt;br /&gt;
&lt;br /&gt;
All 12 /english/ bitmaps are found as separate layers within a GIMP .xcf (project) file. The base character layers are called simply &amp;quot;0&amp;quot; to &amp;quot;5&amp;quot;. The glow characters are called &amp;quot;New Layer&amp;quot;, &amp;quot;New Layer #2&amp;quot;, and so on. (Unfortunately, in this .xcf, they are unhelpfully misnumbered. Just know that a &amp;quot;New Layer&amp;quot; pairs with the base numbered layer immediately below it.) In addition, the early base seventh bitmap is represented here by the extra &amp;quot;Pasted Layer&amp;quot;, whose characters (for /english/ not /russian/) were subsequently copied into layer 5.&lt;br /&gt;
&lt;br /&gt;
So, as layers are individually exported as DDS files, they must be manually distributed appropriately:&lt;br /&gt;
* &amp;quot;New Layer&amp;quot; above &amp;quot;5&amp;quot; ==&amp;gt; mason_glow/fontimage_5_48.dds&lt;br /&gt;
* &amp;quot;5&amp;quot; ==&amp;gt; mason/fontimage_5_48.dds&lt;br /&gt;
* &amp;quot;New Layer&amp;quot; above &amp;quot;4&amp;quot; ==&amp;gt; mason_glow/fontimage_4_48.dds&lt;br /&gt;
* &amp;quot;4&amp;quot; ==&amp;gt; mason/fontimage_4_48.dds&lt;br /&gt;
* &amp;quot;New Layer&amp;quot; above &amp;quot;3&amp;quot; ==&amp;gt; mason_glow/fontimage_3_48.dds&lt;br /&gt;
* &amp;quot;3&amp;quot; ==&amp;gt; mason/fontimage_3_48.dds&lt;br /&gt;
* &amp;quot;New Layer&amp;quot; above &amp;quot;2&amp;quot; ==&amp;gt; mason_glow/fontimage_2_48.dds&lt;br /&gt;
* &amp;quot;2&amp;quot; ==&amp;gt; mason/fontimage_2_48.dds&lt;br /&gt;
* &amp;quot;New Layer&amp;quot; above &amp;quot;1&amp;quot; ==&amp;gt; mason_glow/fontimage_1_48.dds&lt;br /&gt;
* &amp;quot;1&amp;quot; ==&amp;gt; mason/fontimage_1_48.dds&lt;br /&gt;
* &amp;quot;New Layer&amp;quot; above &amp;quot;0&amp;quot; ==&amp;gt; mason_glow/fontimage_0_48.dds&lt;br /&gt;
* &amp;quot;0&amp;quot; ==&amp;gt; mason/fontimage_0_48.dds&lt;br /&gt;
&lt;br /&gt;
==== Deployment and European String Support ====&lt;br /&gt;
Regarding Mason, it was the plan to provide translated text and GUI methodology to all the main menu headlings, e.g., &amp;quot;Settings&amp;quot;, &amp;quot;Load/Save&amp;quot;, and &amp;quot;Mission Archive&amp;quot;. [There are indications this was only realized for some headlines, and finally completed during the 2017-18 update.]&lt;br /&gt;
== 2017-18 Era - Improving English Appearance ==&lt;br /&gt;
&#039;&#039;Adapted from Springheel&#039;s  thread [https://forums.thedarkmod.com/index.php?/topic/19129-menu-update/#comment-412921 &amp;quot;Menu Update&amp;quot;].&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
As time went on, it was observed that the 48pt-sized characters used in Mason, while of adequate crispness for the screen resolutions of Doom and early TDM, were showing their age. In 2017-8, Springheel undertook a revision to fix this. This effort focused on just the English alphabetic characters In the /english/ set. The method involved:&lt;br /&gt;
* Doubling the size of selected bitmap shaders from 256 x 256 to 512 x 512. This involved enlarging the bitmap image, so doubling the size of every glyph contained within (since the goal here was not to pack in more glyphs per bitmap.) Fortunately, the size the characters appearance in-game is unchanged, if the DAT file metrics are unaltered.&lt;br /&gt;
* Within the doubled shaders, selecting and modifying individual glyphs to make them render more crisply.&lt;br /&gt;
&lt;br /&gt;
=== Selective Doubling of &amp;quot;Mason&amp;quot; ===&lt;br /&gt;
An analysis showed that only Mason&#039;s first three shader bitmaps contained the characters of interest.&lt;br /&gt;
So expeditiously, only those were doubled to 512x512. This doubled the size of glyphs of all characters within, including those not of improvement interest. (By not doubling all six bitmaps, the resulting mixed-bitmap dimensions in the set has drawbacks for GIMP layering and tool usage, discussed later.)&lt;br /&gt;
&lt;br /&gt;
In spite of this doubling, the characters must not change in size when rendered. This is done by keeping the DAT&#039;s metrics – particularly imageHeight and imageWidth - unchanged, as well as floating-point boundaries s, t, s2, and t2 expressed as 0..1, but now within the doubled 512 x 512 size.&lt;br /&gt;
&lt;br /&gt;
Expressed in REF terms, the values of imageHeight and imageWidth are unchanged from their 256 x 256 values, but coord_s, coord_t, coord_s2, and coord_t2 integers are doubled. So, as integer coordinates, this may be viewed as applying a 0.50 scaling factor – or for upper-case ASCII characters, composing 0.50 and 1.20 scaling factors.&lt;br /&gt;
&lt;br /&gt;
=== Selective Doubling of &amp;quot;Mason_glow&amp;quot; ===&lt;br /&gt;
Surprisingly, of the corresponding 3 glow bitmaps, only 2 of them were doubled. There are pluses and minuses to doubling glow bitmaps. The main argument &amp;quot;for&amp;quot; is that it permits easy visualization as layers in apps like GIMP. The main argument &amp;quot;against&amp;quot; is that, since the glows are supposed to be fuzzy, they don&#039;t really need to be sharpened.&lt;br /&gt;
&lt;br /&gt;
In any event, the base and glow don&#039;t require the same size shader for proper alignment. The specific requirement is that the following must match for each base and glow character in their respective DAT files:&lt;br /&gt;
* horizontal border dimension s2-s, expressed as a floating point value 0...1&lt;br /&gt;
* vertical border dimension t2-t, expressed as a floating point value 0...1&lt;br /&gt;
* All other numeric metadata.&lt;br /&gt;
&lt;br /&gt;
If border dimensions are expressed as pixel integer in REF terms, this is more complicated, as each border must reflect an appropriate range of 0...256 or 0...512, depending on its bitmap shader.&lt;br /&gt;
&lt;br /&gt;
=== Black Borders Appear ===&lt;br /&gt;
In general, TDM fonts represent every glyph as pure white (RGB 1,1,1), delineated only by alpha channel edges. This was true for mason within the previous-era&#039;s /english/ and /russian/ DDS files.&lt;br /&gt;
&lt;br /&gt;
But in the 3 /english/ base mason dds files that were doubled, every character somehow got a ragged black border (when viewed in GIMP). Specifically, these &amp;quot;black border&amp;quot; glyphs are gray-scale (or maybe black/white dithered) with smudgy white interiors. Perhaps that doesn&#039;t matter so much when game-rendered in black, but still, unhelpful.&lt;br /&gt;
&lt;br /&gt;
=== Selective Sharpening/Redrawing ===&lt;br /&gt;
Finally, the bitmap glyphs were editing to make crisper edges. This was limited to &amp;quot;regular keyboard characters&amp;quot;, not &amp;quot;alternative language characters&amp;quot; (e.g., accented or Cyrillic). For these characters, the &amp;quot;black borders&amp;quot; problems was overwritten: the black borders were minimized (though not eliminated), and the interiors were cleaned to be pure white. [Done with flood fill?]. But the problem remains for other characters.&lt;br /&gt;
&lt;br /&gt;
=== Coverage ===&lt;br /&gt;
Coverage was completed so that all headlines (e.g., Settings, Load/Save, Mission Archive) were rendered translated into European languages. But only the unaccented English characters were uniformly improved.&lt;br /&gt;
&lt;br /&gt;
=== Resulting Bitmaps as Files ===&lt;br /&gt;
To summarize the /english/ base results...&lt;br /&gt;
&lt;br /&gt;
Now of size 512x512 (342 KB), and containing (though not exclusively) redrawn English characters:&lt;br /&gt;
* Masonalternate_0_48.dds&lt;br /&gt;
* Masonalternate_1_48.dds&lt;br /&gt;
* Masonalternate_2_48.dds&lt;br /&gt;
&lt;br /&gt;
Of size 256 x 256 (86 KB), and not containing English characters, so no redrawing:&lt;br /&gt;
* Masonalternate_3_48.dds&lt;br /&gt;
* Masonalternate_4_48.dds&lt;br /&gt;
* Masonalternate_5_48.dds&lt;br /&gt;
&lt;br /&gt;
== 2025 Improvements to Russian [Proposed for TDM 2.14] ==&lt;br /&gt;
&#039;&#039;For more about this project by kalinovka and Geep, including motivations, approaches, and resulting screenshots, test FMs and details of individual characters,, see the &amp;quot;Font localization&amp;quot; thread, particularly this [https://forums.thedarkmod.com/index.php?/topic/22736-font-localization/#comment-501602 this post with links and screenshots].&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
=== Coverage, Appearance, and Bitmaps ===&lt;br /&gt;
&lt;br /&gt;
Mason /russian/ was missing a number of alphabetic glyphs for TDM-defined Cyrillic characters. This upgrade corrected that, so that Mason can be used not just for the main menu system, but in-game (albeit with still only 48pt distributed). When easy to do, some characters also got crisper glyph rendering or improved spacing. (Some characters will remain soft-edged or not-ideally spaced.)&lt;br /&gt;
&lt;br /&gt;
The main approach was to first replace the /russian/ Mason DDS set with the TDM 2.13 /english/ Mason set (with corresponding DAT file changes), then - as fill-in - add newly-generated DDS from a &amp;quot;Lora Regular&amp;quot; font. While less stylish, Lora (in adjusted point sizes) is adequate to &amp;quot;pass&amp;quot; as Mason 48pt. The original &amp;quot;Mason Alternate&amp;quot; TTF source did not include Cyrillic characters.&lt;br /&gt;
&lt;br /&gt;
Specifically, the DDS set, distributed under &amp;quot;tdm_fonts01/dds/fonts/russian/mason&amp;quot;, became as follows.&lt;br /&gt;
Copied from the TDM 2.13 /english/ set (replacing the 2.13 /russian/ set), with Jan. 17, 2021 file dates:&lt;br /&gt;
&lt;br /&gt;
* masonalternate_0_48.dds&lt;br /&gt;
* masonalternate_1_48.dds&lt;br /&gt;
* masonalternate_2_48.dds&lt;br /&gt;
* masonalternate_3_48.dds&lt;br /&gt;
* masonalternate_4_48.dds&lt;br /&gt;
* masonalternate_5_48.dds&lt;br /&gt;
&lt;br /&gt;
Newly generated lower-case and symbols for /russian/, with 2025 file dates:&lt;br /&gt;
&lt;br /&gt;
* lora45_as_mason_6_48.dds&lt;br /&gt;
* lora45_as_mason_7_48.dds&lt;br /&gt;
&lt;br /&gt;
Newly generated upper-case for /russian/, with 2025 file dates:&lt;br /&gt;
&lt;br /&gt;
* lora54_as_mason_8_48.dds&lt;br /&gt;
* lora54_as_mason_9_48.dds&lt;br /&gt;
* lora54_as_mason_10_48.dds&lt;br /&gt;
&lt;br /&gt;
=== Revised DAT File ===&lt;br /&gt;
The contents of several DAT files were hand-merged, to reach the final DAT that mixes shaders for &amp;quot;Mason Alternate&amp;quot; &amp;amp; &amp;quot;Lora Regular&amp;quot; fonts.&lt;br /&gt;
&lt;br /&gt;
At codepoints 0x00-7f, the TDM 2.13 Mason &#039;&#039;/english/&#039;&#039; ASCII characters appear. These render crisply, due to previous bitmap improvements: doubling of bitmap size, followed by glyph redrawing to limit anti-aliasing.&lt;br /&gt;
&lt;br /&gt;
At codepoints 0x80-ff, for Cyrillic, there&#039;s a mix of:&lt;br /&gt;
&lt;br /&gt;
* Cyrillic characters already existing in the Mason /english/ set (some the same glyphs as ASCII, a few the same as European, some previously hand-drawn)&lt;br /&gt;
* New non-capitals generated from Lora 45pt (matching the height of Mason 48pt).&lt;br /&gt;
* New capitals generated from Lora 54pt. Because these were generated at a larger point size, they didn’t require additional 120% DAT scaling (with its added edge-softening) to reach the target size. But they did need DAT adjustments to be top-aligned in the TDM-specific style for this font.&lt;br /&gt;
&lt;br /&gt;
A few characters got additional special treatments.&lt;br /&gt;
&lt;br /&gt;
=== Mason_glow ===&lt;br /&gt;
Finally, the /russian/ mason_glow font was also updated with a clone of these updated /russian/ Mason resources. (This differs from how /english/ glows are implemented.)&lt;br /&gt;
&lt;br /&gt;
== Working with Mason Today ==&lt;br /&gt;
=== Improved Tools to Generate Bitmaps from TTF and to View Font Coverage ===&lt;br /&gt;
The 2025 Improvements to Russian included:&lt;br /&gt;
&lt;br /&gt;
* Creating the [[ExportUnicodeFontToDoom3]] utility, used to generate the new Lora DDS and DAT files.&lt;br /&gt;
* Deploying several test FMs. The final one, testMasonLora3Way.pk4, displays the entirety of the proposed 2.14 /russian/mason font. (This is available via the &amp;quot;Font localization&amp;quot; link above. It is trivial to clone and adapt this FM to show comparable coverage for other /russian/ or /english/ fonts.)&lt;br /&gt;
&lt;br /&gt;
=== Drawbacks of Mixed-Size Bitmaps ===&lt;br /&gt;
==== With GIMP ====&lt;br /&gt;
While you can view multiple images in GIMP, if they are of different sizes, a view of them in aligned layers becomes impractical. This weighs against the use of a single .xcf file to serve as overall source for the set. Instead, individual TGA images make more sense. These can still be edited one at a time in GIMP.&lt;br /&gt;
&lt;br /&gt;
==== With [[Refont]] and [[datBounds]] ====&lt;br /&gt;
&lt;br /&gt;
Refont v2.5 and datBounds v1.6 now supports mixed-sized bitmaps. See in particular [[Refont#Mason Family]].&lt;br /&gt;
&lt;br /&gt;
=== How Mason&#039;s &amp;quot;Glow&amp;quot; is Implemented ===&lt;br /&gt;
A typical usage is the mainmenu_download.gui, where two representations of the current string are overlaid in an aligned manner. One is the text, rendered as opaque black (using RGBA 0,0,0,1). The other is the glow, rendered in pale yellow with some transparency (RGBA 1,1,0.80,0.8). The glow source already has some transparency, so this is even more. For a given character, the glow bitmap has wider and more diffuse strokes than the base font. A link about glow bitmap creation is above.&lt;br /&gt;
&lt;br /&gt;
Here&#039;s one representative gui code snippet, showing placement of the words &amp;quot;Mission Archive&amp;quot; (or it&#039;s non-English equivalent), on a parchment background:&lt;br /&gt;
&lt;br /&gt;
 ...&lt;br /&gt;
    // Mission Archive Headline Translation&lt;br /&gt;
    windowDef MissionArchiveHeadlineTextGlow&lt;br /&gt;
    {&lt;br /&gt;
      rect 10, 15 + &amp;quot;gui::headline_offset&amp;quot;, 300, 100&lt;br /&gt;
      text &amp;quot;#str_menu_mission_archive&amp;quot; // Mission Archive&lt;br /&gt;
      font		&amp;quot;fonts/mason_glow&amp;quot;&lt;br /&gt;
      forecolor 1,1,0.80,0.8&lt;br /&gt;
      textscale	0.65&lt;br /&gt;
      textalign 1&lt;br /&gt;
      textaligny -1&lt;br /&gt;
      visible 1&lt;br /&gt;
    }&lt;br /&gt;
    windowDef MissionArchiveHeadlineText&lt;br /&gt;
    {&lt;br /&gt;
      rect 10, 15 + &amp;quot;gui::headline_offset&amp;quot;, 300, 100&lt;br /&gt;
      text &amp;quot;#str_menu_mission_archive&amp;quot; // Mission Archive&lt;br /&gt;
      font		&amp;quot;fonts/mason&amp;quot;&lt;br /&gt;
      forecolor 0,0,0,1.0&lt;br /&gt;
      textscale	0.65&lt;br /&gt;
      textalign 1&lt;br /&gt;
      visible 1&lt;br /&gt;
    }&lt;br /&gt;
 ...&lt;br /&gt;
&lt;br /&gt;
Observe that the similarity of rect, textscale, and textalign values keeps the two overlays exactly aligned, except for a 1 pixel vertical offset given by textaligny -1.&lt;br /&gt;
&lt;br /&gt;
(Additional GUI event handling, not shown, allows the paired textscale values to be reduced to accommodate a more-verbose European language.)&lt;br /&gt;
&lt;br /&gt;
{{tutorial}} [[Category:Fonts]]&lt;/div&gt;</summary>
		<author><name>Geep</name></author>
	</entry>
	<entry>
		<id>https://wiki.thedarkmod.com/index.php?title=ExportUnicodeFontToDoom3&amp;diff=34078</id>
		<title>ExportUnicodeFontToDoom3</title>
		<link rel="alternate" type="text/html" href="https://wiki.thedarkmod.com/index.php?title=ExportUnicodeFontToDoom3&amp;diff=34078"/>
		<updated>2025-09-11T21:35:55Z</updated>

		<summary type="html">&lt;p&gt;Geep: Add release 1 links&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;By Geep, 2025&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
== Introduction ==&lt;br /&gt;
&lt;br /&gt;
In 2025, kalinovka in [https://forums.thedarkmod.com/index.php?/topic/22736-font-localization Font localization] sought to extend TDM’s Mason 48pt font, used in the main menu, to include missing Cyrillic glyphs. This would allow this font to be used in an FM and still support a Russian translation.&lt;br /&gt;
&lt;br /&gt;
This offshoot of [https://wiki.thedarkmod.com/index.php?title=ExportFontToDoom3 ExportFontToDoom3All256] is a generalized response to that. The main idea to select an input TTF font that includes not just ASCII or ANSI, but offers additional Unicode characters, like Cyrillic. The program still limits output to a maximum of 256 characters, consistent with the DAT format.&lt;br /&gt;
&lt;br /&gt;
To achieve this, it reads in an external human-readable &amp;quot;unicodeMap&amp;quot; file, in Unicode.org’s &amp;quot;Format A&amp;quot;. This format provides a mapping from the traditional 8-bit encoding that TDM uses to the corresponding UCS (Unicode 16-bit) value. Unicode.org provides stock files for standard ISO and Windows 8-bit encodings. Of specific interest here is [https://www.unicode.org/Public/MAPPINGS/VENDORS/MICSFT/WINDOWS/CP1251.TXT cp1251.txt for Cyrillic]. This requires just trivial editing for [https://wiki.thedarkmod.com/index.php?title=I18N_-_Charset TDM-specific codepoints]. As discussed below, you can further edit a unicodeMap file in advance, if you want to generate just a subset of glyphs.&lt;br /&gt;
&lt;br /&gt;
More broadly, this program supersedes ExportFontToDoom3 and ExportFontToDoom3All256.&lt;br /&gt;
&lt;br /&gt;
== New Command Line Arguments ==&lt;br /&gt;
&lt;br /&gt;
These are in-addition to those of [https://wiki.thedarkmod.com/index.php?title=ExportFontToDoom3 ExportFontToDoom3All256].&lt;br /&gt;
&lt;br /&gt;
=== unicodeMap &amp;lt;file&amp;gt; ===&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
 -unicodeMap &amp;quot;./Test/cp1251.txt&amp;quot;&lt;br /&gt;
&lt;br /&gt;
You can edit the unicodeMap file in advance, to specify which particular glyphs you want to generate by suppressing unwanted glyphs, either by:&lt;br /&gt;
&lt;br /&gt;
* Deleting an unwanted line (or block of lines) entirely, or&lt;br /&gt;
* Prepending a &amp;quot;#&amp;quot; to comment-out the line.&lt;br /&gt;
&lt;br /&gt;
Also, this file format allows the Unicode value (e.g., &amp;quot;0x1234&amp;quot;) to be replaced by 6 space characters, when the ISO or Windows standard leaves that character undefined.&lt;br /&gt;
&lt;br /&gt;
In all 3 of those cases, every suppressed character in the output DAT file will be represented by the glyph that the font uses for U+0000. A hollow box is common.&lt;br /&gt;
&lt;br /&gt;
=== startFileNumber &amp;lt;n&amp;gt; ===&lt;br /&gt;
When a set of TGA/DDS files are generated for a particular font size, by default the first file&#039;s name contains _0_, which increments for additional files. You can optionally specify a different 1- or 2-digit start number, e.g., &amp;quot;-startFileNumber 7&amp;quot;. Why? Because...&lt;br /&gt;
&lt;br /&gt;
* the file(s) you are generating are supplemental to, not replacements for, existing TGA/DDS files; and&lt;br /&gt;
* in this run, you are generating just one of the 3 possible font sizes (assuming each size has a different count of existing TGA/DDS files).&lt;br /&gt;
&lt;br /&gt;
When you generate a supplemental set, the new DAT file has no knowledge of what&#039;s in the original set and its DAT file. You will have to interleave-edit the old and new DAT files (e.g., with reFont&#039;s REF files) to create a single DAT file spanning old and new glyphs. There may be a redundant NULL glyph in your new TGA set; just ignore it.&lt;br /&gt;
&lt;br /&gt;
=== awayFromEdge &amp;lt;n&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
Allows specifying in positive integer pixels (e.g., &amp;quot;-awayFromEdge 2&amp;quot;) a small extra boundary at the top and left edges of the overall bitmap. This is for fonts like Mason where extra space (typically 2 pixels) is needed around every character to create a &amp;quot;glow variant&amp;quot;. Routine glyph layout provides usually enough space for this except at the top and (arguably) left edges. See also the &amp;quot;compact&amp;quot; parameter.&lt;br /&gt;
&lt;br /&gt;
=== compact ===&lt;br /&gt;
If specified (i.e, &amp;quot;-compact&amp;quot;), packs the character glyphs more closely together. Particularly recommended for 48pt fonts; it will generate roughly half the files.&lt;br /&gt;
&lt;br /&gt;
Whether &amp;quot;compact&amp;quot; is specified or not, packing is controlled by simply &amp;quot;padding&amp;quot; each glyph’s bounding box. Specifically, this doesn’t change the bounding box, but adds pixel &amp;quot;padding&amp;quot; to just the right and bottom of the bounding box, a simple though asymmetric process. One reason for padding was given ExportFontToDoom3 author Grant Davies in code comments:&lt;br /&gt;
&lt;br /&gt;
&amp;quot;Because of the way Doom 3 Indexes the texture page (using floating point numbers), it is unable to reference exact pixels – there is error. How much error, I don’t know. For this reason, the rectangles needs to be padded out.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Geep suspects that such error with the TDM engine is not really a problem. Likely some error in the past was due to editing with Q3Font and its low floating-point precision. Nevertheless, some padding is good because:&lt;br /&gt;
&lt;br /&gt;
* For the Mason font, 2 pixels around each glyph are needed for &amp;quot;glow&amp;quot; effects (either done as a separate smudge font for /english/ or as a bidirection offset effect for /russian/.)&lt;br /&gt;
* Keeping glyphs separated improves visualization of boundaries with datBounds, and makes editing tweaks easier.&lt;br /&gt;
&lt;br /&gt;
The &amp;quot;compact&amp;quot; setting restores Grant Davies&#039; first algorithm, which just pads the bounding box by 5 pixels to the right and 5 pixels below.&lt;br /&gt;
&lt;br /&gt;
Without &amp;quot;compact&amp;quot;, the default is Grant Davies&#039; second algorithm found in ExportFontToDoom3 v1.02. This likewise first pads each bounding box by 5 pixels to the right and 5 pixels below. It then further pads to make both the width and height a factor of 2; this makes 48pt quite sparse.  (It is possible this improved rendering performance in 2005; not important now. Also, in practice for major fonts, much of this &amp;quot;factor of 2&amp;quot; spacing was overridden by subsequent Font Patcher work.)&lt;br /&gt;
&lt;br /&gt;
=== (hirez - another possible argument) ===&lt;br /&gt;
&#039;&#039;Geep: This is a future idea, but no promises on this.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Change code to allow export of 512x512 bitmaps with larger, thus crisper glyphs. Specifically, add a new command-line option, -hirez, that would&lt;br /&gt;
* output 512x512 TGAs and their DAT.&lt;br /&gt;
* internally, double the character glyph size; so if your requested 48pt, it would make 96pt glyphs. (This is more or less how /english/ 512x512 treats its hand-made glyphs.)&lt;br /&gt;
* make whatever other layout &amp;amp; metric adjustments needed. The imageHeight and imageWidth metrics will be as if the requested 48pt size was generated, so in effect scaling down by a factor of 2 from the 96pt glyph. &lt;br /&gt;
&lt;br /&gt;
== Changed Behavior ==&lt;br /&gt;
In ExportFontToDoom3All256, if the font title was more that 20 characters long, it would truncate it to fit in the DAT file as part of the shader names (i.e., paths to TGA files). But this threshold was wrong. Now, truncation and a warning happens if the font title is more that 17 characters long (or 16 if generated TGAs include any with a 2-digit count instead of 1-digit). If truncation occurs, the user is asked to consider using or revising the -name argument.&lt;br /&gt;
&lt;br /&gt;
== Downloads ==&lt;br /&gt;
Release 1 of 2024-09-10:&lt;br /&gt;
* [https://drive.google.com/file/d/1MqoOfhc5-ovoxoHfRquYAcIEdHEOJAQV/view?usp=sharing ExportUnicodeFontToDoom3_release_1_exe.zip] . Windows binary and required archived versions of FreeType and DevIL DLLs.&lt;br /&gt;
* [https://drive.google.com/file/d/1Frk_byfdtCcMqdr27ulw1XyuFj8vYp9x/view?usp=sharing ExportUnicodeFontToDoom3_release_1_source_project.zip] . The C++ project file with source code, including source &amp;amp; build project of archived library.&lt;br /&gt;
&lt;br /&gt;
The Cyrillic coverage of Lora Regular TTF font, projected to used as Russian Mason supplement in TDM 2.14, may be viewed and font downloaded [https://www.fontsquirrel.com/fonts/lora?filter%5Bclassifications%5D%5B0%5D=serif&amp;amp;filter%5Blanguages%5D%5B0%5D=cyrillic#eula here].&lt;/div&gt;</summary>
		<author><name>Geep</name></author>
	</entry>
	<entry>
		<id>https://wiki.thedarkmod.com/index.php?title=ExportUnicodeFontToDoom3&amp;diff=34076</id>
		<title>ExportUnicodeFontToDoom3</title>
		<link rel="alternate" type="text/html" href="https://wiki.thedarkmod.com/index.php?title=ExportUnicodeFontToDoom3&amp;diff=34076"/>
		<updated>2025-09-10T20:06:33Z</updated>

		<summary type="html">&lt;p&gt;Geep: /* Changed Behavior */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;By Geep, 2025 [WORK IN PROGRESS]&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
== Introduction ==&lt;br /&gt;
&lt;br /&gt;
In 2025, kalinovka in [https://forums.thedarkmod.com/index.php?/topic/22736-font-localization Font localization] sought to extend TDM’s Mason 48pt font, used in the main menu, to include missing Cyrillic glyphs. This would allow this font to be used in an FM and still support a Russian translation.&lt;br /&gt;
&lt;br /&gt;
This offshoot of [https://wiki.thedarkmod.com/index.php?title=ExportFontToDoom3 ExportFontToDoom3All256] is a generalized response to that. The main idea to select an input TTF font that includes not just ASCII or ANSI, but offers additional Unicode characters, like Cyrillic. The program still limits output to a maximum of 256 characters, consistent with the DAT format.&lt;br /&gt;
&lt;br /&gt;
To achieve this, it reads in an external human-readable &amp;quot;unicodeMap&amp;quot; file, in Unicode.org’s &amp;quot;Format A&amp;quot;. This format provides a mapping from the traditional 8-bit encoding that TDM uses to the corresponding UCS (Unicode 16-bit) value. Unicode.org provides stock files for standard ISO and Windows 8-bit encodings. Of specific interest here is [https://www.unicode.org/Public/MAPPINGS/VENDORS/MICSFT/WINDOWS/CP1251.TXT cp1251.txt for Cyrillic]. This requires just trivial editing for [https://wiki.thedarkmod.com/index.php?title=I18N_-_Charset TDM-specific codepoints].&lt;br /&gt;
As discussed below, you can further edit a unicodeMap file in advance, if you want to generate just a subset of glyphs.&lt;br /&gt;
&lt;br /&gt;
== New Command Line Arguments ==&lt;br /&gt;
&lt;br /&gt;
These are in-addition to those of [https://wiki.thedarkmod.com/index.php?title=ExportFontToDoom3 ExportFontToDoom3All256].&lt;br /&gt;
&lt;br /&gt;
=== unicodeMap &amp;lt;file&amp;gt; ===&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
 -unicodeMap &amp;quot;./Test/cp1251.txt&amp;quot;&lt;br /&gt;
&lt;br /&gt;
You can edit the unicodeMap file in advance, to specify which particular glyphs you want to generate by suppressing unwanted glyphs, either by:&lt;br /&gt;
&lt;br /&gt;
* Deleting an unwanted line (or block of lines) entirely, or&lt;br /&gt;
* Prepending a &amp;quot;#&amp;quot; to comment-out the line.&lt;br /&gt;
&lt;br /&gt;
Also, this file format allows the Unicode value (e.g., &amp;quot;0x1234&amp;quot;) to be replaced by 6 space characters, when the ISO or Windows standard leaves that character undefined.&lt;br /&gt;
&lt;br /&gt;
In all 3 of those cases, every suppressed character in the output DAT file will be represented by the glyph that the font uses for U+0000. A hollow box is common.&lt;br /&gt;
&lt;br /&gt;
=== startFileNumber &amp;lt;n&amp;gt; ===&lt;br /&gt;
When a set of TGA/DDS files are generated for a particular font size, by default the first file&#039;s name contains _0_, which increments for additional files. You can optionally specify a different 1- or 2-digit start number, e.g., &amp;quot;-startFileNumber 7&amp;quot;. Why? Because...&lt;br /&gt;
&lt;br /&gt;
* the file(s) you are generating are supplemental to, not replacements for, existing TGA/DDS files; and&lt;br /&gt;
* in this run, you are generating just one of the 3 possible font sizes (assuming each size has a different count of existing TGA/DDS files).&lt;br /&gt;
&lt;br /&gt;
When you generate a supplemental set, the new DAT file has no knowledge of what&#039;s in the original set and its DAT file. You will have to interleave-edit the old and new DAT files (e.g., with reFont&#039;s REF files) to create a single DAT file spanning old and new glyphs. There may be a redundant NULL glyph in your new TGA set; just ignore it.&lt;br /&gt;
&lt;br /&gt;
=== awayFromEdge &amp;lt;n&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
Allows specifying in positive integer pixels (e.g., &amp;quot;-awayFromEdge 2&amp;quot;) a small extra boundary at the top and left edges of the overall bitmap. This is for fonts like Mason where extra space (typically 2 pixels) is needed around every character to create a &amp;quot;glow variant&amp;quot;. Routine glyph layout provides usually enough space for this except at the top and (arguably) left edges. See also the &amp;quot;compact&amp;quot; parameter.&lt;br /&gt;
&lt;br /&gt;
=== compact ===&lt;br /&gt;
If specified (i.e, &amp;quot;-compact&amp;quot;), packs the character glyphs more closely together. Particularly recommended for 48pt fonts; it will generate roughly half the files.&lt;br /&gt;
&lt;br /&gt;
Whether &amp;quot;compact&amp;quot; is specified or not, packing is controlled by simply &amp;quot;padding&amp;quot; each glyph’s bounding box. Specifically, this doesn’t change the bounding box, but adds pixel &amp;quot;padding&amp;quot; to just the right and bottom of the bounding box, a simple though asymmetric process. One reason for padding was given ExportFontToDoom3 author Grant Davies in code comments:&lt;br /&gt;
&lt;br /&gt;
&amp;quot;Because of the way Doom 3 Indexes the texture page (using floating point numbers), it is unable to reference exact pixels – there is error. How much error, I don’t know. For this reason, the rectangles needs to be padded out.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Geep suspects that such error with the TDM engine is not really a problem. Likely some error in the past was due to editing with Q3Font and its low floating-point precision. Nevertheless, some padding is good because:&lt;br /&gt;
&lt;br /&gt;
* For the Mason font, 2 pixels around each glyph are needed for &amp;quot;glow&amp;quot; effects (either done as a separate smudge font for /english/ or as a bidirection offset effect for /russian/.)&lt;br /&gt;
* Keeping glyphs separated improves visualization of boundaries with datBounds, and makes editing tweaks easier.&lt;br /&gt;
&lt;br /&gt;
The &amp;quot;compact&amp;quot; setting restores Grant Davies&#039; first algorithm, which just pads the bounding box by 5 pixels to the right and 5 pixels below.&lt;br /&gt;
&lt;br /&gt;
Without &amp;quot;compact&amp;quot;, the default is Grant Davies&#039; second algorithm found in ExportFontToDoom3 v1.02. This likewise first pads each bounding box by 5 pixels to the right and 5 pixels below. It then further pads to make both the width and height a factor of 2; this makes 48pt quite sparse.  (It is possible this improved rendering performance in 2005; not important now. Also, in practice for major fonts, much of this &amp;quot;factor of 2&amp;quot; spacing was overridden by subsequent Font Patcher work.)&lt;br /&gt;
&lt;br /&gt;
=== (hirez - another possible argument) ===&lt;br /&gt;
&#039;&#039;Geep: This is a future idea, but no promises on this.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Change code to allow export of 512x512 bitmaps with larger, thus crisper glyphs. Specifically, add a new command-line option, -hirez, that would&lt;br /&gt;
* output 512x512 TGAs and their DAT.&lt;br /&gt;
* internally, double the character glyph size; so if your requested 48pt, it would make 96pt glyphs. (This is more or less how /english/ 512x512 treats its hand-made glyphs.)&lt;br /&gt;
* make whatever other layout &amp;amp; metric adjustments needed. The imageHeight and imageWidth metrics will be as if the requested 48pt size was generated, so in effect scaling down by a factor of 2 from the 96pt glyph. &lt;br /&gt;
&lt;br /&gt;
== Changed Behavior ==&lt;br /&gt;
In ExportFontToDoom3All256, if the font title was more that 20 characters long, it would truncate it to fit in the DAT file as part of the shader names (i.e., paths to TGA files). But this threshold was wrong. Now, truncation and a warning happens if the font title is more that 17 characters long (or 16 if generated TGAs include any with a 2-digit count instead of 1-digit). If truncation occurs, the user is asked to consider using or revising the -name argument.&lt;br /&gt;
&lt;br /&gt;
== Downloads ==&lt;br /&gt;
[links to do]&lt;br /&gt;
&lt;br /&gt;
Windows binary and required archived versions of FreeType and DevIL DLLs: &lt;br /&gt;
&lt;br /&gt;
ExportUnicodeFontToDoom3 Release 1 of 09-10-2025.zip&lt;br /&gt;
&lt;br /&gt;
The C++ project file with source code:&lt;br /&gt;
&lt;br /&gt;
ExportUnicodeFontToDoom3_source_project.zip  Release 1 of 09-10-2025. This zip is ... MB, includes source &amp;amp; build project of archived library.&lt;br /&gt;
&lt;br /&gt;
The Cyrillic coverage of Lora Regular TTF font, projected to used as Russian Mason supplement in TDM 2.14, may be viewed and font downloaded [https://www.fontsquirrel.com/fonts/lora?filter%5Bclassifications%5D%5B0%5D=serif&amp;amp;filter%5Blanguages%5D%5B0%5D=cyrillic#eula here].&lt;/div&gt;</summary>
		<author><name>Geep</name></author>
	</entry>
	<entry>
		<id>https://wiki.thedarkmod.com/index.php?title=ExportUnicodeFontToDoom3&amp;diff=34075</id>
		<title>ExportUnicodeFontToDoom3</title>
		<link rel="alternate" type="text/html" href="https://wiki.thedarkmod.com/index.php?title=ExportUnicodeFontToDoom3&amp;diff=34075"/>
		<updated>2025-09-10T20:05:07Z</updated>

		<summary type="html">&lt;p&gt;Geep: /* Downloads */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;By Geep, 2025 [WORK IN PROGRESS]&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
== Introduction ==&lt;br /&gt;
&lt;br /&gt;
In 2025, kalinovka in [https://forums.thedarkmod.com/index.php?/topic/22736-font-localization Font localization] sought to extend TDM’s Mason 48pt font, used in the main menu, to include missing Cyrillic glyphs. This would allow this font to be used in an FM and still support a Russian translation.&lt;br /&gt;
&lt;br /&gt;
This offshoot of [https://wiki.thedarkmod.com/index.php?title=ExportFontToDoom3 ExportFontToDoom3All256] is a generalized response to that. The main idea to select an input TTF font that includes not just ASCII or ANSI, but offers additional Unicode characters, like Cyrillic. The program still limits output to a maximum of 256 characters, consistent with the DAT format.&lt;br /&gt;
&lt;br /&gt;
To achieve this, it reads in an external human-readable &amp;quot;unicodeMap&amp;quot; file, in Unicode.org’s &amp;quot;Format A&amp;quot;. This format provides a mapping from the traditional 8-bit encoding that TDM uses to the corresponding UCS (Unicode 16-bit) value. Unicode.org provides stock files for standard ISO and Windows 8-bit encodings. Of specific interest here is [https://www.unicode.org/Public/MAPPINGS/VENDORS/MICSFT/WINDOWS/CP1251.TXT cp1251.txt for Cyrillic]. This requires just trivial editing for [https://wiki.thedarkmod.com/index.php?title=I18N_-_Charset TDM-specific codepoints].&lt;br /&gt;
As discussed below, you can further edit a unicodeMap file in advance, if you want to generate just a subset of glyphs.&lt;br /&gt;
&lt;br /&gt;
== New Command Line Arguments ==&lt;br /&gt;
&lt;br /&gt;
These are in-addition to those of [https://wiki.thedarkmod.com/index.php?title=ExportFontToDoom3 ExportFontToDoom3All256].&lt;br /&gt;
&lt;br /&gt;
=== unicodeMap &amp;lt;file&amp;gt; ===&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
 -unicodeMap &amp;quot;./Test/cp1251.txt&amp;quot;&lt;br /&gt;
&lt;br /&gt;
You can edit the unicodeMap file in advance, to specify which particular glyphs you want to generate by suppressing unwanted glyphs, either by:&lt;br /&gt;
&lt;br /&gt;
* Deleting an unwanted line (or block of lines) entirely, or&lt;br /&gt;
* Prepending a &amp;quot;#&amp;quot; to comment-out the line.&lt;br /&gt;
&lt;br /&gt;
Also, this file format allows the Unicode value (e.g., &amp;quot;0x1234&amp;quot;) to be replaced by 6 space characters, when the ISO or Windows standard leaves that character undefined.&lt;br /&gt;
&lt;br /&gt;
In all 3 of those cases, every suppressed character in the output DAT file will be represented by the glyph that the font uses for U+0000. A hollow box is common.&lt;br /&gt;
&lt;br /&gt;
=== startFileNumber &amp;lt;n&amp;gt; ===&lt;br /&gt;
When a set of TGA/DDS files are generated for a particular font size, by default the first file&#039;s name contains _0_, which increments for additional files. You can optionally specify a different 1- or 2-digit start number, e.g., &amp;quot;-startFileNumber 7&amp;quot;. Why? Because...&lt;br /&gt;
&lt;br /&gt;
* the file(s) you are generating are supplemental to, not replacements for, existing TGA/DDS files; and&lt;br /&gt;
* in this run, you are generating just one of the 3 possible font sizes (assuming each size has a different count of existing TGA/DDS files).&lt;br /&gt;
&lt;br /&gt;
When you generate a supplemental set, the new DAT file has no knowledge of what&#039;s in the original set and its DAT file. You will have to interleave-edit the old and new DAT files (e.g., with reFont&#039;s REF files) to create a single DAT file spanning old and new glyphs. There may be a redundant NULL glyph in your new TGA set; just ignore it.&lt;br /&gt;
&lt;br /&gt;
=== awayFromEdge &amp;lt;n&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
Allows specifying in positive integer pixels (e.g., &amp;quot;-awayFromEdge 2&amp;quot;) a small extra boundary at the top and left edges of the overall bitmap. This is for fonts like Mason where extra space (typically 2 pixels) is needed around every character to create a &amp;quot;glow variant&amp;quot;. Routine glyph layout provides usually enough space for this except at the top and (arguably) left edges. See also the &amp;quot;compact&amp;quot; parameter.&lt;br /&gt;
&lt;br /&gt;
=== compact ===&lt;br /&gt;
If specified (i.e, &amp;quot;-compact&amp;quot;), packs the character glyphs more closely together. Particularly recommended for 48pt fonts; it will generate roughly half the files.&lt;br /&gt;
&lt;br /&gt;
Whether &amp;quot;compact&amp;quot; is specified or not, packing is controlled by simply &amp;quot;padding&amp;quot; each glyph’s bounding box. Specifically, this doesn’t change the bounding box, but adds pixel &amp;quot;padding&amp;quot; to just the right and bottom of the bounding box, a simple though asymmetric process. One reason for padding was given ExportFontToDoom3 author Grant Davies in code comments:&lt;br /&gt;
&lt;br /&gt;
&amp;quot;Because of the way Doom 3 Indexes the texture page (using floating point numbers), it is unable to reference exact pixels – there is error. How much error, I don’t know. For this reason, the rectangles needs to be padded out.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Geep suspects that such error with the TDM engine is not really a problem. Likely some error in the past was due to editing with Q3Font and its low floating-point precision. Nevertheless, some padding is good because:&lt;br /&gt;
&lt;br /&gt;
* For the Mason font, 2 pixels around each glyph are needed for &amp;quot;glow&amp;quot; effects (either done as a separate smudge font for /english/ or as a bidirection offset effect for /russian/.)&lt;br /&gt;
* Keeping glyphs separated improves visualization of boundaries with datBounds, and makes editing tweaks easier.&lt;br /&gt;
&lt;br /&gt;
The &amp;quot;compact&amp;quot; setting restores Grant Davies&#039; first algorithm, which just pads the bounding box by 5 pixels to the right and 5 pixels below.&lt;br /&gt;
&lt;br /&gt;
Without &amp;quot;compact&amp;quot;, the default is Grant Davies&#039; second algorithm found in ExportFontToDoom3 v1.02. This likewise first pads each bounding box by 5 pixels to the right and 5 pixels below. It then further pads to make both the width and height a factor of 2; this makes 48pt quite sparse.  (It is possible this improved rendering performance in 2005; not important now. Also, in practice for major fonts, much of this &amp;quot;factor of 2&amp;quot; spacing was overridden by subsequent Font Patcher work.)&lt;br /&gt;
&lt;br /&gt;
=== (hirez - another possible argument) ===&lt;br /&gt;
&#039;&#039;Geep: This is a future idea, but no promises on this.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Change code to allow export of 512x512 bitmaps with larger, thus crisper glyphs. Specifically, add a new command-line option, -hirez, that would&lt;br /&gt;
* output 512x512 TGAs and their DAT.&lt;br /&gt;
* internally, double the character glyph size; so if your requested 48pt, it would make 96pt glyphs. (This is more or less how /english/ 512x512 treats its hand-made glyphs.)&lt;br /&gt;
* make whatever other layout &amp;amp; metric adjustments needed. The imageHeight and imageWidth metrics will be as if the requested 48pt size was generated, so in effect scaling down by a factor of 2 from the 96pt glyph. &lt;br /&gt;
&lt;br /&gt;
== Changed Behavior ==&lt;br /&gt;
In ExportFontToDoom3All256, if the font title was more that 20 characters long, it would truncate it to fit in the DAT file as part of the shader names (i.e., paths to TGA files). But this threshold was wrong. Now, truncation and a warning happens if the font title is more that 17 characters long (or 16 if generated TGAs include any with a 2-digit count instead of 1-digit). If truncation occurs, the user is asked to consider using the -name argument.&lt;br /&gt;
&lt;br /&gt;
== Downloads ==&lt;br /&gt;
[links to do]&lt;br /&gt;
&lt;br /&gt;
Windows binary and required archived versions of FreeType and DevIL DLLs: &lt;br /&gt;
&lt;br /&gt;
ExportUnicodeFontToDoom3 Release 1 of 09-10-2025.zip&lt;br /&gt;
&lt;br /&gt;
The C++ project file with source code:&lt;br /&gt;
&lt;br /&gt;
ExportUnicodeFontToDoom3_source_project.zip  Release 1 of 09-10-2025. This zip is ... MB, includes source &amp;amp; build project of archived library.&lt;br /&gt;
&lt;br /&gt;
The Cyrillic coverage of Lora Regular TTF font, projected to used as Russian Mason supplement in TDM 2.14, may be viewed and font downloaded [https://www.fontsquirrel.com/fonts/lora?filter%5Bclassifications%5D%5B0%5D=serif&amp;amp;filter%5Blanguages%5D%5B0%5D=cyrillic#eula here].&lt;/div&gt;</summary>
		<author><name>Geep</name></author>
	</entry>
	<entry>
		<id>https://wiki.thedarkmod.com/index.php?title=ExportUnicodeFontToDoom3&amp;diff=34074</id>
		<title>ExportUnicodeFontToDoom3</title>
		<link rel="alternate" type="text/html" href="https://wiki.thedarkmod.com/index.php?title=ExportUnicodeFontToDoom3&amp;diff=34074"/>
		<updated>2025-09-10T20:04:47Z</updated>

		<summary type="html">&lt;p&gt;Geep: /* Downloads */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;By Geep, 2025 [WORK IN PROGRESS]&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
== Introduction ==&lt;br /&gt;
&lt;br /&gt;
In 2025, kalinovka in [https://forums.thedarkmod.com/index.php?/topic/22736-font-localization Font localization] sought to extend TDM’s Mason 48pt font, used in the main menu, to include missing Cyrillic glyphs. This would allow this font to be used in an FM and still support a Russian translation.&lt;br /&gt;
&lt;br /&gt;
This offshoot of [https://wiki.thedarkmod.com/index.php?title=ExportFontToDoom3 ExportFontToDoom3All256] is a generalized response to that. The main idea to select an input TTF font that includes not just ASCII or ANSI, but offers additional Unicode characters, like Cyrillic. The program still limits output to a maximum of 256 characters, consistent with the DAT format.&lt;br /&gt;
&lt;br /&gt;
To achieve this, it reads in an external human-readable &amp;quot;unicodeMap&amp;quot; file, in Unicode.org’s &amp;quot;Format A&amp;quot;. This format provides a mapping from the traditional 8-bit encoding that TDM uses to the corresponding UCS (Unicode 16-bit) value. Unicode.org provides stock files for standard ISO and Windows 8-bit encodings. Of specific interest here is [https://www.unicode.org/Public/MAPPINGS/VENDORS/MICSFT/WINDOWS/CP1251.TXT cp1251.txt for Cyrillic]. This requires just trivial editing for [https://wiki.thedarkmod.com/index.php?title=I18N_-_Charset TDM-specific codepoints].&lt;br /&gt;
As discussed below, you can further edit a unicodeMap file in advance, if you want to generate just a subset of glyphs.&lt;br /&gt;
&lt;br /&gt;
== New Command Line Arguments ==&lt;br /&gt;
&lt;br /&gt;
These are in-addition to those of [https://wiki.thedarkmod.com/index.php?title=ExportFontToDoom3 ExportFontToDoom3All256].&lt;br /&gt;
&lt;br /&gt;
=== unicodeMap &amp;lt;file&amp;gt; ===&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
 -unicodeMap &amp;quot;./Test/cp1251.txt&amp;quot;&lt;br /&gt;
&lt;br /&gt;
You can edit the unicodeMap file in advance, to specify which particular glyphs you want to generate by suppressing unwanted glyphs, either by:&lt;br /&gt;
&lt;br /&gt;
* Deleting an unwanted line (or block of lines) entirely, or&lt;br /&gt;
* Prepending a &amp;quot;#&amp;quot; to comment-out the line.&lt;br /&gt;
&lt;br /&gt;
Also, this file format allows the Unicode value (e.g., &amp;quot;0x1234&amp;quot;) to be replaced by 6 space characters, when the ISO or Windows standard leaves that character undefined.&lt;br /&gt;
&lt;br /&gt;
In all 3 of those cases, every suppressed character in the output DAT file will be represented by the glyph that the font uses for U+0000. A hollow box is common.&lt;br /&gt;
&lt;br /&gt;
=== startFileNumber &amp;lt;n&amp;gt; ===&lt;br /&gt;
When a set of TGA/DDS files are generated for a particular font size, by default the first file&#039;s name contains _0_, which increments for additional files. You can optionally specify a different 1- or 2-digit start number, e.g., &amp;quot;-startFileNumber 7&amp;quot;. Why? Because...&lt;br /&gt;
&lt;br /&gt;
* the file(s) you are generating are supplemental to, not replacements for, existing TGA/DDS files; and&lt;br /&gt;
* in this run, you are generating just one of the 3 possible font sizes (assuming each size has a different count of existing TGA/DDS files).&lt;br /&gt;
&lt;br /&gt;
When you generate a supplemental set, the new DAT file has no knowledge of what&#039;s in the original set and its DAT file. You will have to interleave-edit the old and new DAT files (e.g., with reFont&#039;s REF files) to create a single DAT file spanning old and new glyphs. There may be a redundant NULL glyph in your new TGA set; just ignore it.&lt;br /&gt;
&lt;br /&gt;
=== awayFromEdge &amp;lt;n&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
Allows specifying in positive integer pixels (e.g., &amp;quot;-awayFromEdge 2&amp;quot;) a small extra boundary at the top and left edges of the overall bitmap. This is for fonts like Mason where extra space (typically 2 pixels) is needed around every character to create a &amp;quot;glow variant&amp;quot;. Routine glyph layout provides usually enough space for this except at the top and (arguably) left edges. See also the &amp;quot;compact&amp;quot; parameter.&lt;br /&gt;
&lt;br /&gt;
=== compact ===&lt;br /&gt;
If specified (i.e, &amp;quot;-compact&amp;quot;), packs the character glyphs more closely together. Particularly recommended for 48pt fonts; it will generate roughly half the files.&lt;br /&gt;
&lt;br /&gt;
Whether &amp;quot;compact&amp;quot; is specified or not, packing is controlled by simply &amp;quot;padding&amp;quot; each glyph’s bounding box. Specifically, this doesn’t change the bounding box, but adds pixel &amp;quot;padding&amp;quot; to just the right and bottom of the bounding box, a simple though asymmetric process. One reason for padding was given ExportFontToDoom3 author Grant Davies in code comments:&lt;br /&gt;
&lt;br /&gt;
&amp;quot;Because of the way Doom 3 Indexes the texture page (using floating point numbers), it is unable to reference exact pixels – there is error. How much error, I don’t know. For this reason, the rectangles needs to be padded out.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Geep suspects that such error with the TDM engine is not really a problem. Likely some error in the past was due to editing with Q3Font and its low floating-point precision. Nevertheless, some padding is good because:&lt;br /&gt;
&lt;br /&gt;
* For the Mason font, 2 pixels around each glyph are needed for &amp;quot;glow&amp;quot; effects (either done as a separate smudge font for /english/ or as a bidirection offset effect for /russian/.)&lt;br /&gt;
* Keeping glyphs separated improves visualization of boundaries with datBounds, and makes editing tweaks easier.&lt;br /&gt;
&lt;br /&gt;
The &amp;quot;compact&amp;quot; setting restores Grant Davies&#039; first algorithm, which just pads the bounding box by 5 pixels to the right and 5 pixels below.&lt;br /&gt;
&lt;br /&gt;
Without &amp;quot;compact&amp;quot;, the default is Grant Davies&#039; second algorithm found in ExportFontToDoom3 v1.02. This likewise first pads each bounding box by 5 pixels to the right and 5 pixels below. It then further pads to make both the width and height a factor of 2; this makes 48pt quite sparse.  (It is possible this improved rendering performance in 2005; not important now. Also, in practice for major fonts, much of this &amp;quot;factor of 2&amp;quot; spacing was overridden by subsequent Font Patcher work.)&lt;br /&gt;
&lt;br /&gt;
=== (hirez - another possible argument) ===&lt;br /&gt;
&#039;&#039;Geep: This is a future idea, but no promises on this.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Change code to allow export of 512x512 bitmaps with larger, thus crisper glyphs. Specifically, add a new command-line option, -hirez, that would&lt;br /&gt;
* output 512x512 TGAs and their DAT.&lt;br /&gt;
* internally, double the character glyph size; so if your requested 48pt, it would make 96pt glyphs. (This is more or less how /english/ 512x512 treats its hand-made glyphs.)&lt;br /&gt;
* make whatever other layout &amp;amp; metric adjustments needed. The imageHeight and imageWidth metrics will be as if the requested 48pt size was generated, so in effect scaling down by a factor of 2 from the 96pt glyph. &lt;br /&gt;
&lt;br /&gt;
== Changed Behavior ==&lt;br /&gt;
In ExportFontToDoom3All256, if the font title was more that 20 characters long, it would truncate it to fit in the DAT file as part of the shader names (i.e., paths to TGA files). But this threshold was wrong. Now, truncation and a warning happens if the font title is more that 17 characters long (or 16 if generated TGAs include any with a 2-digit count instead of 1-digit). If truncation occurs, the user is asked to consider using the -name argument.&lt;br /&gt;
&lt;br /&gt;
== Downloads ==&lt;br /&gt;
[links to do]&lt;br /&gt;
&lt;br /&gt;
Windows binary and required archived versions of FreeType and DevIL DLLs: &lt;br /&gt;
&lt;br /&gt;
ExportUnicodeFontToDoom3 Release 1 of 09-10-2025.zip&lt;br /&gt;
&lt;br /&gt;
The C++ project file with source code:&lt;br /&gt;
&lt;br /&gt;
ExportUnicodeFontToDoom3_source_project.zip  Release 1 of 09-10-2025. This zip is ... MB, includes source &amp;amp; build project of archived library.&lt;br /&gt;
&lt;br /&gt;
The Cyrillic coverage of Lora Regular TTF font, project to used as Russian Mason supplement in TDM 2.14, may be viewed and font downloaded [https://www.fontsquirrel.com/fonts/lora?filter%5Bclassifications%5D%5B0%5D=serif&amp;amp;filter%5Blanguages%5D%5B0%5D=cyrillic#eula here].&lt;/div&gt;</summary>
		<author><name>Geep</name></author>
	</entry>
	<entry>
		<id>https://wiki.thedarkmod.com/index.php?title=ExportUnicodeFontToDoom3&amp;diff=34073</id>
		<title>ExportUnicodeFontToDoom3</title>
		<link rel="alternate" type="text/html" href="https://wiki.thedarkmod.com/index.php?title=ExportUnicodeFontToDoom3&amp;diff=34073"/>
		<updated>2025-09-10T20:02:44Z</updated>

		<summary type="html">&lt;p&gt;Geep: Add Changed Behavior, Downloads [draft] sections&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;By Geep, 2025 [WORK IN PROGRESS]&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
== Introduction ==&lt;br /&gt;
&lt;br /&gt;
In 2025, kalinovka in [https://forums.thedarkmod.com/index.php?/topic/22736-font-localization Font localization] sought to extend TDM’s Mason 48pt font, used in the main menu, to include missing Cyrillic glyphs. This would allow this font to be used in an FM and still support a Russian translation.&lt;br /&gt;
&lt;br /&gt;
This offshoot of [https://wiki.thedarkmod.com/index.php?title=ExportFontToDoom3 ExportFontToDoom3All256] is a generalized response to that. The main idea to select an input TTF font that includes not just ASCII or ANSI, but offers additional Unicode characters, like Cyrillic. The program still limits output to a maximum of 256 characters, consistent with the DAT format.&lt;br /&gt;
&lt;br /&gt;
To achieve this, it reads in an external human-readable &amp;quot;unicodeMap&amp;quot; file, in Unicode.org’s &amp;quot;Format A&amp;quot;. This format provides a mapping from the traditional 8-bit encoding that TDM uses to the corresponding UCS (Unicode 16-bit) value. Unicode.org provides stock files for standard ISO and Windows 8-bit encodings. Of specific interest here is [https://www.unicode.org/Public/MAPPINGS/VENDORS/MICSFT/WINDOWS/CP1251.TXT cp1251.txt for Cyrillic]. This requires just trivial editing for [https://wiki.thedarkmod.com/index.php?title=I18N_-_Charset TDM-specific codepoints].&lt;br /&gt;
As discussed below, you can further edit a unicodeMap file in advance, if you want to generate just a subset of glyphs.&lt;br /&gt;
&lt;br /&gt;
== New Command Line Arguments ==&lt;br /&gt;
&lt;br /&gt;
These are in-addition to those of [https://wiki.thedarkmod.com/index.php?title=ExportFontToDoom3 ExportFontToDoom3All256].&lt;br /&gt;
&lt;br /&gt;
=== unicodeMap &amp;lt;file&amp;gt; ===&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
 -unicodeMap &amp;quot;./Test/cp1251.txt&amp;quot;&lt;br /&gt;
&lt;br /&gt;
You can edit the unicodeMap file in advance, to specify which particular glyphs you want to generate by suppressing unwanted glyphs, either by:&lt;br /&gt;
&lt;br /&gt;
* Deleting an unwanted line (or block of lines) entirely, or&lt;br /&gt;
* Prepending a &amp;quot;#&amp;quot; to comment-out the line.&lt;br /&gt;
&lt;br /&gt;
Also, this file format allows the Unicode value (e.g., &amp;quot;0x1234&amp;quot;) to be replaced by 6 space characters, when the ISO or Windows standard leaves that character undefined.&lt;br /&gt;
&lt;br /&gt;
In all 3 of those cases, every suppressed character in the output DAT file will be represented by the glyph that the font uses for U+0000. A hollow box is common.&lt;br /&gt;
&lt;br /&gt;
=== startFileNumber &amp;lt;n&amp;gt; ===&lt;br /&gt;
When a set of TGA/DDS files are generated for a particular font size, by default the first file&#039;s name contains _0_, which increments for additional files. You can optionally specify a different 1- or 2-digit start number, e.g., &amp;quot;-startFileNumber 7&amp;quot;. Why? Because...&lt;br /&gt;
&lt;br /&gt;
* the file(s) you are generating are supplemental to, not replacements for, existing TGA/DDS files; and&lt;br /&gt;
* in this run, you are generating just one of the 3 possible font sizes (assuming each size has a different count of existing TGA/DDS files).&lt;br /&gt;
&lt;br /&gt;
When you generate a supplemental set, the new DAT file has no knowledge of what&#039;s in the original set and its DAT file. You will have to interleave-edit the old and new DAT files (e.g., with reFont&#039;s REF files) to create a single DAT file spanning old and new glyphs. There may be a redundant NULL glyph in your new TGA set; just ignore it.&lt;br /&gt;
&lt;br /&gt;
=== awayFromEdge &amp;lt;n&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
Allows specifying in positive integer pixels (e.g., &amp;quot;-awayFromEdge 2&amp;quot;) a small extra boundary at the top and left edges of the overall bitmap. This is for fonts like Mason where extra space (typically 2 pixels) is needed around every character to create a &amp;quot;glow variant&amp;quot;. Routine glyph layout provides usually enough space for this except at the top and (arguably) left edges. See also the &amp;quot;compact&amp;quot; parameter.&lt;br /&gt;
&lt;br /&gt;
=== compact ===&lt;br /&gt;
If specified (i.e, &amp;quot;-compact&amp;quot;), packs the character glyphs more closely together. Particularly recommended for 48pt fonts; it will generate roughly half the files.&lt;br /&gt;
&lt;br /&gt;
Whether &amp;quot;compact&amp;quot; is specified or not, packing is controlled by simply &amp;quot;padding&amp;quot; each glyph’s bounding box. Specifically, this doesn’t change the bounding box, but adds pixel &amp;quot;padding&amp;quot; to just the right and bottom of the bounding box, a simple though asymmetric process. One reason for padding was given ExportFontToDoom3 author Grant Davies in code comments:&lt;br /&gt;
&lt;br /&gt;
&amp;quot;Because of the way Doom 3 Indexes the texture page (using floating point numbers), it is unable to reference exact pixels – there is error. How much error, I don’t know. For this reason, the rectangles needs to be padded out.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Geep suspects that such error with the TDM engine is not really a problem. Likely some error in the past was due to editing with Q3Font and its low floating-point precision. Nevertheless, some padding is good because:&lt;br /&gt;
&lt;br /&gt;
* For the Mason font, 2 pixels around each glyph are needed for &amp;quot;glow&amp;quot; effects (either done as a separate smudge font for /english/ or as a bidirection offset effect for /russian/.)&lt;br /&gt;
* Keeping glyphs separated improves visualization of boundaries with datBounds, and makes editing tweaks easier.&lt;br /&gt;
&lt;br /&gt;
The &amp;quot;compact&amp;quot; setting restores Grant Davies&#039; first algorithm, which just pads the bounding box by 5 pixels to the right and 5 pixels below.&lt;br /&gt;
&lt;br /&gt;
Without &amp;quot;compact&amp;quot;, the default is Grant Davies&#039; second algorithm found in ExportFontToDoom3 v1.02. This likewise first pads each bounding box by 5 pixels to the right and 5 pixels below. It then further pads to make both the width and height a factor of 2; this makes 48pt quite sparse.  (It is possible this improved rendering performance in 2005; not important now. Also, in practice for major fonts, much of this &amp;quot;factor of 2&amp;quot; spacing was overridden by subsequent Font Patcher work.)&lt;br /&gt;
&lt;br /&gt;
=== (hirez - another possible argument) ===&lt;br /&gt;
&#039;&#039;Geep: This is a future idea, but no promises on this.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Change code to allow export of 512x512 bitmaps with larger, thus crisper glyphs. Specifically, add a new command-line option, -hirez, that would&lt;br /&gt;
* output 512x512 TGAs and their DAT.&lt;br /&gt;
* internally, double the character glyph size; so if your requested 48pt, it would make 96pt glyphs. (This is more or less how /english/ 512x512 treats its hand-made glyphs.)&lt;br /&gt;
* make whatever other layout &amp;amp; metric adjustments needed. The imageHeight and imageWidth metrics will be as if the requested 48pt size was generated, so in effect scaling down by a factor of 2 from the 96pt glyph. &lt;br /&gt;
&lt;br /&gt;
== Changed Behavior ==&lt;br /&gt;
In ExportFontToDoom3All256, if the font title was more that 20 characters long, it would truncate it to fit in the DAT file as part of the shader names (i.e., paths to TGA files). But this threshold was wrong. Now, truncation and a warning happens if the font title is more that 17 characters long (or 16 if generated TGAs include any with a 2-digit count instead of 1-digit). If truncation occurs, the user is asked to consider using the -name argument.&lt;br /&gt;
&lt;br /&gt;
== Downloads ==&lt;br /&gt;
[links to do]&lt;br /&gt;
&lt;br /&gt;
Windows binary and required archived versions of FreeType and DevIL DLLs: &lt;br /&gt;
&lt;br /&gt;
ExportUnicodeFontToDoom3 Release 1 of 09-10-2025.zip&lt;br /&gt;
&lt;br /&gt;
The C++ project file with source code:&lt;br /&gt;
&lt;br /&gt;
ExportUnicodeFontToDoom3_source_project.zip  Release 1 of 09-10-2025. This zip is ... MB, includes source &amp;amp; build project of archived library.&lt;br /&gt;
&lt;br /&gt;
The Cyrillic coverage of Lora Regular TTF font, used as Russian Mason supplement, may be viewed and font downloaded [https://www.fontsquirrel.com/fonts/lora?filter%5Bclassifications%5D%5B0%5D=serif&amp;amp;filter%5Blanguages%5D%5B0%5D=cyrillic#eula here].&lt;/div&gt;</summary>
		<author><name>Geep</name></author>
	</entry>
	<entry>
		<id>https://wiki.thedarkmod.com/index.php?title=ExportFontToDoom3&amp;diff=34072</id>
		<title>ExportFontToDoom3</title>
		<link rel="alternate" type="text/html" href="https://wiki.thedarkmod.com/index.php?title=ExportFontToDoom3&amp;diff=34072"/>
		<updated>2025-09-10T19:48:47Z</updated>

		<summary type="html">&lt;p&gt;Geep: Add See Also: ExportUnicodeFontToDoom3&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Intro to ExportFontToDoom3 &amp;amp; ExportFontToDoom3All256 ==&lt;br /&gt;
The Windows command-line utility &amp;quot;ExportFontToDoom3&amp;quot; was created by Australian modder Grant Davies in 2005 to get TrueType Fonts, standard on Windows, into the metadata+bitmaps form needed by the Doom 3 engine. His final version, 1.02, was released as open-source and substantially used for TDM. It relies on the open-source DevIL and Freetype2 libraries.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;ExportFontToDoom3&#039;&#039;&#039; exports only the bitmap glyphs assigned to codepoints in the range 0-127, routinely the ASCII characters. The output actually generates metadata for 256 characters, but, due to a bug, upper-half characters are just mapped to the &amp;quot;undefined character&amp;quot; glyph.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;ExportFontToDoom3All256&#039;&#039;&#039; fixes that bug; it exports the glyphs assigned to codepoints in the range 0-255, routinely ANSI characters. It is also easier to run on modern Windows PCs, so recommended. It takes the same command-line arguments as ExportFontToDoom3. Credits to Crispy (for 2009 fix) and (in 2024 form) Geep.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;See Also: successor project [[ExportUnicodeFontToDoom3]]&#039;&#039;&#039;, that can export Cyrillic and other Unicode characters, and adds further useful options.&lt;br /&gt;
&lt;br /&gt;
== Using the Tool ==&lt;br /&gt;
&#039;&#039;The information here is adapted from the description doc included with the ExportFontToDoom3 download.&#039;&#039;&lt;br /&gt;
=== Basic Command ===&lt;br /&gt;
To export with the common settings of 12, 24, and 48 point fonts, simply type:&lt;br /&gt;
 ExportFontToDoom3All256 &#039;&#039;font_filename&#039;&#039;&lt;br /&gt;
For example (and assuming here a font &amp;quot;badtimes&amp;quot; with no legal issues):&lt;br /&gt;
 ExportFontToDoom3All256 badtimes.ttf&lt;br /&gt;
Most standard font formats (from the 2009 timeframe) can be used for export, but TrueType is most common.&lt;br /&gt;
=== Size Option ===&lt;br /&gt;
To export the font in a certain size, use the option:&lt;br /&gt;
 -size &#039;&#039;font_pointsize&#039;&#039;&lt;br /&gt;
For Doom3/TDM, only the sizes 12, 24, and 48 directly produce valid end-products. More than one &amp;quot;-size&amp;quot; arguments may be specified, for example:&lt;br /&gt;
 ExportFontToDoom3All256 badtimes.ttf -size 12 -size 24&lt;br /&gt;
As indicated above, if no &amp;quot;-size&amp;quot; argument is specified, 12, 24, and 48 point fonts are exported.&lt;br /&gt;
&lt;br /&gt;
The set of sizes in a particular generation run will jointly determine the &amp;quot;glyphScale&amp;quot; value specified at the end of bottom of a DAT/REF file, as follows:&lt;br /&gt;
&lt;br /&gt;
 glyphScale[for size n] = largest-size-in-set / size-n&lt;br /&gt;
&lt;br /&gt;
So, depending on how you generate, you may have to hand-adjust the glyphScale later.&lt;br /&gt;
&lt;br /&gt;
It is possible to specify one or more non-standard sizes for special processing, e.g., to do TTF-to-DAT overall scaling. To use in TDM, this will need subsequent file renaming to one of the 3 valid sizes, and glyphScale correction.&lt;br /&gt;
&lt;br /&gt;
=== Name Option ===&lt;br /&gt;
To (re)name the font to be exported, use the option:&lt;br /&gt;
 -name &#039;&#039;fontname&#039;&#039;&lt;br /&gt;
By default, the fontname is instead extracted from the font file. In either case, the fontname string will be truncated if too long. It then begins each of the TGA filename(s), which are referenced in turn in the per-character &amp;quot;shaderName&amp;quot; fields of the DAT file. The shaderName field in a DAT file can have at most 32 characters; when viewed as a REF or FNT file, it has this template:&lt;br /&gt;
 shaderName    fontname_&amp;lt;1- or 2-digit count&amp;gt;_&amp;lt;2-digit fontsize&amp;gt;.tga&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;TIP: If the default fontname is more than 16 characters, it is recommended you use the -name option, to prevent ugly truncation or (corrected in ExportUnicodeFontToDoom3) aborts.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
=== Other Options ===&lt;br /&gt;
In the description doc, there is a great deal of technical discussion about these next options, but of little likely relevance to TDM nowadays. Just ignore them in favor of their default values.&lt;br /&gt;
 -textureFormat &#039;&#039;format&#039;&#039;&lt;br /&gt;
where the default is .tga, which is what you want. Use another tool to convert the output from .tga to .dds, since ExportFontToDoom3 won&#039;t do it correctly.&lt;br /&gt;
 -xOffsetFix &#039;&#039;type&#039;&#039;&lt;br /&gt;
where the default is &amp;quot;none&amp;quot;, which causes the font&#039;s X offset value to be exported to the &amp;quot;pitch&amp;quot; member of TDM .dat file. There is also the related:&lt;br /&gt;
 -noXOffsetWarnings&lt;br /&gt;
&lt;br /&gt;
=== Output ===&lt;br /&gt;
A new folder will be created and all output files will be stored there. The folder will be named according to the font being exported.&lt;br /&gt;
The output will consist of Targa image (.tga) files and .dat files.&lt;br /&gt;
&lt;br /&gt;
Afterwards, from each TGA, you should create a corresponding DDS file.&lt;br /&gt;
&lt;br /&gt;
== Deployment &amp;amp; Further Adaptions ==&lt;br /&gt;
After export, assuming you have an FM set up to test them, rename the files into standard form and move or copy them to the expected locations...&lt;br /&gt;
* For DAT files: fonts/english/&amp;lt;your font name&amp;gt;/&lt;br /&gt;
* For DDS files: dds/english/&amp;lt;your font name&amp;gt;/&lt;br /&gt;
You&#039;ll undoubtedly have to make further iterative adjustments to both the DAT files (using other methods listed in [[Font Conversion &amp;amp; Repair]]) and bitmap files.&lt;br /&gt;
For instance, the &amp;quot;glyphScale&amp;quot; value will likely have to be changed.&lt;br /&gt;
&lt;br /&gt;
== Tutorials that Include ExportFontToDoom3 ==&lt;br /&gt;
Doom3-era tutorials, once posted on www.doom3world, can still be found with the &amp;quot;wayback machine&amp;quot; links given here:&lt;br /&gt;
* [https://web.archive.org/web/20081028224423/http://www.doom3world.org/phpbb2/viewtopic.php?t=11923 Tutorial 10 - Using custom fonts]&lt;br /&gt;
* [https://web.archive.org/web/20100522173219/http://www.doom3world.org/phpbb2/viewtopic.php?t=11924 Tutorial 11 - Editing fonts]&lt;br /&gt;
&lt;br /&gt;
== Downloads of ExportFontToDoom3All256 ==&lt;br /&gt;
Windows binary and required archived versions of FreeType and DevIL DLLs:&lt;br /&gt;
* [https://drive.google.com/file/d/1HzyyuZv0AVEhw4czJEwQ4nDMuqCogRyi/view?usp=sharing &#039;ExportFontToDoom3All256 Release 1 of 04-26-2024.zip&#039;]&lt;br /&gt;
&lt;br /&gt;
This version, having been rebuilt, does not require legacy msvcp71.dll &amp;amp; msvcr71.dll files needed to run ExportFontToDoom3 v 1.02.&lt;br /&gt;
&lt;br /&gt;
The C++ project file with source code:&lt;br /&gt;
* [https://drive.google.com/file/d/1nkXJpBPa8qDqQxVQd9c1HlsSMKgohIw-/view?usp=sharing ExportFontToDoom3All256_source_project.zip] Release 1 of 04-26-2024. This zip is 177 MB; includes source &amp;amp; build project of archived library. Also sample TTF font (distributed with TDM) for debug testing.&lt;br /&gt;
&lt;br /&gt;
For more about the modification and rebuild process, see &amp;quot;ReadMe_about_All256.txt&amp;quot;, included in either of these two .zip downloads.&lt;br /&gt;
&lt;br /&gt;
== Downloads of ExportFontToDoom3 v 1.02 ==&lt;br /&gt;
Windows binary:&lt;br /&gt;
* [https://grantheant.com/products/exportfonttodoom3 Grant Davie&#039;s project page]&lt;br /&gt;
&lt;br /&gt;
Required DLLs:&lt;br /&gt;
To use ExportFontToDoom3 v 1.02 binary, you must have msvcp71.dll &amp;amp; msvcr71.dll installed in Windows or (more practical and safe now) in the same folder as the .exe. Once common, these files are no longer available from Microsoft (and purged from GitHub projects too). If you have an old machine with pre-Win10 OS, you can probably copy them from there. Otherwise, TDM&#039;s ATI Compressonator zip has them, at [[DDS Creation with ATI Compressonator]]; or various sketchy dll sites.&lt;br /&gt;
&lt;br /&gt;
The C++ project file with source code:&lt;br /&gt;
* [https://grantheant.com/products/exportfonttodoom3 Grant Davie&#039;s project page]&lt;br /&gt;
* [https://www.moddb.com/downloads/export-font-to-doom-3-v102 Moddb downloads page]&lt;br /&gt;
* also from wayback machine.&lt;br /&gt;
The project makes use of the circa-2005 FreeType font library (www.freetype.org) and DevIL image library.&lt;br /&gt;
&lt;br /&gt;
== See Also: [[ExportUnicodeFontToDoom3]] ==&lt;br /&gt;
This project, the successor to ExportFontToDoom3All256, can export Cyrillic and other Unicode characters, and adds further useful options.&lt;br /&gt;
&lt;br /&gt;
{{tutorial}} [[Category:Fonts]]&lt;/div&gt;</summary>
		<author><name>Geep</name></author>
	</entry>
	<entry>
		<id>https://wiki.thedarkmod.com/index.php?title=ExportFontToDoom3&amp;diff=34071</id>
		<title>ExportFontToDoom3</title>
		<link rel="alternate" type="text/html" href="https://wiki.thedarkmod.com/index.php?title=ExportFontToDoom3&amp;diff=34071"/>
		<updated>2025-09-10T19:42:27Z</updated>

		<summary type="html">&lt;p&gt;Geep: /* Intro to ExportFontToDoom3 &amp;amp; ExportFontToDoom3All256 */ Add link to ExportUnicdoeFontToDoom3&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Intro to ExportFontToDoom3 &amp;amp; ExportFontToDoom3All256 ==&lt;br /&gt;
The Windows command-line utility &amp;quot;ExportFontToDoom3&amp;quot; was created by Australian modder Grant Davies in 2005 to get TrueType Fonts, standard on Windows, into the metadata+bitmaps form needed by the Doom 3 engine. His final version, 1.02, was released as open-source and substantially used for TDM. It relies on the open-source DevIL and Freetype2 libraries.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;ExportFontToDoom3&#039;&#039;&#039; exports only the bitmap glyphs assigned to codepoints in the range 0-127, routinely the ASCII characters. The output actually generates metadata for 256 characters, but, due to a bug, upper-half characters are just mapped to the &amp;quot;undefined character&amp;quot; glyph.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;ExportFontToDoom3All256&#039;&#039;&#039; fixes that bug; it exports the glyphs assigned to codepoints in the range 0-255, routinely ANSI characters. It is also easier to run on modern Windows PCs, so recommended. It takes the same command-line arguments as ExportFontToDoom3. Credits to Crispy (for 2009 fix) and (in 2024 form) Geep.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;See Also: successor project [[ExportUnicodeFontToDoom3]]&#039;&#039;&#039;, that can export Cyrillic and other Unicode characters, and adds further useful options.&lt;br /&gt;
&lt;br /&gt;
== Using the Tool ==&lt;br /&gt;
&#039;&#039;The information here is adapted from the description doc included with the ExportFontToDoom3 download.&#039;&#039;&lt;br /&gt;
=== Basic Command ===&lt;br /&gt;
To export with the common settings of 12, 24, and 48 point fonts, simply type:&lt;br /&gt;
 ExportFontToDoom3All256 &#039;&#039;font_filename&#039;&#039;&lt;br /&gt;
For example (and assuming here a font &amp;quot;badtimes&amp;quot; with no legal issues):&lt;br /&gt;
 ExportFontToDoom3All256 badtimes.ttf&lt;br /&gt;
Most standard font formats (from the 2009 timeframe) can be used for export, but TrueType is most common.&lt;br /&gt;
=== Size Option ===&lt;br /&gt;
To export the font in a certain size, use the option:&lt;br /&gt;
 -size &#039;&#039;font_pointsize&#039;&#039;&lt;br /&gt;
For Doom3/TDM, only the sizes 12, 24, and 48 directly produce valid end-products. More than one &amp;quot;-size&amp;quot; arguments may be specified, for example:&lt;br /&gt;
 ExportFontToDoom3All256 badtimes.ttf -size 12 -size 24&lt;br /&gt;
As indicated above, if no &amp;quot;-size&amp;quot; argument is specified, 12, 24, and 48 point fonts are exported.&lt;br /&gt;
&lt;br /&gt;
The set of sizes in a particular generation run will jointly determine the &amp;quot;glyphScale&amp;quot; value specified at the end of bottom of a DAT/REF file, as follows:&lt;br /&gt;
&lt;br /&gt;
 glyphScale[for size n] = largest-size-in-set / size-n&lt;br /&gt;
&lt;br /&gt;
So, depending on how you generate, you may have to hand-adjust the glyphScale later.&lt;br /&gt;
&lt;br /&gt;
It is possible to specify one or more non-standard sizes for special processing, e.g., to do TTF-to-DAT overall scaling. To use in TDM, this will need subsequent file renaming to one of the 3 valid sizes, and glyphScale correction.&lt;br /&gt;
&lt;br /&gt;
=== Name Option ===&lt;br /&gt;
To (re)name the font to be exported, use the option:&lt;br /&gt;
 -name &#039;&#039;fontname&#039;&#039;&lt;br /&gt;
By default, the fontname is instead extracted from the font file. In either case, the fontname string will be truncated if too long. It then begins each of the TGA filename(s), which are referenced in turn in the per-character &amp;quot;shaderName&amp;quot; fields of the DAT file. The shaderName field in a DAT file can have at most 32 characters; when viewed as a REF or FNT file, it has this template:&lt;br /&gt;
 shaderName    fontname_&amp;lt;1- or 2-digit count&amp;gt;_&amp;lt;2-digit fontsize&amp;gt;.tga&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;TIP: If the default fontname is more than 16 characters, it is recommended you use the -name option, to prevent ugly truncation or (corrected in ExportUnicodeFontToDoom3) aborts.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
=== Other Options ===&lt;br /&gt;
In the description doc, there is a great deal of technical discussion about these next options, but of little likely relevance to TDM nowadays. Just ignore them in favor of their default values.&lt;br /&gt;
 -textureFormat &#039;&#039;format&#039;&#039;&lt;br /&gt;
where the default is .tga, which is what you want. Use another tool to convert the output from .tga to .dds, since ExportFontToDoom3 won&#039;t do it correctly.&lt;br /&gt;
 -xOffsetFix &#039;&#039;type&#039;&#039;&lt;br /&gt;
where the default is &amp;quot;none&amp;quot;, which causes the font&#039;s X offset value to be exported to the &amp;quot;pitch&amp;quot; member of TDM .dat file. There is also the related:&lt;br /&gt;
 -noXOffsetWarnings&lt;br /&gt;
&lt;br /&gt;
=== Output ===&lt;br /&gt;
A new folder will be created and all output files will be stored there. The folder will be named according to the font being exported.&lt;br /&gt;
The output will consist of Targa image (.tga) files and .dat files.&lt;br /&gt;
&lt;br /&gt;
Afterwards, from each TGA, you should create a corresponding DDS file.&lt;br /&gt;
&lt;br /&gt;
== Deployment &amp;amp; Further Adaptions ==&lt;br /&gt;
After export, assuming you have an FM set up to test them, rename the files into standard form and move or copy them to the expected locations...&lt;br /&gt;
* For DAT files: fonts/english/&amp;lt;your font name&amp;gt;/&lt;br /&gt;
* For DDS files: dds/english/&amp;lt;your font name&amp;gt;/&lt;br /&gt;
You&#039;ll undoubtedly have to make further iterative adjustments to both the DAT files (using other methods listed in [[Font Conversion &amp;amp; Repair]]) and bitmap files.&lt;br /&gt;
For instance, the &amp;quot;glyphScale&amp;quot; value will likely have to be changed.&lt;br /&gt;
&lt;br /&gt;
== Tutorials that Include ExportFontToDoom3 ==&lt;br /&gt;
Doom3-era tutorials, once posted on www.doom3world, can still be found with the &amp;quot;wayback machine&amp;quot; links given here:&lt;br /&gt;
* [https://web.archive.org/web/20081028224423/http://www.doom3world.org/phpbb2/viewtopic.php?t=11923 Tutorial 10 - Using custom fonts]&lt;br /&gt;
* [https://web.archive.org/web/20100522173219/http://www.doom3world.org/phpbb2/viewtopic.php?t=11924 Tutorial 11 - Editing fonts]&lt;br /&gt;
&lt;br /&gt;
== Downloads of ExportFontToDoom3All256 ==&lt;br /&gt;
Windows binary and required archived versions of FreeType and DevIL DLLs:&lt;br /&gt;
* [https://drive.google.com/file/d/1HzyyuZv0AVEhw4czJEwQ4nDMuqCogRyi/view?usp=sharing &#039;ExportFontToDoom3All256 Release 1 of 04-26-2024.zip&#039;]&lt;br /&gt;
&lt;br /&gt;
This version, having been rebuilt, does not require legacy msvcp71.dll &amp;amp; msvcr71.dll files needed to run ExportFontToDoom3 v 1.02.&lt;br /&gt;
&lt;br /&gt;
The C++ project file with source code:&lt;br /&gt;
* [https://drive.google.com/file/d/1nkXJpBPa8qDqQxVQd9c1HlsSMKgohIw-/view?usp=sharing ExportFontToDoom3All256_source_project.zip] Release 1 of 04-26-2024. This zip is 177 MB; includes source &amp;amp; build project of archived library. Also sample TTF font (distributed with TDM) for debug testing.&lt;br /&gt;
&lt;br /&gt;
For more about the modification and rebuild process, see &amp;quot;ReadMe_about_All256.txt&amp;quot;, included in either of these two .zip downloads.&lt;br /&gt;
&lt;br /&gt;
== Downloads of ExportFontToDoom3 v 1.02 ==&lt;br /&gt;
Windows binary:&lt;br /&gt;
* [https://grantheant.com/products/exportfonttodoom3 Grant Davie&#039;s project page]&lt;br /&gt;
&lt;br /&gt;
Required DLLs:&lt;br /&gt;
To use ExportFontToDoom3 v 1.02 binary, you must have msvcp71.dll &amp;amp; msvcr71.dll installed in Windows or (more practical and safe now) in the same folder as the .exe. Once common, these files are no longer available from Microsoft (and purged from GitHub projects too). If you have an old machine with pre-Win10 OS, you can probably copy them from there. Otherwise, TDM&#039;s ATI Compressonator zip has them, at [[DDS Creation with ATI Compressonator]]; or various sketchy dll sites.&lt;br /&gt;
&lt;br /&gt;
The C++ project file with source code:&lt;br /&gt;
* [https://grantheant.com/products/exportfonttodoom3 Grant Davie&#039;s project page]&lt;br /&gt;
* [https://www.moddb.com/downloads/export-font-to-doom-3-v102 Moddb downloads page]&lt;br /&gt;
* also from wayback machine.&lt;br /&gt;
The project makes use of the circa-2005 FreeType font library (www.freetype.org) and DevIL image library.&lt;br /&gt;
&lt;br /&gt;
{{tutorial}} [[Category:Fonts]]&lt;/div&gt;</summary>
		<author><name>Geep</name></author>
	</entry>
	<entry>
		<id>https://wiki.thedarkmod.com/index.php?title=ExportFontToDoom3&amp;diff=34070</id>
		<title>ExportFontToDoom3</title>
		<link rel="alternate" type="text/html" href="https://wiki.thedarkmod.com/index.php?title=ExportFontToDoom3&amp;diff=34070"/>
		<updated>2025-09-10T19:34:41Z</updated>

		<summary type="html">&lt;p&gt;Geep: /* Name Option */ Mention truncation, show template, add tip&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Intro to ExportFontToDoom3 &amp;amp; ExportFontToDoom3All256 ==&lt;br /&gt;
The Windows command-line utility &amp;quot;ExportFontToDoom3&amp;quot; was created by Australian modder Grant Davies in 2005 to get TrueType Fonts, standard on Windows, into the metadata+bitmaps form needed by the Doom 3 engine. His final version, 1.02, was released as open-source and substantially used for TDM. It relies on the open-source DevIL and Freetype2 libraries.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;ExportFontToDoom3&#039;&#039;&#039; exports only the bitmap glyphs assigned to codepoints in the range 0-127, routinely the ASCII characters. The output actually generates metadata for 256 characters, but, due to a bug, upper-half characters are just mapped to the &amp;quot;undefined character&amp;quot; glyph.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;ExportFontToDoom3All256&#039;&#039;&#039; fixes that bug; it exports the glyphs assigned to codepoints in the range 0-255, routinely ANSI characters. It is also easier to run on modern Windows PCs, so recommended. It takes the same command-line arguments as ExportFontToDoom3. Credits to Crispy (for 2009 fix) and (in 2024 form) Geep.&lt;br /&gt;
&lt;br /&gt;
== Using the Tool ==&lt;br /&gt;
&#039;&#039;The information here is adapted from the description doc included with the ExportFontToDoom3 download.&#039;&#039;&lt;br /&gt;
=== Basic Command ===&lt;br /&gt;
To export with the common settings of 12, 24, and 48 point fonts, simply type:&lt;br /&gt;
 ExportFontToDoom3All256 &#039;&#039;font_filename&#039;&#039;&lt;br /&gt;
For example (and assuming here a font &amp;quot;badtimes&amp;quot; with no legal issues):&lt;br /&gt;
 ExportFontToDoom3All256 badtimes.ttf&lt;br /&gt;
Most standard font formats (from the 2009 timeframe) can be used for export, but TrueType is most common.&lt;br /&gt;
=== Size Option ===&lt;br /&gt;
To export the font in a certain size, use the option:&lt;br /&gt;
 -size &#039;&#039;font_pointsize&#039;&#039;&lt;br /&gt;
For Doom3/TDM, only the sizes 12, 24, and 48 directly produce valid end-products. More than one &amp;quot;-size&amp;quot; arguments may be specified, for example:&lt;br /&gt;
 ExportFontToDoom3All256 badtimes.ttf -size 12 -size 24&lt;br /&gt;
As indicated above, if no &amp;quot;-size&amp;quot; argument is specified, 12, 24, and 48 point fonts are exported.&lt;br /&gt;
&lt;br /&gt;
The set of sizes in a particular generation run will jointly determine the &amp;quot;glyphScale&amp;quot; value specified at the end of bottom of a DAT/REF file, as follows:&lt;br /&gt;
&lt;br /&gt;
 glyphScale[for size n] = largest-size-in-set / size-n&lt;br /&gt;
&lt;br /&gt;
So, depending on how you generate, you may have to hand-adjust the glyphScale later.&lt;br /&gt;
&lt;br /&gt;
It is possible to specify one or more non-standard sizes for special processing, e.g., to do TTF-to-DAT overall scaling. To use in TDM, this will need subsequent file renaming to one of the 3 valid sizes, and glyphScale correction.&lt;br /&gt;
&lt;br /&gt;
=== Name Option ===&lt;br /&gt;
To (re)name the font to be exported, use the option:&lt;br /&gt;
 -name &#039;&#039;fontname&#039;&#039;&lt;br /&gt;
By default, the fontname is instead extracted from the font file. In either case, the fontname string will be truncated if too long. It then begins each of the TGA filename(s), which are referenced in turn in the per-character &amp;quot;shaderName&amp;quot; fields of the DAT file. The shaderName field in a DAT file can have at most 32 characters; when viewed as a REF or FNT file, it has this template:&lt;br /&gt;
 shaderName    fontname_&amp;lt;1- or 2-digit count&amp;gt;_&amp;lt;2-digit fontsize&amp;gt;.tga&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;TIP: If the default fontname is more than 16 characters, it is recommended you use the -name option, to prevent ugly truncation or (corrected in ExportUnicodeFontToDoom3) aborts.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
=== Other Options ===&lt;br /&gt;
In the description doc, there is a great deal of technical discussion about these next options, but of little likely relevance to TDM nowadays. Just ignore them in favor of their default values.&lt;br /&gt;
 -textureFormat &#039;&#039;format&#039;&#039;&lt;br /&gt;
where the default is .tga, which is what you want. Use another tool to convert the output from .tga to .dds, since ExportFontToDoom3 won&#039;t do it correctly.&lt;br /&gt;
 -xOffsetFix &#039;&#039;type&#039;&#039;&lt;br /&gt;
where the default is &amp;quot;none&amp;quot;, which causes the font&#039;s X offset value to be exported to the &amp;quot;pitch&amp;quot; member of TDM .dat file. There is also the related:&lt;br /&gt;
 -noXOffsetWarnings&lt;br /&gt;
&lt;br /&gt;
=== Output ===&lt;br /&gt;
A new folder will be created and all output files will be stored there. The folder will be named according to the font being exported.&lt;br /&gt;
The output will consist of Targa image (.tga) files and .dat files.&lt;br /&gt;
&lt;br /&gt;
Afterwards, from each TGA, you should create a corresponding DDS file.&lt;br /&gt;
&lt;br /&gt;
== Deployment &amp;amp; Further Adaptions ==&lt;br /&gt;
After export, assuming you have an FM set up to test them, rename the files into standard form and move or copy them to the expected locations...&lt;br /&gt;
* For DAT files: fonts/english/&amp;lt;your font name&amp;gt;/&lt;br /&gt;
* For DDS files: dds/english/&amp;lt;your font name&amp;gt;/&lt;br /&gt;
You&#039;ll undoubtedly have to make further iterative adjustments to both the DAT files (using other methods listed in [[Font Conversion &amp;amp; Repair]]) and bitmap files.&lt;br /&gt;
For instance, the &amp;quot;glyphScale&amp;quot; value will likely have to be changed.&lt;br /&gt;
&lt;br /&gt;
== Tutorials that Include ExportFontToDoom3 ==&lt;br /&gt;
Doom3-era tutorials, once posted on www.doom3world, can still be found with the &amp;quot;wayback machine&amp;quot; links given here:&lt;br /&gt;
* [https://web.archive.org/web/20081028224423/http://www.doom3world.org/phpbb2/viewtopic.php?t=11923 Tutorial 10 - Using custom fonts]&lt;br /&gt;
* [https://web.archive.org/web/20100522173219/http://www.doom3world.org/phpbb2/viewtopic.php?t=11924 Tutorial 11 - Editing fonts]&lt;br /&gt;
&lt;br /&gt;
== Downloads of ExportFontToDoom3All256 ==&lt;br /&gt;
Windows binary and required archived versions of FreeType and DevIL DLLs:&lt;br /&gt;
* [https://drive.google.com/file/d/1HzyyuZv0AVEhw4czJEwQ4nDMuqCogRyi/view?usp=sharing &#039;ExportFontToDoom3All256 Release 1 of 04-26-2024.zip&#039;]&lt;br /&gt;
&lt;br /&gt;
This version, having been rebuilt, does not require legacy msvcp71.dll &amp;amp; msvcr71.dll files needed to run ExportFontToDoom3 v 1.02.&lt;br /&gt;
&lt;br /&gt;
The C++ project file with source code:&lt;br /&gt;
* [https://drive.google.com/file/d/1nkXJpBPa8qDqQxVQd9c1HlsSMKgohIw-/view?usp=sharing ExportFontToDoom3All256_source_project.zip] Release 1 of 04-26-2024. This zip is 177 MB; includes source &amp;amp; build project of archived library. Also sample TTF font (distributed with TDM) for debug testing.&lt;br /&gt;
&lt;br /&gt;
For more about the modification and rebuild process, see &amp;quot;ReadMe_about_All256.txt&amp;quot;, included in either of these two .zip downloads.&lt;br /&gt;
&lt;br /&gt;
== Downloads of ExportFontToDoom3 v 1.02 ==&lt;br /&gt;
Windows binary:&lt;br /&gt;
* [https://grantheant.com/products/exportfonttodoom3 Grant Davie&#039;s project page]&lt;br /&gt;
&lt;br /&gt;
Required DLLs:&lt;br /&gt;
To use ExportFontToDoom3 v 1.02 binary, you must have msvcp71.dll &amp;amp; msvcr71.dll installed in Windows or (more practical and safe now) in the same folder as the .exe. Once common, these files are no longer available from Microsoft (and purged from GitHub projects too). If you have an old machine with pre-Win10 OS, you can probably copy them from there. Otherwise, TDM&#039;s ATI Compressonator zip has them, at [[DDS Creation with ATI Compressonator]]; or various sketchy dll sites.&lt;br /&gt;
&lt;br /&gt;
The C++ project file with source code:&lt;br /&gt;
* [https://grantheant.com/products/exportfonttodoom3 Grant Davie&#039;s project page]&lt;br /&gt;
* [https://www.moddb.com/downloads/export-font-to-doom-3-v102 Moddb downloads page]&lt;br /&gt;
* also from wayback machine.&lt;br /&gt;
The project makes use of the circa-2005 FreeType font library (www.freetype.org) and DevIL image library.&lt;br /&gt;
&lt;br /&gt;
{{tutorial}} [[Category:Fonts]]&lt;/div&gt;</summary>
		<author><name>Geep</name></author>
	</entry>
	<entry>
		<id>https://wiki.thedarkmod.com/index.php?title=ExportFontToDoom3&amp;diff=34057</id>
		<title>ExportFontToDoom3</title>
		<link rel="alternate" type="text/html" href="https://wiki.thedarkmod.com/index.php?title=ExportFontToDoom3&amp;diff=34057"/>
		<updated>2025-08-27T14:59:28Z</updated>

		<summary type="html">&lt;p&gt;Geep: /* Size Option */ Mention glyphScale, non-standard sizes&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Intro to ExportFontToDoom3 &amp;amp; ExportFontToDoom3All256 ==&lt;br /&gt;
The Windows command-line utility &amp;quot;ExportFontToDoom3&amp;quot; was created by Australian modder Grant Davies in 2005 to get TrueType Fonts, standard on Windows, into the metadata+bitmaps form needed by the Doom 3 engine. His final version, 1.02, was released as open-source and substantially used for TDM. It relies on the open-source DevIL and Freetype2 libraries.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;ExportFontToDoom3&#039;&#039;&#039; exports only the bitmap glyphs assigned to codepoints in the range 0-127, routinely the ASCII characters. The output actually generates metadata for 256 characters, but, due to a bug, upper-half characters are just mapped to the &amp;quot;undefined character&amp;quot; glyph.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;ExportFontToDoom3All256&#039;&#039;&#039; fixes that bug; it exports the glyphs assigned to codepoints in the range 0-255, routinely ANSI characters. It is also easier to run on modern Windows PCs, so recommended. It takes the same command-line arguments as ExportFontToDoom3. Credits to Crispy (for 2009 fix) and (in 2024 form) Geep.&lt;br /&gt;
&lt;br /&gt;
== Using the Tool ==&lt;br /&gt;
&#039;&#039;The information here is adapted from the description doc included with the ExportFontToDoom3 download.&#039;&#039;&lt;br /&gt;
=== Basic Command ===&lt;br /&gt;
To export with the common settings of 12, 24, and 48 point fonts, simply type:&lt;br /&gt;
 ExportFontToDoom3All256 &#039;&#039;font_filename&#039;&#039;&lt;br /&gt;
For example (and assuming here a font &amp;quot;badtimes&amp;quot; with no legal issues):&lt;br /&gt;
 ExportFontToDoom3All256 badtimes.ttf&lt;br /&gt;
Most standard font formats (from the 2009 timeframe) can be used for export, but TrueType is most common.&lt;br /&gt;
=== Size Option ===&lt;br /&gt;
To export the font in a certain size, use the option:&lt;br /&gt;
 -size &#039;&#039;font_pointsize&#039;&#039;&lt;br /&gt;
For Doom3/TDM, only the sizes 12, 24, and 48 directly produce valid end-products. More than one &amp;quot;-size&amp;quot; arguments may be specified, for example:&lt;br /&gt;
 ExportFontToDoom3All256 badtimes.ttf -size 12 -size 24&lt;br /&gt;
As indicated above, if no &amp;quot;-size&amp;quot; argument is specified, 12, 24, and 48 point fonts are exported.&lt;br /&gt;
&lt;br /&gt;
The set of sizes in a particular generation run will jointly determine the &amp;quot;glyphScale&amp;quot; value specified at the end of bottom of a DAT/REF file, as follows:&lt;br /&gt;
&lt;br /&gt;
 glyphScale[for size n] = largest-size-in-set / size-n&lt;br /&gt;
&lt;br /&gt;
So, depending on how you generate, you may have to hand-adjust the glyphScale later.&lt;br /&gt;
&lt;br /&gt;
It is possible to specify one or more non-standard sizes for special processing, e.g., to do TTF-to-DAT overall scaling. To use in TDM, this will need subsequent file renaming to one of the 3 valid sizes, and glyphScale correction.&lt;br /&gt;
&lt;br /&gt;
=== Name Option ===&lt;br /&gt;
To name the font to be exported, use the option:&lt;br /&gt;
 -name &#039;&#039;fontname&#039;&#039;&lt;br /&gt;
By default, the fontname is instead extracted from the font file. In either case, this fontname string will begin each of the TGA filename(s), which are referenced in turn in the per-character &amp;quot;shaderName&amp;quot; fields of the DAT file.&lt;br /&gt;
=== Other Options ===&lt;br /&gt;
In the description doc, there is a great deal of technical discussion about these next options, but of little likely relevance to TDM nowadays. Just ignore them in favor of their default values.&lt;br /&gt;
 -textureFormat &#039;&#039;format&#039;&#039;&lt;br /&gt;
where the default is .tga, which is what you want. Use another tool to convert the output from .tga to .dds, since ExportFontToDoom3 won&#039;t do it correctly.&lt;br /&gt;
 -xOffsetFix &#039;&#039;type&#039;&#039;&lt;br /&gt;
where the default is &amp;quot;none&amp;quot;, which causes the font&#039;s X offset value to be exported to the &amp;quot;pitch&amp;quot; member of TDM .dat file. There is also the related:&lt;br /&gt;
 -noXOffsetWarnings&lt;br /&gt;
&lt;br /&gt;
=== Output ===&lt;br /&gt;
A new folder will be created and all output files will be stored there. The folder will be named according to the font being exported.&lt;br /&gt;
The output will consist of Targa image (.tga) files and .dat files.&lt;br /&gt;
&lt;br /&gt;
Afterwards, from each TGA, you should create a corresponding DDS file.&lt;br /&gt;
&lt;br /&gt;
== Deployment &amp;amp; Further Adaptions ==&lt;br /&gt;
After export, assuming you have an FM set up to test them, rename the files into standard form and move or copy them to the expected locations...&lt;br /&gt;
* For DAT files: fonts/english/&amp;lt;your font name&amp;gt;/&lt;br /&gt;
* For DDS files: dds/english/&amp;lt;your font name&amp;gt;/&lt;br /&gt;
You&#039;ll undoubtedly have to make further iterative adjustments to both the DAT files (using other methods listed in [[Font Conversion &amp;amp; Repair]]) and bitmap files.&lt;br /&gt;
For instance, the &amp;quot;glyphScale&amp;quot; value will likely have to be changed.&lt;br /&gt;
&lt;br /&gt;
== Tutorials that Include ExportFontToDoom3 ==&lt;br /&gt;
Doom3-era tutorials, once posted on www.doom3world, can still be found with the &amp;quot;wayback machine&amp;quot; links given here:&lt;br /&gt;
* [https://web.archive.org/web/20081028224423/http://www.doom3world.org/phpbb2/viewtopic.php?t=11923 Tutorial 10 - Using custom fonts]&lt;br /&gt;
* [https://web.archive.org/web/20100522173219/http://www.doom3world.org/phpbb2/viewtopic.php?t=11924 Tutorial 11 - Editing fonts]&lt;br /&gt;
&lt;br /&gt;
== Downloads of ExportFontToDoom3All256 ==&lt;br /&gt;
Windows binary and required archived versions of FreeType and DevIL DLLs:&lt;br /&gt;
* [https://drive.google.com/file/d/1HzyyuZv0AVEhw4czJEwQ4nDMuqCogRyi/view?usp=sharing &#039;ExportFontToDoom3All256 Release 1 of 04-26-2024.zip&#039;]&lt;br /&gt;
&lt;br /&gt;
This version, having been rebuilt, does not require legacy msvcp71.dll &amp;amp; msvcr71.dll files needed to run ExportFontToDoom3 v 1.02.&lt;br /&gt;
&lt;br /&gt;
The C++ project file with source code:&lt;br /&gt;
* [https://drive.google.com/file/d/1nkXJpBPa8qDqQxVQd9c1HlsSMKgohIw-/view?usp=sharing ExportFontToDoom3All256_source_project.zip] Release 1 of 04-26-2024. This zip is 177 MB; includes source &amp;amp; build project of archived library. Also sample TTF font (distributed with TDM) for debug testing.&lt;br /&gt;
&lt;br /&gt;
For more about the modification and rebuild process, see &amp;quot;ReadMe_about_All256.txt&amp;quot;, included in either of these two .zip downloads.&lt;br /&gt;
&lt;br /&gt;
== Downloads of ExportFontToDoom3 v 1.02 ==&lt;br /&gt;
Windows binary:&lt;br /&gt;
* [https://grantheant.com/products/exportfonttodoom3 Grant Davie&#039;s project page]&lt;br /&gt;
&lt;br /&gt;
Required DLLs:&lt;br /&gt;
To use ExportFontToDoom3 v 1.02 binary, you must have msvcp71.dll &amp;amp; msvcr71.dll installed in Windows or (more practical and safe now) in the same folder as the .exe. Once common, these files are no longer available from Microsoft (and purged from GitHub projects too). If you have an old machine with pre-Win10 OS, you can probably copy them from there. Otherwise, TDM&#039;s ATI Compressonator zip has them, at [[DDS Creation with ATI Compressonator]]; or various sketchy dll sites.&lt;br /&gt;
&lt;br /&gt;
The C++ project file with source code:&lt;br /&gt;
* [https://grantheant.com/products/exportfonttodoom3 Grant Davie&#039;s project page]&lt;br /&gt;
* [https://www.moddb.com/downloads/export-font-to-doom-3-v102 Moddb downloads page]&lt;br /&gt;
* also from wayback machine.&lt;br /&gt;
The project makes use of the circa-2005 FreeType font library (www.freetype.org) and DevIL image library.&lt;br /&gt;
&lt;br /&gt;
{{tutorial}} [[Category:Fonts]]&lt;/div&gt;</summary>
		<author><name>Geep</name></author>
	</entry>
	<entry>
		<id>https://wiki.thedarkmod.com/index.php?title=DatBounds&amp;diff=34054</id>
		<title>DatBounds</title>
		<link rel="alternate" type="text/html" href="https://wiki.thedarkmod.com/index.php?title=DatBounds&amp;diff=34054"/>
		<updated>2025-08-25T15:35:17Z</updated>

		<summary type="html">&lt;p&gt;Geep: /* Downloads */ released version 1.7&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;By Geep, 2024&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
== Introduction ==&lt;br /&gt;
&lt;br /&gt;
DatBounds is a Windows command-line utility to help visualize TDM/Doom3 bitmap font bounding boxes and related metrics. It generates a special set of .tga image files, which are then brought into a tool like GIMP to view. But only view; any needed metric changes must be applied separately (e.g., by editing a .ref file). Nevertheless, this viewing helps (when used in conjunction with other tools like refont&#039;s &amp;quot;stats&amp;quot;) to understand, improve, and extend complex and often overlapping metadata relationships.  &lt;br /&gt;
&lt;br /&gt;
The command-line format is:&lt;br /&gt;
&lt;br /&gt;
 datBounds -in &amp;lt;path to input metrics file&amp;gt; [options]&lt;br /&gt;
&lt;br /&gt;
with options:&lt;br /&gt;
&lt;br /&gt;
 -tag = each drawn bounds box has a 2-hex-digit codepoint label.&lt;br /&gt;
 -hug = show, in tan, horizontal baseline &amp;amp; pitch (as vertical line) that &#039;hug&#039; each glyph.&lt;br /&gt;
 -xskip = show xSkip as red dot on rightside of baseline.&lt;br /&gt;
 -long_baseline_left = draw horizontal baseline from left boundary, instead of from pitch line to right. &#039;&#039;[new v1.3]&#039;&#039;&lt;br /&gt;
 -long_baseline_right = draw horizontal baseline to xSkip red dot, instead of to right boundary. &#039;&#039;[new v1.3]&#039;&#039;&lt;br /&gt;
 -long_pitchline_down = extend vertical pitchline downward to baseline (e.g., below lower boundary). &#039;&#039;[new 1.3]&#039;&#039;&lt;br /&gt;
 -boundless = suppress multicolor outer bounds; e.g., to help make tag-only .tga&amp;quot; &#039;&#039;[new v1.3]&#039;&#039;&lt;br /&gt;
 -from &amp;lt;codepoint num&amp;gt; (default   0)&lt;br /&gt;
 -to   &amp;lt;codepoint num&amp;gt; (default 255)&lt;br /&gt;
     shows codepoints between &#039;from&#039; and &#039;to&#039;, inclusive,&lt;br /&gt;
     where &amp;lt;codepoint num&amp;gt; is 0xHH or decimal from 0 to 255.&lt;br /&gt;
 -alpha = render background transparent instead of white.&lt;br /&gt;
 -scaling_ok = suppress console warnings if per-character scaling.&lt;br /&gt;
 -raw_metrics = show bounds box as imageHeight/Width size, &amp;amp; matching unscaled baseline, pitchline, xSkip.&lt;br /&gt;
&lt;br /&gt;
Running &amp;quot;datbounds&amp;quot; with no arguments, or with &amp;quot;-h&amp;quot; or &amp;quot;?&amp;quot;, will show this summary.&lt;br /&gt;
&lt;br /&gt;
Otherwise, the program will generate one special .tga file for every regular glyph-containing .tga/.dds file. To keep datbounds relatively simple:&lt;br /&gt;
* the .tga format is used for output, instead of, say, .jpg or .png, that need more code or libraries;&lt;br /&gt;
* the names of the output files are not specified, but just derived from shader names contained in the -in file. For example, &amp;quot;stone_0_24&amp;quot; --&amp;gt; &amp;quot;stone_0_24_bounds.tga&amp;quot;;&lt;br /&gt;
* These special files do not contain images of the font glyphs themselves.&lt;br /&gt;
&lt;br /&gt;
So either view each one side by side with the corresponding glyph-containing file [Figure 1 below], or import copies of those paired files into GIMP as separate layers for combined viewing, as discussed further below.&lt;br /&gt;
&lt;br /&gt;
== File I/O ==&lt;br /&gt;
&lt;br /&gt;
The input file, with metadata for a particular font and fontsize, should be one of these formats:&lt;br /&gt;
* TDM/Doom3&#039;s &#039;.dat&#039;&lt;br /&gt;
* refont&#039;s &#039;.ref&#039;&lt;br /&gt;
* q3font&#039;s &#039;.fnt&#039;&lt;br /&gt;
&lt;br /&gt;
Note that DatBounds does not read bitmap files, nor does it make use of refont’s annotation file.&lt;br /&gt;
&lt;br /&gt;
DatBounds outputs multiple .tga files, into the same directory as the input file. The generated filenames are that of the set of shaderNames given in the input file, but with suffix &amp;quot;_bounds.tga&amp;quot;. Within each will be a 256 x 256 image.&lt;br /&gt;
&lt;br /&gt;
Except a few fonts (i.e., in the Mason and Carleton families) incorporate 512 x 512 bitmaps. Currently, for these you must use the REF format as input. A REF file (since refont v2.5) can indicate that any particular shaderName contained within is 512 x 512 by a header line:&lt;br /&gt;
 # bitmap_&amp;lt;n&amp;gt;_size=512&lt;br /&gt;
where &amp;lt;n&amp;gt; is 0 to 9, and refers to shaders present in the REF file with names like, e.g., carleton_3_48.tga; n would be 3 for this.&lt;br /&gt;
&lt;br /&gt;
== Example Output ==&lt;br /&gt;
&lt;br /&gt;
[[File:Screenshot GIMP stone 0 24 bounds (ASCII).jpg|frameless|512px]]&lt;br /&gt;
[[File:Screenshot GIMP stone 0 24.jpg|frameless|512px]]&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Figure 1.&#039;&#039;&#039; [Click either to enlarge further.] These show information about the english/stone font of 24 pt size, as distributed with TDM 2.12 in Feb, 2024. That size requires two bitmaps; we see just one of them here. Both images are screenshots of GIMP. The left image shows the datBounds output, framed in the gray scales of the GIMP view/edit panel. The right image shows the corresponding glyph bitmap, with the usual checkerboard indicating a transparent background.&lt;br /&gt;
&lt;br /&gt;
This datBounds Version 1.0 command was used to generate the left image, which has the default opaque white background:&lt;br /&gt;
&lt;br /&gt;
 datBounds -in fontImage_24.ref -tag -hug -xskip -to 127&lt;br /&gt;
&lt;br /&gt;
With Version 1.3, this would get the same results:&lt;br /&gt;
&lt;br /&gt;
 datBounds -in fontImage_24.ref -tag -hug -xskip -long_baseline_left -to 127&lt;br /&gt;
&lt;br /&gt;
For simplicity, this figure has only bounds for the ASCII codepoints (because of &amp;quot;-to 127&amp;quot;). For each of those, it shows:&lt;br /&gt;
* the overall bounds as a green/blue box&lt;br /&gt;
* the pitch (aka xOffset) as a vertical tan line, and the baseline as a horizontal tan line (because of &amp;quot;-hug&amp;quot;)&lt;br /&gt;
* the 2-digit-hex codepoint label, red on black (because of &amp;quot;-tag&amp;quot;)&lt;br /&gt;
* the horizontal xSkip distance from the pitch line, shown as a red dot near the right end of the baseline (due to &amp;quot;-xskip&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
Regarding the baselines in Figures 1 &amp;amp; 3: These were generated with datBounds Version 1.0, and are slightly shorter in subsequent versions. Version 1.3 introduces the long_baseline_left option, to once-again generate the Version 1.0 form. &amp;quot;See &amp;quot;Downloads&amp;quot; at end for more about this.&lt;br /&gt;
&lt;br /&gt;
== Generated Visualizations and Options ==&lt;br /&gt;
Within each ...bounds.tga will be an image. (The discussion here is in terms of a 256 x 256 image; you can generalize to 512 x 512 cases.) The image contains, for each codepoint&#039;s glyph outer bounds, a two-color box. The walls of the box are defined by integer values in the range 0-255, namely:&lt;br /&gt;
* s_coord, t_coord, (s2_coord - 1), (t2_coord - 1)  &#039;&#039;in .ref terms&#039;&#039;&lt;br /&gt;
* round(s*256), round(t*256), round((s2-1)*256), round ((t2-1)*256) &#039;&#039;in .dat or .fnt terms&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Since s2 &amp;amp; t2 are considered to just beyond the glyph’s actual pixels, 1 is subtracted here. So the glyph pixels (if they were seen) would partially lap the box edges (except for the left edge due to pitch offset.) A box is rendered in two colors to help disambiguate abutting glyphs. Green for top &amp;amp; left edges (sharing s &amp;amp; t), blue for right &amp;amp; bottom (s2 &amp;amp; t2).&lt;br /&gt;
&lt;br /&gt;
===Visualization Order===&lt;br /&gt;
The visualization algorithm uses a loop in codepoint order. Consequently, visual elements of higher codepoint numbers may obscure or hide those of lower numbers. This often occurs with shared or overlapping bounding boxes. While it can’t be avoided, if you wish you can manage it with the &amp;quot;from&amp;quot; and &amp;quot;to&amp;quot; options.&lt;br /&gt;
&lt;br /&gt;
===Tag Option===&lt;br /&gt;
This shows a &amp;quot;tag&amp;quot;, i.e., a label, having the codepoint value as a 2-digit hexadecimal number. It appears in the upper-left corner of the bounding box, with red digits on a black background. The tiny &amp;quot;dot matrix&amp;quot; font here is generated within the program. It is legible with practice when zoomed in within GIMP. (Tags will be generated the same size whether the bitmap is 256x256 or 512x512, so in the latter case, will appear relatively smaller compared to glyphs.)&lt;br /&gt;
&lt;br /&gt;
[[File:DatBoundsDigits.jpg|frameless]]&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Figure 2.&#039;&#039;&#039; Closeup of the digits of datBounds.&lt;br /&gt;
&lt;br /&gt;
===Hug Option===&lt;br /&gt;
This shows two lines in a tan color, that informally can be said to &amp;quot;hug&amp;quot; the glyph:&lt;br /&gt;
* The &amp;quot;baseline&amp;quot;, shown as a horizontal line, offset downward from the bounding box top edge by the &amp;quot;top&amp;quot; metric value. For a glyph without descender, this is often just below the bounding box bottom edge (because of latter’s t2-1 subtraction); the glyph is visualized as resting on the baseline.&lt;br /&gt;
* The &amp;quot;pitchline&amp;quot;, shown as a vertical line, offset rightward from the bounding box left edge by the &amp;quot;pitch&amp;quot; metric value. Most glyphs will not extend leftward beyond the pitch line.&lt;br /&gt;
&lt;br /&gt;
===XSkip Option===&lt;br /&gt;
Invoked with either &amp;quot;-xskip&amp;quot; or &amp;quot;-xSkip&amp;quot;, this shows a red dot on the rightside of the baseline, corresponding to a horizontal location of:&lt;br /&gt;
 s_coord + pitch + xSkip&lt;br /&gt;
&lt;br /&gt;
===Long_baseline_left Option===&lt;br /&gt;
Ordinarily, drawing of the horizontal baseline starts at the vertical pitch line. The &amp;quot;-long_baseline_left&amp;quot; option moves the start leftward, to begin at the left boundary given by coord_s. (Actually, from the leftmost of the pitchline and the left boundary.)&lt;br /&gt;
&lt;br /&gt;
===Long_baseline_right Option===&lt;br /&gt;
Ordinarily, the horizontal baseline ends at the right boundary given by coord_s2 - 1. The &amp;quot;-long_baseline_right&amp;quot; option extends it to abut the xSkip red dot instead. (Actually, to the rightmost of the right boundary and the red dot.)&lt;br /&gt;
&lt;br /&gt;
These &amp;quot;long baseline&amp;quot; options are most useful with odd fonts that use unusual pitch values, e.g., Medusa, that has the pitch line to the right of the character glyph instead of the left.&lt;br /&gt;
&lt;br /&gt;
===Long_pitchline_down Option===&lt;br /&gt;
Ordinarily, the vertical pitch line travels downward to the lower boundary given by coord_t2 - 1. The &amp;quot;-long_pitchline_down&amp;quot; option extends it downward to the baseline given by coord_t + top. (Actually, to the lower of the baseline and lower boundary.) This can be helpful particularly for certain punctuation characters, that with many fonts have tight bounding boxes with baselines far below.&lt;br /&gt;
&lt;br /&gt;
===Boundless Option===&lt;br /&gt;
The &amp;quot;-boundless&amp;quot; option suppresses drawing of the multicolor outer bounds. Its main use is paired with the &amp;quot;-tag&amp;quot; option, to generate tag-only .tga files for GIMP layers.&lt;br /&gt;
&lt;br /&gt;
===From &amp;amp; To: Codepoint Range Options===&lt;br /&gt;
These accept decimal or two-digit hex numbers (the latter preceded by &amp;quot;0x&amp;quot;). If both &amp;quot;-from&amp;quot; and &amp;quot;-to&amp;quot; are given, the value of &amp;quot;-to&amp;quot; should be greater than or equal to &amp;quot;-from&amp;quot;. These options can be helpful to reduce the complexity of visualization with densely overlapping bounding boxes.&lt;br /&gt;
&lt;br /&gt;
===Alpha Option – Make Background Transparent.===&lt;br /&gt;
By default, the background is opaque white. This provides good contrast if, in GIMP, you prefer to turn on grid lines, which are black. However, a transparent background option is provided in case you want to also see the glyphs and metrics superimposed, as discussed next.&lt;br /&gt;
&lt;br /&gt;
===Scaling_ok Option===&lt;br /&gt;
This option (also found in refont) suppresses console warnings when per-character scaling is present, e.g., for the Mason font.&lt;br /&gt;
&lt;br /&gt;
===Raw_metrics Option===&lt;br /&gt;
This option might be of occasional diagnostic interest for fonts with scaling, including large bitmaps (e.g., Carleton and Mason).&lt;br /&gt;
&lt;br /&gt;
Ordinarily, a bounding box is drawn at {coord_s, coord_t, coord_s2, coord_t2}. Conversely, &#039;&#039;&#039;not&#039;&#039;&#039; drawn is a box representing the render-target dimensions, given by metrics imageWidth and imageHeight. Most often, the sizes of these two boxes are the same. If not, horizontal and/or vertical scaling factors (i.e., other than 1.0) can be derived. In that case, the other drawn items (pitchline, baseline [from &amp;quot;top&amp;quot;], xSkip) are routinely placed using such scaling.&lt;br /&gt;
&lt;br /&gt;
If you specify this option, the bounding box is instead shown with imageWidth and imageHeight dimensions, arbitrarily with upper-left origin at {coord_s, coord_t). As before, the other drawn items (pitchline, baseline, and xSkip) are placed relative to the origin, but now at unscaled distances given directly by REF/DAT/FTN numeric values.&lt;br /&gt;
&lt;br /&gt;
== A Combined View of Both Metrics and Glyphs in GIMP ==&lt;br /&gt;
For some fonts and font sizes, there is an existing TDM-created GIMP .xcf project file, that contains each bitmap of a glyph set as a separate layer, and that serves as the source file for TDM’s version of the font. Make a working copy of that for what is described here (as shown in Figure 3).&lt;br /&gt;
&lt;br /&gt;
Or you can create your own version of this, e.g., importing both the _bounds file(s) and the corresponding glyph-containing bitmap file(s) into GIMP, as separate layers.&lt;br /&gt;
&lt;br /&gt;
In either case, GIMP’s &amp;quot;Open as Layers...&amp;quot; is what you use. Be sure the _bounds files were created with the –alpha option. Once files are imported, hide all the layers except those of a particular pair (i.e., matching bounds &amp;amp; glyphs) of interest. Which one you place in front of the other depends on whether it’s more important to see the glyphs unclipped or the tags (if present) un-obscured.&lt;br /&gt;
&lt;br /&gt;
More elaborately, you can import and stack multiple versions of a _bounds file, e.g., with different ranges, to toggle for differences.&lt;br /&gt;
&lt;br /&gt;
TIP: Viewing glyphs against the checkerboard &amp;quot;transparency&amp;quot; pattern can be tedious. Consider adding an all-black background layer. To do so in GIMP, set the foreground color to black, then, when creating a new layer, you can ask it to fill with the foreground color.&lt;br /&gt;
&lt;br /&gt;
You are creating a &amp;quot;snapshot in time&amp;quot;, great for planning and quality control. But of course any subsequent edits to the DAT metrics renders the _bounds file(s) within the .xcf somewhat obsolete.&lt;br /&gt;
&lt;br /&gt;
== Example Combined View ==&lt;br /&gt;
[[File:Screenshot GIMP layers stone 24.jpg|frameless|1000px]]&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Figure 3.&#039;&#039;&#039; In GIMP, this shows the native project file (.xcf) that serves as master source for english stone 24pt bitmaps. This size has two bitmaps (_0_ and _1_). Only layers associated with _0_ are momentarily visible in the left panel. They are the glyph bitmap, and two datBounds bitmaps (lower 128 and upper 128 characters). While these are all transparent, the lowest &amp;quot;black background&amp;quot; layer renders the stack as shown.&lt;br /&gt;
&lt;br /&gt;
This snapshot shows a few early changes towards font completion for TDM 2.13. So, for instance, the N in row 4 now has a tilde above it. Note how N and Ñ have overlapping bounds, allowing them to share the base letter but not the accent. This is common with hand-done font bitmaps to conserve bitmap real estate. (Subsequent to this image, the two bitmaps, further revised, were renamed to be more apt, as &amp;quot;_0_ Mostly ASCII&amp;quot; and &amp;quot;_1_ Mostly ANSI&amp;quot;.)&lt;br /&gt;
&lt;br /&gt;
== Downloads ==&lt;br /&gt;
&#039;&#039;Version 1.7 of 2025, August 18&#039;&#039;. Fixes fatal bug introduced in v1.6 when reading DAT format file.&lt;br /&gt;
* [https://drive.google.com/file/d/1SYaKyKXXCFHAYE5LH4e9XkSuJCGLvFOl/view?usp=sharing executable: datBounds.exe]&lt;br /&gt;
* [https://drive.google.com/file/d/10lHc_LXNublaMdgyZdXpomjmQYbwXXLt/view?usp=sharing Source code datBounds.cpp]&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Earlier Versions&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Version 1.6 of 2025, January 22.&#039;&#039; Fixes shaderName and other issues preventing .tga generation. Shows filenames during write. Supports REF files with refont v2.5 headers for 512x512 bitmaps, plus options scaling_ok and raw_metrics.&lt;br /&gt;
* [https://drive.google.com/file/d/1NiFcAC0cA5-t8_nWH3pUzT5viNihA-u7/view?usp=sharing executable: datBounds.exe]&lt;br /&gt;
* [https://drive.google.com/file/d/1Tit5WwHSaVV7kXsw7xvsKfbC6fhUJiMw/view?usp=sharing Source code: datBounds.cpp]&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Version 1.3 of 2024, August 16.&#039;&#039; Prevents a crash if drawn lines are out of bounds. Fixes a bug where xSkip dot was always showing, even if -xskip not specified. Adds &amp;quot;0x&amp;quot; before hex form output of warnings and errors. Adds command-line options -boundless, -long_baseline_left, -long_baseline_right, and -long_pitchline_down.&lt;br /&gt;
* [https://drive.google.com/file/d/16tVHiXvCuG8pi6WLSOUFrNF0R4-_fWZA/view?usp=sharing executable: datBounds.exe]&lt;br /&gt;
* [https://drive.google.com/file/d/1_qfoH9FTmSBIqys2d1o-ZwD_bYJDzO3t/view?usp=sharing Source code: datBounds.cpp]&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Version 1.2 of 2024, June 9.&#039;&#039; Fixes a bug with codepoint 255 being skipped. Adds metadata consistency checking.&lt;br /&gt;
* [https://drive.google.com/file/d/1mMYc7pAjVDSiWF21a4vdtE3ROBSDzmUb/view?usp=sharing executable: datBounds.exe]&lt;br /&gt;
* [https://drive.google.com/file/d/1zcmBML14eessYvjlK4UjKMt13FOQ5N4u/view?usp=sharing Source code: datBounds.cpp]&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Version 1.1 of 2024, May 20.&#039;&#039; This shortens baselines. The left end of a baseline now begins at the pitch vertical. So that the red xSkip dot will be less likely to be obscured by the baseline of an adjoining character.&lt;br /&gt;
* [https://drive.google.com/file/d/1I5j8Az6bDZ4461_02sbh0RiVfm_1d6fD/view?usp=sharing Windows executable: datBounds.exe]&lt;br /&gt;
* [https://drive.google.com/file/d/1jN-Uvr9QYg1YOs8no3fNvuvnjOGPf48p/view?usp=sharing Source code: datBounds.cpp]&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Version 1.0 of 2024, May 10.&#039;&#039; Original.&lt;br /&gt;
* [https://drive.google.com/file/d/1nL7gTbPAaossPrL_0b39b9P_r7HiB6zq/view?usp=sharing Windows executable: datBounds.exe]&lt;br /&gt;
* [https://drive.google.com/file/d/1208Ce1bvbwXR9R8mY6cHP3fPBPKwtWpc/view?usp=sharing Source code: datBounds.cpp]&lt;br /&gt;
&lt;br /&gt;
== See Also ==&lt;br /&gt;
* [[Font Bitmaps in DDS Files]] provides a broader context to the examples here.&lt;br /&gt;
* [[Font Files]] describes DAT and DDS file naming, directory location, scaling, and usage by TDM.&lt;br /&gt;
* [[Font Metrics &amp;amp; DAT File Format]] provides an Overview and helpful details.&lt;br /&gt;
* [[Font Conversion &amp;amp; Repair]] touches on tools to generate, visualize, and adjust DAT and DSS files, including utilities [[ExportFontToDoom3]], [[Q3Font]], [[Refont]], and [[Font Patcher]].&lt;br /&gt;
&lt;br /&gt;
{{tutorial}} [[Category:Fonts]]&lt;/div&gt;</summary>
		<author><name>Geep</name></author>
	</entry>
	<entry>
		<id>https://wiki.thedarkmod.com/index.php?title=Text_Decals_for_Signs_etc.&amp;diff=34026</id>
		<title>Text Decals for Signs etc.</title>
		<link rel="alternate" type="text/html" href="https://wiki.thedarkmod.com/index.php?title=Text_Decals_for_Signs_etc.&amp;diff=34026"/>
		<updated>2025-08-11T15:51:23Z</updated>

		<summary type="html">&lt;p&gt;Geep: Move #str_ infobox, mention \n in *.lang&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;From [https://forums.thedarkmod.com/index.php?/topic/11159-add-text-to-your-signs-signposts-walls-etc/&amp;amp;tab=comments#comment-218526 Fidcal&#039;s 2010 Posting]. Updated by Geep, 2020.&lt;br /&gt;
==Introduction==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
This article describes how to add non-graphic simple text to signs, signposts, walls, etc. using gui decals. In this image you can see some examples. This method only provides the application of the text itself (ie, does not include the signs, signposts, and so on). For the latter, one starting point is the model collection under darkmod/decorative/signs (avoiding any sign that has an embedded GUI).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;[[Image:text_decals.jpg]]&amp;lt;/center&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Dark Mod (from 1.03 onward) provides convenient prefab assets; or alternatively, see [[#Customising and Making your Own]] below.&lt;br /&gt;
&lt;br /&gt;
For other types of in-game text see [[Text]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Ready-made Prefabs==&lt;br /&gt;
&lt;br /&gt;
This is by far the easiest method. You simply insert a prefab and change the default text and size to what you want:&lt;br /&gt;
&lt;br /&gt;
* This is described for the Dark Radiant editor.&lt;br /&gt;
* For general use all you need do is to find or make your blank wall, sign, etc.&lt;br /&gt;
* RMB in grid view, select &amp;quot;insert prefab&amp;quot;, and navigate to readables/sign_text_decals/.&lt;br /&gt;
* Select a prefab with a desired font (eg, sign_text_carleton.pfb) and one of two sizes (with or without &amp;quot;_small&amp;quot; suffix).&lt;br /&gt;
* Of the Dark Mod fonts shown in [[Fonts Screenshots]], two-thirds are available as prefabs; for others, see [[#Customising and Making your Own]] below.&lt;br /&gt;
* You now have a working text decal, seen in DR as a blue rectangular &amp;quot;Entity GUI&amp;quot;.&lt;br /&gt;
* To set your text, change the spawnarg value gui_parm1 in Entity Inspector to whatever you want.&lt;br /&gt;
* The defaults are all black text with 66% transparency so they blend well onto most surfaces but see [[#Customising and Making your Own]] below for how to change this.&lt;br /&gt;
&lt;br /&gt;
==Text Size, Text Composition, and Multi-line Text==&lt;br /&gt;
&lt;br /&gt;
by Geep, 2020&lt;br /&gt;
&lt;br /&gt;
To change the size of the text, just resize the patch. To do this, first press the TAB key. Remember to press TAB again to get back.&lt;br /&gt;
&lt;br /&gt;
Since you can&#039;t see the rendered text content results directly in DR, you will have to iterate to get what you want. The gui_parm1 value takes a single line of text (with no enveloping quotes). Within the spawnarg, there is no direct way to indicate line breaks; &amp;quot;\n&amp;quot; will not do it.&lt;br /&gt;
&lt;br /&gt;
{{infobox|Note: Instead of using a hard-coded English text, consider using &amp;quot;#str_...&amp;quot;, such as &amp;quot;#str_myFM_brewery_sign&amp;quot;, and create a custom FM dictionary english.lang (and other translations). Strings in *.lang can effectively contain &amp;quot;\n&amp;quot;. See [[I18N|here]] for details.}}&lt;br /&gt;
&lt;br /&gt;
The examples shown here rely entirely upon word-wrapping for multi-line text. In practice, that means inserting spaces to force wordwrap (or see Tip below).&lt;br /&gt;
&lt;br /&gt;
Often, you need to resize the Entity GUI patch to cover a larger area than the visible sign; the patch size and aspect ratio will affect font size and aspect ratio, but not wordwrap and number of visible lines. The decal patch is non-solid and invisible - except for the text itself - so can overlap any visible surface with no problem.&lt;br /&gt;
&lt;br /&gt;
You can offset the Entity GUI with respect to the underlying sign to adjust left and top margins, including to fake centering.&lt;br /&gt;
&lt;br /&gt;
===An Example===&lt;br /&gt;
&lt;br /&gt;
To demonstrate some of this (except use of extra spaces in the text), here&#039;s a series of signs on a wall, all of which have:&lt;br /&gt;
* the same empty wall plaque&lt;br /&gt;
* an Entity GUI with 1:2 ratio (so the aspect ratio of the font characters is kept constant for demonstration purposes)&lt;br /&gt;
* use of a common font family, Carleton&lt;br /&gt;
&lt;br /&gt;
The photos shows the series in DR (top) and in-game (bottom). Each row of signs has the same Entity GUI size and placement. Each column of signs has the same text string and choice of font size. The top left sign is an plaque-centered placement of a 16x32 &amp;quot;Carleton&amp;quot; Entity GUI. This typically results in poor placement, so all the other signs have the upper-left corner of the Entity GUI down and slightly to the right. Going down the first column, as the Entity GUI becomes larger (20x40 in the 3rd row, 28x56 in the 4th row), the font enlarges proportionately to the Entity GUI size, so wordwrap is the same in all cases. In the second column, the gui_parm1 text counts up to ten, but some of it is not rendered due to the Entity GUI boundary. Again, this line clipping is the same in all cases. The third and fourth columns repeat all that, but with the &amp;quot;Carleton Small&amp;quot; font. This allows both more words per line, and more lines. The specifics of those will vary with font family chosen.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;[[File:Example sign Entity GUIs in DR.jpg]]&amp;lt;/center&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;[[File:Example_sign_Entity_GUIs_in-game.jpg| 1100px]]&amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{infobox|Tip 1: Rather than relying on wordwrap for multi-lining, or using #str_ with &amp;quot;\n&amp;quot;, you can create multiple overlapping, offset Entity GUIs, one per desired line, and adjust them independently. This technique also allows different lines to have different fonts and/or scalings.}}&lt;br /&gt;
{{infobox|Tip 2: Want to have text horizontally centered rather than left-justified? You&#039;ll have to do this manually. For a single line of text, either slide the Entity GUI sideways or add leading spaces or both. But for multi-lines, word wrap will ignore excess spaces between words, so spacing can&#039;t be used for centering after line 1. Instead, use the Tip 1 method.}}&lt;br /&gt;
&lt;br /&gt;
== Signs with Illuminated Colored Letters ==&lt;br /&gt;
by Geep 2021&lt;br /&gt;
&lt;br /&gt;
Within the GUI text, you can add Caret Control Codes (see [[Xdata file format]]) around particular words or phrases to give you the look of &#039;&#039;backlit&#039;&#039; letters in bright primary colors, perhaps to indicate wizardry afoot, evoke carnival, or provide eye-catching text for a custom in-game control.&lt;br /&gt;
&lt;br /&gt;
    ^0 default&lt;br /&gt;
    ^1 bright red&lt;br /&gt;
    ^2 bright green&lt;br /&gt;
    ^3 bright yellow&lt;br /&gt;
    ^4 bright blue&lt;br /&gt;
    ^5 bright cyan&lt;br /&gt;
    ^6 bright magenta (pink)&lt;br /&gt;
    ^7 bright white&lt;br /&gt;
    ^8 light grey&lt;br /&gt;
    ^9 black&lt;br /&gt;
&lt;br /&gt;
Example: &amp;quot;This is default black. ^1This is bright red.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
The scope of a code terminates at the end of the line as formatted in the game, at which point it defaults back to the gui default color. So get your word wrapping in shape first, then apply codes. Or bracket around each word if you want it to work no matter the word wrap, e.g.:&lt;br /&gt;
&lt;br /&gt;
&amp;quot;This is default black. ^1This^0 ^1is^0 ^1bright^0 ^1red.^0 Back to black.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Customising and Making your Own==&lt;br /&gt;
&lt;br /&gt;
Here are the steps to make your own text decals or customise the ones provided (say, to use a different font size by changing the gui&#039;s &amp;quot;textscale&amp;quot; value).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===The Decal===&lt;br /&gt;
&lt;br /&gt;
* Create a patch and give it the texture: textures/darkmod/decals/signs/decal_gui . This is only available from Dark Mod update 1.03 onward but if you want it earlier this is what to do:&lt;br /&gt;
** Use textures/common/entityGui instead if it doesn&#039;t matter if the decal is solid.&lt;br /&gt;
** Create the custom texture listed below at [[#The Texture]]&lt;br /&gt;
* In Surface Inspector, use these in order: natural, fit, flip horizontal, rotate left 180 degrees.&lt;br /&gt;
* You should now see a single occurrence of the words Entity GUI on the patch and the words should be upright and not mirrored. If not, adjust, rotate, until they do.&lt;br /&gt;
* Note that the text size will be affected by the size of the patch&lt;br /&gt;
* Convert the patch to a func_static entity&lt;br /&gt;
* Give it the spawnargs:&lt;br /&gt;
** &#039;&#039;&#039;gui&#039;&#039;&#039; with the path and name of your gui (see [[#The GUI]] below) as its value.&lt;br /&gt;
** &#039;&#039;&#039;gui_parm1&#039;&#039;&#039; with your own text as its value.&lt;br /&gt;
&lt;br /&gt;
===The GUI===&lt;br /&gt;
&lt;br /&gt;
This is the gui file that defines the font. If you have Dark Mod update 1.03 you can modify an existing one. Alternatively, just copy and paste this into a text file, and modify:&lt;br /&gt;
 windowDef Desktop&lt;br /&gt;
 {&lt;br /&gt;
 	rect 0, 0, 640, 480&lt;br /&gt;
 	backcolor 0, 0, 0, 0&lt;br /&gt;
 &lt;br /&gt;
 	windowDef SignText&lt;br /&gt;
 	{&lt;br /&gt;
 		rect 0, 0, 640,480&lt;br /&gt;
 		backcolor 0, 0, 0, 0&lt;br /&gt;
 		text	&amp;quot;gui::gui_parm1&amp;quot;&lt;br /&gt;
 		font &amp;quot;fonts/stone&amp;quot;&lt;br /&gt;
 		textscale 2&lt;br /&gt;
 		forecolor 0, 0, 0, 0.8&lt;br /&gt;
 		visible 1&lt;br /&gt;
 	}&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
Save it with your FM in a &amp;quot;guis&amp;quot; (sub)folder. For instance, as guis/readables/sign_text_decals/my_stone_text.gui.&lt;br /&gt;
You will need to add that path and name to the gui spawnarg of the decal entity above, eg,&lt;br /&gt;
 gui   guis/readables/sign_text_decals/my_stone_text.gui&lt;br /&gt;
&lt;br /&gt;
In the above GUI-script definition, these are some of the things you can change:&lt;br /&gt;
&lt;br /&gt;
* Set your font in the font line as shown, it must be in quotation marks as above eg &amp;quot;fonts/stone&amp;quot;. And to change the font just replace the word stone with the new font name - font choices are shown in [[Fonts Screenshots]]. Eg in my case Carleton - &amp;quot;fonts/carleton&amp;quot;&lt;br /&gt;
* Change the font size in textscale. Fractions can be used, eg, 1.5 but remember, resizing the patch or texture scale in Dark Radiant also changes the font size.&lt;br /&gt;
* Change the colour and transparency of the text in the forecolor line. Because of the way Doom 3 blends imagery, for all practical purposes this is limited to very dark colours because they do not react to local game lighting. If you choose lighter colours then they will glow in the dark. (it might be possible to match a colour to a static light situation.) The forecolor values are:&lt;br /&gt;
** red, green, blue, transparency; each in the range 0 to 1.&lt;br /&gt;
** For colours, 0 to 1 is zero to full intensity; for transparency it is invisible (0) to fully opaque (1)&lt;br /&gt;
** For example:&lt;br /&gt;
*** 0.9, 0.9, 0, 1 would be high red, high green, no blue, and fully opaque. Red and green light make yellow so this would give glowing yellow text that would not blend well with its background.&lt;br /&gt;
*** 0.1, 0, 0, 0.66 This is more practical and would give a dark red that blends well onto its background with 66% opacity.&lt;br /&gt;
* A background colour can be set with the backcolor line exactly the same as for forecolor but is probably of limited use for our purposes. 0.9, 0.9, 0, 1 would have the text on a solid bright yellow background that glows in the dark. 0, 0.1,0, 0.33 would give a faint green background of 33% opacity.&lt;br /&gt;
&lt;br /&gt;
===The Texture===&lt;br /&gt;
&lt;br /&gt;
This is the non-solid decal gui texture. Copy and paste it into a text file and save it with your map in a materials folder as eg, mymap.mtr. You will need to reload shaders if you already have Dark Radiant running before you can select it.&lt;br /&gt;
&lt;br /&gt;
 textures/mymap/decals/signs/decal_gui&lt;br /&gt;
 {&lt;br /&gt;
 	qer_editorimage	textures/editor/entityGui.tga&lt;br /&gt;
 	DECAL_MACRO&lt;br /&gt;
 	nonsolid&lt;br /&gt;
 	noimpact&lt;br /&gt;
 	guiSurf	entity&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
where DECAL_MACRO defines these additional keywords for you:&lt;br /&gt;
&lt;br /&gt;
 	polygonOffset 1&lt;br /&gt;
 	discrete&lt;br /&gt;
 	sort decal&lt;br /&gt;
  	noShadows&lt;br /&gt;
&lt;br /&gt;
== See also ==&lt;br /&gt;
&lt;br /&gt;
* [[I18N|Internationalization]] &lt;br /&gt;
&lt;br /&gt;
{{GUI}}&lt;/div&gt;</summary>
		<author><name>Geep</name></author>
	</entry>
	<entry>
		<id>https://wiki.thedarkmod.com/index.php?title=Text_Decals_for_Signs_etc.&amp;diff=34025</id>
		<title>Text Decals for Signs etc.</title>
		<link rel="alternate" type="text/html" href="https://wiki.thedarkmod.com/index.php?title=Text_Decals_for_Signs_etc.&amp;diff=34025"/>
		<updated>2025-08-11T02:55:08Z</updated>

		<summary type="html">&lt;p&gt;Geep: /* The GUI */ provide more typical path example&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;From [https://forums.thedarkmod.com/index.php?/topic/11159-add-text-to-your-signs-signposts-walls-etc/&amp;amp;tab=comments#comment-218526 Fidcal&#039;s 2010 Posting]. Updated by Geep, 2020.&lt;br /&gt;
==Introduction==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
This article describes how to add non-graphic simple text to signs, signposts, walls, etc. using gui decals. In this image you can see some examples. This method only provides the application of the text itself (ie, does not include the signs, signposts, and so on). For the latter, one starting point is the model collection under darkmod/decorative/signs (avoiding any sign that has an embedded GUI).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;[[Image:text_decals.jpg]]&amp;lt;/center&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Dark Mod (from 1.03 onward) provides convenient prefab assets; or alternatively, see [[#Customising and Making your Own]] below.&lt;br /&gt;
&lt;br /&gt;
For other types of in-game text see [[Text]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Ready-made Prefabs==&lt;br /&gt;
&lt;br /&gt;
This is by far the easiest method. You simply insert a prefab and change the default text and size to what you want:&lt;br /&gt;
&lt;br /&gt;
* This is described for the Dark Radiant editor.&lt;br /&gt;
* For general use all you need do is to find or make your blank wall, sign, etc.&lt;br /&gt;
* RMB in grid view, select &amp;quot;insert prefab&amp;quot;, and navigate to readables/sign_text_decals/.&lt;br /&gt;
* Select a prefab with a desired font (eg, sign_text_carleton.pfb) and one of two sizes (with or without &amp;quot;_small&amp;quot; suffix).&lt;br /&gt;
* Of the Dark Mod fonts shown in [[Fonts Screenshots]], two-thirds are available as prefabs; for others, see [[#Customising and Making your Own]] below.&lt;br /&gt;
* You now have a working text decal, seen in DR as a blue rectangular &amp;quot;Entity GUI&amp;quot;.&lt;br /&gt;
* To set your text, change the spawnarg value gui_parm1 in Entity Inspector to whatever you want.&lt;br /&gt;
* The defaults are all black text with 66% transparency so they blend well onto most surfaces but see [[#Customising and Making your Own]] below for how to change this.&lt;br /&gt;
&lt;br /&gt;
==Text Size, Text Composition, and Multi-line Text==&lt;br /&gt;
&lt;br /&gt;
by Geep, 2020&lt;br /&gt;
&lt;br /&gt;
To change the size of the text, just resize the patch. To do this, first press the TAB key. Remember to press TAB again to get back.&lt;br /&gt;
&lt;br /&gt;
Since you can&#039;t see the rendered text content results directly in DR, you will have to iterate to get what you want. The gui_parm1 value takes a single line of text (with no enveloping quotes). It is without a way to indicate line breaks; &amp;quot;\n&amp;quot; will not do it. The examples shown here rely entirely upon word-wrapping for multi-line text. In practice, that means inserting spaces to force wordwrap (or see Tip below).&lt;br /&gt;
&lt;br /&gt;
Often, you need to resize the Entity GUI patch to cover a larger area than the visible sign; the patch size and aspect ratio will affect font size and aspect ratio, but not wordwrap and number of visible lines. The decal patch is non-solid and invisible - except for the text itself - so can overlap any visible surface with no problem.&lt;br /&gt;
&lt;br /&gt;
You can offset the Entity GUI with respect to the underlying sign to adjust left and top margins, including to fake centering.&lt;br /&gt;
&lt;br /&gt;
===An Example===&lt;br /&gt;
&lt;br /&gt;
To demonstrate some of this (except use of extra spaces in the text), here&#039;s a series of signs on a wall, all of which have:&lt;br /&gt;
* the same empty wall plaque&lt;br /&gt;
* an Entity GUI with 1:2 ratio (so the aspect ratio of the font characters is kept constant for demonstration purposes)&lt;br /&gt;
* use of a common font family, Carleton&lt;br /&gt;
&lt;br /&gt;
The photos shows the series in DR (top) and in-game (bottom). Each row of signs has the same Entity GUI size and placement. Each column of signs has the same text string and choice of font size. The top left sign is an plaque-centered placement of a 16x32 &amp;quot;Carleton&amp;quot; Entity GUI. This typically results in poor placement, so all the other signs have the upper-left corner of the Entity GUI down and slightly to the right. Going down the first column, as the Entity GUI becomes larger (20x40 in the 3rd row, 28x56 in the 4th row), the font enlarges proportionately to the Entity GUI size, so wordwrap is the same in all cases. In the second column, the gui_parm1 text counts up to ten, but some of it is not rendered due to the Entity GUI boundary. Again, this line clipping is the same in all cases. The third and fourth columns repeat all that, but with the &amp;quot;Carleton Small&amp;quot; font. This allows both more words per line, and more lines. The specifics of those will vary with font family chosen.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;[[File:Example sign Entity GUIs in DR.jpg]]&amp;lt;/center&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;[[File:Example_sign_Entity_GUIs_in-game.jpg| 1100px]]&amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{infobox|Tip 1: Rather than relying on wordwrap for multi-lining, you can create multiple overlapping, offset Entity GUIs, one per desired line, and adjust them independently. This technique also allows different lines to have different fonts and/or scalings.}}&lt;br /&gt;
{{infobox|Tip 2: Want to have text horizontally centered rather than left-justified? You&#039;ll have to do this manually. For a single line of text, either slide the Entity GUI sideways or add leading spaces or both. But for multi-lines, word wrap will ignore excess spaces between words, so spacing can&#039;t be used for centering after line 1. Instead, use the Tip 1 method.}}&lt;br /&gt;
&lt;br /&gt;
== Signs with Illuminated Colored Letters ==&lt;br /&gt;
by Geep 2021&lt;br /&gt;
&lt;br /&gt;
Within the GUI text, you can add Caret Control Codes (see [[Xdata file format]]) around particular words or phrases to give you the look of &#039;&#039;backlit&#039;&#039; letters in bright primary colors, perhaps to indicate wizardry afoot, evoke carnival, or provide eye-catching text for a custom in-game control.&lt;br /&gt;
&lt;br /&gt;
    ^0 default&lt;br /&gt;
    ^1 bright red&lt;br /&gt;
    ^2 bright green&lt;br /&gt;
    ^3 bright yellow&lt;br /&gt;
    ^4 bright blue&lt;br /&gt;
    ^5 bright cyan&lt;br /&gt;
    ^6 bright magenta (pink)&lt;br /&gt;
    ^7 bright white&lt;br /&gt;
    ^8 light grey&lt;br /&gt;
    ^9 black&lt;br /&gt;
&lt;br /&gt;
Example: &amp;quot;This is default black. ^1This is bright red.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
The scope of a code terminates at the end of the line as formatted in the game, at which point it defaults back to the gui default color. So get your word wrapping in shape first, then apply codes. Or bracket around each word if you want it to work no matter the word wrap, e.g.:&lt;br /&gt;
&lt;br /&gt;
&amp;quot;This is default black. ^1This^0 ^1is^0 ^1bright^0 ^1red.^0 Back to black.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Customising and Making your Own==&lt;br /&gt;
&lt;br /&gt;
Here are the steps to make your own text decals or customise the ones provided (say, to use a different font size by changing the gui&#039;s &amp;quot;textscale&amp;quot; value).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===The Decal===&lt;br /&gt;
&lt;br /&gt;
* Create a patch and give it the texture: textures/darkmod/decals/signs/decal_gui . This is only available from Dark Mod update 1.03 onward but if you want it earlier this is what to do:&lt;br /&gt;
** Use textures/common/entityGui instead if it doesn&#039;t matter if the decal is solid.&lt;br /&gt;
** Create the custom texture listed below at [[#The Texture]]&lt;br /&gt;
* In Surface Inspector, use these in order: natural, fit, flip horizontal, rotate left 180 degrees.&lt;br /&gt;
* You should now see a single occurrence of the words Entity GUI on the patch and the words should be upright and not mirrored. If not, adjust, rotate, until they do.&lt;br /&gt;
* Note that the text size will be affected by the size of the patch&lt;br /&gt;
* Convert the patch to a func_static entity&lt;br /&gt;
* Give it the spawnargs:&lt;br /&gt;
** &#039;&#039;&#039;gui&#039;&#039;&#039; with the path and name of your gui (see [[#The GUI]] below) as its value.&lt;br /&gt;
** &#039;&#039;&#039;gui_parm1&#039;&#039;&#039; with your own text as its value.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{{infobox|Note: Instead of using a hard-coded English text, consider using &amp;quot;#str_20000&amp;quot; and create a custom FM dictionary. See [[I18N|here]] for details.}}&lt;br /&gt;
&lt;br /&gt;
===The GUI===&lt;br /&gt;
&lt;br /&gt;
This is the gui file that defines the font. If you have Dark Mod update 1.03 you can modify an existing one. Alternatively, just copy and paste this into a text file, and modify:&lt;br /&gt;
 windowDef Desktop&lt;br /&gt;
 {&lt;br /&gt;
 	rect 0, 0, 640, 480&lt;br /&gt;
 	backcolor 0, 0, 0, 0&lt;br /&gt;
 &lt;br /&gt;
 	windowDef SignText&lt;br /&gt;
 	{&lt;br /&gt;
 		rect 0, 0, 640,480&lt;br /&gt;
 		backcolor 0, 0, 0, 0&lt;br /&gt;
 		text	&amp;quot;gui::gui_parm1&amp;quot;&lt;br /&gt;
 		font &amp;quot;fonts/stone&amp;quot;&lt;br /&gt;
 		textscale 2&lt;br /&gt;
 		forecolor 0, 0, 0, 0.8&lt;br /&gt;
 		visible 1&lt;br /&gt;
 	}&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
Save it with your FM in a &amp;quot;guis&amp;quot; (sub)folder. For instance, as guis/readables/sign_text_decals/my_stone_text.gui.&lt;br /&gt;
You will need to add that path and name to the gui spawnarg of the decal entity above, eg,&lt;br /&gt;
 gui   guis/readables/sign_text_decals/my_stone_text.gui&lt;br /&gt;
&lt;br /&gt;
In the above GUI-script definition, these are some of the things you can change:&lt;br /&gt;
&lt;br /&gt;
* Set your font in the font line as shown, it must be in quotation marks as above eg &amp;quot;fonts/stone&amp;quot;. And to change the font just replace the word stone with the new font name - font choices are shown in [[Fonts Screenshots]]. Eg in my case Carleton - &amp;quot;fonts/carleton&amp;quot;&lt;br /&gt;
* Change the font size in textscale. Fractions can be used, eg, 1.5 but remember, resizing the patch or texture scale in Dark Radiant also changes the font size.&lt;br /&gt;
* Change the colour and transparency of the text in the forecolor line. Because of the way Doom 3 blends imagery, for all practical purposes this is limited to very dark colours because they do not react to local game lighting. If you choose lighter colours then they will glow in the dark. (it might be possible to match a colour to a static light situation.) The forecolor values are:&lt;br /&gt;
** red, green, blue, transparency; each in the range 0 to 1.&lt;br /&gt;
** For colours, 0 to 1 is zero to full intensity; for transparency it is invisible (0) to fully opaque (1)&lt;br /&gt;
** For example:&lt;br /&gt;
*** 0.9, 0.9, 0, 1 would be high red, high green, no blue, and fully opaque. Red and green light make yellow so this would give glowing yellow text that would not blend well with its background.&lt;br /&gt;
*** 0.1, 0, 0, 0.66 This is more practical and would give a dark red that blends well onto its background with 66% opacity.&lt;br /&gt;
* A background colour can be set with the backcolor line exactly the same as for forecolor but is probably of limited use for our purposes. 0.9, 0.9, 0, 1 would have the text on a solid bright yellow background that glows in the dark. 0, 0.1,0, 0.33 would give a faint green background of 33% opacity.&lt;br /&gt;
&lt;br /&gt;
===The Texture===&lt;br /&gt;
&lt;br /&gt;
This is the non-solid decal gui texture. Copy and paste it into a text file and save it with your map in a materials folder as eg, mymap.mtr. You will need to reload shaders if you already have Dark Radiant running before you can select it.&lt;br /&gt;
&lt;br /&gt;
 textures/mymap/decals/signs/decal_gui&lt;br /&gt;
 {&lt;br /&gt;
 	qer_editorimage	textures/editor/entityGui.tga&lt;br /&gt;
 	DECAL_MACRO&lt;br /&gt;
 	nonsolid&lt;br /&gt;
 	noimpact&lt;br /&gt;
 	guiSurf	entity&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
where DECAL_MACRO defines these additional keywords for you:&lt;br /&gt;
&lt;br /&gt;
 	polygonOffset 1&lt;br /&gt;
 	discrete&lt;br /&gt;
 	sort decal&lt;br /&gt;
  	noShadows&lt;br /&gt;
&lt;br /&gt;
== See also ==&lt;br /&gt;
&lt;br /&gt;
* [[I18N|Internationalization]] &lt;br /&gt;
&lt;br /&gt;
{{GUI}}&lt;/div&gt;</summary>
		<author><name>Geep</name></author>
	</entry>
	<entry>
		<id>https://wiki.thedarkmod.com/index.php?title=ExportUnicodeFontToDoom3&amp;diff=34024</id>
		<title>ExportUnicodeFontToDoom3</title>
		<link rel="alternate" type="text/html" href="https://wiki.thedarkmod.com/index.php?title=ExportUnicodeFontToDoom3&amp;diff=34024"/>
		<updated>2025-08-06T15:43:06Z</updated>

		<summary type="html">&lt;p&gt;Geep: article created&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;By Geep, 2025 [WORK IN PROGRESS]&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
== Introduction ==&lt;br /&gt;
&lt;br /&gt;
In 2025, kalinovka in [https://forums.thedarkmod.com/index.php?/topic/22736-font-localization Font localization] sought to extend TDM’s Mason 48pt font, used in the main menu, to include missing Cyrillic glyphs. This would allow this font to be used in an FM and still support a Russian translation.&lt;br /&gt;
&lt;br /&gt;
This offshoot of [https://wiki.thedarkmod.com/index.php?title=ExportFontToDoom3 ExportFontToDoom3All256] is a generalized response to that. The main idea to select an input TTF font that includes not just ASCII or ANSI, but offers additional Unicode characters, like Cyrillic. The program still limits output to a maximum of 256 characters, consistent with the DAT format.&lt;br /&gt;
&lt;br /&gt;
To achieve this, it reads in an external human-readable &amp;quot;unicodeMap&amp;quot; file, in Unicode.org’s &amp;quot;Format A&amp;quot;. This format provides a mapping from the traditional 8-bit encoding that TDM uses to the corresponding UCS (Unicode 16-bit) value. Unicode.org provides stock files for standard ISO and Windows 8-bit encodings. Of specific interest here is [https://www.unicode.org/Public/MAPPINGS/VENDORS/MICSFT/WINDOWS/CP1251.TXT cp1251.txt for Cyrillic]. This requires just trivial editing for [https://wiki.thedarkmod.com/index.php?title=I18N_-_Charset TDM-specific codepoints].&lt;br /&gt;
As discussed below, you can further edit a unicodeMap file in advance, if you want to generate just a subset of glyphs.&lt;br /&gt;
&lt;br /&gt;
== New Command Line Arguments ==&lt;br /&gt;
&lt;br /&gt;
These are in-addition to those of [https://wiki.thedarkmod.com/index.php?title=ExportFontToDoom3 ExportFontToDoom3All256].&lt;br /&gt;
&lt;br /&gt;
=== unicodeMap &amp;lt;file&amp;gt; ===&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
 -unicodeMap &amp;quot;./Test/cp1251.txt&amp;quot;&lt;br /&gt;
&lt;br /&gt;
You can edit the unicodeMap file in advance, to specify which particular glyphs you want to generate by suppressing unwanted glyphs, either by:&lt;br /&gt;
&lt;br /&gt;
* Deleting an unwanted line (or block of lines) entirely, or&lt;br /&gt;
* Prepending a &amp;quot;#&amp;quot; to comment-out the line.&lt;br /&gt;
&lt;br /&gt;
Also, this file format allows the Unicode value (e.g., &amp;quot;0x1234&amp;quot;) to be replaced by 6 space characters, when the ISO or Windows standard leaves that character undefined.&lt;br /&gt;
&lt;br /&gt;
In all 3 of those cases, every suppressed character in the output DAT file will be represented by the glyph that the font uses for U+0000. A hollow box is common.&lt;br /&gt;
&lt;br /&gt;
=== startFileNumber &amp;lt;n&amp;gt; ===&lt;br /&gt;
When a set of TGA/DDS files are generated for a particular font size, by default the first file&#039;s name contains _0_, which increments for additional files. You can optionally specify a different 1- or 2-digit start number, e.g., &amp;quot;-startFileNumber 7&amp;quot;. Why? Because...&lt;br /&gt;
&lt;br /&gt;
* the file(s) you are generating are supplemental to, not replacements for, existing TGA/DDS files; and&lt;br /&gt;
* in this run, you are generating just one of the 3 possible font sizes (assuming each size has a different count of existing TGA/DDS files).&lt;br /&gt;
&lt;br /&gt;
When you generate a supplemental set, the new DAT file has no knowledge of what&#039;s in the original set and its DAT file. You will have to interleave-edit the old and new DAT files (e.g., with reFont&#039;s REF files) to create a single DAT file spanning old and new glyphs. There may be a redundant NULL glyph in your new TGA set; just ignore it.&lt;br /&gt;
&lt;br /&gt;
=== awayFromEdge &amp;lt;n&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
Allows specifying in positive integer pixels (e.g., &amp;quot;-awayFromEdge 2&amp;quot;) a small extra boundary at the top and left edges of the overall bitmap. This is for fonts like Mason where extra space (typically 2 pixels) is needed around every character to create a &amp;quot;glow variant&amp;quot;. Routine glyph layout provides usually enough space for this except at the top and (arguably) left edges. See also the &amp;quot;compact&amp;quot; parameter.&lt;br /&gt;
&lt;br /&gt;
=== compact ===&lt;br /&gt;
If specified (i.e, &amp;quot;-compact&amp;quot;), packs the character glyphs more closely together. Particularly recommended for 48pt fonts; it will generate roughly half the files.&lt;br /&gt;
&lt;br /&gt;
Whether &amp;quot;compact&amp;quot; is specified or not, packing is controlled by simply &amp;quot;padding&amp;quot; each glyph’s bounding box. Specifically, this doesn’t change the bounding box, but adds pixel &amp;quot;padding&amp;quot; to just the right and bottom of the bounding box, a simple though asymmetric process. One reason for padding was given ExportFontToDoom3 author Grant Davies in code comments:&lt;br /&gt;
&lt;br /&gt;
&amp;quot;Because of the way Doom 3 Indexes the texture page (using floating point numbers), it is unable to reference exact pixels – there is error. How much error, I don’t know. For this reason, the rectangles needs to be padded out.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Geep suspects that such error with the TDM engine is not really a problem. Likely some error in the past was due to editing with Q3Font and its low floating-point precision. Nevertheless, some padding is gppd because:&lt;br /&gt;
&lt;br /&gt;
* For the Mason font, 2 pixels around each glyph are needed for &amp;quot;glow&amp;quot; effects (either done as a separate smudge font for /english/ or as a bidirection offset effect for /russian/.)&lt;br /&gt;
* Keeping glyphs separated improves visualization of boundaries with datBounds, and makes editing tweaks easier.&lt;br /&gt;
&lt;br /&gt;
The &amp;quot;compact&amp;quot; setting restores Grant Davies&#039; first algorithm, which just pads the bounding box by 5 pixels to the right and 5 pixels below.&lt;br /&gt;
&lt;br /&gt;
Without &amp;quot;compact&amp;quot;, the default is Grant Davies&#039; second algorithm found in ExportFontToDoom3 v1.02. This likewise first pads each bounding box by 5 pixels to the right and 5 pixels below. It then further pads to make both the width and height a factor of 2; this makes 48pt quite sparse.  (It is possible this improved rendering performance in 2005; not important now. Also, in practice for major fonts, much of this &amp;quot;factor of 2&amp;quot; spacing was overridden by subsequent Font Patcher work.)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;[MORE TO COME]&#039;&#039;&lt;/div&gt;</summary>
		<author><name>Geep</name></author>
	</entry>
	<entry>
		<id>https://wiki.thedarkmod.com/index.php?title=Refont&amp;diff=34018</id>
		<title>Refont</title>
		<link rel="alternate" type="text/html" href="https://wiki.thedarkmod.com/index.php?title=Refont&amp;diff=34018"/>
		<updated>2025-07-28T20:03:08Z</updated>

		<summary type="html">&lt;p&gt;Geep: /* Downloads */ release 2.6. Link contents refreshed&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;By Geep, 2024, and similar to the article about Q3Font.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Introduced in 2024, the &amp;quot;refont&amp;quot; command-line utility allows inspection and alteration of [[Font Metrics &amp;amp; DAT File Format | font metrics]].&lt;br /&gt;
It is designed to be an easier-to-use version of the inspection/alteration functionalities of [[Q3Font]].&lt;br /&gt;
It also provides a font analysis feature.&lt;br /&gt;
&lt;br /&gt;
== Comparison with Font Patcher ==&lt;br /&gt;
&lt;br /&gt;
Refont can be seen as complementary to [[Font Patcher]]. The latter has additional features that may be better if planning a wholesale rearrangement or expansion of characters within a bitmap, particularly for a new font immediately after conversion from a TTF font. But refont is easier to use in later years, and  Font Patcher requires installation of Perl, while refont.exe is more drop and go.&lt;br /&gt;
&lt;br /&gt;
== Comparison with Q3Font ==&lt;br /&gt;
&lt;br /&gt;
For metric alteration, q3font has a native &amp;quot;*.fnt&amp;quot; human-readable format, and supports DAT &amp;lt;==&amp;gt; FNT conversions. For compatibility, so does refont.&lt;br /&gt;
&lt;br /&gt;
=== Advantages of Q3Font ===&lt;br /&gt;
&lt;br /&gt;
* This has been an important traditional tool for Doom3/TDM font manipulation.&lt;br /&gt;
* In addition to production/consumption of FNT, it -&lt;br /&gt;
** Allows creation of DAT &amp;amp; TGA files from a TrueType font (although for this purpose, [[ExportFontToDoom3]] has been preferred in practice).&lt;br /&gt;
** Can write (but not read) an alternative &amp;quot;compact report&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
=== Advantages of Refont ===&lt;br /&gt;
&lt;br /&gt;
* It&#039;s open-source, so further C++ development is possible.&lt;br /&gt;
* It has its own native human-readable format, &amp;quot;*.ref&amp;quot;, similar to .fnt but better.&lt;br /&gt;
* The REF format can be read by [[datBounds]] to generate bitmap boundary &amp;amp; metrics visualizations.&lt;br /&gt;
&lt;br /&gt;
The better features of REF are:&lt;br /&gt;
&lt;br /&gt;
* Codepoints are enumerated in not just decimal, but also hex.&lt;br /&gt;
* Coordinates of the overall image box within its bitmap are expressed in pixel units, rather than [0...1] fractional floating point. So the user is spared having to manually do this tedious and error-prone calculation.&lt;br /&gt;
* This overcomes a drawback of FNT, that expresses the coordinates with only 6 digits after the decimal point, not quite enough to avoid minor mis-precisions.&lt;br /&gt;
* if optionally provided, a separate, read-only annotation file will automatically decorate the .ref file with helpful information as the file is generated. This is explained below.&lt;br /&gt;
&lt;br /&gt;
Because the code is open-source, there&#039;s better clarity about -&lt;br /&gt;
* how parsing and calculations are done.&lt;br /&gt;
* what warnings are emitted.&lt;br /&gt;
&lt;br /&gt;
Also, using &amp;quot;-stats&amp;quot;, refont can write (but not read) an analysis of a DAT file, particularly looking for problematic/unimplemented Western-language characters.&lt;br /&gt;
&lt;br /&gt;
== For Inspection &amp;amp; Correction of DAT files ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;To Get the Data in Readable, Editable Form&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
For viewing and altering in a text editor, two formats are provided. Both list every codepoint, in order from 0 to 255, as a block of data. Within each block, every item gets its own line.&lt;br /&gt;
&lt;br /&gt;
=== As a FNT File ===&lt;br /&gt;
&lt;br /&gt;
To create a q3font-compatable &amp;quot;&amp;lt;dat-name&amp;gt;.fnt&amp;quot; file:&lt;br /&gt;
&lt;br /&gt;
 refont -decompile &amp;lt;path to given .dat file&amp;gt; -fnt&lt;br /&gt;
&lt;br /&gt;
where the path can be a full path, a relative path (e.g., starting with &amp;quot;./&amp;quot; or &amp;quot;../&amp;quot;), or just the file name in the current working directory. The resulting .fnt file will appear in the same directory. It have the same name as the .dat file, except for the extension. As a convenience to keep track of versions, it is not required that the file name be in the standard fontImage_nn.dat form.&lt;br /&gt;
&lt;br /&gt;
Example code block for the letter A:&lt;br /&gt;
 	...&lt;br /&gt;
 	char 65&lt;br /&gt;
 	{&lt;br /&gt;
 		height 18&lt;br /&gt;
 		top 18&lt;br /&gt;
 		bottom 0&lt;br /&gt;
 		pitch 3&lt;br /&gt;
 		xSkip 18&lt;br /&gt;
 		imageWidth 20&lt;br /&gt;
 		imageHeight 18&lt;br /&gt;
 		s 0.769531&lt;br /&gt;
 		t 0.250000&lt;br /&gt;
 		s2 0.847656&lt;br /&gt;
 		t2 0.320313&lt;br /&gt;
 		glyph 0&lt;br /&gt;
 		shaderName fonts/stone_0_24.tga&lt;br /&gt;
 	}&lt;br /&gt;
  	...&lt;br /&gt;
&lt;br /&gt;
Note that Q3Font FNT expresses the s, t, s2, and t2 coordinates with only 6 digits after the decimal point, causing minor low-precision rounding during DAT --&amp;gt; FNT --&amp;gt; DAT roundtrips. For compatibility, Refont FNT does likewise.&lt;br /&gt;
&lt;br /&gt;
=== As a REF File ===&lt;br /&gt;
&#039;&#039;Starting with Refont v2.5, a mixture of 256x256 and 512x512 bitmap shaders, encountered with Carleton and Mason family fonts, can be handled. See further below.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
To create a refont-specific &amp;quot;&amp;lt;dat-name&amp;gt;.ref&amp;quot; file:&lt;br /&gt;
&lt;br /&gt;
 refont -decompile &amp;lt;path to given .dat file&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The same path and naming conventions as for .fnt generation discussed above apply here.&lt;br /&gt;
&lt;br /&gt;
Example code block for the letter A when no supplemental annotation file is present (nor any per-line comments, e.g., with warnings):&lt;br /&gt;
&lt;br /&gt;
 	...&lt;br /&gt;
 	char 65 &amp;lt;b&amp;gt;(0x41)&amp;lt;/b&amp;gt;&lt;br /&gt;
 	{&lt;br /&gt;
 		height 18&lt;br /&gt;
 		top 18&lt;br /&gt;
 		bottom 0&lt;br /&gt;
 		pitch 3&lt;br /&gt;
 		xSkip 18&lt;br /&gt;
 		imageWidth 20&lt;br /&gt;
 		imageHeight 18&lt;br /&gt;
 		&amp;lt;b&amp;gt;coord_s 197&lt;br /&gt;
 		coord_t 64&lt;br /&gt;
 		coord_s2 217&lt;br /&gt;
 		coord_t2 82&amp;lt;/b&amp;gt;&lt;br /&gt;
 		glyph 0&lt;br /&gt;
 		shaderName fonts/stone_0_24.tga&lt;br /&gt;
 	}&lt;br /&gt;
 	...&lt;br /&gt;
&lt;br /&gt;
Items bolded differ from FNT format. The starting line expresses the value in hex. And rather than s, t, s2, t2 in fractional [0...1] floating point, the &amp;quot;coord_...&amp;quot; values are expressed (and editable) as integer coordinates of the bitmap, with a range reflecting bitmap size. The default TDM bitmap size is 256x256, but a few fonts use 512x512 and require special treatment discussed further below.&lt;br /&gt;
&lt;br /&gt;
== When Editing ==&lt;br /&gt;
Refont has a minimal parser. To keep it happy, preserve the file&#039;s line structure. In particular:&lt;br /&gt;
* every REF and FNT file has the same number of lines. &#039;&#039;(Exception: REF may have additional starting lines to flag 512x512 bitmaps, discussed below. Generally, you won&#039;t edit these.)&#039;&#039;&lt;br /&gt;
* all keywords within a block must be present, and in a particular order.&lt;br /&gt;
* each block must have exactly the same number of lines (except for the special one at the end).&lt;br /&gt;
&lt;br /&gt;
The meaning of the font metrics are explained in [[Font_Metrics_%26_DAT_File_Format]]. The [[Q3Font]] article has an example of simple metric editing that is also pertinent to refont.&lt;br /&gt;
&lt;br /&gt;
== To Move Changed FNT or REF Data Back to a DAT ==&lt;br /&gt;
&lt;br /&gt;
 refont -compile &amp;lt;path to given .fnt or .ref file&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This reverses the -decompile process, to create a .dat file whose name is derived from the .fnt or .ref file. Importantly, this decompile/compile cycle leaves .tga/.dds files untouched.&lt;br /&gt;
&lt;br /&gt;
== The Annotation File ==&lt;br /&gt;
When told to generate a REF file (but not FNT), refont.exe also looks for a file called &amp;quot;refont_char_annotations.txt&amp;quot;, in the same folder as refont.exe.  That file should have exactly 256 data lines in it, one for each of the codepoints, in order. As the REF is generated, the line that starts a codepoint&#039;s data block gets the corresponding annotation line appended  to it. Having the annotations come from an external file, instead of hard-coded into refont, allows required flexibility as to what information is presented. It even potentially allows refont to be used with other idTech3/4 games that don&#039;t necessarily used the TDM-specific codepoints. Also, the annotation files contain helpful specific comments (as lines that start with &amp;quot;;&amp;quot;).&lt;br /&gt;
&lt;br /&gt;
Each annotation:&lt;br /&gt;
* indicates what character symbol is &#039;&#039;expected&#039;&#039;; it is oblivious as to what character if any is actually within the bounding box described by the DAT data.&lt;br /&gt;
* lives only in a REF file, and is not retained when converted to a DAT file. This also true for any manual supplementary annotations you might make.&lt;br /&gt;
&lt;br /&gt;
This is clearer with examples. In &#039;Downloads&#039; below are 4 different versions of &amp;quot;refont_char_annotations[...].txt&amp;quot;. Three of these, specific to TDM&#039;s custom &#039;english&#039; (i.e., composite European) codepage, are discussed here. To deploy, edit the filename of one of them to remove the square bracket text.&lt;br /&gt;
&lt;br /&gt;
=== English with Symbol Only ===&lt;br /&gt;
&lt;br /&gt;
This simple format is best for most purposes. The file entry for letter &#039;A&#039; is just:&lt;br /&gt;
&lt;br /&gt;
 A&lt;br /&gt;
&lt;br /&gt;
Then the block in a generated REF file would have that string appended, but with &amp;quot; // &amp;quot; inserted.&lt;br /&gt;
 	...&lt;br /&gt;
 	char 65 (0x41) // A&lt;br /&gt;
 	{&lt;br /&gt;
 		height 18&lt;br /&gt;
 		top 18&lt;br /&gt;
 		bottom 0&lt;br /&gt;
 		pitch 3&lt;br /&gt;
 		xSkip 18&lt;br /&gt;
 		imageWidth 20&lt;br /&gt;
 		imageHeight 18&lt;br /&gt;
 		coord_s 197&lt;br /&gt;
 		coord_t 64&lt;br /&gt;
 		coord_s2 217&lt;br /&gt;
 		coord_t2 82&lt;br /&gt;
 		glyph 0&lt;br /&gt;
 		shaderName fonts/stone_0_24.tga&lt;br /&gt;
 	}&lt;br /&gt;
 	...&lt;br /&gt;
&lt;br /&gt;
=== English with Unicode-16 Codes and Names ===&lt;br /&gt;
&lt;br /&gt;
This supplies the Unicode Consortium&#039;s official 16-bit codepoints (where U+NNNN = 0xNNNN) and their names, in the formal all-caps convention.&lt;br /&gt;
&lt;br /&gt;
The file entry for letter &#039;A&#039; is:&lt;br /&gt;
&lt;br /&gt;
 U+0041 LATIN CAPITAL LETTER A&lt;br /&gt;
&lt;br /&gt;
Then the first line of the corresponding block in a generated REF file would show:&lt;br /&gt;
 	...&lt;br /&gt;
 	char 65 (0x41) // U+0041 LATIN CAPITAL LETTER A&lt;br /&gt;
 	...&lt;br /&gt;
Here&#039;s another example from that REF:&lt;br /&gt;
 	...&lt;br /&gt;
 	char 129 (0x81) // U+015A LATIN CAPITAL LETTER S WITH ACUTE&lt;br /&gt;
 	...&lt;br /&gt;
For control or TDM undefined characters, this annotation file assumes a hollow box glyph is the appropriate mapping:&lt;br /&gt;
 	...&lt;br /&gt;
 	char 0 (0x00) // U+24A1 WHITE SQUARE&lt;br /&gt;
 	...&lt;br /&gt;
But there are other choices, so edit the annotation file as you see fit.&lt;br /&gt;
=== English with 8859-x Source ===&lt;br /&gt;
&lt;br /&gt;
This verbose format may be useful during font analysis. For letters that are in their expected locations as defined by ASCII or ISO 8859-1 (Latin-1) or Windows-1252 (&amp;quot;Western Europe&amp;quot;), the annotation is fairly minimal. Thus, letter &#039;A&#039; has this:&lt;br /&gt;
&lt;br /&gt;
 0x41 is A&lt;br /&gt;
&lt;br /&gt;
(TIP: If authoring your own annotation file, consider including a codepoint number on each line, like &amp;quot;0x41&amp;quot; here, to make the process easier.)&lt;br /&gt;
&lt;br /&gt;
Then the first line of the corresponding block in a generated REF file would show:&lt;br /&gt;
 	...&lt;br /&gt;
 	char 65 (0x41) // 0x41 is A&lt;br /&gt;
 	...&lt;br /&gt;
Here are a few more interesting examples from that REF, with more expansive annotations:&lt;br /&gt;
 	...&lt;br /&gt;
 	char 5 (0x05) // 0x05 is a control character, unusable in TDM&lt;br /&gt;
 	...&lt;br /&gt;
 	char 166 (0xa6) // 0xA6 is Š (not ISO 8859-1 ¦) (from A9 in ISO 8859-2) (TDM only)&lt;br /&gt;
 	...&lt;br /&gt;
&lt;br /&gt;
== Revising or Making Your Own Annotations File ==&lt;br /&gt;
If creating your own refont_char_annotations.txt file, note that encoding upper-range characters in UTF-8 will be more universal than using Windows region-specific codepages. To enter a UTF-8 character using its four digit hex Unicode (say, in a range of interest 0x0080-0x00FF):&lt;br /&gt;
* Under Windows, type the four hex digits followed by Alt-X.&lt;br /&gt;
* Under Linux, hold down Ctrl+Shift, type U followed by the 4 digits; release Ctrl+Shift.&lt;br /&gt;
&lt;br /&gt;
When refont reads refont_char_annotations.txt, any line that starts with &amp;quot;;&amp;quot; will be ignored. The latter is so that you can put comments into the file, that will not propagate to the generated REF file. TIP: If such commenting is unwanted, start the line with &amp;lt;space&amp;gt; before &amp;quot;;&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Other than that, be sure to have exactly 256 lines of annotations (though refont will check and issue a warning if not). A line can be empty, i.e., have only the linebreak.&lt;br /&gt;
&lt;br /&gt;
When generating a REF file, refont will automatically add &amp;quot; // &amp;quot; before each non-empty annotation, so don&#039;t include that.&lt;br /&gt;
&lt;br /&gt;
== Adding Your Own Annotations to a REF File ==&lt;br /&gt;
Beyond the refont_char_annotation.txt content, you can add certain commentary to the REF file without it affecting its ability to convert to a DAT file. Here are the rules:&lt;br /&gt;
* Don&#039;t add or subtract lines, or comment out non-blank lines&lt;br /&gt;
* Feel free to append a comment to the end of a line, by beginning the comment with &amp;quot; //&amp;quot;.&lt;br /&gt;
* Likewise, on a line starting with &amp;quot;char&amp;quot; that had an annotation automatically added, you can revise the annotation as you see fit.&lt;br /&gt;
&lt;br /&gt;
Example with revision in bold:&lt;br /&gt;
 	...&lt;br /&gt;
 	char 65 (0x41) // &#039;&#039;&#039;Capital A was slightly clipped. Decremented s, s2 by 1. Looks OK now.&#039;&#039;&#039;&lt;br /&gt;
 	{&lt;br /&gt;
 		height 18&lt;br /&gt;
 		top 18&lt;br /&gt;
 		bottom 0&lt;br /&gt;
 		pitch 3&lt;br /&gt;
 		xSkip 18&lt;br /&gt;
 		imageWidth 20&lt;br /&gt;
 		imageHeight 18&lt;br /&gt;
 		coord_s 196 &#039;&#039;&#039;// WAS: 197&#039;&#039;&#039;&lt;br /&gt;
 		coord_t 64&lt;br /&gt;
 		coord_s2 216 &#039;&#039;&#039;// WAS: 217&#039;&#039;&#039;&lt;br /&gt;
 		coord_t2 82&lt;br /&gt;
 		glyph 0&lt;br /&gt;
 		shaderName fonts/stone_0_24.tga&lt;br /&gt;
  	}&lt;br /&gt;
 	...&lt;br /&gt;
&lt;br /&gt;
In this way, you can markup a REF file as a record of work to do, work in progress, or work completed.&lt;br /&gt;
&lt;br /&gt;
==Errors, Warnings, and Auto-Corrections==&lt;br /&gt;
&#039;&#039;This covers the major overhaul of Refont v 2.1, and its added options -no_warn_comments and -scaling_ok.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
During the compile or decompile, errors and warnings may be generated in the console. Fatal errors are largely due to: &lt;br /&gt;
* file I/O problems;&lt;br /&gt;
* deviations from the strict DAT, REF, and FNT formats.&lt;br /&gt;
&lt;br /&gt;
Warnings, which are not fatal, are largely due to anomolous numeric values. The TDM engine can tolerant some of these, so they don&#039;t necessarily need fixing. &lt;br /&gt;
&lt;br /&gt;
===Fatal Errors when Parsing REF or FNT as Input===&lt;br /&gt;
A fatal error, due to divergence from the expected format while parsing, stops the program. While potentially due to many causes (e.g., adding or deleting lines), errors will be reported - with line number - as failures of:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Variable Name Checks.&#039;&#039; The parser expects every variable name in a particular order. A mismatch happened.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Integer Checks.&#039;&#039; Integer value was unparsable, or out of range for integer type. Checked for per-character variables height, top, bottom, pitch, xSkip, imageWidth, imageHeight, and glyph. Plus REF’s coord_s, coord_t, coord_s2, and coord_ t2.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Float Checks.&#039;&#039; Floating point value was unparsable, or out of range for float type. Checked for glyphScale, and FNT’s per-character variables s, t, s2, t2.&lt;br /&gt;
&lt;br /&gt;
===Post-Read MAJOR Warnings about REF, FNT, and DAT Input Values===&lt;br /&gt;
After parsing, the input process concludes with a separate loop of non-fatal warning analysis. Warnings during input, broadly categorized as major or minor, report to the console, but don’t do any value corrections (which is instead left to the subsequent file-write stage).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;For FNT’s and DAT’s s, t, s2, t2&#039;&#039;&lt;br /&gt;
* Inexact Integer. The given bounding box value, expected in the range 0-1, when multiplied by 256.0 should be exactly an integer. If not, the divergence is likely due to miscalculation.  (Actually, a divergence from an integer of under +/- 0.001 is tolerated by Refont and considered a minor warning, discussed below.) &lt;br /&gt;
* Float Out of Range 0.0 - 1.0. Or equivalently, post-multiplication, 0.0 - 256.0. (See the discussion of the edge cases under minor warnings below.)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;For Other Metrics of DAT, FNT, and REF&#039;&#039;&lt;br /&gt;
* Integer Out of Range 0-256. For height, top, bottom, pitch, xSkip, imageWidth, imageHeight, and REF’s coord_s, coord_t, coord_s2, and coord_t2.&lt;br /&gt;
* Integer Non Zero. For glyph.&lt;br /&gt;
* Float Less Than Zero. For glyphScale (which is independent of a particular character).&lt;br /&gt;
* Inconsistent Metrics. For a given character, this compares two metrics and looks for inconsistencies. We’ll state this here in REF terms, e.g., using “coord_s” rather than “ROUND_TO_INT(s * 256.0f)”:&lt;br /&gt;
** imageHeight == height?&lt;br /&gt;
** imageWidth == coord_s2 - coord_s?&lt;br /&gt;
** imageHeight == coord_t2 - coord_t?&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Suppressing Warnings Due to Scaling.&#039;&#039; The last two &amp;quot;Inconsistent Metrics&amp;quot; criteria will not be true if there is per-character scaling. (Only TDM’s mason and mason-glow use per-character scaling, specifically for all upper-case characters.) In such a case, to avoid generating a lot of useless major warnings, use the refont option &amp;quot;-scaling_ok&amp;quot;.&lt;br /&gt;
===Post-Read MINOR Warnings for FNT’s and DAT’s s, t, s2, t2===&lt;br /&gt;
&#039;&#039;Low Precision.&#039;&#039; This value, when multiplied by 256.0, should be exactly an integer. However, some generation or revision procedure (e.g., Q3Font’s DAT  FNT  DAT) may have not used sufficient precision to ensure this. An offset from an integer value of less than +/- 0.001 is considered a minor problem; otherwise, major as above.&lt;br /&gt;
&lt;br /&gt;
This problem, when it occurs with a file, typically happens a lot. Consequently, it is not reported in an itemized way, but instead, the console will show total counts of affected characters and values.&lt;br /&gt;
&lt;br /&gt;
Edge cases: a value of {s, s2, t, or t2} * 256.0 that is negative but closer to zero than -0.001000 is considered this type of minor problem (and is not considered out of range, which would be major). Likewise, if that value is greater than 256.000000, but less than 256.001000&lt;br /&gt;
===Automatic Corrections during Output to a REF File===&lt;br /&gt;
Certain problems, first detected during DAT input, are further addressed at write time. Because these problems were already reported to the console during the DAT read, nothing additional is written to console. Instead, there may be reporting within the REF file itself.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Automatic Corrections.&#039;&#039; When writing a REF file, the integer values of coord_s, coord_t, coord_s2, and coord_t2 are calculated from DAT floats s, t, s2, and t2 respectively. A calculated coord_... value, if not already resulting in an integer, is automatically forced to the nearest integer. This is so whether it was earlier reported to the console as a Major or Minor Warning. (Before refont v 2.1, the REF might assign an unrounded decimal value; no longer true.)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Warnings Not Automatically Corrected.&#039;&#039; Automatic fixing of other warnings is unwise and not offered. Why? Because the fix is not obvious or complex, and sometimes, the corresponding character glyph in the bitmap needs adjustment. This pertains to Major Warnings about:&lt;br /&gt;
* Integer values outside their expected range (e.g., 0-256), including post-rounding coord_... values.&lt;br /&gt;
* Inconsistent Metrics&lt;br /&gt;
===Generated Within-REF Comments during Output===&lt;br /&gt;
For most causes of a Major Warning during DAT read, during subsequent writing of the REF file, a similar comment is also generated within the REF, on the same line as the parameter assignment. For example:&lt;br /&gt;
 char 95 (0x5f) // _&lt;br /&gt;
 {&lt;br /&gt;
    ...&lt;br /&gt;
    top -6 // WARNING: Not in range 0-256. Does bitmap or other metrics need adjusting?&lt;br /&gt;
    ...&lt;br /&gt;
 }&lt;br /&gt;
 ...&lt;br /&gt;
 char 140 (0x8c) // Ń&lt;br /&gt;
 {&lt;br /&gt;
    ...&lt;br /&gt;
    coord_t -10 // WARNING: Underlying DAT value -0.03906250, * 256.0 gave -10.000000000, not in range 0-256 once rounded. Does bitmap or other metrics need adjusting?&lt;br /&gt;
    ...&lt;br /&gt;
 }&lt;br /&gt;
&#039;&#039;Suppressing Comment Generation.&#039;&#039; Use the refont option “-no_warn_comments”. &#039;&#039;New to v 2.1.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
TIP: When editing a REF file with comments, you can keep them, change them, or delete them as you prefer. They have no impact on subsequent compiles to DAT.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Coverage of Generated Within-REF Comments.&#039;&#039; A calculated value of coord_s, coord_t, coord_s2, or coord_t2 would have been flagged as a “Major Warning” during read if:&lt;br /&gt;
* the discrepancy from being an integer was non-trivial (+/- 0.001 or more), or&lt;br /&gt;
* the calculated and rounded integer is outside the range given by bitmap size, e.g., 0-256.&lt;br /&gt;
&lt;br /&gt;
For these, a comment is generated. Other causes are:&lt;br /&gt;
* Integer Out of Range 0-256 &#039;&#039;(or 0-512 as applicable)&#039;&#039;. For height, top, bottom, pitch, xSkip, imageWidth, imageHeight.&lt;br /&gt;
* Integer Non Zero. For glyph.&lt;br /&gt;
* Float Less Than Zero. For glyphScale (which is independent of a particular character).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Major Warnings that Don’t Cause Within-REF Comments.&#039;&#039; Currently, this is limited to “Inconsistent Metrics”, which would probably require tagging on multiple lines.&lt;br /&gt;
&lt;br /&gt;
== Special Handling of Fonts with 512x512 Bitmaps ==&lt;br /&gt;
Some DAT files reference bitmap shaders where some or all are of size 512x512, instead of the default 256x256. Refont v2.5+ can support this (replacing an insufficient first attempt in v2.4).&lt;br /&gt;
&lt;br /&gt;
Font developers went to double-sized bitmaps to:&lt;br /&gt;
* in the case of Carleton, allow freehand drawing of missing European characters, which could be drawn more easily if twice standard size.&lt;br /&gt;
* in the case of Mason, have larger ASCII alphanumeric glyphs that would render with crisper edges.&lt;br /&gt;
&lt;br /&gt;
In either case, the font characters when rendered in, say, the game main menu will be the same size as if from 256x256. This is because the imageWidth and imageHeight metrics are not doubled.&lt;br /&gt;
In effect, a scaling by half is requested for all characters in the DAT file and applied by the engine.&lt;br /&gt;
&lt;br /&gt;
=== When generating a REF file from a DAT file ===&lt;br /&gt;
&lt;br /&gt;
 refont -decompile &amp;lt;path to given .dat file&amp;gt; -512_&amp;lt;n&amp;gt;   &#039;&#039;where &amp;lt;n&amp;gt; is a single digit, e.g. &#039;1&#039; in referenced shader name &amp;quot;font/Carleton_1_24.tga&amp;quot; &#039;&#039;&lt;br /&gt;
&lt;br /&gt;
You should use multiple instances of the -512_&amp;lt;n&amp;gt; option, to cover all the 512x512 bitmaps found in the DAT file.&lt;br /&gt;
&lt;br /&gt;
If &#039;&#039;all&#039;&#039; of a given DATs shaders are 512x512, you can use this shorter form:&lt;br /&gt;
&lt;br /&gt;
 refont -decompile &amp;lt;path to given .dat file&amp;gt; -512&lt;br /&gt;
&lt;br /&gt;
Exercising -512... options will mean that in the generated REF file:&lt;br /&gt;
&lt;br /&gt;
* There will be a one or more starting lines like:&lt;br /&gt;
  # bitmap_&amp;lt;n&amp;gt;_size=512 &#039;&#039;(Refont will look for this if doing a subsequent compile to DAT)&#039;&#039;&lt;br /&gt;
* If you specified the short form, it will expand to just the right number of starting lines.&lt;br /&gt;
* Values for coord_s, coord_s2, coord_t, and coord_t2 will have a normal range of 0-512 when appropriate. [COMING SOON: Those values may then be read properly by datBounds.].&lt;br /&gt;
* Any warnings expressed (within the file or within the command-line window) will be in terms of the correct range of values. &lt;br /&gt;
* Warning checks will expect a scaling by half for all characters. That is, while 512... requires scaling down by half, that scaling will not generate a warning (unless it&#039;s not EXACTLY by half), so the -scaling_ok option is not needed just for the exactly-by-half scaling.&lt;br /&gt;
&lt;br /&gt;
=== When generating a DAT file from a REF file ===&lt;br /&gt;
&lt;br /&gt;
During refont -compile, no special command line options are needed. Instead, REF&#039;s starting lines of form &amp;quot;# bitmap_&amp;lt;n&amp;gt;_size=512&amp;quot; are inspected and coord ranges will be interpreted as 0-512 whenever appropriate. &lt;br /&gt;
&lt;br /&gt;
=== Special Handling Recommendations for Carleton and Mason ===&lt;br /&gt;
&#039;&#039;For fonts shipped with TDM 2.12 in tdm_fonts01.pk4. Illustrative command paths are shown; adjust to your working copy.&#039;&#039;&lt;br /&gt;
==== Mason Family ====&lt;br /&gt;
The [[Mason Font]] uses within-DAT per-character scaling, as well as some but not all 512x512 bitmaps. Only 48pt Mason is shipped.&lt;br /&gt;
&lt;br /&gt;
Because, under /dds/fonts/english/mason/, bitmaps masonalternate_0_48.dds to _2_ are 512x512, but _3_ to _5_ are not, use:&lt;br /&gt;
&lt;br /&gt;
 -decompile /fonts/english/mason/fontimage_48.dat -512_0 -512_1 -512_2 -scaling_ok&lt;br /&gt;
&lt;br /&gt;
Because, under /dds/fonts/english/mason_glow/, bitmaps masonalternate_1_48.dds and _2_ are 512x512, but _0_ and _3_ to _5_ are not, use:&lt;br /&gt;
&lt;br /&gt;
 -decompile /fonts/english/mason_glow/fontimage_48.dat -512_1 -512_2 -scaling_ok&lt;br /&gt;
&lt;br /&gt;
Russian versions use the default 256x256. [These possibly benefit from -scaling_ok; didn&#039;t investigate.]&lt;br /&gt;
==== Carleton Family ====&lt;br /&gt;
The 24pt size of carleton has two bitmaps under /dds/fonts/english/carleton/, namely carleton_0_24.dds and _1_, both of size 512x512. So use:&lt;br /&gt;
&lt;br /&gt;
 -decompile /fonts/english/carleton/fontimage_24.dat -512_0 -512_1&lt;br /&gt;
  &#039;&#039;or&#039;&#039;&lt;br /&gt;
 -decompile /fonts/english/carleton/fontimage_24.dat -512&lt;br /&gt;
 &lt;br /&gt;
The 24pt size of carleton_bold has bitmaps with identical content to carleton&#039;s, so use the same options:&lt;br /&gt;
&lt;br /&gt;
 -decompile /fonts/english/carleton_bold/fontimage_24.dat -512_0 -512_1&lt;br /&gt;
  &#039;&#039;or&#039;&#039;&lt;br /&gt;
 -decompile /fonts/english/carleton_bold/fontimage_24.dat -512&lt;br /&gt;
&lt;br /&gt;
Other members of this family use the default 256x256 bitmaps:&lt;br /&gt;
* Sizes 12pt &amp;amp; 48pt&lt;br /&gt;
* carleton_condensed and carleton_glow. (Note: while helpful, it is not required that the base &amp;amp; glow have identical bitmap sizes.)&lt;br /&gt;
* Russian versions&lt;br /&gt;
&lt;br /&gt;
==== These Fonts with Stats ====&lt;br /&gt;
With -stats discussed next, if reading a DAT file, you may use the -512... and scaling_ok options to be most correct, although neglecting to specify them will likely have no significant impact on the analytical results. If reading a REF file, the included &amp;quot;# bitmap_...&amp;quot; lines will take care of that for you.&lt;br /&gt;
&lt;br /&gt;
== For Statistics on Unimplemented or Problematic Font Characters ==&lt;br /&gt;
DAT or (as of v2.3) REF file analysis here is primarily designed to benefit english/european fonts. It will use the optional annotation file if provided. Syntax:&lt;br /&gt;
&lt;br /&gt;
     refont -stats &amp;lt;path to given .dat or .ref file&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Use &amp;quot;-stats&amp;quot; by itself, not combined with &amp;quot;-compile&amp;quot; or &amp;quot;-decompile&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
The resulting analysis report will have the same name and location as the input file, but with a &amp;quot;.txt&amp;quot; suffix.&lt;br /&gt;
The report provides categorized totals and (for problematic characters) itemizations across all 256 character codepoints.&lt;br /&gt;
The counts of problems should be considered minimums, since no inspection of bitmap files (TGA or DDS) is done.&lt;br /&gt;
But a perhaps surprising amount of insight can be gleaned just from DAT/REF file metrics.&lt;br /&gt;
Itemizations include annotations from the &#039;ref_char_annotation&#039; file, if provided.&lt;br /&gt;
&lt;br /&gt;
In the hunt for missing characters, 3 signatures are important:&lt;br /&gt;
&lt;br /&gt;
* Presumed &#039;Hollow Box&#039; = glyph&#039;s &#039;shadername&#039; is &amp;lt;fontname&amp;gt;_0_&amp;lt;size&amp;gt;.dds only, and s &amp;amp; t are zero, but not s2 &amp;amp; t2&lt;br /&gt;
* &#039;&amp;lt;Space&amp;gt;&#039; = same test as &#039;Hollow Box&#039;, but pointed to by char 32 (0x20)&lt;br /&gt;
* &#039;Zero Box&#039; = No glyph box (s, t, s2, t2 all zero)&lt;br /&gt;
&lt;br /&gt;
A given analysis will assume either &#039;Hollow Box&#039; or &#039;&amp;lt;Space&amp;gt;&#039; but not both.&lt;br /&gt;
&lt;br /&gt;
The analysis provides totals and itemizations - grouped into lower (0-127) and upper ranges (128-255) - in several passes: &lt;br /&gt;
&lt;br /&gt;
* Pass 1 - Handling of unprintable/unsupported/missing codepoints, indicated by Hollow Box, Zero Box, or &amp;lt;Space&amp;gt;. Some of these are not a problem, but some are tagged as &amp;quot;Undesirable&amp;quot;.&lt;br /&gt;
* Pass 2 - Bad glyph box (negative s, t, s2, or t2; or s2 &amp;lt;= s, t2 &amp;lt;= t) or good glyph box with dubious metrics (imageHeight &amp;lt;= 0, imageWidth &amp;lt;=0, imageHeight != height). Excludes those already counted as &amp;quot;Undesirable&amp;quot; in Pass 1. &lt;br /&gt;
* Pass 3 - Detection of duplicate glyph boxes (other than Hollow Box, Zero Box, or &amp;lt;Space&amp;gt;). Detected by: glyph&#039;s values for shadername, s, t, s2, &amp;amp; t2 exactly match those of another codepoint. These are grouped into &amp;quot;Dup Sets&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Then, across passes 1-3, a count if given of the minimum &amp;quot;Total Glyphs Needing Work&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Refont version 2.3 adds additional passes:&lt;br /&gt;
&lt;br /&gt;
* Pass 4 - Reports &amp;quot;Overlap Sets&amp;quot; rather than just &amp;quot;Dup Sets&amp;quot;. A set here may include an unaccented &amp;quot;base character&amp;quot; that has been serving as a substitute work-around target for one or more missing accented characters. (What constitutes an &amp;quot;overlap&amp;quot; is idiosyncratic; see the source code for details.)&lt;br /&gt;
* Pass 5 - Same information as Pass 4, but sorted first by shader name (i.e., bitmap). Helpful for organizing bitmap-editing work.&lt;br /&gt;
* Pass 6 - An analysis focusing just on the planned migration of duplicate O/o-circumflex codepoints to G/g-cup glyphs.&lt;br /&gt;
&lt;br /&gt;
== Downloads ==&lt;br /&gt;
Release 2.6 of July 28, 2025:&lt;br /&gt;
* [https://drive.google.com/file/d/1ABf4771Jr1C1hKbLx4xWq8lx8Kn7HdKP/view?usp=sharing refont.exe]&lt;br /&gt;
* [https://drive.google.com/file/d/1-k68eo0CHKZ-sM7JGP05axm49cc5De0T/view?usp=sharing source code: refont.cpp]&lt;br /&gt;
&lt;br /&gt;
===Annotations===&lt;br /&gt;
&#039;&#039;After download, to use any one of these, edit filename to remove &amp;quot;[...]&amp;quot; substring.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Update of June 20, 2024. This reflects a change to the TDM charmap for 2.13, to replace duplicate O/o circumflex characters with G/g breve:&lt;br /&gt;
&lt;br /&gt;
* refont_char_annotations[english with symbol only. With G-breve update].txt [https://drive.google.com/file/d/1rrt-O9DgD7Zn2Hxt7nBtViIlO4kv_gQB/view?usp=sharing here]. Recommended for most purposes with &#039;english&#039; fonts.&lt;br /&gt;
* refont_char_annotations[english with Unicode-16 codes &amp;amp; names. With G-breve update].txt [https://drive.google.com/file/d/1AMxDKQc_DE33gsExiEkGp3x67eb4aGFh/view?usp=sharing here].&lt;br /&gt;
* refont_char_annotations[english with 8859-x source. With G-breve update].txt [https://drive.google.com/file/d/1xoeZ1poTbmkls-gE5PnbbMxdoz5KnMD7/view?usp=sharing].&lt;br /&gt;
* For Russian, see the previous update next.&lt;br /&gt;
&lt;br /&gt;
Update of April 13, 2024:&lt;br /&gt;
&lt;br /&gt;
* refont_char_annotations[english with symbol only].txt [https://drive.google.com/file/d/1ItM-aXps0xQE655HdaJM7Aje5lHewUfC/view?usp=sharing here]. Recommended for most purposes with &#039;english&#039; fonts.&lt;br /&gt;
* refont_char_annotations[english with Unicode-16 codes and names].txt [https://drive.google.com/file/d/1gW7oO_wLqCEPSdm6b05OaTNYHnyuUSA-/view?usp=sharing here].&lt;br /&gt;
* refont_char_annotations[english with 8859-x source].txt [https://drive.google.com/file/d/1ZTcgA4QJYwXzNdqbolYkn0CCEDILD1bX/view?usp=sharing here]. Corrects and supersedes original english file.&lt;br /&gt;
* refont_char_annotations[russian].txt [https://drive.google.com/file/d/10txNXsSCtaTiT2iGT9o3iDxBU7HVYNxi/view?usp=sharing here]. Recommended for &#039;russian&#039; fonts.&lt;br /&gt;
&lt;br /&gt;
== For More ==&lt;br /&gt;
* See the [https://forums.thedarkmod.com/index.php?/topic/22427-analysis-of-212-tdm-fonts/ summary analysis of 2.12 TDM fonts], based on applying &#039;refont -stats ...&#039; to all &#039;english&#039; DAT files.&lt;br /&gt;
&lt;br /&gt;
{{tutorial}} [[Category:Fonts]]&lt;/div&gt;</summary>
		<author><name>Geep</name></author>
	</entry>
	<entry>
		<id>https://wiki.thedarkmod.com/index.php?title=Gen_Lang_Programs&amp;diff=34005</id>
		<title>Gen Lang Programs</title>
		<link rel="alternate" type="text/html" href="https://wiki.thedarkmod.com/index.php?title=Gen_Lang_Programs&amp;diff=34005"/>
		<updated>2025-07-16T20:21:25Z</updated>

		<summary type="html">&lt;p&gt;Geep: Add [Catalan]&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;By Geep, from February 2025&lt;br /&gt;
== Introduction to Gen_lang.pl (&amp;quot;PL&amp;quot;) and Gen_lang_plus (&amp;quot;PLUS&amp;quot;) ==&lt;br /&gt;
This describes two software implementations of command-line programs that essentially do the same thing;&lt;br /&gt;
# The Perl program &amp;quot;gen_lang.pl&amp;quot; (dubbed here PL), created by Tels in the 2010-14 timeframe. This is easily deployed under Linux that has Perl capabilities. Version 17 Is current.&lt;br /&gt;
# The C++ program &amp;quot;gen_lang_plus&amp;quot; (dubbed here PLUS), a re-implementation with minor improvements created by Geep in 2025. This is lightly Windows-specific at this time. (Please volunteer if you want to make it run under Linux.) Version 1.0 is current.&lt;br /&gt;
&lt;br /&gt;
The purpose of both is as follows.&lt;br /&gt;
* Read and write files in child folder &amp;quot;strings&amp;quot;. (Caution: &amp;quot;not strings/fm&amp;quot;, even if you specify the &amp;quot;fm&amp;quot; option.)&lt;br /&gt;
* Read an &amp;quot;all.lang&amp;quot; file, either that associated with the main-menu-system, or with a specific FM under development. This UTF-8 input file has translations of strings for all TDM-supported languages (currently 17). There are individual sections for each target language. Each string is of form&lt;br /&gt;
&lt;br /&gt;
 &amp;quot;#str_&amp;lt;id&amp;gt;&amp;quot; &amp;quot;&amp;lt;string content&amp;gt;&amp;quot; // optional comment.&lt;br /&gt;
* Generate a set of individual &amp;quot;&amp;lt;language&amp;gt;.lang&amp;quot; files, with the appropriate translated strings. Each file is generated in a standard 8-bit encoding (e.g., defined by one of the iso-8859 standards) designated for the target language. If a translator did not provide a given string in the target language, the master English string is automatically substituted.&lt;br /&gt;
* Finally, as requested by command-line options, various analyses can be performed. For example, a set of &amp;quot;missing_&amp;lt;language&amp;gt;.txt&amp;quot; files can be generated, to suggest where translation efforts are still needed.&lt;br /&gt;
This article details both programs, with important differences noted. Running this functionality is intended to be done, infrequently, by the person overseeing translation improvements to all.lang.&lt;br /&gt;
&lt;br /&gt;
For more quick overviews of this process, see&lt;br /&gt;
* the wiki article [[Internationalization]]. This also covers the i18n.pl program, which is beyond the scope here.&lt;br /&gt;
* the preamble of the all.lang file, found in tdm_base01.pk4&#039;s \strings\.&lt;br /&gt;
&lt;br /&gt;
It is helpful to mention what these two programs do &#039;&#039;&#039;not&#039;&#039;&#039; take into account:&lt;br /&gt;
* the &amp;lt;language&amp;gt;.map file that reroutes European codepoints from a standardized encoding to the TDM-specific custom 8-bit encoding discussed in [[I18N_-_Charset]].&lt;br /&gt;
* what UTF8 characters are allowed by that TDM-specific coding (as opposed to the ISO-8859 encoding).&lt;br /&gt;
* the font and fontsize a specific string will use, and what limitations that entails, and what within-DAT glyph-substitutions may be in effect.&lt;br /&gt;
&lt;br /&gt;
== Runtime Environment for PLUS ==&lt;br /&gt;
To function in all aspects, PLUS requires Windows with certain UTF8 capabilities, introduced in later versions of Windows 10. Because the PLUS build is told explicitly to use UTF8, in theory what your &amp;quot;system locale&amp;quot; is set to should not matter. In particular, you are not required you set the system locale to the Windows 11 beta UTF8 codepage. (PLUS was developed on a dev box with the English (US) locale.)&lt;br /&gt;
&lt;br /&gt;
You may run it under the traditional Windows console. However, that will not display UTF8 characters correctly on screen, which is mainly an issue with the -charstats and -charpunts options. Instead, use Windows Terminal (or Powershell with UTF8 encoding). Or pipe the console output to a file (i.e., &amp;quot;&amp;gt; myfile.txt&amp;quot;), that can be viewed as UTF8 with Notepad and other text editors.&lt;br /&gt;
&lt;br /&gt;
== Overview of Command-Line Options ==&lt;br /&gt;
&lt;br /&gt;
===For both PL and PLUS===&lt;br /&gt;
 --csv		Generate CSV file&lt;br /&gt;
 --missing	Generate files with lists of missing strings for each language.&lt;br /&gt;
 --charstats	Generate statistics about foreign characters.&lt;br /&gt;
 --show-ranges	Show occupied string index ranges.&lt;br /&gt;
 --show-holes	Show holes in the string index ranges.&lt;br /&gt;
&lt;br /&gt;
With PLUS, one may use a single &amp;quot;-&amp;quot; before an option, instead of &amp;quot;--&amp;quot;, and/or leave off the &amp;quot;show-&amp;quot; prefix. (Regarding &amp;quot;charstats&amp;quot;, for consistency, since this option outputs to screen, PL should have used the &amp;quot;show-&amp;quot; prefix, but didn&#039;t. PLUS does, optionally.)&lt;br /&gt;
&lt;br /&gt;
===For PLUS Only===&lt;br /&gt;
 -old-preamble					Keep &amp;lt;language&amp;gt;.lang preamble just like that of gen_lang.pl. Don&#039;t include file generation date or PLUS version number.&lt;br /&gt;
 -charpunts &#039;&#039;or&#039;&#039; --show-charpunts			Reports lines in which &amp;quot;?&amp;quot; was substituted for any character.&lt;br /&gt;
 -charpunts-extra &#039;&#039;or&#039;&#039; --show-charpunts-extra	Like charpunt, but includes &amp;quot;// comment&amp;quot; characters.&lt;br /&gt;
 -fm						Program used for an fm, not main menu; affects what&#039;s considered a valid numeric #str_&amp;lt;id&amp;gt; range.&lt;br /&gt;
 -cvs-unsorted					Like -csv, but row order stays like that of all.lang [English].&lt;br /&gt;
&lt;br /&gt;
== Charpunts and Charpunts-Extra Options [PLUS Only] ==&lt;br /&gt;
During generation of a particular &amp;lt;language&amp;gt;.lang file, if a valid data line contains 1 or more characters that can&#039;t be rendered in the target encoding, then a 3-line report is issued to console. Specifically:&lt;br /&gt;
 -charpunts		Considers characters within the line&#039;s content (excluding comments).&lt;br /&gt;
 -charpunts-extra	Same as charpunts, but also considers characters within the line&#039;s &amp;quot;// comment&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
When entering these options, you may use the &amp;quot;show-&amp;quot; prefix if you&#039;d like, with 1 or 2 leading dashes.&lt;br /&gt;
&lt;br /&gt;
By &amp;quot;// comment&amp;quot;, is meant the optional comment that starts with &amp;quot;//&amp;quot; at the end of a #str_&amp;lt;id&amp;gt; line (but still excluding any other comment forms; these latter won&#039;t be present in &amp;lt;language&amp;gt;.lang).&lt;br /&gt;
&lt;br /&gt;
Note – it is assumed that #str_&amp;lt;id&amp;gt; contains only 0-9, A-Z, a-z, or underline... so is not inspected by these options.&lt;br /&gt;
&lt;br /&gt;
An example report for [Hungarian] encoded as iso-8859-2:&lt;br /&gt;
&lt;br /&gt;
 Output line 177...&lt;br /&gt;
 from:   &amp;quot;#str_02208&amp;quot;    &amp;quot;Küldetési idõ&amp;quot;&lt;br /&gt;
   to:   &amp;quot;#str_02208&amp;quot;    &amp;quot;K�ldet�si id?&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Important: in this example, only õ, the last character in the &amp;quot;from:&amp;quot; line, could not be encoded in iso-8859-2 and so is replaced by &amp;quot;?&amp;quot; in the &amp;quot;to:&amp;quot; line. The &amp;quot;to:&amp;quot; line characters indicated by � were successfully encoded, but now are not valid UTF8, so can no longer be shown as such. That is, the &amp;quot;to:&amp;quot; line has the identical string placed into the hungarian.lang file.&lt;br /&gt;
&lt;br /&gt;
Here is an -charpunts-extra example where only the comment has characters that don&#039;t encode, in this case into iso-8859-1 for [English]:&lt;br /&gt;
&lt;br /&gt;
 Output line 396...&lt;br /&gt;
 from:   &amp;quot;#str_02482&amp;quot;    &amp;quot;Srpski&amp;quot;// Serbian (Српски - same exception as Russian)&lt;br /&gt;
   to:   &amp;quot;#str_02482&amp;quot;    &amp;quot;Srpski&amp;quot;// Serbian (?????? - same exception as Russian)&lt;br /&gt;
&lt;br /&gt;
TIP: If the results of this option is too voluminous, recall that output from a console app can be directed into a file using &amp;quot;... &amp;gt; filename.txt&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
These reports give the output line number within &amp;lt;language&amp;gt;.lang, rather than the input line in all.lang, because of difficulties getting the latter value to be correct in the face of, for instance, multiline comments. (Any line numbers that PL reports are usually off.)&lt;br /&gt;
&lt;br /&gt;
== Old Preamble Option [PLUS Only] ==&lt;br /&gt;
Each &amp;lt;language&amp;gt;.lang file gets a standard preamble. For PL, the first line looks like this example:&lt;br /&gt;
 // String table - english (iso-8859-1)&lt;br /&gt;
&lt;br /&gt;
For PLUS, the first line by default also has UTC time and program version, like this example:&lt;br /&gt;
 // String table - english (iso-8859-1) - created on 2025-02-15T04:00:21Z  with gen_lang_plus v. 1.0&lt;br /&gt;
&lt;br /&gt;
But you can ask PLUS to use PL&#039;s format, with the &amp;quot;-old-preamble&amp;quot; option. Why? To simplify comparing a particular &amp;lt;language&amp;gt;.lang file generated with both programs.&lt;br /&gt;
Since this is more a debugging option, it&#039;s not listed in the help, just here.&lt;br /&gt;
&lt;br /&gt;
== Missing Option ==&lt;br /&gt;
This option alerts translators to untranslated strings. For each language (other than English, the master) it generates a file named &amp;quot;missing_&amp;lt;language&amp;gt;.txt, with lists of missing UTF8 strings. Each line has the quoted #str_&amp;lt;id&amp;gt; and quoted content, but not comments.&lt;br /&gt;
&lt;br /&gt;
===What&#039;s Considered &amp;quot;Missing&amp;quot;?===&lt;br /&gt;
This categorization was established in PL and now mimicked in PLUS.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;If for a given master [English] #str_&amp;lt;id&amp;gt;, there&#039;s no matching #str_&amp;lt;id&amp;gt; in the target language.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
It&#039;s &amp;quot;missing&amp;quot;, unless there&#039;s a (hard-coded) exception:&lt;br /&gt;
&lt;br /&gt;
* The master string&#039;s content is in the &amp;quot;master_non_translatable&amp;quot; group, namely:&lt;br /&gt;
** An empty or whitespaces-only string.&lt;br /&gt;
** &amp;quot;TDM&amp;quot; or &amp;quot;The Dark Mod&amp;quot;.&lt;br /&gt;
** A prefix designating a function key (&amp;quot;F&amp;quot;) or port (&amp;quot;AUX&amp;quot; or &amp;quot;JOY&amp;quot;) followed by 1 or 2 digits.&lt;br /&gt;
** A special numeric format like &amp;quot;320x400;640x480&amp;quot; or &amp;quot;123;345&amp;quot; or &amp;quot;1x;2x&amp;quot;.&lt;br /&gt;
* The master string&#039;s content is a font selector, i.e., beginning with &amp;quot;fonts/&amp;quot;.&lt;br /&gt;
* The #str_&amp;lt;id&amp;gt; has a numeric &amp;lt;id&amp;gt; within a &amp;quot;master_id_non_translatable&amp;quot; range. Just one range, 02460 – 02490, is so reserved, for language names.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;If the #str_&amp;lt;id&amp;gt; in English and the target language have identical content (not counting comments)&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
It&#039;s &amp;quot;missing&amp;quot;, unless there&#039;s an exception:&lt;br /&gt;
&lt;br /&gt;
* The target line has a &amp;quot;//&amp;quot; comment indicating &amp;quot;stays the same&amp;quot;&lt;br /&gt;
* The &amp;quot;master_non_translatable&amp;quot;, font selector, or &amp;quot;master_id_non_translatable&amp;quot; exclusions apply.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Otherwise, it&#039;s not missing.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
That covers this additional case, where for the matching #str_&amp;lt;id&amp;gt; in English and the target language, there&#039;s different content (ignoring comments). Surprisingly, this is considered &amp;quot;not missing&amp;quot; even when the English content exists and the target language content is an empty string.&lt;br /&gt;
&lt;br /&gt;
Rarely, the master content can be empty, but the translated string may or may not be. An example is #str_02313, representing an optional second line needed for some languages.&lt;br /&gt;
&lt;br /&gt;
== CSV Options ==&lt;br /&gt;
These options read the contents of all.lang and rearrange them for export as a comma-separated-values &amp;quot;tdm_all_lang.csv&amp;quot; UTF8 file in the &amp;quot;strings&amp;quot; folder. The options have different generated row order:&lt;br /&gt;
&lt;br /&gt;
 -csv		Rows sorted by #str_&amp;lt;id&amp;gt;; seriously buggy ordering in PL, works in PLUS.&lt;br /&gt;
 -csv-unsorted	PLUS only. Keeps row order of [English] in all.lang&lt;br /&gt;
&lt;br /&gt;
The exported CSV file can then be imported into other tools for translators, e.g., Excel spreadsheets. Be aware as you process this data further: maintaining the UTF8 (or other Unicode) encoding ensures character integrity.&lt;br /&gt;
&lt;br /&gt;
=== Generated CVS File Format ===&lt;br /&gt;
The first line of the file has the field (aka column) headers, with languages in alphabetic order:&lt;br /&gt;
&lt;br /&gt;
 ID,catalan,czech,danish,dutch,english,french,german,hungarian,italian,polish,portuguese,romanian,russian,slovak,spanish,swedish,turkish,comment&lt;br /&gt;
There are 19 comma-separated fields here, so the results is very wide. (Recall in a spreadsheet, you can hide columns not of current interest.)&lt;br /&gt;
&lt;br /&gt;
Broadly, the .csv format comes in different variants. Traditionally, as here, comma is the separator. If a field contains a comma, the field overall is wrapped in double quotes. PL also so wraps if there&#039;s a contained double-quote, colon, or semi-colon. PLUS mimics that policy. PL unfortunately only considers the language fields for wrapping. PLUS goes a bit further, to consider the &amp;quot;comment&amp;quot; field.&lt;br /&gt;
&lt;br /&gt;
So, after the header each subsequent line has fields separated by commas, where:&lt;br /&gt;
&lt;br /&gt;
* The first field, &amp;quot;ID&amp;quot;, has #str_&amp;lt;id&amp;gt;. Unlike in all.lang, there are no enclosing double quotes.&lt;br /&gt;
* Remaining fields have translations. As expected, language fields are in the alphabetic header order shown, not necessarily the [language] section order in all.lang. English is in field 5. A field might be empty, have translation text, or have a copy of the master [English] text. (see &amp;quot;What&#039;s in Each Language Field&amp;quot; below). There are enclosing double quotes as needed.&lt;br /&gt;
* The last field has any comment from the master {English], beginning with &amp;quot;//&amp;quot;. If there was no comment, a trailing comma ends the line.&lt;br /&gt;
&lt;br /&gt;
An example row with some empty fields, for the English word &amp;quot;Error&amp;quot;, with no comment:&lt;br /&gt;
&lt;br /&gt;
 #str_02000,Error.,,Fejl,,Error,Erreur,Fehler,Hiba,Errore,Błąd,Erro,Eroare,Ошибка,Chyba,,,Hata,&lt;br /&gt;
Comments on source lines in sections other than [english] are not included.&lt;br /&gt;
&lt;br /&gt;
=== Sorted and Unsorted Row Orders ===&lt;br /&gt;
&lt;br /&gt;
With the -csv option:&lt;br /&gt;
&lt;br /&gt;
* For PLUS, the row order is sorted by #str_&amp;lt;id&amp;gt;.&lt;br /&gt;
* While PL intended the row order to be sorted by #str_&amp;lt;id&amp;gt;, the actual sorting is scattershot. (A cause may be the more-recent presence of numerous non-numeric IDs. The sort uses a custom comparator, which knows only about numeric IDs. Other IDs are &amp;quot;tied&amp;quot; in order, not good for many sort algorithms. The Perl code that writes the &amp;lt;language&amp;gt;.lang files uses a better comparator.) The workaround is to import the data into your spreadsheet (keeping UTF8 encoding) and do row sorting there.&lt;br /&gt;
&lt;br /&gt;
With the -csv-unsorted option [PLUS only]:&lt;br /&gt;
&lt;br /&gt;
* Sometimes, it is more helpful to have rows in the same order as in the master [english] section of all.lang, e.g., not necessarily sorted; so perhaps meaningfully grouped. (Caution: in all.lang, there is sometimes a preceding full-line comment that describes a given grouping. That will not be present in the .csv file.)&lt;br /&gt;
&lt;br /&gt;
=== What&#039;s in Each Language Field ===&lt;br /&gt;
As discussed above, a field will have enclosing double quotes as needed.&lt;br /&gt;
&lt;br /&gt;
The master &amp;quot;english&amp;quot; field, will simply have the [English] content (which could in rare cases be empty).&lt;br /&gt;
&lt;br /&gt;
The situation for other languages is more complex. PL appears, in its separate csv implementation, to be following a middle course, between:&lt;br /&gt;
* the &amp;quot;always use translation if available; otherwise English&amp;quot; policy for &amp;lt;language&amp;gt;.lang generation.&lt;br /&gt;
* the categorization of the Missing Option.&lt;br /&gt;
&lt;br /&gt;
To make clear the difference, we repeat the Missing Options description, but with &#039;&#039;&#039;lines crossed out&#039;&#039;&#039; below. (PLUS follows what PL does here, but FYI, there is commented-out code that could implement the crossed-out conditions.)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
A field considered &amp;quot;missing&amp;quot; will be empty (e.g., between 2 commas).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;If for a given master [English] #str_&amp;lt;id&amp;gt;, there&#039;s no matching #str_&amp;lt;id&amp;gt; in the target language.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
It&#039;s &amp;quot;missing&amp;quot;, unless there&#039;s a (hard-coded) exception:&lt;br /&gt;
* The master string&#039;s content is in the &amp;quot;master_non_translatable&amp;quot; group, namely:&lt;br /&gt;
** An empty or whitespaces-only string.&lt;br /&gt;
** &amp;quot;TDM&amp;quot; or &amp;quot;The Dark Mod&amp;quot;.&lt;br /&gt;
** A prefix designating a function key (&amp;quot;F&amp;quot;) or port (&amp;quot;AUX&amp;quot; or &amp;quot;JOY&amp;quot;) followed by 1 or 2 digits.&lt;br /&gt;
** A special numeric format like &amp;quot;320x400;640x480&amp;quot; or &amp;quot;123;345&amp;quot; or &amp;quot;1x;2x&amp;quot;.&lt;br /&gt;
* &amp;lt;s&amp;gt;The master string&#039;s content is a font selector, i.e., beginning with &amp;quot;fonts/&amp;quot;.&amp;lt;/s&amp;gt;&lt;br /&gt;
* &amp;lt;s&amp;gt;The #str_&amp;lt;id&amp;gt; has a numeric &amp;lt;id&amp;gt; within a &amp;quot;master_id_non_translatable&amp;quot; range. Just one range, 2460 – 2490, is so reserved, for language names.&amp;lt;/s&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In this case, if it&#039;s not missing, the &#039;&#039;&#039;master string&#039;s content&#039;&#039;&#039; will be used.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;If the #str_&amp;lt;id&amp;gt; in English and the target language have identical content (not counting comments)&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
It&#039;s &amp;quot;missing&amp;quot;, unless there&#039;s an exception:&lt;br /&gt;
* &amp;lt;s&amp;gt;The target line has a &amp;quot;// comment&amp;quot; indicating &amp;quot;stays the same&amp;quot;.&amp;lt;/s&amp;gt;&lt;br /&gt;
* The &amp;quot;master_non_translatable&amp;quot;, &amp;lt;s&amp;gt;font selector, or &amp;quot;master_id_non_translatable&amp;quot;&amp;lt;/s&amp;gt; exclusions apply.&lt;br /&gt;
&lt;br /&gt;
In this case, if it&#039;s not missing, the &#039;&#039;&#039;translated string content (same as master string&#039;s content)&#039;&#039;&#039; will be used. As indicated, any &amp;quot;stays the same&amp;quot; phrase in the line&#039;s comment within the [language] section is ignored.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Otherwise, it&#039;s not missing.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;&#039;translated string&#039;s content&#039;&#039;&#039; will be used. This is the normal &amp;quot;translation provided&amp;quot; case, where for the matching #str_&amp;lt;id&amp;gt; in English and the target language, there&#039;s different content (ignoring comments). Note that if English content exists but the target language content is an empty string, while this categorization would call it &amp;quot;not missing&amp;quot;, it still has the same result: nothing between the commmas.&lt;br /&gt;
&lt;br /&gt;
=== Differences in Comments between PL and PLUS ===&lt;br /&gt;
As noted above , PLUS will enclose the comment field in double quotes if needed. Also, if the comment field contains any unescaped double-quotes, they are backslash-escaped.&lt;br /&gt;
PL will do none of that. This is a bug. When the .csv file is imported into a spreadsheet, extra spurious columns may result, requiring manual fix-up.&lt;br /&gt;
Also, there is a difference in handling of how characters appear in comments. PLUS will preserve UTF8 characters. PL will replace characters not in ISO-8859-1 with &amp;quot;?&amp;quot; (resulting in the same appearance as in english.lang).&lt;br /&gt;
&lt;br /&gt;
== Charstats Option ==&lt;br /&gt;
Creating bitmap font glyphs can be a time-consuming process. This option provides information to suggest, among European (i.e., non-ASCII, non-Cyrillic) characters, which ones should take priority in that process, based on what translators have provided to all.lang.&lt;br /&gt;
&lt;br /&gt;
The results go to the console. PL and PLUS formats differ. PL groups compactly by &amp;quot;Top 5&amp;quot;, &amp;quot;Top 10&amp;quot;, and so on, and is not particularly Unicode-aware.&lt;br /&gt;
PLUS gives each character its own line, with rank and additional data. (And the output here is in utf8 form, better viewed in Windows Terminal than the traditional console. Or pipe to a text file that, e.g., Notepad can treat as UTF8.) Example output:&lt;br /&gt;
&lt;br /&gt;
 Non-ASCII UTF8 characters in &#039;all.lang&#039; across all languages except [Russian],&lt;br /&gt;
 by descending frequency. (Excludes characters in comments.)&lt;br /&gt;
 &lt;br /&gt;
 Rank, unicode codepoint, utf8 char, frequency (i.e., count out of 13563 total listed)&lt;br /&gt;
 &lt;br /&gt;
  1 U+00e1 á 1504&lt;br /&gt;
  2 U+00e9 é 1420&lt;br /&gt;
  3 U+00ed í 1099&lt;br /&gt;
  4 U+0131 ı 1075&lt;br /&gt;
  5 U+00fc ü 755&lt;br /&gt;
  6 U+010d č 644&lt;br /&gt;
  7 U+00f3 ó 498&lt;br /&gt;
  8 U+00f6 ö 418&lt;br /&gt;
  9 U+00fa ú 407&lt;br /&gt;
  ....&lt;br /&gt;
  93 U+0152 Œ 1&lt;br /&gt;
  94 U+0158 Ř 1&lt;br /&gt;
  95 U+0179 Ź 1&lt;br /&gt;
&lt;br /&gt;
== Ranges Option and Holes Option ==&lt;br /&gt;
Traditionally, #str_&amp;lt;id&amp;gt;s had only 5-digit numeric values. When a new string needed to be added (i.e., to the [English] master), it was helpful to know what numeric ranges were already fully in use, and conversely, what ranges are unoccupied, dubbed &amp;quot;holes&amp;quot;. With these options, that info gets reported to the console. Note that for PL, &amp;quot;holes&amp;quot; reports only if &amp;quot;ranges&amp;quot; is not given as an option. PLUS removes that restriction.&lt;br /&gt;
PL processes and reports &amp;lt;id&amp;gt;s in [English] listing order; if that is non-monotonic, this can cause anomalies for the &amp;quot;holes&amp;quot; output. To fix that, PLUS does a pre-sort into monotonic order.&lt;br /&gt;
PL and PLUS formats differ slightly. An example PLUS output for &amp;quot;-ranges&amp;quot;:&lt;br /&gt;
&lt;br /&gt;
 There are 48 occupied numeric #str_ ranges in [English]:&lt;br /&gt;
 &lt;br /&gt;
   1000-1019 (with 20 entries)&lt;br /&gt;
   1050-1062 (with 13 entries)&lt;br /&gt;
   1500-1503 (with 4 entries)&lt;br /&gt;
   2000-2016 (with 17 entries)&lt;br /&gt;
   ...&lt;br /&gt;
   8980-8988 (with 9 entries)&lt;br /&gt;
   10000-10162 (with 163 entries)&lt;br /&gt;
   10180-10185 (with 6 entries)&lt;br /&gt;
 &lt;br /&gt;
 Also, there are 54 non-numeric #str_ entries.&lt;br /&gt;
&lt;br /&gt;
In the last line, you see that, unlike PL, PLUS is aware of non-numeric &amp;lt;id&amp;gt;s, but just reports them as a total.&lt;br /&gt;
An example PLUS output for &amp;quot;-holes&amp;quot;:&lt;br /&gt;
&lt;br /&gt;
 There are 44 unoccupied numeric #str_ ranges (aka holes) in [English]:&lt;br /&gt;
 &lt;br /&gt;
   0-999 (with 1000 openings)&lt;br /&gt;
   1020-1049 (with 30 openings)&lt;br /&gt;
   1063-1499 (with 437 openings)&lt;br /&gt;
   1504-1999 (with 496 openings)&lt;br /&gt;
   ....&lt;br /&gt;
   8989-9999 (with 1011 openings)&lt;br /&gt;
   10163-10179 (with 17 openings)&lt;br /&gt;
   10185-19999 (with 9814 openings)&lt;br /&gt;
&lt;br /&gt;
The range from 20000-99999 is reserved for FMs. Using #str_&amp;lt;id&amp;gt; in that range in all.lang will trigger a fatal error (with the –range or –hole option). (See also the FM Option.)&lt;br /&gt;
&lt;br /&gt;
== FM Option [PLUS only] ==&lt;br /&gt;
By default, when either the -ranges or -holes option is in effect, the valid range for #str_&amp;lt;id&amp;gt; numeric values is enforced by PLUS as 0-19999. If you are using this for FM strings, select this option to make the valid range 20000-99999.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;These days, many but not all main menu #str_&amp;lt;id&amp;gt;s contain a substring &amp;quot;_menu_&amp;quot;. There could be future enforcement of alphanumeric substrings.&#039;&#039;&lt;br /&gt;
== Details about Main File Formats and Processing ==&lt;br /&gt;
&lt;br /&gt;
=== All.lang File Input Format ===&lt;br /&gt;
The file begins with a preamble (in C-style comment form) of notes for translators, some of which we restate here. Then an opening &amp;quot;{&amp;quot; by itself, followed by a series of language sections. Each starts with a line with one of these headers (shown in the order currently seen in the main menu all.lang file):&lt;br /&gt;
&lt;br /&gt;
 	[English]&lt;br /&gt;
 	[German]&lt;br /&gt;
 	[French]&lt;br /&gt;
 	[Italian]&lt;br /&gt;
 	[Spanish&lt;br /&gt;
 	[Polish]&lt;br /&gt;
 	[Romanian]&lt;br /&gt;
 	[Russian]&lt;br /&gt;
 	[Portuguese}&lt;br /&gt;
 	[Czech]&lt;br /&gt;
 	[Hungarian]&lt;br /&gt;
 	[Slovak]&lt;br /&gt;
 	[Swedish]&lt;br /&gt;
 	[Danish]&lt;br /&gt;
 	[Dutch]&lt;br /&gt;
 	[Turkish]&lt;br /&gt;
 	[Catalan]&lt;br /&gt;
&lt;br /&gt;
Case of the language name doesn&#039;t matter, nor does order in which sections are listed. But it is a convention to list English first. After the header comes a series of convertible lines and comment lines, as discussed in next sections. The last line of the file has the closing &amp;quot;}&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
=== Converting Each Line ===&lt;br /&gt;
Within any particular language section of all.lang, a convertible line will have in this order:&lt;br /&gt;
&lt;br /&gt;
# A #str_&amp;lt;id&amp;gt;, in double quotes, where &amp;lt;id&amp;gt; is an unsigned integer, or a string composed of ASCII characters a-z, A-Z, 0-9, or underscore. Preferred for the latter are all lower case with underscores as word separators. Camel-case is tolerated, but not spaces or dashes. Ignoring the &amp;quot;#str_&amp;quot; prefix, the &amp;lt;id&amp;gt; must be no less than 5 and no more than 63 characters long. Leading zeros should be used to pad a numeric &amp;lt;id&amp;gt; to 5 digits. [Note: program i18n.pl possibly deals only with numeric &amp;lt;id&amp;gt;s.]&lt;br /&gt;
# The language-specific UTF8 &amp;lt;string content&amp;gt;, in double quotes&lt;br /&gt;
# An optional comment beginning with &amp;quot;//&amp;quot;. The next section covers overall treatment of comments.&lt;br /&gt;
&lt;br /&gt;
These are led and separated by whitespace. A leading tab is normal, with tab separators.&lt;br /&gt;
&lt;br /&gt;
No particular ordering of #str_&amp;lt;id&amp;gt;s is required, though ordering numeric &amp;lt;id&amp;gt;s (at least within sub-groups) is desirable.&lt;br /&gt;
==== Duplicates Across Lines Within a Section ====&lt;br /&gt;
If a particular &amp;lt;id&amp;gt; value appears more than once in a section, the last value is the effective one. A console warning will generally occur during parsing, in the case of PLUS like:&lt;br /&gt;
 Warning - #str_02518 redefined within [english]...&lt;br /&gt;
  from: malformed&lt;br /&gt;
  to:   100&lt;br /&gt;
&lt;br /&gt;
In the [English] section, there might be separate &amp;lt;id&amp;gt;s with the same content. This will generally cause a warning, in the case of PLUS like:&lt;br /&gt;
 Caution - These strings have the same content (&#039;Master&#039;): #str_08206, #str_03008&lt;br /&gt;
&lt;br /&gt;
To avoid the latter warning, a group of duplicates can be assigned a group number and hard-coded in the &amp;quot;master_double_exceptions&amp;quot; list. Only one group of ten members is so defined currently, those with a required empty string as content. More generally (says a PL comment):  &amp;quot;Sometimes it can make sense to have two different strings as when they are translated into different strings in another language. A [theoretical] example would be &amp;quot;Saw&amp;quot; (I saw something, ich hab etwas gesehen) and &amp;quot;Saw&amp;quot; (Saw, Säge).&amp;quot;&lt;br /&gt;
&lt;br /&gt;
==== Substituting English when No Translation ====&lt;br /&gt;
Ideally, a #str_&amp;lt;id&amp;gt; in the master [English] section has a match in a target language&#039;s section. Then the translated content will always be used for encoding and listing in the &amp;lt;language&amp;gt;.lang file. If no match, the English content is substituted. (Note that only a subset of these substituted strings will categorized as &amp;quot;Missing&amp;quot; if the -missing option is used. Also note that the substitution policy is slightly different with the -csv option.)&lt;br /&gt;
&lt;br /&gt;
==== Conversion Differences between PL and PLUS ====&lt;br /&gt;
* To do encoding, PL uses the Perl Encode module, that can autoload language-specific encode/decode tables.&lt;br /&gt;
* In the C++ implementation, source file &amp;quot;UTF8_8859_convert.cpp&amp;quot; includes similar (albeit custom) tables for the codepages TDM supports. The overall approach is convert from UTF8 to UTF16, then to the target ISO encoding.  That process does not use &amp;lt;locale&amp;gt; facets (which are problematic for our purposes), but standard C++ library &amp;quot;codecvt_utf8_utf16&amp;quot; and &amp;quot;wstring_convert&amp;quot; capabilities.&lt;br /&gt;
&lt;br /&gt;
=== The &amp;lt;language&amp;gt;.Lang File Output Format ===&lt;br /&gt;
* A preamble states the language name and specific ISO encoding.&lt;br /&gt;
* This is followed by the &amp;quot;#str_&amp;lt;id&amp;gt; ...&amp;quot; lines; sorted in alphabetic order; &amp;lt;id&amp;gt; in numeric form will be listed before those in alphabetic form.  Among the latter, an upper case letter will sort before all lower case letters.&lt;br /&gt;
* Trailing &amp;quot;//&amp;quot; comments  on &amp;quot;#str_&amp;lt;id&amp;gt;&amp;quot; lines from all.lang are preserved.&lt;br /&gt;
* Comments of the form /*...*/ in all.lang are skipped, whether spanning multiple lines or part of a single line.&lt;br /&gt;
* Blank lines, or lines with only whitespace or a &amp;quot;//&amp;quot; comment, are likewise skipped. The latter comments typically contain headers to organize groups of items in all.lang, but that organization is not retained, replaced by alphanumeric ordering as mentioned.&lt;br /&gt;
&lt;br /&gt;
==== Output File Differences between PL and PLUS ====&lt;br /&gt;
These differences are not thought to have functional implications:&lt;br /&gt;
&lt;br /&gt;
* The first line of the preamble will differ unless PLUS&#039;s -old_preamble option is used.&lt;br /&gt;
* Between a string content and any comment, PLUS preserves tabs and spaces found in all.lang, while PL substitutes two tabs. This is means that simple file comparison programs (like Windows &amp;quot;fc&amp;quot;, even with /T or /W options) will find lots of trivial differences. It is suggested you use a more sophisticated comparison tool, for instance, Notepad++ with the ComparePlus plugin and &amp;quot;Ignore changed spaces&amp;quot; selected.&lt;br /&gt;
&lt;br /&gt;
== Notes on PLUS Internals ==&lt;br /&gt;
A hand-crafted conversion from a static analysis of PL, PLUS preserves many variable names, some reimagined as functions. Befitting a straightforward conversion, it offers a procedural, C-like style, without much in the way of a class hierarchy, overarching object-oriented design pattern, or advanced C++ features. (This may be of benefit if part or all of its functionality is ever integrated into the TDM engine and/or DR.)&lt;br /&gt;
Not much effort was spent on performance optimization. However, as a compiled language, it will of course run much faster than PL. Also, the C++ implementation avoids use of regular expressions, which are heavily featured in PL and are notoriously slow and also hard for most coders to read.&lt;br /&gt;
&lt;br /&gt;
Platform-independent C++ standard-library structures like vectors, (ordered) sets, maps, and multimaps are employed. However, to do the UTF8 to ISO conversions, a Windows-specific approach is taken, to convert via unencoding from utf8 to wide characters and then re-encoding to target ISOs. (While it is possible to do such conversions entirely within 8-bit characters, the resulting code is a puzzle box, best left to third-party libraries.) Instead of using a third-party library, the encode/decode implementation here includes use of the &amp;quot;deprecated&amp;quot; C++ standard &amp;quot;codecvt&amp;quot; feature; while deprecated, the C++ standard committee has not (as of 2025) come up with a viable replacement.&lt;br /&gt;
&lt;br /&gt;
Like PL, PLUS has some DEBUG statements defined (requiring recompile for C++). These reflect specific concerns during development and testing and are of limited general interest.&lt;br /&gt;
&lt;br /&gt;
== Downloads ==&lt;br /&gt;
For PLUS v1.1 of 2025, July 16 (mainly adds Catalan as a supported language)&lt;br /&gt;
&lt;br /&gt;
* [https://drive.google.com/file/d/1R_qajkfq5_drIGEMYQ8ahpJwfN1LdkiT/view?usp=sharing gen_lang_plus_source_v1.1.zip]. This is a Visual Studio project. Includes open-source license.&lt;br /&gt;
* [https://drive.google.com/file/d/1kj_zE9VN7l1DMztnOHx-UaNbIAECIE6M/view?usp=sharing gen_lang_plus.exe]&lt;br /&gt;
&lt;br /&gt;
For PLUS v1.0 of 2025, Feb 28:&lt;br /&gt;
&lt;br /&gt;
* [https://drive.google.com/file/d/1V_FSMEBYsinXPMKlH3_OmzcS8f1zjVeL/view?usp=sharing gen_lang_plus_source_v1.0.zip]. This is a Visual Studio project.&lt;br /&gt;
* [https://drive.google.com/file/d/1xsas9kZ-6tRdNdFhKHS736xYK5-aYGMg/view?usp=sharing gen_lang_plus.exe]&lt;br /&gt;
&lt;br /&gt;
== See Also ==&lt;br /&gt;
The Perl program &amp;quot;i18n.pl&amp;quot; contains similar functionality for FM-specific strings, but also parses and edits the FM .map file, so is considerably more complicated.&lt;/div&gt;</summary>
		<author><name>Geep</name></author>
	</entry>
	<entry>
		<id>https://wiki.thedarkmod.com/index.php?title=Gen_Lang_Programs&amp;diff=34004</id>
		<title>Gen Lang Programs</title>
		<link rel="alternate" type="text/html" href="https://wiki.thedarkmod.com/index.php?title=Gen_Lang_Programs&amp;diff=34004"/>
		<updated>2025-07-16T18:24:19Z</updated>

		<summary type="html">&lt;p&gt;Geep: /* Downloads */ Add links for v1.1&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;By Geep, from February 2025&lt;br /&gt;
== Introduction to Gen_lang.pl (&amp;quot;PL&amp;quot;) and Gen_lang_plus (&amp;quot;PLUS&amp;quot;) ==&lt;br /&gt;
This describes two software implementations of command-line programs that essentially do the same thing;&lt;br /&gt;
# The Perl program &amp;quot;gen_lang.pl&amp;quot; (dubbed here PL), created by Tels in the 2010-14 timeframe. This is easily deployed under Linux that has Perl capabilities. Version 17 Is current.&lt;br /&gt;
# The C++ program &amp;quot;gen_lang_plus&amp;quot; (dubbed here PLUS), a re-implementation with minor improvements created by Geep in 2025. This is lightly Windows-specific at this time. (Please volunteer if you want to make it run under Linux.) Version 1.0 is current.&lt;br /&gt;
&lt;br /&gt;
The purpose of both is as follows.&lt;br /&gt;
* Read and write files in child folder &amp;quot;strings&amp;quot;. (Caution: &amp;quot;not strings/fm&amp;quot;, even if you specify the &amp;quot;fm&amp;quot; option.)&lt;br /&gt;
* Read an &amp;quot;all.lang&amp;quot; file, either that associated with the main-menu-system, or with a specific FM under development. This UTF-8 input file has translations of strings for all TDM-supported languages (currently 17). There are individual sections for each target language. Each string is of form&lt;br /&gt;
&lt;br /&gt;
 &amp;quot;#str_&amp;lt;id&amp;gt;&amp;quot; &amp;quot;&amp;lt;string content&amp;gt;&amp;quot; // optional comment.&lt;br /&gt;
* Generate a set of individual &amp;quot;&amp;lt;language&amp;gt;.lang&amp;quot; files, with the appropriate translated strings. Each file is generated in a standard 8-bit encoding (e.g., defined by one of the iso-8859 standards) designated for the target language. If a translator did not provide a given string in the target language, the master English string is automatically substituted.&lt;br /&gt;
* Finally, as requested by command-line options, various analyses can be performed. For example, a set of &amp;quot;missing_&amp;lt;language&amp;gt;.txt&amp;quot; files can be generated, to suggest where translation efforts are still needed.&lt;br /&gt;
This article details both programs, with important differences noted. Running this functionality is intended to be done, infrequently, by the person overseeing translation improvements to all.lang.&lt;br /&gt;
&lt;br /&gt;
For more quick overviews of this process, see&lt;br /&gt;
* the wiki article [[Internationalization]]. This also covers the i18n.pl program, which is beyond the scope here.&lt;br /&gt;
* the preamble of the all.lang file, found in tdm_base01.pk4&#039;s \strings\.&lt;br /&gt;
&lt;br /&gt;
It is helpful to mention what these two programs do &#039;&#039;&#039;not&#039;&#039;&#039; take into account:&lt;br /&gt;
* the &amp;lt;language&amp;gt;.map file that reroutes European codepoints from a standardized encoding to the TDM-specific custom 8-bit encoding discussed in [[I18N_-_Charset]].&lt;br /&gt;
* what UTF8 characters are allowed by that TDM-specific coding (as opposed to the ISO-8859 encoding).&lt;br /&gt;
* the font and fontsize a specific string will use, and what limitations that entails, and what within-DAT glyph-substitutions may be in effect.&lt;br /&gt;
&lt;br /&gt;
== Runtime Environment for PLUS ==&lt;br /&gt;
To function in all aspects, PLUS requires Windows with certain UTF8 capabilities, introduced in later versions of Windows 10. Because the PLUS build is told explicitly to use UTF8, in theory what your &amp;quot;system locale&amp;quot; is set to should not matter. In particular, you are not required you set the system locale to the Windows 11 beta UTF8 codepage. (PLUS was developed on a dev box with the English (US) locale.)&lt;br /&gt;
&lt;br /&gt;
You may run it under the traditional Windows console. However, that will not display UTF8 characters correctly on screen, which is mainly an issue with the -charstats and -charpunts options. Instead, use Windows Terminal (or Powershell with UTF8 encoding). Or pipe the console output to a file (i.e., &amp;quot;&amp;gt; myfile.txt&amp;quot;), that can be viewed as UTF8 with Notepad and other text editors.&lt;br /&gt;
&lt;br /&gt;
== Overview of Command-Line Options ==&lt;br /&gt;
&lt;br /&gt;
===For both PL and PLUS===&lt;br /&gt;
 --csv		Generate CSV file&lt;br /&gt;
 --missing	Generate files with lists of missing strings for each language.&lt;br /&gt;
 --charstats	Generate statistics about foreign characters.&lt;br /&gt;
 --show-ranges	Show occupied string index ranges.&lt;br /&gt;
 --show-holes	Show holes in the string index ranges.&lt;br /&gt;
&lt;br /&gt;
With PLUS, one may use a single &amp;quot;-&amp;quot; before an option, instead of &amp;quot;--&amp;quot;, and/or leave off the &amp;quot;show-&amp;quot; prefix. (Regarding &amp;quot;charstats&amp;quot;, for consistency, since this option outputs to screen, PL should have used the &amp;quot;show-&amp;quot; prefix, but didn&#039;t. PLUS does, optionally.)&lt;br /&gt;
&lt;br /&gt;
===For PLUS Only===&lt;br /&gt;
 -old-preamble					Keep &amp;lt;language&amp;gt;.lang preamble just like that of gen_lang.pl. Don&#039;t include file generation date or PLUS version number.&lt;br /&gt;
 -charpunts &#039;&#039;or&#039;&#039; --show-charpunts			Reports lines in which &amp;quot;?&amp;quot; was substituted for any character.&lt;br /&gt;
 -charpunts-extra &#039;&#039;or&#039;&#039; --show-charpunts-extra	Like charpunt, but includes &amp;quot;// comment&amp;quot; characters.&lt;br /&gt;
 -fm						Program used for an fm, not main menu; affects what&#039;s considered a valid numeric #str_&amp;lt;id&amp;gt; range.&lt;br /&gt;
 -cvs-unsorted					Like -csv, but row order stays like that of all.lang [English].&lt;br /&gt;
&lt;br /&gt;
== Charpunts and Charpunts-Extra Options [PLUS Only] ==&lt;br /&gt;
During generation of a particular &amp;lt;language&amp;gt;.lang file, if a valid data line contains 1 or more characters that can&#039;t be rendered in the target encoding, then a 3-line report is issued to console. Specifically:&lt;br /&gt;
 -charpunts		Considers characters within the line&#039;s content (excluding comments).&lt;br /&gt;
 -charpunts-extra	Same as charpunts, but also considers characters within the line&#039;s &amp;quot;// comment&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
When entering these options, you may use the &amp;quot;show-&amp;quot; prefix if you&#039;d like, with 1 or 2 leading dashes.&lt;br /&gt;
&lt;br /&gt;
By &amp;quot;// comment&amp;quot;, is meant the optional comment that starts with &amp;quot;//&amp;quot; at the end of a #str_&amp;lt;id&amp;gt; line (but still excluding any other comment forms; these latter won&#039;t be present in &amp;lt;language&amp;gt;.lang).&lt;br /&gt;
&lt;br /&gt;
Note – it is assumed that #str_&amp;lt;id&amp;gt; contains only 0-9, A-Z, a-z, or underline... so is not inspected by these options.&lt;br /&gt;
&lt;br /&gt;
An example report for [Hungarian] encoded as iso-8859-2:&lt;br /&gt;
&lt;br /&gt;
 Output line 177...&lt;br /&gt;
 from:   &amp;quot;#str_02208&amp;quot;    &amp;quot;Küldetési idõ&amp;quot;&lt;br /&gt;
   to:   &amp;quot;#str_02208&amp;quot;    &amp;quot;K�ldet�si id?&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Important: in this example, only õ, the last character in the &amp;quot;from:&amp;quot; line, could not be encoded in iso-8859-2 and so is replaced by &amp;quot;?&amp;quot; in the &amp;quot;to:&amp;quot; line. The &amp;quot;to:&amp;quot; line characters indicated by � were successfully encoded, but now are not valid UTF8, so can no longer be shown as such. That is, the &amp;quot;to:&amp;quot; line has the identical string placed into the hungarian.lang file.&lt;br /&gt;
&lt;br /&gt;
Here is an -charpunts-extra example where only the comment has characters that don&#039;t encode, in this case into iso-8859-1 for [English]:&lt;br /&gt;
&lt;br /&gt;
 Output line 396...&lt;br /&gt;
 from:   &amp;quot;#str_02482&amp;quot;    &amp;quot;Srpski&amp;quot;// Serbian (Српски - same exception as Russian)&lt;br /&gt;
   to:   &amp;quot;#str_02482&amp;quot;    &amp;quot;Srpski&amp;quot;// Serbian (?????? - same exception as Russian)&lt;br /&gt;
&lt;br /&gt;
TIP: If the results of this option is too voluminous, recall that output from a console app can be directed into a file using &amp;quot;... &amp;gt; filename.txt&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
These reports give the output line number within &amp;lt;language&amp;gt;.lang, rather than the input line in all.lang, because of difficulties getting the latter value to be correct in the face of, for instance, multiline comments. (Any line numbers that PL reports are usually off.)&lt;br /&gt;
&lt;br /&gt;
== Old Preamble Option [PLUS Only] ==&lt;br /&gt;
Each &amp;lt;language&amp;gt;.lang file gets a standard preamble. For PL, the first line looks like this example:&lt;br /&gt;
 // String table - english (iso-8859-1)&lt;br /&gt;
&lt;br /&gt;
For PLUS, the first line by default also has UTC time and program version, like this example:&lt;br /&gt;
 // String table - english (iso-8859-1) - created on 2025-02-15T04:00:21Z  with gen_lang_plus v. 1.0&lt;br /&gt;
&lt;br /&gt;
But you can ask PLUS to use PL&#039;s format, with the &amp;quot;-old-preamble&amp;quot; option. Why? To simplify comparing a particular &amp;lt;language&amp;gt;.lang file generated with both programs.&lt;br /&gt;
Since this is more a debugging option, it&#039;s not listed in the help, just here.&lt;br /&gt;
&lt;br /&gt;
== Missing Option ==&lt;br /&gt;
This option alerts translators to untranslated strings. For each language (other than English, the master) it generates a file named &amp;quot;missing_&amp;lt;language&amp;gt;.txt, with lists of missing UTF8 strings. Each line has the quoted #str_&amp;lt;id&amp;gt; and quoted content, but not comments.&lt;br /&gt;
&lt;br /&gt;
===What&#039;s Considered &amp;quot;Missing&amp;quot;?===&lt;br /&gt;
This categorization was established in PL and now mimicked in PLUS.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;If for a given master [English] #str_&amp;lt;id&amp;gt;, there&#039;s no matching #str_&amp;lt;id&amp;gt; in the target language.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
It&#039;s &amp;quot;missing&amp;quot;, unless there&#039;s a (hard-coded) exception:&lt;br /&gt;
&lt;br /&gt;
* The master string&#039;s content is in the &amp;quot;master_non_translatable&amp;quot; group, namely:&lt;br /&gt;
** An empty or whitespaces-only string.&lt;br /&gt;
** &amp;quot;TDM&amp;quot; or &amp;quot;The Dark Mod&amp;quot;.&lt;br /&gt;
** A prefix designating a function key (&amp;quot;F&amp;quot;) or port (&amp;quot;AUX&amp;quot; or &amp;quot;JOY&amp;quot;) followed by 1 or 2 digits.&lt;br /&gt;
** A special numeric format like &amp;quot;320x400;640x480&amp;quot; or &amp;quot;123;345&amp;quot; or &amp;quot;1x;2x&amp;quot;.&lt;br /&gt;
* The master string&#039;s content is a font selector, i.e., beginning with &amp;quot;fonts/&amp;quot;.&lt;br /&gt;
* The #str_&amp;lt;id&amp;gt; has a numeric &amp;lt;id&amp;gt; within a &amp;quot;master_id_non_translatable&amp;quot; range. Just one range, 02460 – 02490, is so reserved, for language names.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;If the #str_&amp;lt;id&amp;gt; in English and the target language have identical content (not counting comments)&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
It&#039;s &amp;quot;missing&amp;quot;, unless there&#039;s an exception:&lt;br /&gt;
&lt;br /&gt;
* The target line has a &amp;quot;//&amp;quot; comment indicating &amp;quot;stays the same&amp;quot;&lt;br /&gt;
* The &amp;quot;master_non_translatable&amp;quot;, font selector, or &amp;quot;master_id_non_translatable&amp;quot; exclusions apply.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Otherwise, it&#039;s not missing.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
That covers this additional case, where for the matching #str_&amp;lt;id&amp;gt; in English and the target language, there&#039;s different content (ignoring comments). Surprisingly, this is considered &amp;quot;not missing&amp;quot; even when the English content exists and the target language content is an empty string.&lt;br /&gt;
&lt;br /&gt;
Rarely, the master content can be empty, but the translated string may or may not be. An example is #str_02313, representing an optional second line needed for some languages.&lt;br /&gt;
&lt;br /&gt;
== CSV Options ==&lt;br /&gt;
These options read the contents of all.lang and rearrange them for export as a comma-separated-values &amp;quot;tdm_all_lang.csv&amp;quot; UTF8 file in the &amp;quot;strings&amp;quot; folder. The options have different generated row order:&lt;br /&gt;
&lt;br /&gt;
 -csv		Rows sorted by #str_&amp;lt;id&amp;gt;; seriously buggy ordering in PL, works in PLUS.&lt;br /&gt;
 -csv-unsorted	PLUS only. Keeps row order of [English] in all.lang&lt;br /&gt;
&lt;br /&gt;
The exported CSV file can then be imported into other tools for translators, e.g., Excel spreadsheets. Be aware as you process this data further: maintaining the UTF8 (or other Unicode) encoding ensures character integrity.&lt;br /&gt;
&lt;br /&gt;
=== Generated CVS File Format ===&lt;br /&gt;
The first line of the file has the field (aka column) headers, with languages in alphabetic order:&lt;br /&gt;
&lt;br /&gt;
 ID,catalan,czech,danish,dutch,english,french,german,hungarian,italian,polish,portuguese,romanian,russian,slovak,spanish,swedish,turkish,comment&lt;br /&gt;
There are 19 comma-separated fields here, so the results is very wide. (Recall in a spreadsheet, you can hide columns not of current interest.)&lt;br /&gt;
&lt;br /&gt;
Broadly, the .csv format comes in different variants. Traditionally, as here, comma is the separator. If a field contains a comma, the field overall is wrapped in double quotes. PL also so wraps if there&#039;s a contained double-quote, colon, or semi-colon. PLUS mimics that policy. PL unfortunately only considers the language fields for wrapping. PLUS goes a bit further, to consider the &amp;quot;comment&amp;quot; field.&lt;br /&gt;
&lt;br /&gt;
So, after the header each subsequent line has fields separated by commas, where:&lt;br /&gt;
&lt;br /&gt;
* The first field, &amp;quot;ID&amp;quot;, has #str_&amp;lt;id&amp;gt;. Unlike in all.lang, there are no enclosing double quotes.&lt;br /&gt;
* Remaining fields have translations. As expected, language fields are in the alphabetic header order shown, not necessarily the [language] section order in all.lang. English is in field 5. A field might be empty, have translation text, or have a copy of the master [English] text. (see &amp;quot;What&#039;s in Each Language Field&amp;quot; below). There are enclosing double quotes as needed.&lt;br /&gt;
* The last field has any comment from the master {English], beginning with &amp;quot;//&amp;quot;. If there was no comment, a trailing comma ends the line.&lt;br /&gt;
&lt;br /&gt;
An example row with some empty fields, for the English word &amp;quot;Error&amp;quot;, with no comment:&lt;br /&gt;
&lt;br /&gt;
 #str_02000,Error.,,Fejl,,Error,Erreur,Fehler,Hiba,Errore,Błąd,Erro,Eroare,Ошибка,Chyba,,,Hata,&lt;br /&gt;
Comments on source lines in sections other than [english] are not included.&lt;br /&gt;
&lt;br /&gt;
=== Sorted and Unsorted Row Orders ===&lt;br /&gt;
&lt;br /&gt;
With the -csv option:&lt;br /&gt;
&lt;br /&gt;
* For PLUS, the row order is sorted by #str_&amp;lt;id&amp;gt;.&lt;br /&gt;
* While PL intended the row order to be sorted by #str_&amp;lt;id&amp;gt;, the actual sorting is scattershot. (A cause may be the more-recent presence of numerous non-numeric IDs. The sort uses a custom comparator, which knows only about numeric IDs. Other IDs are &amp;quot;tied&amp;quot; in order, not good for many sort algorithms. The Perl code that writes the &amp;lt;language&amp;gt;.lang files uses a better comparator.) The workaround is to import the data into your spreadsheet (keeping UTF8 encoding) and do row sorting there.&lt;br /&gt;
&lt;br /&gt;
With the -csv-unsorted option [PLUS only]:&lt;br /&gt;
&lt;br /&gt;
* Sometimes, it is more helpful to have rows in the same order as in the master [english] section of all.lang, e.g., not necessarily sorted; so perhaps meaningfully grouped. (Caution: in all.lang, there is sometimes a preceding full-line comment that describes a given grouping. That will not be present in the .csv file.)&lt;br /&gt;
&lt;br /&gt;
=== What&#039;s in Each Language Field ===&lt;br /&gt;
As discussed above, a field will have enclosing double quotes as needed.&lt;br /&gt;
&lt;br /&gt;
The master &amp;quot;english&amp;quot; field, will simply have the [English] content (which could in rare cases be empty).&lt;br /&gt;
&lt;br /&gt;
The situation for other languages is more complex. PL appears, in its separate csv implementation, to be following a middle course, between:&lt;br /&gt;
* the &amp;quot;always use translation if available; otherwise English&amp;quot; policy for &amp;lt;language&amp;gt;.lang generation.&lt;br /&gt;
* the categorization of the Missing Option.&lt;br /&gt;
&lt;br /&gt;
To make clear the difference, we repeat the Missing Options description, but with &#039;&#039;&#039;lines crossed out&#039;&#039;&#039; below. (PLUS follows what PL does here, but FYI, there is commented-out code that could implement the crossed-out conditions.)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
A field considered &amp;quot;missing&amp;quot; will be empty (e.g., between 2 commas).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;If for a given master [English] #str_&amp;lt;id&amp;gt;, there&#039;s no matching #str_&amp;lt;id&amp;gt; in the target language.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
It&#039;s &amp;quot;missing&amp;quot;, unless there&#039;s a (hard-coded) exception:&lt;br /&gt;
* The master string&#039;s content is in the &amp;quot;master_non_translatable&amp;quot; group, namely:&lt;br /&gt;
** An empty or whitespaces-only string.&lt;br /&gt;
** &amp;quot;TDM&amp;quot; or &amp;quot;The Dark Mod&amp;quot;.&lt;br /&gt;
** A prefix designating a function key (&amp;quot;F&amp;quot;) or port (&amp;quot;AUX&amp;quot; or &amp;quot;JOY&amp;quot;) followed by 1 or 2 digits.&lt;br /&gt;
** A special numeric format like &amp;quot;320x400;640x480&amp;quot; or &amp;quot;123;345&amp;quot; or &amp;quot;1x;2x&amp;quot;.&lt;br /&gt;
* &amp;lt;s&amp;gt;The master string&#039;s content is a font selector, i.e., beginning with &amp;quot;fonts/&amp;quot;.&amp;lt;/s&amp;gt;&lt;br /&gt;
* &amp;lt;s&amp;gt;The #str_&amp;lt;id&amp;gt; has a numeric &amp;lt;id&amp;gt; within a &amp;quot;master_id_non_translatable&amp;quot; range. Just one range, 2460 – 2490, is so reserved, for language names.&amp;lt;/s&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In this case, if it&#039;s not missing, the &#039;&#039;&#039;master string&#039;s content&#039;&#039;&#039; will be used.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;If the #str_&amp;lt;id&amp;gt; in English and the target language have identical content (not counting comments)&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
It&#039;s &amp;quot;missing&amp;quot;, unless there&#039;s an exception:&lt;br /&gt;
* &amp;lt;s&amp;gt;The target line has a &amp;quot;// comment&amp;quot; indicating &amp;quot;stays the same&amp;quot;.&amp;lt;/s&amp;gt;&lt;br /&gt;
* The &amp;quot;master_non_translatable&amp;quot;, &amp;lt;s&amp;gt;font selector, or &amp;quot;master_id_non_translatable&amp;quot;&amp;lt;/s&amp;gt; exclusions apply.&lt;br /&gt;
&lt;br /&gt;
In this case, if it&#039;s not missing, the &#039;&#039;&#039;translated string content (same as master string&#039;s content)&#039;&#039;&#039; will be used. As indicated, any &amp;quot;stays the same&amp;quot; phrase in the line&#039;s comment within the [language] section is ignored.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Otherwise, it&#039;s not missing.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;&#039;translated string&#039;s content&#039;&#039;&#039; will be used. This is the normal &amp;quot;translation provided&amp;quot; case, where for the matching #str_&amp;lt;id&amp;gt; in English and the target language, there&#039;s different content (ignoring comments). Note that if English content exists but the target language content is an empty string, while this categorization would call it &amp;quot;not missing&amp;quot;, it still has the same result: nothing between the commmas.&lt;br /&gt;
&lt;br /&gt;
=== Differences in Comments between PL and PLUS ===&lt;br /&gt;
As noted above , PLUS will enclose the comment field in double quotes if needed. Also, if the comment field contains any unescaped double-quotes, they are backslash-escaped.&lt;br /&gt;
PL will do none of that. This is a bug. When the .csv file is imported into a spreadsheet, extra spurious columns may result, requiring manual fix-up.&lt;br /&gt;
Also, there is a difference in handling of how characters appear in comments. PLUS will preserve UTF8 characters. PL will replace characters not in ISO-8859-1 with &amp;quot;?&amp;quot; (resulting in the same appearance as in english.lang).&lt;br /&gt;
&lt;br /&gt;
== Charstats Option ==&lt;br /&gt;
Creating bitmap font glyphs can be a time-consuming process. This option provides information to suggest, among European (i.e., non-ASCII, non-Cyrillic) characters, which ones should take priority in that process, based on what translators have provided to all.lang.&lt;br /&gt;
&lt;br /&gt;
The results go to the console. PL and PLUS formats differ. PL groups compactly by &amp;quot;Top 5&amp;quot;, &amp;quot;Top 10&amp;quot;, and so on, and is not particularly Unicode-aware.&lt;br /&gt;
PLUS gives each character its own line, with rank and additional data. (And the output here is in utf8 form, better viewed in Windows Terminal than the traditional console. Or pipe to a text file that, e.g., Notepad can treat as UTF8.) Example output:&lt;br /&gt;
&lt;br /&gt;
 Non-ASCII UTF8 characters in &#039;all.lang&#039; across all languages except [Russian],&lt;br /&gt;
 by descending frequency. (Excludes characters in comments.)&lt;br /&gt;
 &lt;br /&gt;
 Rank, unicode codepoint, utf8 char, frequency (i.e., count out of 13563 total listed)&lt;br /&gt;
 &lt;br /&gt;
  1 U+00e1 á 1504&lt;br /&gt;
  2 U+00e9 é 1420&lt;br /&gt;
  3 U+00ed í 1099&lt;br /&gt;
  4 U+0131 ı 1075&lt;br /&gt;
  5 U+00fc ü 755&lt;br /&gt;
  6 U+010d č 644&lt;br /&gt;
  7 U+00f3 ó 498&lt;br /&gt;
  8 U+00f6 ö 418&lt;br /&gt;
  9 U+00fa ú 407&lt;br /&gt;
  ....&lt;br /&gt;
  93 U+0152 Œ 1&lt;br /&gt;
  94 U+0158 Ř 1&lt;br /&gt;
  95 U+0179 Ź 1&lt;br /&gt;
&lt;br /&gt;
== Ranges Option and Holes Option ==&lt;br /&gt;
Traditionally, #str_&amp;lt;id&amp;gt;s had only 5-digit numeric values. When a new string needed to be added (i.e., to the [English] master), it was helpful to know what numeric ranges were already fully in use, and conversely, what ranges are unoccupied, dubbed &amp;quot;holes&amp;quot;. With these options, that info gets reported to the console. Note that for PL, &amp;quot;holes&amp;quot; reports only if &amp;quot;ranges&amp;quot; is not given as an option. PLUS removes that restriction.&lt;br /&gt;
PL processes and reports &amp;lt;id&amp;gt;s in [English] listing order; if that is non-monotonic, this can cause anomalies for the &amp;quot;holes&amp;quot; output. To fix that, PLUS does a pre-sort into monotonic order.&lt;br /&gt;
PL and PLUS formats differ slightly. An example PLUS output for &amp;quot;-ranges&amp;quot;:&lt;br /&gt;
&lt;br /&gt;
 There are 48 occupied numeric #str_ ranges in [English]:&lt;br /&gt;
 &lt;br /&gt;
   1000-1019 (with 20 entries)&lt;br /&gt;
   1050-1062 (with 13 entries)&lt;br /&gt;
   1500-1503 (with 4 entries)&lt;br /&gt;
   2000-2016 (with 17 entries)&lt;br /&gt;
   ...&lt;br /&gt;
   8980-8988 (with 9 entries)&lt;br /&gt;
   10000-10162 (with 163 entries)&lt;br /&gt;
   10180-10185 (with 6 entries)&lt;br /&gt;
 &lt;br /&gt;
 Also, there are 54 non-numeric #str_ entries.&lt;br /&gt;
&lt;br /&gt;
In the last line, you see that, unlike PL, PLUS is aware of non-numeric &amp;lt;id&amp;gt;s, but just reports them as a total.&lt;br /&gt;
An example PLUS output for &amp;quot;-holes&amp;quot;:&lt;br /&gt;
&lt;br /&gt;
 There are 44 unoccupied numeric #str_ ranges (aka holes) in [English]:&lt;br /&gt;
 &lt;br /&gt;
   0-999 (with 1000 openings)&lt;br /&gt;
   1020-1049 (with 30 openings)&lt;br /&gt;
   1063-1499 (with 437 openings)&lt;br /&gt;
   1504-1999 (with 496 openings)&lt;br /&gt;
   ....&lt;br /&gt;
   8989-9999 (with 1011 openings)&lt;br /&gt;
   10163-10179 (with 17 openings)&lt;br /&gt;
   10185-19999 (with 9814 openings)&lt;br /&gt;
&lt;br /&gt;
The range from 20000-99999 is reserved for FMs. Using #str_&amp;lt;id&amp;gt; in that range in all.lang will trigger a fatal error (with the –range or –hole option). (See also the FM Option.)&lt;br /&gt;
&lt;br /&gt;
== FM Option [PLUS only] ==&lt;br /&gt;
By default, when either the -ranges or -holes option is in effect, the valid range for #str_&amp;lt;id&amp;gt; numeric values is enforced by PLUS as 0-19999. If you are using this for FM strings, select this option to make the valid range 20000-99999.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;These days, many but not all main menu #str_&amp;lt;id&amp;gt;s contain a substring &amp;quot;_menu_&amp;quot;. There could be future enforcement of alphanumeric substrings.&#039;&#039;&lt;br /&gt;
== Details about Main File Formats and Processing ==&lt;br /&gt;
&lt;br /&gt;
=== All.lang File Input Format ===&lt;br /&gt;
The file begins with a preamble (in C-style comment form) of notes for translators, some of which we restate here. Then an opening &amp;quot;{&amp;quot; by itself, followed by a series of language sections. Each starts with a line with one of these headers (shown in the order currently seen in the main menu all.lang file):&lt;br /&gt;
&lt;br /&gt;
 	[English]&lt;br /&gt;
 	[German]&lt;br /&gt;
 	[French]&lt;br /&gt;
 	[Italian]&lt;br /&gt;
 	[Spanish&lt;br /&gt;
 	[Polish]&lt;br /&gt;
 	[Romanian]&lt;br /&gt;
 	[Russian]&lt;br /&gt;
 	[Portuguese}&lt;br /&gt;
 	[Czech]&lt;br /&gt;
 	[Hungarian]&lt;br /&gt;
 	[Slovak]&lt;br /&gt;
 	[Swedish]&lt;br /&gt;
 	[Danish]&lt;br /&gt;
 	[Dutch]&lt;br /&gt;
 	[Turkish]&lt;br /&gt;
&lt;br /&gt;
Case of the language name doesn&#039;t matter, nor does order in which sections are listed. But it is a convention to list English first. After the header comes a series of convertible lines and comment lines, as discussed in next sections. The last line of the file has the closing &amp;quot;}&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
=== Converting Each Line ===&lt;br /&gt;
Within any particular language section of all.lang, a convertible line will have in this order:&lt;br /&gt;
&lt;br /&gt;
# A #str_&amp;lt;id&amp;gt;, in double quotes, where &amp;lt;id&amp;gt; is an unsigned integer, or a string composed of ASCII characters a-z, A-Z, 0-9, or underscore. Preferred for the latter are all lower case with underscores as word separators. Camel-case is tolerated, but not spaces or dashes. Ignoring the &amp;quot;#str_&amp;quot; prefix, the &amp;lt;id&amp;gt; must be no less than 5 and no more than 63 characters long. Leading zeros should be used to pad a numeric &amp;lt;id&amp;gt; to 5 digits. [Note: program i18n.pl possibly deals only with numeric &amp;lt;id&amp;gt;s.]&lt;br /&gt;
# The language-specific UTF8 &amp;lt;string content&amp;gt;, in double quotes&lt;br /&gt;
# An optional comment beginning with &amp;quot;//&amp;quot;. The next section covers overall treatment of comments.&lt;br /&gt;
&lt;br /&gt;
These are led and separated by whitespace. A leading tab is normal, with tab separators.&lt;br /&gt;
&lt;br /&gt;
No particular ordering of #str_&amp;lt;id&amp;gt;s is required, though ordering numeric &amp;lt;id&amp;gt;s (at least within sub-groups) is desirable.&lt;br /&gt;
==== Duplicates Across Lines Within a Section ====&lt;br /&gt;
If a particular &amp;lt;id&amp;gt; value appears more than once in a section, the last value is the effective one. A console warning will generally occur during parsing, in the case of PLUS like:&lt;br /&gt;
 Warning - #str_02518 redefined within [english]...&lt;br /&gt;
  from: malformed&lt;br /&gt;
  to:   100&lt;br /&gt;
&lt;br /&gt;
In the [English] section, there might be separate &amp;lt;id&amp;gt;s with the same content. This will generally cause a warning, in the case of PLUS like:&lt;br /&gt;
 Caution - These strings have the same content (&#039;Master&#039;): #str_08206, #str_03008&lt;br /&gt;
&lt;br /&gt;
To avoid the latter warning, a group of duplicates can be assigned a group number and hard-coded in the &amp;quot;master_double_exceptions&amp;quot; list. Only one group of ten members is so defined currently, those with a required empty string as content. More generally (says a PL comment):  &amp;quot;Sometimes it can make sense to have two different strings as when they are translated into different strings in another language. A [theoretical] example would be &amp;quot;Saw&amp;quot; (I saw something, ich hab etwas gesehen) and &amp;quot;Saw&amp;quot; (Saw, Säge).&amp;quot;&lt;br /&gt;
&lt;br /&gt;
==== Substituting English when No Translation ====&lt;br /&gt;
Ideally, a #str_&amp;lt;id&amp;gt; in the master [English] section has a match in a target language&#039;s section. Then the translated content will always be used for encoding and listing in the &amp;lt;language&amp;gt;.lang file. If no match, the English content is substituted. (Note that only a subset of these substituted strings will categorized as &amp;quot;Missing&amp;quot; if the -missing option is used. Also note that the substitution policy is slightly different with the -csv option.)&lt;br /&gt;
&lt;br /&gt;
==== Conversion Differences between PL and PLUS ====&lt;br /&gt;
* To do encoding, PL uses the Perl Encode module, that can autoload language-specific encode/decode tables.&lt;br /&gt;
* In the C++ implementation, source file &amp;quot;UTF8_8859_convert.cpp&amp;quot; includes similar (albeit custom) tables for the codepages TDM supports. The overall approach is convert from UTF8 to UTF16, then to the target ISO encoding.  That process does not use &amp;lt;locale&amp;gt; facets (which are problematic for our purposes), but standard C++ library &amp;quot;codecvt_utf8_utf16&amp;quot; and &amp;quot;wstring_convert&amp;quot; capabilities.&lt;br /&gt;
&lt;br /&gt;
=== The &amp;lt;language&amp;gt;.Lang File Output Format ===&lt;br /&gt;
* A preamble states the language name and specific ISO encoding.&lt;br /&gt;
* This is followed by the &amp;quot;#str_&amp;lt;id&amp;gt; ...&amp;quot; lines; sorted in alphabetic order; &amp;lt;id&amp;gt; in numeric form will be listed before those in alphabetic form.  Among the latter, an upper case letter will sort before all lower case letters.&lt;br /&gt;
* Trailing &amp;quot;//&amp;quot; comments  on &amp;quot;#str_&amp;lt;id&amp;gt;&amp;quot; lines from all.lang are preserved.&lt;br /&gt;
* Comments of the form /*...*/ in all.lang are skipped, whether spanning multiple lines or part of a single line.&lt;br /&gt;
* Blank lines, or lines with only whitespace or a &amp;quot;//&amp;quot; comment, are likewise skipped. The latter comments typically contain headers to organize groups of items in all.lang, but that organization is not retained, replaced by alphanumeric ordering as mentioned.&lt;br /&gt;
&lt;br /&gt;
==== Output File Differences between PL and PLUS ====&lt;br /&gt;
These differences are not thought to have functional implications:&lt;br /&gt;
&lt;br /&gt;
* The first line of the preamble will differ unless PLUS&#039;s -old_preamble option is used.&lt;br /&gt;
* Between a string content and any comment, PLUS preserves tabs and spaces found in all.lang, while PL substitutes two tabs. This is means that simple file comparison programs (like Windows &amp;quot;fc&amp;quot;, even with /T or /W options) will find lots of trivial differences. It is suggested you use a more sophisticated comparison tool, for instance, Notepad++ with the ComparePlus plugin and &amp;quot;Ignore changed spaces&amp;quot; selected.&lt;br /&gt;
&lt;br /&gt;
== Notes on PLUS Internals ==&lt;br /&gt;
A hand-crafted conversion from a static analysis of PL, PLUS preserves many variable names, some reimagined as functions. Befitting a straightforward conversion, it offers a procedural, C-like style, without much in the way of a class hierarchy, overarching object-oriented design pattern, or advanced C++ features. (This may be of benefit if part or all of its functionality is ever integrated into the TDM engine and/or DR.)&lt;br /&gt;
Not much effort was spent on performance optimization. However, as a compiled language, it will of course run much faster than PL. Also, the C++ implementation avoids use of regular expressions, which are heavily featured in PL and are notoriously slow and also hard for most coders to read.&lt;br /&gt;
&lt;br /&gt;
Platform-independent C++ standard-library structures like vectors, (ordered) sets, maps, and multimaps are employed. However, to do the UTF8 to ISO conversions, a Windows-specific approach is taken, to convert via unencoding from utf8 to wide characters and then re-encoding to target ISOs. (While it is possible to do such conversions entirely within 8-bit characters, the resulting code is a puzzle box, best left to third-party libraries.) Instead of using a third-party library, the encode/decode implementation here includes use of the &amp;quot;deprecated&amp;quot; C++ standard &amp;quot;codecvt&amp;quot; feature; while deprecated, the C++ standard committee has not (as of 2025) come up with a viable replacement.&lt;br /&gt;
&lt;br /&gt;
Like PL, PLUS has some DEBUG statements defined (requiring recompile for C++). These reflect specific concerns during development and testing and are of limited general interest.&lt;br /&gt;
&lt;br /&gt;
== Downloads ==&lt;br /&gt;
For PLUS v1.1 of 2025, July 16 (mainly adds Catalan as a supported language)&lt;br /&gt;
&lt;br /&gt;
* [https://drive.google.com/file/d/1R_qajkfq5_drIGEMYQ8ahpJwfN1LdkiT/view?usp=sharing gen_lang_plus_source_v1.1.zip]. This is a Visual Studio project. Includes open-source license.&lt;br /&gt;
* [https://drive.google.com/file/d/1kj_zE9VN7l1DMztnOHx-UaNbIAECIE6M/view?usp=sharing gen_lang_plus.exe]&lt;br /&gt;
&lt;br /&gt;
For PLUS v1.0 of 2025, Feb 28:&lt;br /&gt;
&lt;br /&gt;
* [https://drive.google.com/file/d/1V_FSMEBYsinXPMKlH3_OmzcS8f1zjVeL/view?usp=sharing gen_lang_plus_source_v1.0.zip]. This is a Visual Studio project.&lt;br /&gt;
* [https://drive.google.com/file/d/1xsas9kZ-6tRdNdFhKHS736xYK5-aYGMg/view?usp=sharing gen_lang_plus.exe]&lt;br /&gt;
&lt;br /&gt;
== See Also ==&lt;br /&gt;
The Perl program &amp;quot;i18n.pl&amp;quot; contains similar functionality for FM-specific strings, but also parses and edits the FM .map file, so is considerably more complicated.&lt;/div&gt;</summary>
		<author><name>Geep</name></author>
	</entry>
	<entry>
		<id>https://wiki.thedarkmod.com/index.php?title=Gen_Lang_Programs&amp;diff=34003</id>
		<title>Gen Lang Programs</title>
		<link rel="alternate" type="text/html" href="https://wiki.thedarkmod.com/index.php?title=Gen_Lang_Programs&amp;diff=34003"/>
		<updated>2025-07-16T16:48:56Z</updated>

		<summary type="html">&lt;p&gt;Geep: /* Charpunts and Charpunts-Extra Options [PLUS Only] */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;By Geep, from February 2025&lt;br /&gt;
== Introduction to Gen_lang.pl (&amp;quot;PL&amp;quot;) and Gen_lang_plus (&amp;quot;PLUS&amp;quot;) ==&lt;br /&gt;
This describes two software implementations of command-line programs that essentially do the same thing;&lt;br /&gt;
# The Perl program &amp;quot;gen_lang.pl&amp;quot; (dubbed here PL), created by Tels in the 2010-14 timeframe. This is easily deployed under Linux that has Perl capabilities. Version 17 Is current.&lt;br /&gt;
# The C++ program &amp;quot;gen_lang_plus&amp;quot; (dubbed here PLUS), a re-implementation with minor improvements created by Geep in 2025. This is lightly Windows-specific at this time. (Please volunteer if you want to make it run under Linux.) Version 1.0 is current.&lt;br /&gt;
&lt;br /&gt;
The purpose of both is as follows.&lt;br /&gt;
* Read and write files in child folder &amp;quot;strings&amp;quot;. (Caution: &amp;quot;not strings/fm&amp;quot;, even if you specify the &amp;quot;fm&amp;quot; option.)&lt;br /&gt;
* Read an &amp;quot;all.lang&amp;quot; file, either that associated with the main-menu-system, or with a specific FM under development. This UTF-8 input file has translations of strings for all TDM-supported languages (currently 17). There are individual sections for each target language. Each string is of form&lt;br /&gt;
&lt;br /&gt;
 &amp;quot;#str_&amp;lt;id&amp;gt;&amp;quot; &amp;quot;&amp;lt;string content&amp;gt;&amp;quot; // optional comment.&lt;br /&gt;
* Generate a set of individual &amp;quot;&amp;lt;language&amp;gt;.lang&amp;quot; files, with the appropriate translated strings. Each file is generated in a standard 8-bit encoding (e.g., defined by one of the iso-8859 standards) designated for the target language. If a translator did not provide a given string in the target language, the master English string is automatically substituted.&lt;br /&gt;
* Finally, as requested by command-line options, various analyses can be performed. For example, a set of &amp;quot;missing_&amp;lt;language&amp;gt;.txt&amp;quot; files can be generated, to suggest where translation efforts are still needed.&lt;br /&gt;
This article details both programs, with important differences noted. Running this functionality is intended to be done, infrequently, by the person overseeing translation improvements to all.lang.&lt;br /&gt;
&lt;br /&gt;
For more quick overviews of this process, see&lt;br /&gt;
* the wiki article [[Internationalization]]. This also covers the i18n.pl program, which is beyond the scope here.&lt;br /&gt;
* the preamble of the all.lang file, found in tdm_base01.pk4&#039;s \strings\.&lt;br /&gt;
&lt;br /&gt;
It is helpful to mention what these two programs do &#039;&#039;&#039;not&#039;&#039;&#039; take into account:&lt;br /&gt;
* the &amp;lt;language&amp;gt;.map file that reroutes European codepoints from a standardized encoding to the TDM-specific custom 8-bit encoding discussed in [[I18N_-_Charset]].&lt;br /&gt;
* what UTF8 characters are allowed by that TDM-specific coding (as opposed to the ISO-8859 encoding).&lt;br /&gt;
* the font and fontsize a specific string will use, and what limitations that entails, and what within-DAT glyph-substitutions may be in effect.&lt;br /&gt;
&lt;br /&gt;
== Runtime Environment for PLUS ==&lt;br /&gt;
To function in all aspects, PLUS requires Windows with certain UTF8 capabilities, introduced in later versions of Windows 10. Because the PLUS build is told explicitly to use UTF8, in theory what your &amp;quot;system locale&amp;quot; is set to should not matter. In particular, you are not required you set the system locale to the Windows 11 beta UTF8 codepage. (PLUS was developed on a dev box with the English (US) locale.)&lt;br /&gt;
&lt;br /&gt;
You may run it under the traditional Windows console. However, that will not display UTF8 characters correctly on screen, which is mainly an issue with the -charstats and -charpunts options. Instead, use Windows Terminal (or Powershell with UTF8 encoding). Or pipe the console output to a file (i.e., &amp;quot;&amp;gt; myfile.txt&amp;quot;), that can be viewed as UTF8 with Notepad and other text editors.&lt;br /&gt;
&lt;br /&gt;
== Overview of Command-Line Options ==&lt;br /&gt;
&lt;br /&gt;
===For both PL and PLUS===&lt;br /&gt;
 --csv		Generate CSV file&lt;br /&gt;
 --missing	Generate files with lists of missing strings for each language.&lt;br /&gt;
 --charstats	Generate statistics about foreign characters.&lt;br /&gt;
 --show-ranges	Show occupied string index ranges.&lt;br /&gt;
 --show-holes	Show holes in the string index ranges.&lt;br /&gt;
&lt;br /&gt;
With PLUS, one may use a single &amp;quot;-&amp;quot; before an option, instead of &amp;quot;--&amp;quot;, and/or leave off the &amp;quot;show-&amp;quot; prefix. (Regarding &amp;quot;charstats&amp;quot;, for consistency, since this option outputs to screen, PL should have used the &amp;quot;show-&amp;quot; prefix, but didn&#039;t. PLUS does, optionally.)&lt;br /&gt;
&lt;br /&gt;
===For PLUS Only===&lt;br /&gt;
 -old-preamble					Keep &amp;lt;language&amp;gt;.lang preamble just like that of gen_lang.pl. Don&#039;t include file generation date or PLUS version number.&lt;br /&gt;
 -charpunts &#039;&#039;or&#039;&#039; --show-charpunts			Reports lines in which &amp;quot;?&amp;quot; was substituted for any character.&lt;br /&gt;
 -charpunts-extra &#039;&#039;or&#039;&#039; --show-charpunts-extra	Like charpunt, but includes &amp;quot;// comment&amp;quot; characters.&lt;br /&gt;
 -fm						Program used for an fm, not main menu; affects what&#039;s considered a valid numeric #str_&amp;lt;id&amp;gt; range.&lt;br /&gt;
 -cvs-unsorted					Like -csv, but row order stays like that of all.lang [English].&lt;br /&gt;
&lt;br /&gt;
== Charpunts and Charpunts-Extra Options [PLUS Only] ==&lt;br /&gt;
During generation of a particular &amp;lt;language&amp;gt;.lang file, if a valid data line contains 1 or more characters that can&#039;t be rendered in the target encoding, then a 3-line report is issued to console. Specifically:&lt;br /&gt;
 -charpunts		Considers characters within the line&#039;s content (excluding comments).&lt;br /&gt;
 -charpunts-extra	Same as charpunts, but also considers characters within the line&#039;s &amp;quot;// comment&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
When entering these options, you may use the &amp;quot;show-&amp;quot; prefix if you&#039;d like, with 1 or 2 leading dashes.&lt;br /&gt;
&lt;br /&gt;
By &amp;quot;// comment&amp;quot;, is meant the optional comment that starts with &amp;quot;//&amp;quot; at the end of a #str_&amp;lt;id&amp;gt; line (but still excluding any other comment forms; these latter won&#039;t be present in &amp;lt;language&amp;gt;.lang).&lt;br /&gt;
&lt;br /&gt;
Note – it is assumed that #str_&amp;lt;id&amp;gt; contains only 0-9, A-Z, a-z, or underline... so is not inspected by these options.&lt;br /&gt;
&lt;br /&gt;
An example report for [Hungarian] encoded as iso-8859-2:&lt;br /&gt;
&lt;br /&gt;
 Output line 177...&lt;br /&gt;
 from:   &amp;quot;#str_02208&amp;quot;    &amp;quot;Küldetési idõ&amp;quot;&lt;br /&gt;
   to:   &amp;quot;#str_02208&amp;quot;    &amp;quot;K�ldet�si id?&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Important: in this example, only õ, the last character in the &amp;quot;from:&amp;quot; line, could not be encoded in iso-8859-2 and so is replaced by &amp;quot;?&amp;quot; in the &amp;quot;to:&amp;quot; line. The &amp;quot;to:&amp;quot; line characters indicated by � were successfully encoded, but now are not valid UTF8, so can no longer be shown as such. That is, the &amp;quot;to:&amp;quot; line has the identical string placed into the hungarian.lang file.&lt;br /&gt;
&lt;br /&gt;
Here is an -charpunts-extra example where only the comment has characters that don&#039;t encode, in this case into iso-8859-1 for [English]:&lt;br /&gt;
&lt;br /&gt;
 Output line 396...&lt;br /&gt;
 from:   &amp;quot;#str_02482&amp;quot;    &amp;quot;Srpski&amp;quot;// Serbian (Српски - same exception as Russian)&lt;br /&gt;
   to:   &amp;quot;#str_02482&amp;quot;    &amp;quot;Srpski&amp;quot;// Serbian (?????? - same exception as Russian)&lt;br /&gt;
&lt;br /&gt;
TIP: If the results of this option is too voluminous, recall that output from a console app can be directed into a file using &amp;quot;... &amp;gt; filename.txt&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
These reports give the output line number within &amp;lt;language&amp;gt;.lang, rather than the input line in all.lang, because of difficulties getting the latter value to be correct in the face of, for instance, multiline comments. (Any line numbers that PL reports are usually off.)&lt;br /&gt;
&lt;br /&gt;
== Old Preamble Option [PLUS Only] ==&lt;br /&gt;
Each &amp;lt;language&amp;gt;.lang file gets a standard preamble. For PL, the first line looks like this example:&lt;br /&gt;
 // String table - english (iso-8859-1)&lt;br /&gt;
&lt;br /&gt;
For PLUS, the first line by default also has UTC time and program version, like this example:&lt;br /&gt;
 // String table - english (iso-8859-1) - created on 2025-02-15T04:00:21Z  with gen_lang_plus v. 1.0&lt;br /&gt;
&lt;br /&gt;
But you can ask PLUS to use PL&#039;s format, with the &amp;quot;-old-preamble&amp;quot; option. Why? To simplify comparing a particular &amp;lt;language&amp;gt;.lang file generated with both programs.&lt;br /&gt;
Since this is more a debugging option, it&#039;s not listed in the help, just here.&lt;br /&gt;
&lt;br /&gt;
== Missing Option ==&lt;br /&gt;
This option alerts translators to untranslated strings. For each language (other than English, the master) it generates a file named &amp;quot;missing_&amp;lt;language&amp;gt;.txt, with lists of missing UTF8 strings. Each line has the quoted #str_&amp;lt;id&amp;gt; and quoted content, but not comments.&lt;br /&gt;
&lt;br /&gt;
===What&#039;s Considered &amp;quot;Missing&amp;quot;?===&lt;br /&gt;
This categorization was established in PL and now mimicked in PLUS.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;If for a given master [English] #str_&amp;lt;id&amp;gt;, there&#039;s no matching #str_&amp;lt;id&amp;gt; in the target language.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
It&#039;s &amp;quot;missing&amp;quot;, unless there&#039;s a (hard-coded) exception:&lt;br /&gt;
&lt;br /&gt;
* The master string&#039;s content is in the &amp;quot;master_non_translatable&amp;quot; group, namely:&lt;br /&gt;
** An empty or whitespaces-only string.&lt;br /&gt;
** &amp;quot;TDM&amp;quot; or &amp;quot;The Dark Mod&amp;quot;.&lt;br /&gt;
** A prefix designating a function key (&amp;quot;F&amp;quot;) or port (&amp;quot;AUX&amp;quot; or &amp;quot;JOY&amp;quot;) followed by 1 or 2 digits.&lt;br /&gt;
** A special numeric format like &amp;quot;320x400;640x480&amp;quot; or &amp;quot;123;345&amp;quot; or &amp;quot;1x;2x&amp;quot;.&lt;br /&gt;
* The master string&#039;s content is a font selector, i.e., beginning with &amp;quot;fonts/&amp;quot;.&lt;br /&gt;
* The #str_&amp;lt;id&amp;gt; has a numeric &amp;lt;id&amp;gt; within a &amp;quot;master_id_non_translatable&amp;quot; range. Just one range, 02460 – 02490, is so reserved, for language names.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;If the #str_&amp;lt;id&amp;gt; in English and the target language have identical content (not counting comments)&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
It&#039;s &amp;quot;missing&amp;quot;, unless there&#039;s an exception:&lt;br /&gt;
&lt;br /&gt;
* The target line has a &amp;quot;//&amp;quot; comment indicating &amp;quot;stays the same&amp;quot;&lt;br /&gt;
* The &amp;quot;master_non_translatable&amp;quot;, font selector, or &amp;quot;master_id_non_translatable&amp;quot; exclusions apply.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Otherwise, it&#039;s not missing.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
That covers this additional case, where for the matching #str_&amp;lt;id&amp;gt; in English and the target language, there&#039;s different content (ignoring comments). Surprisingly, this is considered &amp;quot;not missing&amp;quot; even when the English content exists and the target language content is an empty string.&lt;br /&gt;
&lt;br /&gt;
Rarely, the master content can be empty, but the translated string may or may not be. An example is #str_02313, representing an optional second line needed for some languages.&lt;br /&gt;
&lt;br /&gt;
== CSV Options ==&lt;br /&gt;
These options read the contents of all.lang and rearrange them for export as a comma-separated-values &amp;quot;tdm_all_lang.csv&amp;quot; UTF8 file in the &amp;quot;strings&amp;quot; folder. The options have different generated row order:&lt;br /&gt;
&lt;br /&gt;
 -csv		Rows sorted by #str_&amp;lt;id&amp;gt;; seriously buggy ordering in PL, works in PLUS.&lt;br /&gt;
 -csv-unsorted	PLUS only. Keeps row order of [English] in all.lang&lt;br /&gt;
&lt;br /&gt;
The exported CSV file can then be imported into other tools for translators, e.g., Excel spreadsheets. Be aware as you process this data further: maintaining the UTF8 (or other Unicode) encoding ensures character integrity.&lt;br /&gt;
&lt;br /&gt;
=== Generated CVS File Format ===&lt;br /&gt;
The first line of the file has the field (aka column) headers, with languages in alphabetic order:&lt;br /&gt;
&lt;br /&gt;
 ID,catalan,czech,danish,dutch,english,french,german,hungarian,italian,polish,portuguese,romanian,russian,slovak,spanish,swedish,turkish,comment&lt;br /&gt;
There are 19 comma-separated fields here, so the results is very wide. (Recall in a spreadsheet, you can hide columns not of current interest.)&lt;br /&gt;
&lt;br /&gt;
Broadly, the .csv format comes in different variants. Traditionally, as here, comma is the separator. If a field contains a comma, the field overall is wrapped in double quotes. PL also so wraps if there&#039;s a contained double-quote, colon, or semi-colon. PLUS mimics that policy. PL unfortunately only considers the language fields for wrapping. PLUS goes a bit further, to consider the &amp;quot;comment&amp;quot; field.&lt;br /&gt;
&lt;br /&gt;
So, after the header each subsequent line has fields separated by commas, where:&lt;br /&gt;
&lt;br /&gt;
* The first field, &amp;quot;ID&amp;quot;, has #str_&amp;lt;id&amp;gt;. Unlike in all.lang, there are no enclosing double quotes.&lt;br /&gt;
* Remaining fields have translations. As expected, language fields are in the alphabetic header order shown, not necessarily the [language] section order in all.lang. English is in field 5. A field might be empty, have translation text, or have a copy of the master [English] text. (see &amp;quot;What&#039;s in Each Language Field&amp;quot; below). There are enclosing double quotes as needed.&lt;br /&gt;
* The last field has any comment from the master {English], beginning with &amp;quot;//&amp;quot;. If there was no comment, a trailing comma ends the line.&lt;br /&gt;
&lt;br /&gt;
An example row with some empty fields, for the English word &amp;quot;Error&amp;quot;, with no comment:&lt;br /&gt;
&lt;br /&gt;
 #str_02000,Error.,,Fejl,,Error,Erreur,Fehler,Hiba,Errore,Błąd,Erro,Eroare,Ошибка,Chyba,,,Hata,&lt;br /&gt;
Comments on source lines in sections other than [english] are not included.&lt;br /&gt;
&lt;br /&gt;
=== Sorted and Unsorted Row Orders ===&lt;br /&gt;
&lt;br /&gt;
With the -csv option:&lt;br /&gt;
&lt;br /&gt;
* For PLUS, the row order is sorted by #str_&amp;lt;id&amp;gt;.&lt;br /&gt;
* While PL intended the row order to be sorted by #str_&amp;lt;id&amp;gt;, the actual sorting is scattershot. (A cause may be the more-recent presence of numerous non-numeric IDs. The sort uses a custom comparator, which knows only about numeric IDs. Other IDs are &amp;quot;tied&amp;quot; in order, not good for many sort algorithms. The Perl code that writes the &amp;lt;language&amp;gt;.lang files uses a better comparator.) The workaround is to import the data into your spreadsheet (keeping UTF8 encoding) and do row sorting there.&lt;br /&gt;
&lt;br /&gt;
With the -csv-unsorted option [PLUS only]:&lt;br /&gt;
&lt;br /&gt;
* Sometimes, it is more helpful to have rows in the same order as in the master [english] section of all.lang, e.g., not necessarily sorted; so perhaps meaningfully grouped. (Caution: in all.lang, there is sometimes a preceding full-line comment that describes a given grouping. That will not be present in the .csv file.)&lt;br /&gt;
&lt;br /&gt;
=== What&#039;s in Each Language Field ===&lt;br /&gt;
As discussed above, a field will have enclosing double quotes as needed.&lt;br /&gt;
&lt;br /&gt;
The master &amp;quot;english&amp;quot; field, will simply have the [English] content (which could in rare cases be empty).&lt;br /&gt;
&lt;br /&gt;
The situation for other languages is more complex. PL appears, in its separate csv implementation, to be following a middle course, between:&lt;br /&gt;
* the &amp;quot;always use translation if available; otherwise English&amp;quot; policy for &amp;lt;language&amp;gt;.lang generation.&lt;br /&gt;
* the categorization of the Missing Option.&lt;br /&gt;
&lt;br /&gt;
To make clear the difference, we repeat the Missing Options description, but with &#039;&#039;&#039;lines crossed out&#039;&#039;&#039; below. (PLUS follows what PL does here, but FYI, there is commented-out code that could implement the crossed-out conditions.)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
A field considered &amp;quot;missing&amp;quot; will be empty (e.g., between 2 commas).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;If for a given master [English] #str_&amp;lt;id&amp;gt;, there&#039;s no matching #str_&amp;lt;id&amp;gt; in the target language.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
It&#039;s &amp;quot;missing&amp;quot;, unless there&#039;s a (hard-coded) exception:&lt;br /&gt;
* The master string&#039;s content is in the &amp;quot;master_non_translatable&amp;quot; group, namely:&lt;br /&gt;
** An empty or whitespaces-only string.&lt;br /&gt;
** &amp;quot;TDM&amp;quot; or &amp;quot;The Dark Mod&amp;quot;.&lt;br /&gt;
** A prefix designating a function key (&amp;quot;F&amp;quot;) or port (&amp;quot;AUX&amp;quot; or &amp;quot;JOY&amp;quot;) followed by 1 or 2 digits.&lt;br /&gt;
** A special numeric format like &amp;quot;320x400;640x480&amp;quot; or &amp;quot;123;345&amp;quot; or &amp;quot;1x;2x&amp;quot;.&lt;br /&gt;
* &amp;lt;s&amp;gt;The master string&#039;s content is a font selector, i.e., beginning with &amp;quot;fonts/&amp;quot;.&amp;lt;/s&amp;gt;&lt;br /&gt;
* &amp;lt;s&amp;gt;The #str_&amp;lt;id&amp;gt; has a numeric &amp;lt;id&amp;gt; within a &amp;quot;master_id_non_translatable&amp;quot; range. Just one range, 2460 – 2490, is so reserved, for language names.&amp;lt;/s&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In this case, if it&#039;s not missing, the &#039;&#039;&#039;master string&#039;s content&#039;&#039;&#039; will be used.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;If the #str_&amp;lt;id&amp;gt; in English and the target language have identical content (not counting comments)&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
It&#039;s &amp;quot;missing&amp;quot;, unless there&#039;s an exception:&lt;br /&gt;
* &amp;lt;s&amp;gt;The target line has a &amp;quot;// comment&amp;quot; indicating &amp;quot;stays the same&amp;quot;.&amp;lt;/s&amp;gt;&lt;br /&gt;
* The &amp;quot;master_non_translatable&amp;quot;, &amp;lt;s&amp;gt;font selector, or &amp;quot;master_id_non_translatable&amp;quot;&amp;lt;/s&amp;gt; exclusions apply.&lt;br /&gt;
&lt;br /&gt;
In this case, if it&#039;s not missing, the &#039;&#039;&#039;translated string content (same as master string&#039;s content)&#039;&#039;&#039; will be used. As indicated, any &amp;quot;stays the same&amp;quot; phrase in the line&#039;s comment within the [language] section is ignored.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Otherwise, it&#039;s not missing.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;&#039;translated string&#039;s content&#039;&#039;&#039; will be used. This is the normal &amp;quot;translation provided&amp;quot; case, where for the matching #str_&amp;lt;id&amp;gt; in English and the target language, there&#039;s different content (ignoring comments). Note that if English content exists but the target language content is an empty string, while this categorization would call it &amp;quot;not missing&amp;quot;, it still has the same result: nothing between the commmas.&lt;br /&gt;
&lt;br /&gt;
=== Differences in Comments between PL and PLUS ===&lt;br /&gt;
As noted above , PLUS will enclose the comment field in double quotes if needed. Also, if the comment field contains any unescaped double-quotes, they are backslash-escaped.&lt;br /&gt;
PL will do none of that. This is a bug. When the .csv file is imported into a spreadsheet, extra spurious columns may result, requiring manual fix-up.&lt;br /&gt;
Also, there is a difference in handling of how characters appear in comments. PLUS will preserve UTF8 characters. PL will replace characters not in ISO-8859-1 with &amp;quot;?&amp;quot; (resulting in the same appearance as in english.lang).&lt;br /&gt;
&lt;br /&gt;
== Charstats Option ==&lt;br /&gt;
Creating bitmap font glyphs can be a time-consuming process. This option provides information to suggest, among European (i.e., non-ASCII, non-Cyrillic) characters, which ones should take priority in that process, based on what translators have provided to all.lang.&lt;br /&gt;
&lt;br /&gt;
The results go to the console. PL and PLUS formats differ. PL groups compactly by &amp;quot;Top 5&amp;quot;, &amp;quot;Top 10&amp;quot;, and so on, and is not particularly Unicode-aware.&lt;br /&gt;
PLUS gives each character its own line, with rank and additional data. (And the output here is in utf8 form, better viewed in Windows Terminal than the traditional console. Or pipe to a text file that, e.g., Notepad can treat as UTF8.) Example output:&lt;br /&gt;
&lt;br /&gt;
 Non-ASCII UTF8 characters in &#039;all.lang&#039; across all languages except [Russian],&lt;br /&gt;
 by descending frequency. (Excludes characters in comments.)&lt;br /&gt;
 &lt;br /&gt;
 Rank, unicode codepoint, utf8 char, frequency (i.e., count out of 13563 total listed)&lt;br /&gt;
 &lt;br /&gt;
  1 U+00e1 á 1504&lt;br /&gt;
  2 U+00e9 é 1420&lt;br /&gt;
  3 U+00ed í 1099&lt;br /&gt;
  4 U+0131 ı 1075&lt;br /&gt;
  5 U+00fc ü 755&lt;br /&gt;
  6 U+010d č 644&lt;br /&gt;
  7 U+00f3 ó 498&lt;br /&gt;
  8 U+00f6 ö 418&lt;br /&gt;
  9 U+00fa ú 407&lt;br /&gt;
  ....&lt;br /&gt;
  93 U+0152 Œ 1&lt;br /&gt;
  94 U+0158 Ř 1&lt;br /&gt;
  95 U+0179 Ź 1&lt;br /&gt;
&lt;br /&gt;
== Ranges Option and Holes Option ==&lt;br /&gt;
Traditionally, #str_&amp;lt;id&amp;gt;s had only 5-digit numeric values. When a new string needed to be added (i.e., to the [English] master), it was helpful to know what numeric ranges were already fully in use, and conversely, what ranges are unoccupied, dubbed &amp;quot;holes&amp;quot;. With these options, that info gets reported to the console. Note that for PL, &amp;quot;holes&amp;quot; reports only if &amp;quot;ranges&amp;quot; is not given as an option. PLUS removes that restriction.&lt;br /&gt;
PL processes and reports &amp;lt;id&amp;gt;s in [English] listing order; if that is non-monotonic, this can cause anomalies for the &amp;quot;holes&amp;quot; output. To fix that, PLUS does a pre-sort into monotonic order.&lt;br /&gt;
PL and PLUS formats differ slightly. An example PLUS output for &amp;quot;-ranges&amp;quot;:&lt;br /&gt;
&lt;br /&gt;
 There are 48 occupied numeric #str_ ranges in [English]:&lt;br /&gt;
 &lt;br /&gt;
   1000-1019 (with 20 entries)&lt;br /&gt;
   1050-1062 (with 13 entries)&lt;br /&gt;
   1500-1503 (with 4 entries)&lt;br /&gt;
   2000-2016 (with 17 entries)&lt;br /&gt;
   ...&lt;br /&gt;
   8980-8988 (with 9 entries)&lt;br /&gt;
   10000-10162 (with 163 entries)&lt;br /&gt;
   10180-10185 (with 6 entries)&lt;br /&gt;
 &lt;br /&gt;
 Also, there are 54 non-numeric #str_ entries.&lt;br /&gt;
&lt;br /&gt;
In the last line, you see that, unlike PL, PLUS is aware of non-numeric &amp;lt;id&amp;gt;s, but just reports them as a total.&lt;br /&gt;
An example PLUS output for &amp;quot;-holes&amp;quot;:&lt;br /&gt;
&lt;br /&gt;
 There are 44 unoccupied numeric #str_ ranges (aka holes) in [English]:&lt;br /&gt;
 &lt;br /&gt;
   0-999 (with 1000 openings)&lt;br /&gt;
   1020-1049 (with 30 openings)&lt;br /&gt;
   1063-1499 (with 437 openings)&lt;br /&gt;
   1504-1999 (with 496 openings)&lt;br /&gt;
   ....&lt;br /&gt;
   8989-9999 (with 1011 openings)&lt;br /&gt;
   10163-10179 (with 17 openings)&lt;br /&gt;
   10185-19999 (with 9814 openings)&lt;br /&gt;
&lt;br /&gt;
The range from 20000-99999 is reserved for FMs. Using #str_&amp;lt;id&amp;gt; in that range in all.lang will trigger a fatal error (with the –range or –hole option). (See also the FM Option.)&lt;br /&gt;
&lt;br /&gt;
== FM Option [PLUS only] ==&lt;br /&gt;
By default, when either the -ranges or -holes option is in effect, the valid range for #str_&amp;lt;id&amp;gt; numeric values is enforced by PLUS as 0-19999. If you are using this for FM strings, select this option to make the valid range 20000-99999.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;These days, many but not all main menu #str_&amp;lt;id&amp;gt;s contain a substring &amp;quot;_menu_&amp;quot;. There could be future enforcement of alphanumeric substrings.&#039;&#039;&lt;br /&gt;
== Details about Main File Formats and Processing ==&lt;br /&gt;
&lt;br /&gt;
=== All.lang File Input Format ===&lt;br /&gt;
The file begins with a preamble (in C-style comment form) of notes for translators, some of which we restate here. Then an opening &amp;quot;{&amp;quot; by itself, followed by a series of language sections. Each starts with a line with one of these headers (shown in the order currently seen in the main menu all.lang file):&lt;br /&gt;
&lt;br /&gt;
 	[English]&lt;br /&gt;
 	[German]&lt;br /&gt;
 	[French]&lt;br /&gt;
 	[Italian]&lt;br /&gt;
 	[Spanish&lt;br /&gt;
 	[Polish]&lt;br /&gt;
 	[Romanian]&lt;br /&gt;
 	[Russian]&lt;br /&gt;
 	[Portuguese}&lt;br /&gt;
 	[Czech]&lt;br /&gt;
 	[Hungarian]&lt;br /&gt;
 	[Slovak]&lt;br /&gt;
 	[Swedish]&lt;br /&gt;
 	[Danish]&lt;br /&gt;
 	[Dutch]&lt;br /&gt;
 	[Turkish]&lt;br /&gt;
&lt;br /&gt;
Case of the language name doesn&#039;t matter, nor does order in which sections are listed. But it is a convention to list English first. After the header comes a series of convertible lines and comment lines, as discussed in next sections. The last line of the file has the closing &amp;quot;}&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
=== Converting Each Line ===&lt;br /&gt;
Within any particular language section of all.lang, a convertible line will have in this order:&lt;br /&gt;
&lt;br /&gt;
# A #str_&amp;lt;id&amp;gt;, in double quotes, where &amp;lt;id&amp;gt; is an unsigned integer, or a string composed of ASCII characters a-z, A-Z, 0-9, or underscore. Preferred for the latter are all lower case with underscores as word separators. Camel-case is tolerated, but not spaces or dashes. Ignoring the &amp;quot;#str_&amp;quot; prefix, the &amp;lt;id&amp;gt; must be no less than 5 and no more than 63 characters long. Leading zeros should be used to pad a numeric &amp;lt;id&amp;gt; to 5 digits. [Note: program i18n.pl possibly deals only with numeric &amp;lt;id&amp;gt;s.]&lt;br /&gt;
# The language-specific UTF8 &amp;lt;string content&amp;gt;, in double quotes&lt;br /&gt;
# An optional comment beginning with &amp;quot;//&amp;quot;. The next section covers overall treatment of comments.&lt;br /&gt;
&lt;br /&gt;
These are led and separated by whitespace. A leading tab is normal, with tab separators.&lt;br /&gt;
&lt;br /&gt;
No particular ordering of #str_&amp;lt;id&amp;gt;s is required, though ordering numeric &amp;lt;id&amp;gt;s (at least within sub-groups) is desirable.&lt;br /&gt;
==== Duplicates Across Lines Within a Section ====&lt;br /&gt;
If a particular &amp;lt;id&amp;gt; value appears more than once in a section, the last value is the effective one. A console warning will generally occur during parsing, in the case of PLUS like:&lt;br /&gt;
 Warning - #str_02518 redefined within [english]...&lt;br /&gt;
  from: malformed&lt;br /&gt;
  to:   100&lt;br /&gt;
&lt;br /&gt;
In the [English] section, there might be separate &amp;lt;id&amp;gt;s with the same content. This will generally cause a warning, in the case of PLUS like:&lt;br /&gt;
 Caution - These strings have the same content (&#039;Master&#039;): #str_08206, #str_03008&lt;br /&gt;
&lt;br /&gt;
To avoid the latter warning, a group of duplicates can be assigned a group number and hard-coded in the &amp;quot;master_double_exceptions&amp;quot; list. Only one group of ten members is so defined currently, those with a required empty string as content. More generally (says a PL comment):  &amp;quot;Sometimes it can make sense to have two different strings as when they are translated into different strings in another language. A [theoretical] example would be &amp;quot;Saw&amp;quot; (I saw something, ich hab etwas gesehen) and &amp;quot;Saw&amp;quot; (Saw, Säge).&amp;quot;&lt;br /&gt;
&lt;br /&gt;
==== Substituting English when No Translation ====&lt;br /&gt;
Ideally, a #str_&amp;lt;id&amp;gt; in the master [English] section has a match in a target language&#039;s section. Then the translated content will always be used for encoding and listing in the &amp;lt;language&amp;gt;.lang file. If no match, the English content is substituted. (Note that only a subset of these substituted strings will categorized as &amp;quot;Missing&amp;quot; if the -missing option is used. Also note that the substitution policy is slightly different with the -csv option.)&lt;br /&gt;
&lt;br /&gt;
==== Conversion Differences between PL and PLUS ====&lt;br /&gt;
* To do encoding, PL uses the Perl Encode module, that can autoload language-specific encode/decode tables.&lt;br /&gt;
* In the C++ implementation, source file &amp;quot;UTF8_8859_convert.cpp&amp;quot; includes similar (albeit custom) tables for the codepages TDM supports. The overall approach is convert from UTF8 to UTF16, then to the target ISO encoding.  That process does not use &amp;lt;locale&amp;gt; facets (which are problematic for our purposes), but standard C++ library &amp;quot;codecvt_utf8_utf16&amp;quot; and &amp;quot;wstring_convert&amp;quot; capabilities.&lt;br /&gt;
&lt;br /&gt;
=== The &amp;lt;language&amp;gt;.Lang File Output Format ===&lt;br /&gt;
* A preamble states the language name and specific ISO encoding.&lt;br /&gt;
* This is followed by the &amp;quot;#str_&amp;lt;id&amp;gt; ...&amp;quot; lines; sorted in alphabetic order; &amp;lt;id&amp;gt; in numeric form will be listed before those in alphabetic form.  Among the latter, an upper case letter will sort before all lower case letters.&lt;br /&gt;
* Trailing &amp;quot;//&amp;quot; comments  on &amp;quot;#str_&amp;lt;id&amp;gt;&amp;quot; lines from all.lang are preserved.&lt;br /&gt;
* Comments of the form /*...*/ in all.lang are skipped, whether spanning multiple lines or part of a single line.&lt;br /&gt;
* Blank lines, or lines with only whitespace or a &amp;quot;//&amp;quot; comment, are likewise skipped. The latter comments typically contain headers to organize groups of items in all.lang, but that organization is not retained, replaced by alphanumeric ordering as mentioned.&lt;br /&gt;
&lt;br /&gt;
==== Output File Differences between PL and PLUS ====&lt;br /&gt;
These differences are not thought to have functional implications:&lt;br /&gt;
&lt;br /&gt;
* The first line of the preamble will differ unless PLUS&#039;s -old_preamble option is used.&lt;br /&gt;
* Between a string content and any comment, PLUS preserves tabs and spaces found in all.lang, while PL substitutes two tabs. This is means that simple file comparison programs (like Windows &amp;quot;fc&amp;quot;, even with /T or /W options) will find lots of trivial differences. It is suggested you use a more sophisticated comparison tool, for instance, Notepad++ with the ComparePlus plugin and &amp;quot;Ignore changed spaces&amp;quot; selected.&lt;br /&gt;
&lt;br /&gt;
== Notes on PLUS Internals ==&lt;br /&gt;
A hand-crafted conversion from a static analysis of PL, PLUS preserves many variable names, some reimagined as functions. Befitting a straightforward conversion, it offers a procedural, C-like style, without much in the way of a class hierarchy, overarching object-oriented design pattern, or advanced C++ features. (This may be of benefit if part or all of its functionality is ever integrated into the TDM engine and/or DR.)&lt;br /&gt;
Not much effort was spent on performance optimization. However, as a compiled language, it will of course run much faster than PL. Also, the C++ implementation avoids use of regular expressions, which are heavily featured in PL and are notoriously slow and also hard for most coders to read.&lt;br /&gt;
&lt;br /&gt;
Platform-independent C++ standard-library structures like vectors, (ordered) sets, maps, and multimaps are employed. However, to do the UTF8 to ISO conversions, a Windows-specific approach is taken, to convert via unencoding from utf8 to wide characters and then re-encoding to target ISOs. (While it is possible to do such conversions entirely within 8-bit characters, the resulting code is a puzzle box, best left to third-party libraries.) Instead of using a third-party library, the encode/decode implementation here includes use of the &amp;quot;deprecated&amp;quot; C++ standard &amp;quot;codecvt&amp;quot; feature; while deprecated, the C++ standard committee has not (as of 2025) come up with a viable replacement.&lt;br /&gt;
&lt;br /&gt;
Like PL, PLUS has some DEBUG statements defined (requiring recompile for C++). These reflect specific concerns during development and testing and are of limited general interest.&lt;br /&gt;
&lt;br /&gt;
== Downloads ==&lt;br /&gt;
For PLUS v1.1 of 2025, July 16 (mainly adds Catalan as a supported language)&lt;br /&gt;
&lt;br /&gt;
[soon]&lt;br /&gt;
&lt;br /&gt;
For PLUS v1.0 of 2025, Feb 28:&lt;br /&gt;
&lt;br /&gt;
* [https://drive.google.com/file/d/1V_FSMEBYsinXPMKlH3_OmzcS8f1zjVeL/view?usp=sharing gen_lang_plus_source_v1.0.zip]. This is a Visual Studio project.&lt;br /&gt;
* [https://drive.google.com/file/d/1xsas9kZ-6tRdNdFhKHS736xYK5-aYGMg/view?usp=sharing gen_lang_plus.exe]&lt;br /&gt;
&lt;br /&gt;
== See Also ==&lt;br /&gt;
The Perl program &amp;quot;i18n.pl&amp;quot; contains similar functionality for FM-specific strings, but also parses and edits the FM .map file, so is considerably more complicated.&lt;/div&gt;</summary>
		<author><name>Geep</name></author>
	</entry>
	<entry>
		<id>https://wiki.thedarkmod.com/index.php?title=Gen_Lang_Programs&amp;diff=34002</id>
		<title>Gen Lang Programs</title>
		<link rel="alternate" type="text/html" href="https://wiki.thedarkmod.com/index.php?title=Gen_Lang_Programs&amp;diff=34002"/>
		<updated>2025-07-16T16:43:51Z</updated>

		<summary type="html">&lt;p&gt;Geep: Clarify use of strings folder; Get ready for v1.1 release.with Catalan&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;By Geep, from February 2025&lt;br /&gt;
== Introduction to Gen_lang.pl (&amp;quot;PL&amp;quot;) and Gen_lang_plus (&amp;quot;PLUS&amp;quot;) ==&lt;br /&gt;
This describes two software implementations of command-line programs that essentially do the same thing;&lt;br /&gt;
# The Perl program &amp;quot;gen_lang.pl&amp;quot; (dubbed here PL), created by Tels in the 2010-14 timeframe. This is easily deployed under Linux that has Perl capabilities. Version 17 Is current.&lt;br /&gt;
# The C++ program &amp;quot;gen_lang_plus&amp;quot; (dubbed here PLUS), a re-implementation with minor improvements created by Geep in 2025. This is lightly Windows-specific at this time. (Please volunteer if you want to make it run under Linux.) Version 1.0 is current.&lt;br /&gt;
&lt;br /&gt;
The purpose of both is as follows.&lt;br /&gt;
* Read and write files in child folder &amp;quot;strings&amp;quot;. (Caution: &amp;quot;not strings/fm&amp;quot;, even if you specify the &amp;quot;fm&amp;quot; option.)&lt;br /&gt;
* Read an &amp;quot;all.lang&amp;quot; file, either that associated with the main-menu-system, or with a specific FM under development. This UTF-8 input file has translations of strings for all TDM-supported languages (currently 17). There are individual sections for each target language. Each string is of form&lt;br /&gt;
&lt;br /&gt;
 &amp;quot;#str_&amp;lt;id&amp;gt;&amp;quot; &amp;quot;&amp;lt;string content&amp;gt;&amp;quot; // optional comment.&lt;br /&gt;
* Generate a set of individual &amp;quot;&amp;lt;language&amp;gt;.lang&amp;quot; files, with the appropriate translated strings. Each file is generated in a standard 8-bit encoding (e.g., defined by one of the iso-8859 standards) designated for the target language. If a translator did not provide a given string in the target language, the master English string is automatically substituted.&lt;br /&gt;
* Finally, as requested by command-line options, various analyses can be performed. For example, a set of &amp;quot;missing_&amp;lt;language&amp;gt;.txt&amp;quot; files can be generated, to suggest where translation efforts are still needed.&lt;br /&gt;
This article details both programs, with important differences noted. Running this functionality is intended to be done, infrequently, by the person overseeing translation improvements to all.lang.&lt;br /&gt;
&lt;br /&gt;
For more quick overviews of this process, see&lt;br /&gt;
* the wiki article [[Internationalization]]. This also covers the i18n.pl program, which is beyond the scope here.&lt;br /&gt;
* the preamble of the all.lang file, found in tdm_base01.pk4&#039;s \strings\.&lt;br /&gt;
&lt;br /&gt;
It is helpful to mention what these two programs do &#039;&#039;&#039;not&#039;&#039;&#039; take into account:&lt;br /&gt;
* the &amp;lt;language&amp;gt;.map file that reroutes European codepoints from a standardized encoding to the TDM-specific custom 8-bit encoding discussed in [[I18N_-_Charset]].&lt;br /&gt;
* what UTF8 characters are allowed by that TDM-specific coding (as opposed to the ISO-8859 encoding).&lt;br /&gt;
* the font and fontsize a specific string will use, and what limitations that entails, and what within-DAT glyph-substitutions may be in effect.&lt;br /&gt;
&lt;br /&gt;
== Runtime Environment for PLUS ==&lt;br /&gt;
To function in all aspects, PLUS requires Windows with certain UTF8 capabilities, introduced in later versions of Windows 10. Because the PLUS build is told explicitly to use UTF8, in theory what your &amp;quot;system locale&amp;quot; is set to should not matter. In particular, you are not required you set the system locale to the Windows 11 beta UTF8 codepage. (PLUS was developed on a dev box with the English (US) locale.)&lt;br /&gt;
&lt;br /&gt;
You may run it under the traditional Windows console. However, that will not display UTF8 characters correctly on screen, which is mainly an issue with the -charstats and -charpunts options. Instead, use Windows Terminal (or Powershell with UTF8 encoding). Or pipe the console output to a file (i.e., &amp;quot;&amp;gt; myfile.txt&amp;quot;), that can be viewed as UTF8 with Notepad and other text editors.&lt;br /&gt;
&lt;br /&gt;
== Overview of Command-Line Options ==&lt;br /&gt;
&lt;br /&gt;
===For both PL and PLUS===&lt;br /&gt;
 --csv		Generate CSV file&lt;br /&gt;
 --missing	Generate files with lists of missing strings for each language.&lt;br /&gt;
 --charstats	Generate statistics about foreign characters.&lt;br /&gt;
 --show-ranges	Show occupied string index ranges.&lt;br /&gt;
 --show-holes	Show holes in the string index ranges.&lt;br /&gt;
&lt;br /&gt;
With PLUS, one may use a single &amp;quot;-&amp;quot; before an option, instead of &amp;quot;--&amp;quot;, and/or leave off the &amp;quot;show-&amp;quot; prefix. (Regarding &amp;quot;charstats&amp;quot;, for consistency, since this option outputs to screen, PL should have used the &amp;quot;show-&amp;quot; prefix, but didn&#039;t. PLUS does, optionally.)&lt;br /&gt;
&lt;br /&gt;
===For PLUS Only===&lt;br /&gt;
 -old-preamble					Keep &amp;lt;language&amp;gt;.lang preamble just like that of gen_lang.pl. Don&#039;t include file generation date or PLUS version number.&lt;br /&gt;
 -charpunts &#039;&#039;or&#039;&#039; --show-charpunts			Reports lines in which &amp;quot;?&amp;quot; was substituted for any character.&lt;br /&gt;
 -charpunts-extra &#039;&#039;or&#039;&#039; --show-charpunts-extra	Like charpunt, but includes &amp;quot;// comment&amp;quot; characters.&lt;br /&gt;
 -fm						Program used for an fm, not main menu; affects what&#039;s considered a valid numeric #str_&amp;lt;id&amp;gt; range.&lt;br /&gt;
 -cvs-unsorted					Like -csv, but row order stays like that of all.lang [English].&lt;br /&gt;
&lt;br /&gt;
== Charpunts and Charpunts-Extra Options [PLUS Only] ==&lt;br /&gt;
During generation of a particular &amp;lt;language&amp;gt;.lang file, if a valid data line contains 1 or more characters that can&#039;t be rendered in the target encoding, then a 3-line report is issued to console. Specifically:&lt;br /&gt;
 -charpunts		Considers characters within the line&#039;s content (excluding comments).&lt;br /&gt;
 -charpunts-extra	Same as charpunts, but also considers characters within the line&#039;s &amp;quot;// comment&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
When entering these options, you may use the &amp;quot;show-&amp;quot; prefix if you&#039;d like, with 1 or 2 leading dashes.&lt;br /&gt;
&lt;br /&gt;
By &amp;quot;// comment&amp;quot;, is meant the optional comment that starts with &amp;quot;//&amp;quot; at the end of a #str_&amp;lt;id&amp;gt; line (but still excluding any other comment forms; these latter won&#039;t be present in &amp;lt;language&amp;gt;.lang).&lt;br /&gt;
&lt;br /&gt;
Note – it is assumed that #str_&amp;lt;id&amp;gt; contains only 0-9, A-Z, a-z, or underline... so is not inspected by these options.&lt;br /&gt;
&lt;br /&gt;
An example report for [Hungarian] encoded as iso-8859-2:&lt;br /&gt;
&lt;br /&gt;
 Output line 177...&lt;br /&gt;
 from:   &amp;quot;#str_02208&amp;quot;    &amp;quot;Küldetési idõ&amp;quot;&lt;br /&gt;
   to:   &amp;quot;#str_02208&amp;quot;    &amp;quot;K�ldet�si id?&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Important: in this example, only õ, the last character in the &amp;quot;from:&amp;quot; line, could not be encoded in iso-8859-2 and so is replaced by &amp;quot;?&amp;quot; in the &amp;quot;to:&amp;quot; line. The &amp;quot;to:&amp;quot; line characters indicated by � were successfully encoded, but now are not valid UTF8, so can no longer be shown as such. That is, the &amp;quot;to:&amp;quot; line has the identical string placed into the hungarian.lang file.&lt;br /&gt;
&lt;br /&gt;
Here is an -charpunts-extra example where only the comment has characters that don&#039;t encode, in this case into iso-8859-1 for [English]:&lt;br /&gt;
&lt;br /&gt;
 Output line 396...&lt;br /&gt;
 from:   &amp;quot;#str_02482&amp;quot;    &amp;quot;Srpski&amp;quot;// Serbian (Српски - same exception as Russian)&lt;br /&gt;
   to:   &amp;quot;#str_02482&amp;quot;    &amp;quot;Srpski&amp;quot;// Serbian (?????? - same exception as Russian)&lt;br /&gt;
&lt;br /&gt;
TIP: If the results of this option is too voluminous, recall that output from a console app can be directed into a file using &amp;quot;... &amp;gt; filename.txt&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
These reports give the output line number within &amp;lt;language&amp;gt;.lang, rather than the input line in all.lang, because of difficulties getting the latter value right in the face of, for instance, multiline comments. (Any line numbers that PL reports are usually off.)&lt;br /&gt;
&lt;br /&gt;
== Old Preamble Option [PLUS Only] ==&lt;br /&gt;
Each &amp;lt;language&amp;gt;.lang file gets a standard preamble. For PL, the first line looks like this example:&lt;br /&gt;
 // String table - english (iso-8859-1)&lt;br /&gt;
&lt;br /&gt;
For PLUS, the first line by default also has UTC time and program version, like this example:&lt;br /&gt;
 // String table - english (iso-8859-1) - created on 2025-02-15T04:00:21Z  with gen_lang_plus v. 1.0&lt;br /&gt;
&lt;br /&gt;
But you can ask PLUS to use PL&#039;s format, with the &amp;quot;-old-preamble&amp;quot; option. Why? To simplify comparing a particular &amp;lt;language&amp;gt;.lang file generated with both programs.&lt;br /&gt;
Since this is more a debugging option, it&#039;s not listed in the help, just here.&lt;br /&gt;
&lt;br /&gt;
== Missing Option ==&lt;br /&gt;
This option alerts translators to untranslated strings. For each language (other than English, the master) it generates a file named &amp;quot;missing_&amp;lt;language&amp;gt;.txt, with lists of missing UTF8 strings. Each line has the quoted #str_&amp;lt;id&amp;gt; and quoted content, but not comments.&lt;br /&gt;
&lt;br /&gt;
===What&#039;s Considered &amp;quot;Missing&amp;quot;?===&lt;br /&gt;
This categorization was established in PL and now mimicked in PLUS.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;If for a given master [English] #str_&amp;lt;id&amp;gt;, there&#039;s no matching #str_&amp;lt;id&amp;gt; in the target language.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
It&#039;s &amp;quot;missing&amp;quot;, unless there&#039;s a (hard-coded) exception:&lt;br /&gt;
&lt;br /&gt;
* The master string&#039;s content is in the &amp;quot;master_non_translatable&amp;quot; group, namely:&lt;br /&gt;
** An empty or whitespaces-only string.&lt;br /&gt;
** &amp;quot;TDM&amp;quot; or &amp;quot;The Dark Mod&amp;quot;.&lt;br /&gt;
** A prefix designating a function key (&amp;quot;F&amp;quot;) or port (&amp;quot;AUX&amp;quot; or &amp;quot;JOY&amp;quot;) followed by 1 or 2 digits.&lt;br /&gt;
** A special numeric format like &amp;quot;320x400;640x480&amp;quot; or &amp;quot;123;345&amp;quot; or &amp;quot;1x;2x&amp;quot;.&lt;br /&gt;
* The master string&#039;s content is a font selector, i.e., beginning with &amp;quot;fonts/&amp;quot;.&lt;br /&gt;
* The #str_&amp;lt;id&amp;gt; has a numeric &amp;lt;id&amp;gt; within a &amp;quot;master_id_non_translatable&amp;quot; range. Just one range, 02460 – 02490, is so reserved, for language names.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;If the #str_&amp;lt;id&amp;gt; in English and the target language have identical content (not counting comments)&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
It&#039;s &amp;quot;missing&amp;quot;, unless there&#039;s an exception:&lt;br /&gt;
&lt;br /&gt;
* The target line has a &amp;quot;//&amp;quot; comment indicating &amp;quot;stays the same&amp;quot;&lt;br /&gt;
* The &amp;quot;master_non_translatable&amp;quot;, font selector, or &amp;quot;master_id_non_translatable&amp;quot; exclusions apply.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Otherwise, it&#039;s not missing.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
That covers this additional case, where for the matching #str_&amp;lt;id&amp;gt; in English and the target language, there&#039;s different content (ignoring comments). Surprisingly, this is considered &amp;quot;not missing&amp;quot; even when the English content exists and the target language content is an empty string.&lt;br /&gt;
&lt;br /&gt;
Rarely, the master content can be empty, but the translated string may or may not be. An example is #str_02313, representing an optional second line needed for some languages.&lt;br /&gt;
&lt;br /&gt;
== CSV Options ==&lt;br /&gt;
These options read the contents of all.lang and rearrange them for export as a comma-separated-values &amp;quot;tdm_all_lang.csv&amp;quot; UTF8 file in the &amp;quot;strings&amp;quot; folder. The options have different generated row order:&lt;br /&gt;
&lt;br /&gt;
 -csv		Rows sorted by #str_&amp;lt;id&amp;gt;; seriously buggy ordering in PL, works in PLUS.&lt;br /&gt;
 -csv-unsorted	PLUS only. Keeps row order of [English] in all.lang&lt;br /&gt;
&lt;br /&gt;
The exported CSV file can then be imported into other tools for translators, e.g., Excel spreadsheets. Be aware as you process this data further: maintaining the UTF8 (or other Unicode) encoding ensures character integrity.&lt;br /&gt;
&lt;br /&gt;
=== Generated CVS File Format ===&lt;br /&gt;
The first line of the file has the field (aka column) headers, with languages in alphabetic order:&lt;br /&gt;
&lt;br /&gt;
 ID,catalan,czech,danish,dutch,english,french,german,hungarian,italian,polish,portuguese,romanian,russian,slovak,spanish,swedish,turkish,comment&lt;br /&gt;
There are 19 comma-separated fields here, so the results is very wide. (Recall in a spreadsheet, you can hide columns not of current interest.)&lt;br /&gt;
&lt;br /&gt;
Broadly, the .csv format comes in different variants. Traditionally, as here, comma is the separator. If a field contains a comma, the field overall is wrapped in double quotes. PL also so wraps if there&#039;s a contained double-quote, colon, or semi-colon. PLUS mimics that policy. PL unfortunately only considers the language fields for wrapping. PLUS goes a bit further, to consider the &amp;quot;comment&amp;quot; field.&lt;br /&gt;
&lt;br /&gt;
So, after the header each subsequent line has fields separated by commas, where:&lt;br /&gt;
&lt;br /&gt;
* The first field, &amp;quot;ID&amp;quot;, has #str_&amp;lt;id&amp;gt;. Unlike in all.lang, there are no enclosing double quotes.&lt;br /&gt;
* Remaining fields have translations. As expected, language fields are in the alphabetic header order shown, not necessarily the [language] section order in all.lang. English is in field 5. A field might be empty, have translation text, or have a copy of the master [English] text. (see &amp;quot;What&#039;s in Each Language Field&amp;quot; below). There are enclosing double quotes as needed.&lt;br /&gt;
* The last field has any comment from the master {English], beginning with &amp;quot;//&amp;quot;. If there was no comment, a trailing comma ends the line.&lt;br /&gt;
&lt;br /&gt;
An example row with some empty fields, for the English word &amp;quot;Error&amp;quot;, with no comment:&lt;br /&gt;
&lt;br /&gt;
 #str_02000,Error.,,Fejl,,Error,Erreur,Fehler,Hiba,Errore,Błąd,Erro,Eroare,Ошибка,Chyba,,,Hata,&lt;br /&gt;
Comments on source lines in sections other than [english] are not included.&lt;br /&gt;
&lt;br /&gt;
=== Sorted and Unsorted Row Orders ===&lt;br /&gt;
&lt;br /&gt;
With the -csv option:&lt;br /&gt;
&lt;br /&gt;
* For PLUS, the row order is sorted by #str_&amp;lt;id&amp;gt;.&lt;br /&gt;
* While PL intended the row order to be sorted by #str_&amp;lt;id&amp;gt;, the actual sorting is scattershot. (A cause may be the more-recent presence of numerous non-numeric IDs. The sort uses a custom comparator, which knows only about numeric IDs. Other IDs are &amp;quot;tied&amp;quot; in order, not good for many sort algorithms. The Perl code that writes the &amp;lt;language&amp;gt;.lang files uses a better comparator.) The workaround is to import the data into your spreadsheet (keeping UTF8 encoding) and do row sorting there.&lt;br /&gt;
&lt;br /&gt;
With the -csv-unsorted option [PLUS only]:&lt;br /&gt;
&lt;br /&gt;
* Sometimes, it is more helpful to have rows in the same order as in the master [english] section of all.lang, e.g., not necessarily sorted; so perhaps meaningfully grouped. (Caution: in all.lang, there is sometimes a preceding full-line comment that describes a given grouping. That will not be present in the .csv file.)&lt;br /&gt;
&lt;br /&gt;
=== What&#039;s in Each Language Field ===&lt;br /&gt;
As discussed above, a field will have enclosing double quotes as needed.&lt;br /&gt;
&lt;br /&gt;
The master &amp;quot;english&amp;quot; field, will simply have the [English] content (which could in rare cases be empty).&lt;br /&gt;
&lt;br /&gt;
The situation for other languages is more complex. PL appears, in its separate csv implementation, to be following a middle course, between:&lt;br /&gt;
* the &amp;quot;always use translation if available; otherwise English&amp;quot; policy for &amp;lt;language&amp;gt;.lang generation.&lt;br /&gt;
* the categorization of the Missing Option.&lt;br /&gt;
&lt;br /&gt;
To make clear the difference, we repeat the Missing Options description, but with &#039;&#039;&#039;lines crossed out&#039;&#039;&#039; below. (PLUS follows what PL does here, but FYI, there is commented-out code that could implement the crossed-out conditions.)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
A field considered &amp;quot;missing&amp;quot; will be empty (e.g., between 2 commas).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;If for a given master [English] #str_&amp;lt;id&amp;gt;, there&#039;s no matching #str_&amp;lt;id&amp;gt; in the target language.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
It&#039;s &amp;quot;missing&amp;quot;, unless there&#039;s a (hard-coded) exception:&lt;br /&gt;
* The master string&#039;s content is in the &amp;quot;master_non_translatable&amp;quot; group, namely:&lt;br /&gt;
** An empty or whitespaces-only string.&lt;br /&gt;
** &amp;quot;TDM&amp;quot; or &amp;quot;The Dark Mod&amp;quot;.&lt;br /&gt;
** A prefix designating a function key (&amp;quot;F&amp;quot;) or port (&amp;quot;AUX&amp;quot; or &amp;quot;JOY&amp;quot;) followed by 1 or 2 digits.&lt;br /&gt;
** A special numeric format like &amp;quot;320x400;640x480&amp;quot; or &amp;quot;123;345&amp;quot; or &amp;quot;1x;2x&amp;quot;.&lt;br /&gt;
* &amp;lt;s&amp;gt;The master string&#039;s content is a font selector, i.e., beginning with &amp;quot;fonts/&amp;quot;.&amp;lt;/s&amp;gt;&lt;br /&gt;
* &amp;lt;s&amp;gt;The #str_&amp;lt;id&amp;gt; has a numeric &amp;lt;id&amp;gt; within a &amp;quot;master_id_non_translatable&amp;quot; range. Just one range, 2460 – 2490, is so reserved, for language names.&amp;lt;/s&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In this case, if it&#039;s not missing, the &#039;&#039;&#039;master string&#039;s content&#039;&#039;&#039; will be used.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;If the #str_&amp;lt;id&amp;gt; in English and the target language have identical content (not counting comments)&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
It&#039;s &amp;quot;missing&amp;quot;, unless there&#039;s an exception:&lt;br /&gt;
* &amp;lt;s&amp;gt;The target line has a &amp;quot;// comment&amp;quot; indicating &amp;quot;stays the same&amp;quot;.&amp;lt;/s&amp;gt;&lt;br /&gt;
* The &amp;quot;master_non_translatable&amp;quot;, &amp;lt;s&amp;gt;font selector, or &amp;quot;master_id_non_translatable&amp;quot;&amp;lt;/s&amp;gt; exclusions apply.&lt;br /&gt;
&lt;br /&gt;
In this case, if it&#039;s not missing, the &#039;&#039;&#039;translated string content (same as master string&#039;s content)&#039;&#039;&#039; will be used. As indicated, any &amp;quot;stays the same&amp;quot; phrase in the line&#039;s comment within the [language] section is ignored.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Otherwise, it&#039;s not missing.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;&#039;translated string&#039;s content&#039;&#039;&#039; will be used. This is the normal &amp;quot;translation provided&amp;quot; case, where for the matching #str_&amp;lt;id&amp;gt; in English and the target language, there&#039;s different content (ignoring comments). Note that if English content exists but the target language content is an empty string, while this categorization would call it &amp;quot;not missing&amp;quot;, it still has the same result: nothing between the commmas.&lt;br /&gt;
&lt;br /&gt;
=== Differences in Comments between PL and PLUS ===&lt;br /&gt;
As noted above , PLUS will enclose the comment field in double quotes if needed. Also, if the comment field contains any unescaped double-quotes, they are backslash-escaped.&lt;br /&gt;
PL will do none of that. This is a bug. When the .csv file is imported into a spreadsheet, extra spurious columns may result, requiring manual fix-up.&lt;br /&gt;
Also, there is a difference in handling of how characters appear in comments. PLUS will preserve UTF8 characters. PL will replace characters not in ISO-8859-1 with &amp;quot;?&amp;quot; (resulting in the same appearance as in english.lang).&lt;br /&gt;
&lt;br /&gt;
== Charstats Option ==&lt;br /&gt;
Creating bitmap font glyphs can be a time-consuming process. This option provides information to suggest, among European (i.e., non-ASCII, non-Cyrillic) characters, which ones should take priority in that process, based on what translators have provided to all.lang.&lt;br /&gt;
&lt;br /&gt;
The results go to the console. PL and PLUS formats differ. PL groups compactly by &amp;quot;Top 5&amp;quot;, &amp;quot;Top 10&amp;quot;, and so on, and is not particularly Unicode-aware.&lt;br /&gt;
PLUS gives each character its own line, with rank and additional data. (And the output here is in utf8 form, better viewed in Windows Terminal than the traditional console. Or pipe to a text file that, e.g., Notepad can treat as UTF8.) Example output:&lt;br /&gt;
&lt;br /&gt;
 Non-ASCII UTF8 characters in &#039;all.lang&#039; across all languages except [Russian],&lt;br /&gt;
 by descending frequency. (Excludes characters in comments.)&lt;br /&gt;
 &lt;br /&gt;
 Rank, unicode codepoint, utf8 char, frequency (i.e., count out of 13563 total listed)&lt;br /&gt;
 &lt;br /&gt;
  1 U+00e1 á 1504&lt;br /&gt;
  2 U+00e9 é 1420&lt;br /&gt;
  3 U+00ed í 1099&lt;br /&gt;
  4 U+0131 ı 1075&lt;br /&gt;
  5 U+00fc ü 755&lt;br /&gt;
  6 U+010d č 644&lt;br /&gt;
  7 U+00f3 ó 498&lt;br /&gt;
  8 U+00f6 ö 418&lt;br /&gt;
  9 U+00fa ú 407&lt;br /&gt;
  ....&lt;br /&gt;
  93 U+0152 Œ 1&lt;br /&gt;
  94 U+0158 Ř 1&lt;br /&gt;
  95 U+0179 Ź 1&lt;br /&gt;
&lt;br /&gt;
== Ranges Option and Holes Option ==&lt;br /&gt;
Traditionally, #str_&amp;lt;id&amp;gt;s had only 5-digit numeric values. When a new string needed to be added (i.e., to the [English] master), it was helpful to know what numeric ranges were already fully in use, and conversely, what ranges are unoccupied, dubbed &amp;quot;holes&amp;quot;. With these options, that info gets reported to the console. Note that for PL, &amp;quot;holes&amp;quot; reports only if &amp;quot;ranges&amp;quot; is not given as an option. PLUS removes that restriction.&lt;br /&gt;
PL processes and reports &amp;lt;id&amp;gt;s in [English] listing order; if that is non-monotonic, this can cause anomalies for the &amp;quot;holes&amp;quot; output. To fix that, PLUS does a pre-sort into monotonic order.&lt;br /&gt;
PL and PLUS formats differ slightly. An example PLUS output for &amp;quot;-ranges&amp;quot;:&lt;br /&gt;
&lt;br /&gt;
 There are 48 occupied numeric #str_ ranges in [English]:&lt;br /&gt;
 &lt;br /&gt;
   1000-1019 (with 20 entries)&lt;br /&gt;
   1050-1062 (with 13 entries)&lt;br /&gt;
   1500-1503 (with 4 entries)&lt;br /&gt;
   2000-2016 (with 17 entries)&lt;br /&gt;
   ...&lt;br /&gt;
   8980-8988 (with 9 entries)&lt;br /&gt;
   10000-10162 (with 163 entries)&lt;br /&gt;
   10180-10185 (with 6 entries)&lt;br /&gt;
 &lt;br /&gt;
 Also, there are 54 non-numeric #str_ entries.&lt;br /&gt;
&lt;br /&gt;
In the last line, you see that, unlike PL, PLUS is aware of non-numeric &amp;lt;id&amp;gt;s, but just reports them as a total.&lt;br /&gt;
An example PLUS output for &amp;quot;-holes&amp;quot;:&lt;br /&gt;
&lt;br /&gt;
 There are 44 unoccupied numeric #str_ ranges (aka holes) in [English]:&lt;br /&gt;
 &lt;br /&gt;
   0-999 (with 1000 openings)&lt;br /&gt;
   1020-1049 (with 30 openings)&lt;br /&gt;
   1063-1499 (with 437 openings)&lt;br /&gt;
   1504-1999 (with 496 openings)&lt;br /&gt;
   ....&lt;br /&gt;
   8989-9999 (with 1011 openings)&lt;br /&gt;
   10163-10179 (with 17 openings)&lt;br /&gt;
   10185-19999 (with 9814 openings)&lt;br /&gt;
&lt;br /&gt;
The range from 20000-99999 is reserved for FMs. Using #str_&amp;lt;id&amp;gt; in that range in all.lang will trigger a fatal error (with the –range or –hole option). (See also the FM Option.)&lt;br /&gt;
&lt;br /&gt;
== FM Option [PLUS only] ==&lt;br /&gt;
By default, when either the -ranges or -holes option is in effect, the valid range for #str_&amp;lt;id&amp;gt; numeric values is enforced by PLUS as 0-19999. If you are using this for FM strings, select this option to make the valid range 20000-99999.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;These days, many but not all main menu #str_&amp;lt;id&amp;gt;s contain a substring &amp;quot;_menu_&amp;quot;. There could be future enforcement of alphanumeric substrings.&#039;&#039;&lt;br /&gt;
== Details about Main File Formats and Processing ==&lt;br /&gt;
&lt;br /&gt;
=== All.lang File Input Format ===&lt;br /&gt;
The file begins with a preamble (in C-style comment form) of notes for translators, some of which we restate here. Then an opening &amp;quot;{&amp;quot; by itself, followed by a series of language sections. Each starts with a line with one of these headers (shown in the order currently seen in the main menu all.lang file):&lt;br /&gt;
&lt;br /&gt;
 	[English]&lt;br /&gt;
 	[German]&lt;br /&gt;
 	[French]&lt;br /&gt;
 	[Italian]&lt;br /&gt;
 	[Spanish&lt;br /&gt;
 	[Polish]&lt;br /&gt;
 	[Romanian]&lt;br /&gt;
 	[Russian]&lt;br /&gt;
 	[Portuguese}&lt;br /&gt;
 	[Czech]&lt;br /&gt;
 	[Hungarian]&lt;br /&gt;
 	[Slovak]&lt;br /&gt;
 	[Swedish]&lt;br /&gt;
 	[Danish]&lt;br /&gt;
 	[Dutch]&lt;br /&gt;
 	[Turkish]&lt;br /&gt;
&lt;br /&gt;
Case of the language name doesn&#039;t matter, nor does order in which sections are listed. But it is a convention to list English first. After the header comes a series of convertible lines and comment lines, as discussed in next sections. The last line of the file has the closing &amp;quot;}&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
=== Converting Each Line ===&lt;br /&gt;
Within any particular language section of all.lang, a convertible line will have in this order:&lt;br /&gt;
&lt;br /&gt;
# A #str_&amp;lt;id&amp;gt;, in double quotes, where &amp;lt;id&amp;gt; is an unsigned integer, or a string composed of ASCII characters a-z, A-Z, 0-9, or underscore. Preferred for the latter are all lower case with underscores as word separators. Camel-case is tolerated, but not spaces or dashes. Ignoring the &amp;quot;#str_&amp;quot; prefix, the &amp;lt;id&amp;gt; must be no less than 5 and no more than 63 characters long. Leading zeros should be used to pad a numeric &amp;lt;id&amp;gt; to 5 digits. [Note: program i18n.pl possibly deals only with numeric &amp;lt;id&amp;gt;s.]&lt;br /&gt;
# The language-specific UTF8 &amp;lt;string content&amp;gt;, in double quotes&lt;br /&gt;
# An optional comment beginning with &amp;quot;//&amp;quot;. The next section covers overall treatment of comments.&lt;br /&gt;
&lt;br /&gt;
These are led and separated by whitespace. A leading tab is normal, with tab separators.&lt;br /&gt;
&lt;br /&gt;
No particular ordering of #str_&amp;lt;id&amp;gt;s is required, though ordering numeric &amp;lt;id&amp;gt;s (at least within sub-groups) is desirable.&lt;br /&gt;
==== Duplicates Across Lines Within a Section ====&lt;br /&gt;
If a particular &amp;lt;id&amp;gt; value appears more than once in a section, the last value is the effective one. A console warning will generally occur during parsing, in the case of PLUS like:&lt;br /&gt;
 Warning - #str_02518 redefined within [english]...&lt;br /&gt;
  from: malformed&lt;br /&gt;
  to:   100&lt;br /&gt;
&lt;br /&gt;
In the [English] section, there might be separate &amp;lt;id&amp;gt;s with the same content. This will generally cause a warning, in the case of PLUS like:&lt;br /&gt;
 Caution - These strings have the same content (&#039;Master&#039;): #str_08206, #str_03008&lt;br /&gt;
&lt;br /&gt;
To avoid the latter warning, a group of duplicates can be assigned a group number and hard-coded in the &amp;quot;master_double_exceptions&amp;quot; list. Only one group of ten members is so defined currently, those with a required empty string as content. More generally (says a PL comment):  &amp;quot;Sometimes it can make sense to have two different strings as when they are translated into different strings in another language. A [theoretical] example would be &amp;quot;Saw&amp;quot; (I saw something, ich hab etwas gesehen) and &amp;quot;Saw&amp;quot; (Saw, Säge).&amp;quot;&lt;br /&gt;
&lt;br /&gt;
==== Substituting English when No Translation ====&lt;br /&gt;
Ideally, a #str_&amp;lt;id&amp;gt; in the master [English] section has a match in a target language&#039;s section. Then the translated content will always be used for encoding and listing in the &amp;lt;language&amp;gt;.lang file. If no match, the English content is substituted. (Note that only a subset of these substituted strings will categorized as &amp;quot;Missing&amp;quot; if the -missing option is used. Also note that the substitution policy is slightly different with the -csv option.)&lt;br /&gt;
&lt;br /&gt;
==== Conversion Differences between PL and PLUS ====&lt;br /&gt;
* To do encoding, PL uses the Perl Encode module, that can autoload language-specific encode/decode tables.&lt;br /&gt;
* In the C++ implementation, source file &amp;quot;UTF8_8859_convert.cpp&amp;quot; includes similar (albeit custom) tables for the codepages TDM supports. The overall approach is convert from UTF8 to UTF16, then to the target ISO encoding.  That process does not use &amp;lt;locale&amp;gt; facets (which are problematic for our purposes), but standard C++ library &amp;quot;codecvt_utf8_utf16&amp;quot; and &amp;quot;wstring_convert&amp;quot; capabilities.&lt;br /&gt;
&lt;br /&gt;
=== The &amp;lt;language&amp;gt;.Lang File Output Format ===&lt;br /&gt;
* A preamble states the language name and specific ISO encoding.&lt;br /&gt;
* This is followed by the &amp;quot;#str_&amp;lt;id&amp;gt; ...&amp;quot; lines; sorted in alphabetic order; &amp;lt;id&amp;gt; in numeric form will be listed before those in alphabetic form.  Among the latter, an upper case letter will sort before all lower case letters.&lt;br /&gt;
* Trailing &amp;quot;//&amp;quot; comments  on &amp;quot;#str_&amp;lt;id&amp;gt;&amp;quot; lines from all.lang are preserved.&lt;br /&gt;
* Comments of the form /*...*/ in all.lang are skipped, whether spanning multiple lines or part of a single line.&lt;br /&gt;
* Blank lines, or lines with only whitespace or a &amp;quot;//&amp;quot; comment, are likewise skipped. The latter comments typically contain headers to organize groups of items in all.lang, but that organization is not retained, replaced by alphanumeric ordering as mentioned.&lt;br /&gt;
&lt;br /&gt;
==== Output File Differences between PL and PLUS ====&lt;br /&gt;
These differences are not thought to have functional implications:&lt;br /&gt;
&lt;br /&gt;
* The first line of the preamble will differ unless PLUS&#039;s -old_preamble option is used.&lt;br /&gt;
* Between a string content and any comment, PLUS preserves tabs and spaces found in all.lang, while PL substitutes two tabs. This is means that simple file comparison programs (like Windows &amp;quot;fc&amp;quot;, even with /T or /W options) will find lots of trivial differences. It is suggested you use a more sophisticated comparison tool, for instance, Notepad++ with the ComparePlus plugin and &amp;quot;Ignore changed spaces&amp;quot; selected.&lt;br /&gt;
&lt;br /&gt;
== Notes on PLUS Internals ==&lt;br /&gt;
A hand-crafted conversion from a static analysis of PL, PLUS preserves many variable names, some reimagined as functions. Befitting a straightforward conversion, it offers a procedural, C-like style, without much in the way of a class hierarchy, overarching object-oriented design pattern, or advanced C++ features. (This may be of benefit if part or all of its functionality is ever integrated into the TDM engine and/or DR.)&lt;br /&gt;
Not much effort was spent on performance optimization. However, as a compiled language, it will of course run much faster than PL. Also, the C++ implementation avoids use of regular expressions, which are heavily featured in PL and are notoriously slow and also hard for most coders to read.&lt;br /&gt;
&lt;br /&gt;
Platform-independent C++ standard-library structures like vectors, (ordered) sets, maps, and multimaps are employed. However, to do the UTF8 to ISO conversions, a Windows-specific approach is taken, to convert via unencoding from utf8 to wide characters and then re-encoding to target ISOs. (While it is possible to do such conversions entirely within 8-bit characters, the resulting code is a puzzle box, best left to third-party libraries.) Instead of using a third-party library, the encode/decode implementation here includes use of the &amp;quot;deprecated&amp;quot; C++ standard &amp;quot;codecvt&amp;quot; feature; while deprecated, the C++ standard committee has not (as of 2025) come up with a viable replacement.&lt;br /&gt;
&lt;br /&gt;
Like PL, PLUS has some DEBUG statements defined (requiring recompile for C++). These reflect specific concerns during development and testing and are of limited general interest.&lt;br /&gt;
&lt;br /&gt;
== Downloads ==&lt;br /&gt;
For PLUS v1.1 of 2025, July 16 (mainly adds Catalan as a supported language)&lt;br /&gt;
&lt;br /&gt;
[soon]&lt;br /&gt;
&lt;br /&gt;
For PLUS v1.0 of 2025, Feb 28:&lt;br /&gt;
&lt;br /&gt;
* [https://drive.google.com/file/d/1V_FSMEBYsinXPMKlH3_OmzcS8f1zjVeL/view?usp=sharing gen_lang_plus_source_v1.0.zip]. This is a Visual Studio project.&lt;br /&gt;
* [https://drive.google.com/file/d/1xsas9kZ-6tRdNdFhKHS736xYK5-aYGMg/view?usp=sharing gen_lang_plus.exe]&lt;br /&gt;
&lt;br /&gt;
== See Also ==&lt;br /&gt;
The Perl program &amp;quot;i18n.pl&amp;quot; contains similar functionality for FM-specific strings, but also parses and edits the FM .map file, so is considerably more complicated.&lt;/div&gt;</summary>
		<author><name>Geep</name></author>
	</entry>
	<entry>
		<id>https://wiki.thedarkmod.com/index.php?title=Installing_and_Running_Fan_Missions&amp;diff=34000</id>
		<title>Installing and Running Fan Missions</title>
		<link rel="alternate" type="text/html" href="https://wiki.thedarkmod.com/index.php?title=Installing_and_Running_Fan_Missions&amp;diff=34000"/>
		<updated>2025-07-01T19:53:54Z</updated>

		<summary type="html">&lt;p&gt;Geep: /* By installing with the in-game downloader */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Installing a New Mission =&lt;br /&gt;
&amp;lt;big&amp;gt;There are two ways to install a new mission:&lt;br /&gt;
# By downloading a mission pk4 file and placing it in the fms folder&lt;br /&gt;
# By using the in-game mission downloader&lt;br /&gt;
&amp;lt;/big&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== By downloading the mission PK4 ==&lt;br /&gt;
# Go to [https://www.thedarkmod.com/missions/ thedarkmod.com/missions] (say, by selecting &amp;quot;Missions&amp;quot; from the site top menu strip) to see a list of available FMs.&lt;br /&gt;
# For an FM of interest, click on &amp;quot;Download Details&amp;quot;.&lt;br /&gt;
# Each FM is contained in a PK4 file, which contains all the files necessary to run the mission. Choose one of the equivalent links to download, and drop the PK4 file into the fms/ folder, e.g. &amp;lt;tt&amp;gt;C:\Games\darkmod\fms\&amp;lt;/tt&amp;gt;.&lt;br /&gt;
# Launch The Dark Mod game to &#039;&#039;&#039;automatically install the mission&#039;&#039;&#039;. That is, upon launch, the game will detect the new mission package in the fms/ folder and will add it to the list of available missions. (Note: the PK4 file will be automatically moved into a subfolder. This is normal operation).&lt;br /&gt;
&lt;br /&gt;
== By installing with the in-game downloader == &lt;br /&gt;
[[Image:Download-mission210.jpg|right|thumb]]&lt;br /&gt;
# Launch The Dark Mod.&lt;br /&gt;
# From the main menu, click &#039;&#039;Mission List&#039;&#039; (&#039;&#039;formerly &#039;&#039;New Mission&#039;&#039;, as shown in figures here).&lt;br /&gt;
# Click &#039;&#039;Download Missions&#039;&#039; in the lower border of the Mission List.&lt;br /&gt;
&lt;br /&gt;
In this screen on the left is the &#039;&#039;Online Mission Archive&#039;&#039;, with a list of FMs that:&lt;br /&gt;
* you don&#039;t yet have, but are available to download and install; and&lt;br /&gt;
* you &#039;&#039;&#039;do&#039;&#039;&#039; have already installed, but that have an update or new (or at least not-yet-installed) translation available.&lt;br /&gt;
If you click on a listed mission, you see information under it. You can click on &#039;&#039;More...&#039;&#039; to get a more detailed screen with a description and screenshots from the mission.&lt;br /&gt;
&lt;br /&gt;
Last steps:&lt;br /&gt;
# With a row selected, click on &#039;&#039;Select for download&#039;&#039; to move a listing to the right-hand &#039;&#039;Download Status/Selected For DownLoad&#039;&#039; pane. Repeat to build up a list to download.&lt;br /&gt;
# Or &#039;&#039;Select all&#039;&#039; to download all missions, but &#039;&#039;&#039;not recommended&#039;&#039;&#039; because it will stress the download mirrors unnecessary.&lt;br /&gt;
# Then click &amp;quot;Start Download&amp;quot;. FMs will be queued to download and automatically install.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Selecting a New or Different Mission to Play =&lt;br /&gt;
[[Image:new-mission210.jpg|right|thumb]]&lt;br /&gt;
# From the main menu, click &#039;&#039;Mission List&#039;&#039;&lt;br /&gt;
# On the right of the screen, you&#039;ll see a list of available missions that you&#039;ve installed.&lt;br /&gt;
# Click on a mission within the list. Information about it will pop up in the left pane (as shown in figure), and &#039;&#039;Notes&#039;&#039; often has more.&lt;br /&gt;
# When you&#039;ve made your choice, click &#039;&#039;Select Mission&#039;&#039; at the lower right corner. &lt;br /&gt;
# The game will restart itself automatically.&amp;lt;br style=&amp;quot;clear: both&amp;quot; /&amp;gt;&lt;br /&gt;
== Starting the mission ==&lt;br /&gt;
After the restart, click &#039;&#039;Start this Mission&#039;&#039;. You&#039;ll be taken to the mission&#039;s briefing.&amp;lt;br style=&amp;quot;clear: both&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Resuming a mission ==&lt;br /&gt;
Once installed, a Fan Mission will stay installed until you uninstall it (click &#039;&#039;deselect mission&#039;&#039;) or install a different FM. As each Fan Mission is &amp;quot;run&amp;quot; in a separate folder, your savegames &#039;&#039;&#039;will be preserved&#039;&#039;&#039; when switching between them. (However, a savefile will generally not be functional after an update to its FM or core TDM.)&lt;br /&gt;
&lt;br /&gt;
To resume a mission from a savegame, make sure the FM is installed, then just go to the Load/Save game menu and select one from the list.&lt;br /&gt;
&lt;br /&gt;
== Updating a mission ==&lt;br /&gt;
Whenever the mission author releases a new version of his FM, you need to re-install the mission. Missions do not auto-update. See above for instructions.&lt;br /&gt;
&lt;br /&gt;
= Does a Mission Have Translations? =&lt;br /&gt;
Some FMs support additional languages besides English, contained in a &amp;quot;Localization Pack&amp;quot;. This is a separate PK4 file, routinely named &amp;lt;myFM&amp;gt;_l10n_&amp;lt;checksum&amp;gt;.pk4, where &amp;quot;l10n&amp;quot; abbreviates &amp;quot;localization&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
== Overviews across FMs ==&lt;br /&gt;
For an overview of which FMs have Localization Packs, see [[Fan Missions for The Dark Mod]], and look at the table&#039;s &#039;Translation Pack&#039; column. &lt;br /&gt;
&lt;br /&gt;
Unfortunately, at this time it is difficult to know which FMs have a Localization Pack that includes &#039;&#039;your&#039;&#039; particular language of interest. The [[I18N Status]] page (where &amp;quot;I18N&amp;quot; stands for Internationalization) gives information about some older FMs, but has not been updated for quite awhile.&lt;br /&gt;
&lt;br /&gt;
== For a Given FM ==&lt;br /&gt;
It&#039;s easy enough to verify if a Localization Pack is available; the installation process described below will let you know if not.&lt;br /&gt;
&lt;br /&gt;
As for support for a particular language, after you install the Localization Pack:&lt;br /&gt;
* look within the .pk4 (temporarily renamed to .zip if necessary) and its /strings/ folder. The presence of a *.lang (e.g., french.lang) is required for support.&lt;br /&gt;
* or just play the game to find out. Be aware that there are degrees of translation support.&lt;br /&gt;
 &lt;br /&gt;
= Installing a Mission&#039;s Translations =&lt;br /&gt;
The basic install above provides English. &#039;&#039;&#039;Do that first&#039;&#039;&#039;. There are then two official ways to get and install a Localization Pack.&lt;br /&gt;
&lt;br /&gt;
== By downloading the localization pack ==&lt;br /&gt;
Starting from the site&#039;s &#039;&#039;Mission&#039;&#039; page and then to the &#039;&#039;Download Details&#039;&#039; page for given FM, the Localization Packs section will tell you if a pack of translations is available, and if so provide a choice of equivalent links. [I guess download into the /fms folder and get it auto-installed on game restart? Or download it into the particular /fm folder? TBD]&lt;br /&gt;
&lt;br /&gt;
== By installing with the in-game downloader ==&lt;br /&gt;
For this process to work, you must have already installed the FM. Then, revisit the &#039;&#039;Online Mission Archive&#039;&#039; page. Is there an &amp;quot;#&amp;quot; annotation (for &amp;quot;# Translation&amp;quot;) next to your FM name? Then &#039;&#039;&#039;download again&#039;&#039;&#039; to get the Pack and have it auto-installed. Note - Only in the &#039;Online Mission Archive&#039; page will there be &amp;quot;#&amp;quot; and &amp;quot;*&amp;quot; (for &amp;quot;* Update&amp;quot;) annotations; not in the Mission List page.&lt;br /&gt;
&lt;br /&gt;
== See also ==&lt;br /&gt;
* [[The Dark Mod Gameplay]]&lt;br /&gt;
* [[FAQ]] (for troubleshooting etc.)&lt;br /&gt;
[[Category:Gameplay]]&lt;br /&gt;
[[Category:Fan Missions]]&lt;br /&gt;
[[Category:Gameplay concepts and settings]]&lt;/div&gt;</summary>
		<author><name>Geep</name></author>
	</entry>
	<entry>
		<id>https://wiki.thedarkmod.com/index.php?title=I18N.pl&amp;diff=33987</id>
		<title>I18N.pl</title>
		<link rel="alternate" type="text/html" href="https://wiki.thedarkmod.com/index.php?title=I18N.pl&amp;diff=33987"/>
		<updated>2025-06-19T02:02:47Z</updated>

		<summary type="html">&lt;p&gt;Geep: In Intro, correct &amp;quot;fm_translate.pl&amp;quot; to &amp;quot;I18N.pl&amp;quot;. Add missing step to make strings folder &amp;amp; copy english.lang&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction ==&lt;br /&gt;
&lt;br /&gt;
The script I18N.pl separates the main FM data from all the texts and other assets that need to be changed in order for translation. It can either transform an English FM, or match an English FM to other languages.&lt;br /&gt;
&lt;br /&gt;
== Requirements ==&lt;br /&gt;
&lt;br /&gt;
* Perl. For Windows, use [http://strawberryperl.com/ Strawberry Perl].&lt;br /&gt;
* The script from [http://bloodgate.com/mirrors/tdm/pub/scripts/ Bloodgate].&lt;br /&gt;
* The TDM-distribution language files under &#039;&#039;&#039;&amp;lt;tt&amp;gt;strings/*.lang&amp;lt;/tt&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
== Usage ==&lt;br /&gt;
&lt;br /&gt;
In the following examples we will use &#039;&#039;myfm&#039;&#039; in place of your FM name:&lt;br /&gt;
&lt;br /&gt;
=== Windows ===&lt;br /&gt;
&lt;br /&gt;
* Install Perl from [http://strawberryperl.com/ Strawberry Perl]. You may need to reboot&lt;br /&gt;
* Download &#039;&#039;&#039;I18N_script.zip&#039;&#039;&#039; from [http://bloodgate.com/mirrors/tdm/pub/scripts/ here].&lt;br /&gt;
* Extract the contents of this file to somewhere, f.i. &amp;lt;tt&amp;gt;&#039;&#039;&#039;C:\&#039;&#039;&#039;&amp;lt;/tt&amp;gt;, so that you now have there an I18N directory with a directory &#039;&#039;I18N.pl&#039;&#039; in it. The text below assumes you have choosen that path. If not, replace it everywhere it occurs.&lt;br /&gt;
* Open this directory in Explorer, and copy your FM&#039;s PK4 file to it (for example &amp;quot;myfm.pk4&amp;quot;)&lt;br /&gt;
* If you have other versions of your FM in a different language, copy them there, too. For instance if you have a file named &amp;quot;myfm_italian.pk4&amp;quot; which is &#039;&#039;&#039;the same version of your FM, but in Italian&#039;&#039;&#039;, then copy it there, too.&lt;br /&gt;
* Open a console aka a &amp;quot;DOS Window&amp;quot; (see [http://www.computerhope.com/issues/chdos.htm here] if you do not know how to do this)&lt;br /&gt;
* Navigate to the directory you have uncompressed the script to, e.g. by typing&lt;br /&gt;
&lt;br /&gt;
 chdir c:\I18N\I18N.pl&lt;br /&gt;
&lt;br /&gt;
* Make a &amp;quot;\strings\&amp;quot; subdirectory, and copy TDM&#039;s &amp;quot;english.lang&amp;quot; there (and any other .lang files for which you have myfm_&amp;lt;lang&amp;gt;.pk4 versions).&lt;br /&gt;
* Run the script (we assume here you have only the english version:)&lt;br /&gt;
&lt;br /&gt;
 perl I18N.pl --english myfm.pk4&lt;br /&gt;
&lt;br /&gt;
The output packages will be created under output, as:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
C:\I18N\I18N.pl\output\myfm.pk4&lt;br /&gt;
C:\I18N\I18N.pl\output\myfm_l10n.pk4&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Linux ===&lt;br /&gt;
&lt;br /&gt;
* Install Perl (it is probably already installed)&lt;br /&gt;
* Download &#039;&#039;&#039;I18N_script.zip&#039;&#039;&#039; from [http://bloodgate.com/mirrors/tdm/pub/scripts/ here].&lt;br /&gt;
* Extract the contents of this file to somewhere, f.i. &amp;lt;tt&amp;gt;&#039;&#039;&#039;/home/yourusernamehere/&#039;&#039;&#039;&amp;lt;/tt&amp;gt;, so that you now have there an I18N directory with a file &#039;&#039;I18N.pl&#039;&#039; in it. The text below assumes you have choosen that path. If not, replace it everywhere it occurs.&lt;br /&gt;
* Open this directory in your favourite file manager, and copy your FM&#039;s PK4 file to it (for example &#039;&#039;&#039;&amp;lt;tt&amp;gt;myfm.pk4&amp;lt;/tt&amp;gt;&#039;&#039;&#039;)&lt;br /&gt;
* If you have other versions of your FM in a different language, copy them there, too. For instance if you have a file named &amp;lt;tt&amp;gt;&#039;&#039;&#039;myfm_italian.pk4&#039;&#039;&#039;&amp;lt;/tt&amp;gt; which is &#039;&#039;&#039;the same version of your FM, but in Italian&#039;&#039;&#039;, then copy it there, too.&lt;br /&gt;
* Open a console&lt;br /&gt;
* Navigate to the directory you have uncompressed the script to, e.g. by typing&lt;br /&gt;
&lt;br /&gt;
 cd ~/I18N/I18N.pl&lt;br /&gt;
&lt;br /&gt;
* Make a &amp;quot;/strings/&amp;quot; subdirectory, and copy TDM&#039;s &amp;quot;english.lang&amp;quot; there (and any other .lang files for which you have myfm_&amp;lt;lang&amp;gt;.pk4 versions).&lt;br /&gt;
* Run the script (we assume here you have only the english version:)&lt;br /&gt;
&lt;br /&gt;
 perl I18N.pl --english myfm.pk4&lt;br /&gt;
&lt;br /&gt;
The output packages will be created under output, as:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
./output/myfm.pk4&lt;br /&gt;
./output/myfm_l10n.pk4&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== The FM dictionaries ==&lt;br /&gt;
&lt;br /&gt;
Once the script is finished, it will replace as much hard-coded strings like &amp;quot;Silver Key&amp;quot; with string templates like &amp;quot;#str_20000&amp;quot; and place these in a FM-specific dictionary. These dictionaries are put into a sep. PK4 file (named &#039;&#039;myfm_l10n.pk4&#039;&#039;), they can be found inside this file under the directory &#039;&#039;&#039;strings/fm/&#039;&#039;&#039;. &lt;br /&gt;
&lt;br /&gt;
See &#039;&#039;&#039;[[I18N - Translating Fan Missions|here]]&#039;&#039;&#039; for examples and how to translate these files.&lt;br /&gt;
&lt;br /&gt;
== Bugs ==&lt;br /&gt;
&lt;br /&gt;
=== GUI files ===&lt;br /&gt;
&lt;br /&gt;
Currently GUI files are not parsed, and thus their strings not entered into the FM dictionary. Mainly this means you need to manually edit &#039;&#039;&#039;guis/maps/FMNAME.gui&#039;&#039;&#039; and replace things like:&lt;br /&gt;
&lt;br /&gt;
 text   &amp;quot;Mission Loading&amp;quot;&lt;br /&gt;
&lt;br /&gt;
with&lt;br /&gt;
&lt;br /&gt;
 text   &amp;quot;#str_02236&amp;quot;       // Mission Loading&lt;br /&gt;
&lt;br /&gt;
If there are other texts in it, like &amp;quot;Loading finished&amp;quot;, and these cannot be found in strings/all.lang in the TDM core, then you need to use numbers above 20000 (best use 20100 and above) and then also add the strings into the &#039;&#039;&#039;strings/fm/english.lang&#039;&#039;&#039; etc. file.&lt;br /&gt;
&lt;br /&gt;
{{infobox|Also note that the main PK4 file should &#039;&#039;&#039;always&#039;&#039;&#039; contain a copy of the strings/fm/english.lang file, so that people who do not have the _l10n.pk4 file can still play the FM.}}&lt;br /&gt;
&lt;br /&gt;
=== README.txt and darkmod.txt ===&lt;br /&gt;
&lt;br /&gt;
Due to [http://bugs.thedarkmod.com/view.php?id=3012 bug #3012] README.txt and darkmod.txt cannot yet be translated.&lt;br /&gt;
&lt;br /&gt;
== FAQ ==&lt;br /&gt;
&lt;br /&gt;
=== Do I need different languages of my FM? ===&lt;br /&gt;
&lt;br /&gt;
No, the script can also just use the English version. But the English version is mandatory, you cannot just use a French FM!&lt;br /&gt;
&lt;br /&gt;
=== How must the PK4 files be named? ===&lt;br /&gt;
&lt;br /&gt;
The names can be anything, they are not important.&lt;br /&gt;
&lt;br /&gt;
=== Do I need to increase the version of my FM? ===&lt;br /&gt;
&lt;br /&gt;
The FM database on thedarkmod.com uses an arbitrary integer to denote the current version, everytime this is incremented, users which have the same FM with a lesser number get asked to upgrade it.&lt;br /&gt;
&lt;br /&gt;
However, it is a wise idea to increase the version in your README, too, because that is the one that users will refer to when talking about your FM.&lt;br /&gt;
&lt;br /&gt;
=== My mission has image files with text on it. How do I translate them? ===&lt;br /&gt;
&lt;br /&gt;
See this article [[I18N - Translating Fan Missions|Translating Fan Missions]].&lt;br /&gt;
&lt;br /&gt;
=== Who can do the translation? ===&lt;br /&gt;
&lt;br /&gt;
Anybody who wants to. There is a [[I18N_-_List_of_TDM_translators|list of translators]], these people might be able to help you.&lt;br /&gt;
&lt;br /&gt;
== See also ==&lt;br /&gt;
&lt;br /&gt;
* [[Internationalization]] - Main article&lt;br /&gt;
* [[I18N - Translating Fan Missions|Translating Fan Missions]]&lt;br /&gt;
* [http://strawberryperl.com/ Strawberry Perl].&lt;br /&gt;
* [http://bloodgate.com/mirrors/tdm/pub/scripts/I18N_script.zip The script itself]&lt;br /&gt;
&lt;br /&gt;
{{editing}}&lt;/div&gt;</summary>
		<author><name>Geep</name></author>
	</entry>
	<entry>
		<id>https://wiki.thedarkmod.com/index.php?title=Installing_and_Running_Fan_Missions&amp;diff=33982</id>
		<title>Installing and Running Fan Missions</title>
		<link rel="alternate" type="text/html" href="https://wiki.thedarkmod.com/index.php?title=Installing_and_Running_Fan_Missions&amp;diff=33982"/>
		<updated>2025-06-09T21:54:14Z</updated>

		<summary type="html">&lt;p&gt;Geep: Add translation info&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Installing a New Mission =&lt;br /&gt;
&amp;lt;big&amp;gt;There are two ways to install a new mission:&lt;br /&gt;
# By downloading a mission pk4 file and placing it in the fms folder&lt;br /&gt;
# By using the in-game mission downloader&lt;br /&gt;
&amp;lt;/big&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== By downloading the mission PK4 ==&lt;br /&gt;
# Go to [https://www.thedarkmod.com/missions/ thedarkmod.com/missions] (say, by selecting &amp;quot;Missions&amp;quot; from the site top menu strip) to see a list of available FMs.&lt;br /&gt;
# For an FM of interest, click on &amp;quot;Download Details&amp;quot;.&lt;br /&gt;
# Each FM is contained in a PK4 file, which contains all the files necessary to run the mission. Choose one of the equivalent links to download, and drop the PK4 file into the fms/ folder, e.g. &amp;lt;tt&amp;gt;C:\Games\darkmod\fms\&amp;lt;/tt&amp;gt;.&lt;br /&gt;
# Launch The Dark Mod game to &#039;&#039;&#039;automatically install the mission&#039;&#039;&#039;. That is, upon launch, the game will detect the new mission package in the fms/ folder and will add it to the list of available missions. (Note: the PK4 file will be automatically moved into a subfolder. This is normal operation).&lt;br /&gt;
&lt;br /&gt;
== By installing with the in-game downloader == &lt;br /&gt;
[[Image:Download-mission210.jpg|right|thumb]]&lt;br /&gt;
# Launch The Dark Mod.&lt;br /&gt;
# From the main menu, click &#039;&#039;Mission List&#039;&#039; (&#039;&#039;formerly &#039;&#039;New Mission&#039;&#039;, as shown in figures here).&lt;br /&gt;
# Click &#039;&#039;Download Missions&#039;&#039; in the lower border of the Mission List.&lt;br /&gt;
&lt;br /&gt;
In this screen on the left is the &#039;&#039;Online Mission Archive&#039;&#039;, with a list of FMs that:&lt;br /&gt;
* you don&#039;t yet have, but are available to download and install; and&lt;br /&gt;
* you &#039;&#039;&#039;do&#039;&#039;&#039; have already installed, but that have an update or new (or at least not-yet-installed) translation available.&lt;br /&gt;
If you click on a listed mission, you see information under it. You can click on &#039;&#039;More...&#039;&#039; to get a more detailed screen with a description and screenshots from the mission.&lt;br /&gt;
&lt;br /&gt;
Last steps:&lt;br /&gt;
# With a row selected, click on &#039;&#039;Select for download&#039;&#039; to move a listing to the right-hand &#039;&#039;Download Status/Selected For DownLoad&#039;&#039; pane. Repeat to build up a list to download.&lt;br /&gt;
# Or &#039;&#039;Select all&#039;&#039; to download all missions, but &#039;&#039;&#039;not recommended&#039;&#039;&#039; because it will stress the download mirrors unnecessary.&lt;br /&gt;
# Then click &amp;quot;Start Download&amp;quot;. FMs will be queued to download and automatically install.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Selecting a New or Different Mission to Play =&lt;br /&gt;
[[Image:new-mission210.jpg|right|thumb]]&lt;br /&gt;
# From the main menu, click &#039;&#039;Mission List&#039;&#039;&lt;br /&gt;
# On the right of the screen, you&#039;ll see a list of available missions that you&#039;ve installed.&lt;br /&gt;
# Click on a mission within the list. Information about it will pop up in the left pane (as shown in figure), and &#039;&#039;Notes&#039;&#039; often has more.&lt;br /&gt;
# When you&#039;ve made your choice, click &#039;&#039;Select Mission&#039;&#039; at the lower right corner. &lt;br /&gt;
# The game will restart itself automatically.&amp;lt;br style=&amp;quot;clear: both&amp;quot; /&amp;gt;&lt;br /&gt;
== Starting the mission ==&lt;br /&gt;
After the restart, click &#039;&#039;Start this Mission&#039;&#039;. You&#039;ll be taken to the mission&#039;s briefing.&amp;lt;br style=&amp;quot;clear: both&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Resuming a mission ==&lt;br /&gt;
Once installed, a Fan Mission will stay installed until you uninstall it (click &#039;&#039;deselect mission&#039;&#039;) or install a different FM. As each Fan Mission is &amp;quot;run&amp;quot; in a separate folder, your savegames &#039;&#039;&#039;will be preserved&#039;&#039;&#039; when switching between them. (However, a savefile will generally not be functional after an update to its FM or core TDM.)&lt;br /&gt;
&lt;br /&gt;
To resume a mission from a savegame, make sure the FM is installed, then just go to the Load/Save game menu and select one from the list.&lt;br /&gt;
&lt;br /&gt;
== Updating a mission ==&lt;br /&gt;
Whenever the mission author releases a new version of his FM, you need to re-install the mission. Missions do not auto-update. See above for instructions.&lt;br /&gt;
&lt;br /&gt;
= Does a Mission Have Translations? =&lt;br /&gt;
Some FMs support additional languages besides English, contained in a &amp;quot;Localization Pack&amp;quot;. This is a separate PK4 file, routinely named &amp;lt;myFM&amp;gt;_l10n_&amp;lt;checksum&amp;gt;.pk4, where &amp;quot;l10n&amp;quot; abbreviates &amp;quot;localization&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
== Overviews across FMs ==&lt;br /&gt;
For an overview of which FMs have Localization Packs, see [[Fan Missions for The Dark Mod]], and look at the table&#039;s &#039;Translation Pack&#039; column. &lt;br /&gt;
&lt;br /&gt;
Unfortunately, at this time it is difficult to know which FMs have a Localization Pack that includes &#039;&#039;your&#039;&#039; particular language of interest. The [[I18N Status]] page (where &amp;quot;I18N&amp;quot; stands for Internationalization) gives information about some older FMs, but has not been updated for quite awhile.&lt;br /&gt;
&lt;br /&gt;
== For a Given FM ==&lt;br /&gt;
It&#039;s easy enough to verify if a Localization Pack is available; the installation process described below will let you know if not.&lt;br /&gt;
&lt;br /&gt;
As for support for a particular language, after you install the Localization Pack:&lt;br /&gt;
* look within the .pk4 (temporarily renamed to .zip if necessary) and its /strings/ folder. The presence of a *.lang (e.g., french.lang) is required for support.&lt;br /&gt;
* or just play the game to find out. Be aware that there are degrees of translation support.&lt;br /&gt;
 &lt;br /&gt;
= Installing a Mission&#039;s Translations =&lt;br /&gt;
The basic install above provides English. &#039;&#039;&#039;Do that first&#039;&#039;&#039;. There are then two official ways to get and install a Localization Pack.&lt;br /&gt;
&lt;br /&gt;
== By downloading the localization pack ==&lt;br /&gt;
Starting from the site&#039;s &#039;&#039;Mission&#039;&#039; page and then to the &#039;&#039;Download Details&#039;&#039; page for given FM, the Localization Packs section will tell you if a pack of translations is available, and if so provide a choice of equivalent links. [I guess download into the /fms folder and get it auto-installed on game restart? Or download it into the particular /fm folder? TBD]&lt;br /&gt;
&lt;br /&gt;
== By installing with the in-game downloader ==&lt;br /&gt;
For this process to work, you must have already installed the FM. Then, revisit the &#039;&#039;Online Mission Archive&#039;&#039; page. Is there an &amp;quot;#&amp;quot; annotation (for &amp;quot;# Translation&amp;quot;) next to your FM name? Then &#039;&#039;&#039;download again&#039;&#039;&#039; to get the Pack and have it auto-installed. Note - Only in the &#039;Online Mission Archive&#039; page will there be &amp;quot;#&amp;quot; and &amp;quot;*&amp;quot; (for &amp;quot;* Update&amp;quot; annotations; not in the Mission List page.&lt;br /&gt;
&lt;br /&gt;
== See also ==&lt;br /&gt;
* [[The Dark Mod Gameplay]]&lt;br /&gt;
* [[FAQ]] (for troubleshooting etc.)&lt;br /&gt;
[[Category:Gameplay]]&lt;br /&gt;
[[Category:Fan Missions]]&lt;br /&gt;
[[Category:Gameplay concepts and settings]]&lt;/div&gt;</summary>
		<author><name>Geep</name></author>
	</entry>
	<entry>
		<id>https://wiki.thedarkmod.com/index.php?title=Installing_and_Running_Fan_Missions&amp;diff=33981</id>
		<title>Installing and Running Fan Missions</title>
		<link rel="alternate" type="text/html" href="https://wiki.thedarkmod.com/index.php?title=Installing_and_Running_Fan_Missions&amp;diff=33981"/>
		<updated>2025-06-09T20:19:37Z</updated>

		<summary type="html">&lt;p&gt;Geep: Revise headings, freshen text&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Installing a New Mission =&lt;br /&gt;
&amp;lt;big&amp;gt;There are two ways to install a new mission:&lt;br /&gt;
# By downloading a mission pk4 file and placing it in the fms folder&lt;br /&gt;
# By using the in-game mission downloader&lt;br /&gt;
&amp;lt;/big&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== By downloading the mission PK4 ==&lt;br /&gt;
# Go to [https://www.thedarkmod.com/missions/ thedarkmod.com/missions] (say, by selecting &amp;quot;Missions&amp;quot; from the site top menu strip) to see a list of available FMs.&lt;br /&gt;
# For an FM of interest, click on &amp;quot;Download Details&amp;quot;.&lt;br /&gt;
# Each FM is contained in a PK4 file, which contains all the files necessary to run the mission. Choose one of the equivalent links to download, and drop the PK4 file into the fms/ folder, e.g. &amp;lt;tt&amp;gt;C:\Games\darkmod\fms\&amp;lt;/tt&amp;gt;.&lt;br /&gt;
# Launch The Dark Mod game to &#039;&#039;&#039;automatically install the mission&#039;&#039;&#039;. That is, upon launch, the game will detect the new mission package in the fms/ folder and will add it to the list of available missions. (Note: the PK4 file will be automatically moved into a subfolder. This is normal operation).&lt;br /&gt;
&lt;br /&gt;
== By installing with the in-game downloader == &lt;br /&gt;
[[Image:Download-mission210.jpg|right|thumb]]&lt;br /&gt;
# Launch The Dark Mod.&lt;br /&gt;
# From the main menu, click &#039;&#039;Mission List&#039;&#039; (&#039;&#039;formerly &#039;&#039;New Mission&#039;&#039;, as shown in figures here).&lt;br /&gt;
# Click &#039;&#039;Download Missions&#039;&#039; in the lower border of the Mission List.&lt;br /&gt;
&lt;br /&gt;
In this screen on the left is the &#039;&#039;Online Mission Archive&#039;&#039;, with a list of FMs that:&lt;br /&gt;
* you don&#039;t yet have, but are available to download and install; and&lt;br /&gt;
* you &#039;&#039;&#039;do&#039;&#039;&#039; have already installed, but that have an update or new (or at least not-yet-installed) translation available.&lt;br /&gt;
If you click on a listed mission, you see information under it. You can click on &#039;&#039;More...&#039;&#039; to get a more detailed screen with a description and screenshots from the mission.&lt;br /&gt;
&lt;br /&gt;
Last steps:&lt;br /&gt;
# With a row selected, click on &#039;&#039;Select for download&#039;&#039; to move a listing to the right-hand &#039;&#039;Download Status/Selected For DownLoad&#039;&#039; pane. Repeat to build up a list to download.&lt;br /&gt;
# Or &#039;&#039;Select all&#039;&#039; to download all missions, but &#039;&#039;&#039;not recommended&#039;&#039;&#039; because it will stress the download mirrors unnecessary.&lt;br /&gt;
# Then click &amp;quot;Start Download&amp;quot;. FMs will be queued to download and automatically install.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Selecting a New or Different Mission to Play =&lt;br /&gt;
[[Image:new-mission210.jpg|right|thumb]]&lt;br /&gt;
# From the main menu, click &#039;&#039;Mission List&#039;&#039;&lt;br /&gt;
# On the right of the screen, you&#039;ll see a list of available missions that you&#039;ve installed.&lt;br /&gt;
# Click on a mission within the list. Information about it will pop up in the left pane (as shown in figure), and &#039;&#039;Notes&#039;&#039; often has more.&lt;br /&gt;
# When you&#039;ve made your choice, click &#039;&#039;Select Mission&#039;&#039; at the lower right corner. &lt;br /&gt;
# The game will restart itself automatically.&amp;lt;br style=&amp;quot;clear: both&amp;quot; /&amp;gt;&lt;br /&gt;
== Starting the mission ==&lt;br /&gt;
After the restart, click &#039;&#039;Start this Mission&#039;&#039;. You&#039;ll be taken to the mission&#039;s briefing.&amp;lt;br style=&amp;quot;clear: both&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Resuming a mission ==&lt;br /&gt;
Once installed, a Fan Mission will stay installed until you uninstall it (click &#039;&#039;deselect mission&#039;&#039;) or install a different FM. As each Fan Mission is &amp;quot;run&amp;quot; in a separate folder, your savegames &#039;&#039;&#039;will be preserved&#039;&#039;&#039; when switching between them. (However, a savefile will generally not be functional after an update to its FM or core TDM.)&lt;br /&gt;
&lt;br /&gt;
To resume a mission from a savegame, make sure the FM is installed, then just go to the Load/Save game menu and select one from the list.&lt;br /&gt;
&lt;br /&gt;
== Updating a mission ==&lt;br /&gt;
Whenever the mission author releases a new version of his FM, you need to re-install the mission. Missions do not auto-update. See above for instructions.&lt;br /&gt;
&lt;br /&gt;
== See also ==&lt;br /&gt;
* [[The Dark Mod Gameplay]]&lt;br /&gt;
* [[FAQ]] (for troubleshooting etc.)&lt;br /&gt;
[[Category:Gameplay]]&lt;br /&gt;
[[Category:Fan Missions]]&lt;br /&gt;
[[Category:Gameplay concepts and settings]]&lt;/div&gt;</summary>
		<author><name>Geep</name></author>
	</entry>
	<entry>
		<id>https://wiki.thedarkmod.com/index.php?title=Skybox_Tutorial&amp;diff=33973</id>
		<title>Skybox Tutorial</title>
		<link rel="alternate" type="text/html" href="https://wiki.thedarkmod.com/index.php?title=Skybox_Tutorial&amp;diff=33973"/>
		<updated>2025-05-10T19:31:46Z</updated>

		<summary type="html">&lt;p&gt;Geep: /* See Also */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Skybox Tutorial =&lt;br /&gt;
This is the tutorial for skybox creation by Sotha.&lt;br /&gt;
== Motivation ==&lt;br /&gt;
Why bother creating a custom skybox? The standard starry prefab is just fine!&lt;br /&gt;
&lt;br /&gt;
It indeed is, but everyone has seen it so many times. Creating a specific sky just for your mission gives your mission personality. With the sky, you can relate atmosphere and information on the location where the mission takes place. In the plains just outside the City? In the top of a high mountain, in the eternal snow?&lt;br /&gt;
With a some hours invested in sky creation you can make your mission seem real as it seems to be located somewhere. It does not exist alone in the world, you can see the world around it. You can see the tiny hamlets and the fields surrounding the wealthy merchants manor.&lt;br /&gt;
&lt;br /&gt;
== Introduction ==&lt;br /&gt;
In this tutorial you will learn&lt;br /&gt;
*how to create a sky texture using Terragen.&lt;br /&gt;
*how to build a skybox using the landscape texture you created.&lt;br /&gt;
*how to add details (buildings) to the skybox.&lt;br /&gt;
&lt;br /&gt;
== Preparing ==&lt;br /&gt;
*Get aquainted with the basic idea what we are going to do. https://modwiki.dhewm3.org/Cube_maps&lt;br /&gt;
*Download and install Terragen. &#039;&#039;[Geep comments in 2025: The original (16-bit?) version of free Terragen for which this tutorial was written is no longer available from vendor planetside.co.uk. Instead now offered is a [https://planetside.co.uk/free-downloads/terragen-4-free-download/ free version of Terragen 4.] Video tutorials about Terragen 4 are available. In particular, within the 12-part series by Vladimir Chopine [GeekatPlay], [https://www.youtube.com/watch?v=_A4mrkVLs88 part 3 discusses skyboxes.] If anyone tries Terragen 4 for TDM, please update our tutorial here as needed.]&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
== Basic Scenery Building ==&lt;br /&gt;
The program window is shown in the picture 1.&lt;br /&gt;
[[Image:Skybox_tutorial_terra1.jpg|200px|thumb|right|Picture 1]]&lt;br /&gt;
&lt;br /&gt;
First create your first terrain. Click the Generate Terrain -button and click again the Generate Terrain button in the appearing window. You&#039;ll see a grey topology map appear. Close the Terrain Genesis window. &lt;br /&gt;
&lt;br /&gt;
Since we are doing a skybox, we need the camera to be located near the middle of the map, so we are surrounded by the scene. Click left mouse button on the topology map on the Rendering Control -window to place camera in the middle of the scene. You can change the direction with the right mouse button. The grayscale topography image may not give much information on the resulting scene, so you can use the 3D preview button on the left. You can also use Rendering Preview and the actual Render Image -buttons to check what the camera sees.&lt;br /&gt;
&lt;br /&gt;
Now that you know how to see what you&#039;ve created, you need to try to select the parameters so that you&#039;ll get close the kind of scenery you want (plains with distant mountains or barren mountain range). Hold your mouse above the settings (Realism, Smoothing, etc) to see what each parameters does. Experiment until you get something close what you want. The closer you get with the parameters, the easier the sculpting phase is.&lt;br /&gt;
== Sculpting the Scenery ==&lt;br /&gt;
When you&#039;re close with the scenery you want, save it so you can start from where you were is something goes wrong. Landscape Window -&amp;gt; Terrain -&amp;gt; Save. Now we will sculpt the map. Click the topology map on the Landscape window. Now you can sculpt the scene with the Basic Sculpting Tool. Raise a mountain, remove a mountain, smoothen the plains and add a pit with smooth edges for a lake, or make a river.&lt;br /&gt;
== Water, Surface and Skies ==&lt;br /&gt;
Next we set the water level. Click the water-button on the left. Set the water level and press update maps. You&#039;ll see light blue colors in areas with water. Set the levels so that you&#039;ve realistic looking sea. Sculpt shores to be gently sloping.&lt;br /&gt;
&lt;br /&gt;
Then we set the surface. In the landscape window there is Surface Map -section. Select open and try to pick up the kind of terrain textures you need. For plains &amp;quot;grass and sand&amp;quot; is just fine. For others you probably need to create your own surface map. I cannot help with this at this time.&lt;br /&gt;
&lt;br /&gt;
You can edit the sky&#039;s clouds by selecting the Clouds button on the left and set the ambience haze from the atmosphere button on the left.&lt;br /&gt;
== Buildings? ==&lt;br /&gt;
&#039;&#039;Geep 2025 comments:&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Terragen 4 and its predecessors have no native way to create distant buildings. One approach, before capturing the skybox cubemap:&lt;br /&gt;
* Acquire such open-source assets in one of the Terragen object import formats (.obj, .lwo, .tgo). To import, see TerraTuts&#039; &amp;quot;Terragen 4 Basics&amp;quot; series, particularly [https://www.youtube.com/watch?v=Fj0VdxEL7bQ &amp;quot;Importing a Single 3D Object&amp;quot;] and [https://www.youtube.com/watch?v=kc1tyruEwKM &amp;quot;Positioning a Single 3D Object&amp;quot;.]&lt;br /&gt;
* Or use a tool like Blender to build your own model of building(s).&lt;br /&gt;
An advantage is that the building and landscape will share lighting, so match easily.&lt;br /&gt;
&lt;br /&gt;
Alternatively, after cubemap texture capture, create miniatures in DR to add near the walls of your skybox, discussed under &amp;quot;Creating the Skybox&amp;quot; below.&lt;br /&gt;
== Lighting ==&lt;br /&gt;
Finally we set the lighting conditions with the button on the left. Since TDM is a sneaking game you probably want to set the sun below the horizon. Maybe the mission occurs at midnight? Or just after sunset? Set the sun appropriately. Check the rendering preview. It probably looks too bright with the sun gone, so decrease Shadow Lightness (located in Lighting Conditions -&amp;gt; Background Light). If you end up in pitch black scenery, increase the Exposure time in Rendering Control -&amp;gt; Camera Settings.&lt;br /&gt;
== Rendering the Scenery ==&lt;br /&gt;
When you have everything the way you want we can proceed to the image capture phase. DOUBLE CHECK your work with the Render Image -button in every direction with low detail settings so everything looks good. Once the images have been captured you need to capture everything again if you notice something unpleasing in the resulting work.&lt;br /&gt;
&lt;br /&gt;
Set all detail knobs you can find to maximum (Rendering Control -&amp;gt; Render Settings, Rendering Control -&amp;gt; Detail). Set image size to 960x960. This is the maximum resolution you&#039;ll get from the free version. Double check your camera settings. Is the camera in the correct position? Does it capture the scenery details you want? Is the camera height from the surface correct? I used 6m for the plains skybox in picture 3. &#039;&#039;&#039;Check the camera ZOOM in Camera Settings: if this is any other than 1.0 your skybox will not align correctly (it defaults to 1.4 so change it!)&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Terragen 2+ evidently would use &amp;quot;FOV 90&amp;quot; instead of Zoom, [https://forums.thedarkmod.com/index.php?/topic/9082-newbie-darkradiant-questions/page/130/#findComment-309011 says post by someTaff.]&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Then capture the images.&lt;br /&gt;
*Set Camera orientation: head 0, pitch 0, bank 0&lt;br /&gt;
*Render image and save it as yoursky_&#039;&#039;&#039;forward&#039;&#039;&#039;.bmp&lt;br /&gt;
*Set Camera orientation: head 90, pitch 0, bank 0&lt;br /&gt;
*Render image and save it as yoursky_&#039;&#039;&#039;right&#039;&#039;&#039;.bmp&lt;br /&gt;
*Set Camera orientation: head 180, pitch 0, bank 0&lt;br /&gt;
*Render image and save it as yoursky_&#039;&#039;&#039;back&#039;&#039;&#039;.bmp&lt;br /&gt;
*Set Camera orientation: head 270, pitch 0, bank 0&lt;br /&gt;
*Render image and save it as yoursky_&#039;&#039;&#039;left&#039;&#039;&#039;.bmp&lt;br /&gt;
*Set Camera orientation: head 0, pitch 90, bank 0&lt;br /&gt;
*Render image and save it as yoursky_&#039;&#039;&#039;up&#039;&#039;&#039;.bmp&lt;br /&gt;
*Set Camera orientation: head 0, pitch -90, bank 0&lt;br /&gt;
*Render image and save it as yoursky_&#039;&#039;&#039;down&#039;&#039;&#039;.bmp&lt;br /&gt;
&lt;br /&gt;
Open each of your image files with GIMP or whatever and save them as .tga in to folder darkmod\env\custom&lt;br /&gt;
&lt;br /&gt;
== Create Material ==&lt;br /&gt;
Create a material file for your sky in folder darkmod\materials. Create a text file called Customskies.mtr. Fill in the following&lt;br /&gt;
 textures/skies/custom/yoursky&lt;br /&gt;
 {&lt;br /&gt;
 qer_editorimage   textures/custom/skies/yoursky.tga&lt;br /&gt;
 noFragment&lt;br /&gt;
 noshadows&lt;br /&gt;
 nooverlays&lt;br /&gt;
 forceOpaque            // so transparent windows can draw on top of it&lt;br /&gt;
 {&lt;br /&gt;
 blend      add      // so transparent windows can draw on top of it&lt;br /&gt;
 cameraCubeMap   env/custom/yoursky&lt;br /&gt;
 forceHighQuality&lt;br /&gt;
 texgen      skybox&lt;br /&gt;
 texgen         wobblesky .0 .0 .0&lt;br /&gt;
  }&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
== Creating the Skybox ==&lt;br /&gt;
Fire up DR. You could just apply the sky texture you created (it should be in DR textures/skies/custom) on the ceilings on your map, but for distant buildings it is better to put smf/portal_sky where your sky should be.&lt;br /&gt;
&lt;br /&gt;
Create somewhere away from your main map a box shaped room with the texture you created. Place an entity info_portalsky exactly in the middle of the room. Now all the surfaces with the portal_sky textures show the contents of the info_portalsky room. Now you add details to your skybox by adding buildings in the small info_portalsky -room you created. You will notice that you have to make small toy-houses and place them just slightly below the info_portalsky and next to the wall in the skybox -room. See picture 3 to see a suggested setup. Notice the position and orientation of the moon slab, the size scale of the buildings and the position of the info_portalsky.&lt;br /&gt;
[[Image:Skybox_tutorial_skybox.jpg|200px|thumb|right|Picture 2]]&lt;br /&gt;
Add light source to make the buildings bathe in moonlight. Create the moon itself: add a simple square brush with nodraw on all sides. Rotate the brush so that it&#039;s wide face is pointed straight towards the info_portalsky. To this face add the moon texture and FIT it there with surface inspector. Add more buildings and details. You&#039;ll get a decent illusion of distant structures (see picture 3). You can also add particle effects which show in the sky portals as well. Important note: if you have a sunset in your skybox, go ingame and check the compass if the sunset is in an incorrect direction. You can remedy this by a) turn the sky texture or b) rotate the info_portalsky entity. Also check that your moon&#039;s light side is pointed towards the sunset.&lt;br /&gt;
[[Image:Skybox_tutorial_result.png|200px|thumb|right|Picture 3. Zoom in to see night-time details.]]&lt;br /&gt;
&lt;br /&gt;
I&#039;ve tried scaling existing models down with the rotation parameter, but they do not light up correctly by light sources. Therefore you have to create all small detail objects from normal brushes as the ones seen in picture 2.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Geep comments, 2020: This finding predated DR&#039;s model rescaling tool, which now offers another way to downsize existing models... more compatible with light sources?&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
== Rotating the Skybox ==&lt;br /&gt;
If your compass shows that north is not in the correct direction you can rotate the info_portalsky. This is not a good solution, since this changes the north of the map. Objects in the skybox north won&#039;t be in game world north. It might get really confusing to make changes in the skybox later if you take this path. To maintain consistency, you should rotate the skybox instead. It is done as follows:&lt;br /&gt;
*Check the cubemap picture here for reference: [https://modwiki.dhewm3.org/Cube_maps]. Basically we are going nudge each direction file one slot leftwise.&lt;br /&gt;
*Cut your skybox files to a temporary safe folder. Copy your _up.tga and _down.tga files back to the env/custom -folder. I&#039;ll talk only in shorthand form. &amp;quot;_up.tga&amp;quot; means &amp;quot;yoursky_up.tga&amp;quot;&lt;br /&gt;
*Copy _forward.tga back to your env/custom/ folder. Rename it to _left.&lt;br /&gt;
*Copy _right -&amp;gt; _forward&lt;br /&gt;
*Copy _back -&amp;gt; _right&lt;br /&gt;
*Copy _left -&amp;gt; _back&lt;br /&gt;
*Go ingame and check direction. If its still wrong, repeat these steps until you get it right.&lt;br /&gt;
*When you got the surrounding correctly, go ingame and check how badly the sky texture and ground texture are unaligned with the rest of the scenery. Pay attention how many 90 degree turns to what direction is needed to make it match with the surroundings.&lt;br /&gt;
*Open them with you favourite image manipulation software and rotate the files accordingly.&lt;br /&gt;
&#039;&#039;Geep comments, 2020: You might also need to do this procedure if, rather than creating your own skybox texture, you are using one acquired from a third-party sharing repository. This is because the skybox format is not universal across game platforms. Expect to both re-name and rotate some of the images individually.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This concludes the tutorial and you should now be able to create your very own scenery! Go forth and create!&lt;br /&gt;
== See Also ==&lt;br /&gt;
* [[Skybox Basic Details]] has more about using the standard prefab tdm_sky_starry1.pfb. But of pertinence here, it touches on inside-skybox lighting considerations. There is also a quick backgrounder on using a skybox best in TDM.&lt;br /&gt;
* Besides the projected terrain of the sky box, there is world-scale terrain within TDM itself. Generally, this is not created with Terragen-like tools, but by hand-building DR patches. Some terrain may be inaccessible, outside city walls; this can present visportalling and performance challenges. Accessible terrain will need additional work for path finding. For more: [[Systematic Method for Adding Pathfinding to Uneven Terrain]]; [[Pathfinding]]; [[Roads]].&lt;br /&gt;
{{tutorial-editing}}&lt;br /&gt;
[[Category:Skybox]]&lt;/div&gt;</summary>
		<author><name>Geep</name></author>
	</entry>
</feed>