<?xml version="1.0"?>
<?xml-stylesheet type="text/css" href="http://fileformats.archiveteam.org/skins/common/feed.css?303"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
		<id>http://fileformats.archiveteam.org/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Cypherpunks</id>
		<title>Just Solve the File Format Problem - User contributions [en]</title>
		<link rel="self" type="application/atom+xml" href="http://fileformats.archiveteam.org/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Cypherpunks"/>
		<link rel="alternate" type="text/html" href="http://fileformats.archiveteam.org/wiki/Special:Contributions/Cypherpunks"/>
		<updated>2026-04-17T11:10:03Z</updated>
		<subtitle>User contributions</subtitle>
		<generator>MediaWiki 1.19.2</generator>

	<entry>
		<id>http://fileformats.archiveteam.org/wiki/BMP</id>
		<title>BMP</title>
		<link rel="alternate" type="text/html" href="http://fileformats.archiveteam.org/wiki/BMP"/>
				<updated>2021-04-16T04:20:01Z</updated>
		
		<summary type="html">&lt;p&gt;Cypherpunks: add note about negative height&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{FormatInfo&lt;br /&gt;
|formattype=electronic&lt;br /&gt;
|subcat=Graphics&lt;br /&gt;
|extensions={{ext|bmp}}, {{ext|rle}}, {{ext|dib}}, others&lt;br /&gt;
|mimetypes={{mimetype|image/bmp}}&lt;br /&gt;
|locfdd={{LoCFDD|fdd000189}}&lt;br /&gt;
|pronom={{PRONOM|fmt/116}}, others&lt;br /&gt;
|wikidata={{wikidata|Q192869}}&lt;br /&gt;
|kaitai struct=bmp&lt;br /&gt;
|released=1987&lt;br /&gt;
}}&lt;br /&gt;
'''BMP''' is a family of raster image file formats primarily used on Microsoft Windows and OS/2 operating systems. The format is sometimes known as '''Device-Independent Bitmap''' ('''DIB'''), since, when loaded into memory using Windows software, the image is held as a DIB structure.&lt;br /&gt;
&lt;br /&gt;
Though seemingly a simple format, it is complicated by its many different versions, lack of an official specification, lack of any version control process, and ambiguities and contradictions in the documentation.&lt;br /&gt;
&lt;br /&gt;
== Discussion ==&lt;br /&gt;
The term ''DIB'' can mean several different things:&lt;br /&gt;
* A synonym for BMP file format.&lt;br /&gt;
* An in-memory DIB object, with no file header. The header data and the bitmap data do not have to be stored contiguously. Some Win32 API functions use this format.&lt;br /&gt;
* A &amp;quot;packed DIB&amp;quot; memory object or file component, with no file header. The header data and the bitmap data are stored contiguously. This is a standard [[Windows clipboard|clipboard format]], for example.&lt;br /&gt;
* A &amp;quot;packed DIB&amp;quot; stored in a file by itself.&lt;br /&gt;
&lt;br /&gt;
A number of Windows-centric formats contain some nonstandard modified or compressed form of BMP/DIB, intended to be reconstructed as a DIB at runtime.&lt;br /&gt;
&lt;br /&gt;
== Format details ==&lt;br /&gt;
&lt;br /&gt;
=== Compression ===&lt;br /&gt;
Images are usually uncompressed, but [[Run-length encoding|RLE]] compression can be used under some conditions. [[JPEG]], [[PNG]], and [[Modified Huffman|Huffman 1D]] compression are also theoretically possible, but rarely supported.&lt;br /&gt;
&lt;br /&gt;
=== File structure ===&lt;br /&gt;
A BMP file starts with a 14-byte &amp;quot;BITMAPFILEHEADER&amp;quot; structure.&lt;br /&gt;
&lt;br /&gt;
Immediately after that is another header which we'll refer to as the &amp;quot;info header&amp;quot;, though some versions of it are named &amp;quot;core header&amp;quot; instead. There are a number of different versions and sub-versions of it. It starts with 4-byte integer indicating its size, which ''mostly'' reveals its version.&lt;br /&gt;
&lt;br /&gt;
The pixel data is pointed to by a field in BITMAPFILEHEADER. There can be other data segments, e.g. for a color palette, before (and, rarely, after) the pixel data.&lt;br /&gt;
&lt;br /&gt;
Pixel data is usually stored from bottom up (but is top-down if the header indicates a negative height). If uncompressed, each row is padded to a multiple of 4 bytes.&lt;br /&gt;
&lt;br /&gt;
== Identifiers ==&lt;br /&gt;
No MIME type has been officially registered. Strings found in practice are:  image/bmp; image/x-bmp; image/x-ms-bmp&lt;br /&gt;
&lt;br /&gt;
The usual filename extension is '''.bmp'''. Extensions '''.rle''' (for RLE-compressed images) and '''.dib''' (which sometimes indicates that the file lacks a ''file header'') are also sometimes seen. Many other extensions have been used by various applications.&lt;br /&gt;
&lt;br /&gt;
== Identification ==&lt;br /&gt;
BMP files start with the ASCII signature &amp;quot;{{magic|BM}}&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
The bytes at the beginning of the file match one of these two patterns:&lt;br /&gt;
&lt;br /&gt;
 42 4d ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? 00 00 0c 00 &lt;br /&gt;
 00 00 ?? ?? ?? ?? 01 00 ?? 00&lt;br /&gt;
&lt;br /&gt;
or&lt;br /&gt;
&lt;br /&gt;
 42 4d ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? 00 00 ?? 00 &lt;br /&gt;
 00 00 ?? ?? ?? ?? ?? ?? ?? ?? 01 00 ?? 00&lt;br /&gt;
&lt;br /&gt;
The &amp;quot;reserved&amp;quot; bytes at offset 6 to 9 are usually all zero, but a few OS/2 BMP files have nonzero &amp;quot;hotspot coordinates&amp;quot; there.&lt;br /&gt;
&lt;br /&gt;
Compare to [[VBM (VDC BitMap)]], an obscure format with a similar signature.&lt;br /&gt;
&lt;br /&gt;
== Well-known versions ==&lt;br /&gt;
&lt;br /&gt;
=== Windows BMP v2 ===&lt;br /&gt;
* Info header size: 12&lt;br /&gt;
* Info header name: BITMAPCOREHEADER&lt;br /&gt;
* PRONOM: {{PRONOM|fmt/115}}&lt;br /&gt;
&lt;br /&gt;
See also OS/2 BMP 1.0, below.&lt;br /&gt;
&lt;br /&gt;
=== Windows BMP v3 ===&lt;br /&gt;
* Info header size: 40&lt;br /&gt;
* Info header name: BITMAPINFOHEADER&lt;br /&gt;
* PRONOM: {{PRONOM|fmt/116}}, {{PRONOM|fmt/117}}&lt;br /&gt;
&lt;br /&gt;
This is by far the most widely used version of BMP. It was introduced with Windows 3.x. Windows NT extended it to support 16 and 32 bits/pixel.&lt;br /&gt;
&lt;br /&gt;
Windows CE also extended it, for example to allow 2 bits/pixel (see [[Pocket PC Bitmap]]), but its extensions were not migrated to the BMP v4 and v5 formats.&lt;br /&gt;
&lt;br /&gt;
Microsoft's GDI+ reportedly supports BMP images with 64 bits/pixel[https://docs.microsoft.com/en-us/windows/win32/gdiplus/-gdiplus-types-of-bitmaps-about], but no technical documentation of this extension has been located.&lt;br /&gt;
&lt;br /&gt;
It is apparently possible for OS/2 BMP 2.0 format to masquerade as Windows BMP v3. The upshot is that if the compression type is 3 and the bit depth is 1, or the compression type is 4 and the bit depth is 24, then the file should be treated as OS/2 BMP 2.0.&lt;br /&gt;
&lt;br /&gt;
=== Windows BMP v4 ===&lt;br /&gt;
* Info header size: 108&lt;br /&gt;
* Info header name: BITMAPV4HEADER&lt;br /&gt;
* PRONOM: {{PRONOM|fmt/118}}&lt;br /&gt;
&lt;br /&gt;
Introduced with Windows 95. Adds support for transparency and colorimetry.&lt;br /&gt;
&lt;br /&gt;
=== Windows BMP v5 ===&lt;br /&gt;
* Info header size: 124&lt;br /&gt;
* Info header name: BITMAPV5HEADER&lt;br /&gt;
* PRONOM: {{PRONOM|fmt/119}}&lt;br /&gt;
&lt;br /&gt;
Introduced with Windows 98. Adds support for [[ICC profile|ICC profiles]].&lt;br /&gt;
&lt;br /&gt;
== Other versions ==&lt;br /&gt;
&lt;br /&gt;
=== Windows BMP v1 ===&lt;br /&gt;
* PRONOM: {{PRONOM|fmt/114}}&lt;br /&gt;
&lt;br /&gt;
Also called DDB, this is the bitmap file format used by Windows 1.0. It's not really a BMP format. Refer to [[Windows DDB]].&lt;br /&gt;
&lt;br /&gt;
=== OS/2 BMP 1.0 ===&lt;br /&gt;
:''See also the [[OS/2 BMP|OS/2 BMP disambiguation page]].''&lt;br /&gt;
* Info header size: 12&lt;br /&gt;
* Info header name: BITMAPCOREHEADER or OS21XBITMAPHEADER&lt;br /&gt;
* PRONOM: {{PRONOM|x-fmt/25}} (deprecated), {{PRONOM|fmt/115}}&lt;br /&gt;
&lt;br /&gt;
For practical purposes, OS/2 BMP 1.0 is identical to Windows BMP v2. But there can be at least one small difference: In OS/2 formats, the &amp;quot;Size&amp;quot; field at offset 2 (variously named &amp;quot;cbSize&amp;quot;, &amp;quot;FileSize&amp;quot;, or &amp;quot;bfSize&amp;quot;) is sometimes set to the size of the headers, instead of the size of the file. For v1, that means it will be 26 (14+12). For v2, it can range from 30 to 78.&lt;br /&gt;
&lt;br /&gt;
=== OS/2 BMP 2.0 ===&lt;br /&gt;
* Info header size: 16–64 (16, 24, 40, 48, and 64 may be most common)&lt;br /&gt;
* Info header name: BITMAPCOREHEADER2 or OS22XBITMAPHEADER&lt;br /&gt;
* PRONOM: {{PRONOM|x-fmt/270}}&lt;br /&gt;
&lt;br /&gt;
OS/2 BMP 2.0 defines several file subtypes; here we are describing only the &amp;quot;Bitmap&amp;quot; subtype (files with a signature of &amp;quot;BM&amp;quot;). For other subtypes, see [[OS/2 bitmap family]].&lt;br /&gt;
&lt;br /&gt;
The header size can be reduced from its full size of 64 bytes. Omitted fields are assumed to have a value of zero.&lt;br /&gt;
&lt;br /&gt;
The fields in the first 40 bytes of the header are (nearly) identical to those in Windows BMP v3, v4, and v5. The remaining fields are different.&lt;br /&gt;
&lt;br /&gt;
OS/2 BMP 2.0 supports compression types &amp;quot;Huffman 1D&amp;quot; and &amp;quot;RLE24&amp;quot;, unlike any other version of BMP.&lt;br /&gt;
&lt;br /&gt;
=== BITMAPV2INFOHEADER ===&lt;br /&gt;
* Info header size: 52&lt;br /&gt;
* Info header name: BITMAPV2INFOHEADER&lt;br /&gt;
&lt;br /&gt;
Uncertain; possibly an abbreviated V4/V5 header.&lt;br /&gt;
&lt;br /&gt;
=== BITMAPV3INFOHEADER ===&lt;br /&gt;
* Info header size: 56&lt;br /&gt;
* Info header name: BITMAPV3INFOHEADER&lt;br /&gt;
&lt;br /&gt;
Uncertain; possibly an abbreviated V4/V5 header.&lt;br /&gt;
&lt;br /&gt;
=== Packed DIB file ===&lt;br /&gt;
Same as the common BMP formats, but omits the 14-byte ''file header''.&lt;br /&gt;
&lt;br /&gt;
=== OS/2 Bitmap Array ===&lt;br /&gt;
Sometimes, an [[OS/2 Bitmap Array]] file containing one or more bitmaps is considered to be a kind of BMP file. Such a file begins with an extra 14-byte header, with signature &amp;quot;&amp;lt;code&amp;gt;BA&amp;lt;/code&amp;gt;&amp;quot;. (But note that deleting this header is not quite enough to get a valid BMP file.)&lt;br /&gt;
&lt;br /&gt;
== Symbol definitions ==&lt;br /&gt;
Here are the definitions, from the Windows SDKs, of some of the symbols used in the BMP documentation.&lt;br /&gt;
&lt;br /&gt;
All integers use little-endian [[Endianness|byte order]].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Symbol&lt;br /&gt;
! Definition&lt;br /&gt;
|-&lt;br /&gt;
|WORD || unsigned 16-bit integer&lt;br /&gt;
|-&lt;br /&gt;
|DWORD || unsigned 32-bit integer&lt;br /&gt;
|-&lt;br /&gt;
|LONG || signed 32-bit integer&lt;br /&gt;
|-&lt;br /&gt;
|BI_RGB || 0&lt;br /&gt;
|-&lt;br /&gt;
|BI_RLE8 || 1&lt;br /&gt;
|-&lt;br /&gt;
|BI_RLE4 || 2&lt;br /&gt;
|-&lt;br /&gt;
|BI_BITFIELDS || 3&lt;br /&gt;
|-&lt;br /&gt;
|(Huffman 1D) || 3&lt;br /&gt;
|-&lt;br /&gt;
|BI_JPEG || 4&lt;br /&gt;
|-&lt;br /&gt;
|(24-bit RLE) || 4&lt;br /&gt;
|-&lt;br /&gt;
|BI_PNG || 5&lt;br /&gt;
|-&lt;br /&gt;
|BI_ALPHABITFIELDS || 6&lt;br /&gt;
|-&lt;br /&gt;
|BI_SRCPREROTATE || 0x8000 (?)&lt;br /&gt;
|-&lt;br /&gt;
|LCS_CALIBRATED_RGB || 0&lt;br /&gt;
|-&lt;br /&gt;
|LCS_sRGB || &amp;lt;code&amp;gt;'sRGB'&amp;lt;/code&amp;gt; = 0x73524742&lt;br /&gt;
|-&lt;br /&gt;
|LCS_WINDOWS_COLOR_SPACE || &amp;lt;code&amp;gt;'Win '&amp;lt;/code&amp;gt; = 0x57696e20&lt;br /&gt;
|-&lt;br /&gt;
|PROFILE_LINKED || &amp;lt;code&amp;gt;'LINK'&amp;lt;/code&amp;gt; = 0x4c494e4b&lt;br /&gt;
|-&lt;br /&gt;
|PROFILE_EMBEDDED || &amp;lt;code&amp;gt;'MBED'&amp;lt;/code&amp;gt; = 0x4d424544&lt;br /&gt;
|-&lt;br /&gt;
|LCS_GM_BUSINESS || 1&lt;br /&gt;
|-&lt;br /&gt;
|LCS_GM_GRAPHICS || 2&lt;br /&gt;
|-&lt;br /&gt;
|LCS_GM_IMAGES || 4&lt;br /&gt;
|-&lt;br /&gt;
|LCS_GM_ABS_COLORIMETRIC || 8&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Specifications ==&lt;br /&gt;
* Most of the format (but not the BITMAPFILEHEADER) is defined in the [https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-wmf/4813e7fd-52d0-4f42-965f-228c8b7488d2 Windows Metafile Specification] (as &amp;quot;DeviceIndependentBitmap&amp;quot;)&lt;br /&gt;
* Defined in the [https://www.aelius.com/njh/wavemetatools/doc/riffmci.pdf RIFF specification] (as Device Independent Bitmap File Format)&lt;br /&gt;
* [https://docs.microsoft.com/en-us/windows/win32/api/wingdi/ns-wingdi-bitmapfileheader BITMAPFILEHEADER]&lt;br /&gt;
* [https://docs.microsoft.com/en-us/windows/win32/api/wingdi/ns-wingdi-bitmapcoreheader BITMAPCOREHEADER]&lt;br /&gt;
* [https://docs.microsoft.com/en-us/previous-versions/dd183376(v=vs.85) BITMAPINFOHEADER]&lt;br /&gt;
* [https://docs.microsoft.com/en-us/previous-versions/windows/embedded/aa452885(v=msdn.10) BITMAPINFOHEADER (Windows CE 5.0)]&lt;br /&gt;
* [https://docs.microsoft.com/en-us/windows/win32/api/wingdi/ns-wingdi-bitmapv4header BITMAPV4HEADER]&lt;br /&gt;
* [https://docs.microsoft.com/en-us/windows/win32/api/wingdi/ns-wingdi-bitmapv5header BITMAPV5HEADER]&lt;br /&gt;
* [http://www.digicamsoft.com/bmp/bmp.html Another site with format descriptions]&lt;br /&gt;
* [http://www.fileformat.info/format/os2bmp/spec/902d5c253f2a43ada39c2b81034f27fd/view.htm OS/2 Presentation Manager Programming Reference Guide, Vol III]&lt;br /&gt;
* [http://whatis.rest7.com/how-to-open-bmp-file Specification of BMP headers]&lt;br /&gt;
* [http://zig.tgschultz.com/bmp_file_format.txt BMP format information by T. Schultz]&lt;br /&gt;
&lt;br /&gt;
== Metaformat files ==&lt;br /&gt;
&lt;br /&gt;
* {{Synalysis|bitmap}}&lt;br /&gt;
&lt;br /&gt;
== Software ==&lt;br /&gt;
BMP is widely supported by graphics software, including web browsers. Software listed here has been arbitrarily selected.&lt;br /&gt;
* [[Netpbm]]: bmptopnm, ppmtobmp&lt;br /&gt;
* [[ImageMagick]]&lt;br /&gt;
* [[XnView]]&lt;br /&gt;
* [[Tom's Viewer]]&lt;br /&gt;
&lt;br /&gt;
== Sample files ==&lt;br /&gt;
=== Windows BMP v2 ===&lt;br /&gt;
This format is fairly common, but examples of it can be hard to spot amidst all the BMPv3 files.&lt;br /&gt;
* [https://samples.libav.org/image-samples/money-2-%28os2%29.bmp money-2-(os2).bmp], [https://samples.libav.org/image-samples/money-16-%28os2%29.bmp money-16-(os2).bmp], [https://samples.libav.org/image-samples/money-256-%28os2%29.bmp money-256-(os2).bmp], [https://samples.libav.org/image-samples/money-24bit-os2.bmp money-24bit-os2.bmp]&lt;br /&gt;
* {{CdTextfilesURL|hobbesos29709/disk2/MULTIMED/BMP/}} → BMPS*.ZIP, OS2ORBIT.ZIP, REALMERL.BMP&lt;br /&gt;
&lt;br /&gt;
=== Windows BMP v3 ===&lt;br /&gt;
* {{CdTextfilesURL|mmplatinum/IMAGES/BMP/}}&lt;br /&gt;
* {{CdTextfilesURL|monstmedia/WIN/ICONS/}}&lt;br /&gt;
* {{CdTextfilesURL|maxx/tothemaxww/BMPMISC/}}&lt;br /&gt;
&lt;br /&gt;
=== OS/2 BMP 2.0 ===&lt;br /&gt;
* [http://kimludvigsen.dk/os2/os2/graphx/teamlog2.zip teamlog2.zip] → TEAMcol.bmp, teamcol2.bmp&lt;br /&gt;
* [https://samples.libav.org/image-samples/bmp-files/test4os2v2.bmp test4os2v2.bmp]&lt;br /&gt;
* {{CdTextfiles|hobbesos29709/disk2/MULTIMED/BMP/CARDBMPS.ZIP|CARDBMPS.ZIP}} - Most of the files are OS/2 BMP 2.0&lt;br /&gt;
* {{CdTextfiles|hobbesos29709/disk1/GAMES/MAKMAN10.ZIP|MAKMAN10.ZIP}} - Some of the files are files OS/2 BMP 2.0&lt;br /&gt;
* {{CdTextfiles|monstmedia/IMAGES/JUR_OS2.BMP|JUR_OS2.BMP}}&lt;br /&gt;
* {{CdTextfilesURL|pier/pier09/cdrom/036/}} → os2bmp*.zip&lt;br /&gt;
&lt;br /&gt;
=== Various ===&lt;br /&gt;
* [http://wvnvms.wvnet.edu/vmswww/bmp.html Example BMP images (all Windows v3 except as indicated)]&lt;br /&gt;
* [https://archive.org/details/OS2BBS OS/2 BBS Files Archive] → 13-Bitmap.zip - Lots of OS/2 BMP 1.0 &amp;amp; 2.0 files&lt;br /&gt;
* [https://entropymine.com/jason/bmpsuite/bmpsuite/html/bmpsuite.html BMP Suite Image List]&lt;br /&gt;
* https://telparia.com/fileFormatSamples/image/bmp/&lt;br /&gt;
&lt;br /&gt;
== See also ==&lt;br /&gt;
* [[CUR]]&lt;br /&gt;
* [[ICO]]&lt;br /&gt;
* [[OS/2 bitmap family]]&lt;br /&gt;
* [[OS/2 Bitmap Array]]&lt;br /&gt;
* [[packPNM]]&lt;br /&gt;
* [[Pocket PC Bitmap]]&lt;br /&gt;
* [[Poser Bump Map]]&lt;br /&gt;
* [[Segmented Hypergraphics]]&lt;br /&gt;
* [[Windows DDB]]&lt;br /&gt;
* [[Winzle Puzzle]]&lt;br /&gt;
&lt;br /&gt;
== Links ==&lt;br /&gt;
* [[Wikipedia:BMP file format|Wikipedia: BMP file format]]&lt;br /&gt;
* {{EGFF|bmp|Microsoft Windows Bitmap File Format Summary}}, from the [[Encyclopedia of Graphics File Formats]]&lt;br /&gt;
* {{EGFF|os2bmp|OS/2 Bitmap File Format Summary}}, from the [[Encyclopedia of Graphics File Formats]]&lt;br /&gt;
* [http://coptr.digipres.org/Bad_Peggy Bad Peggy: scans images for problems]&lt;br /&gt;
* [https://web.archive.org/web/20190919034602/http://forensicswiki.org/wiki/BMP ForensicsWiki entry] (not much useful info except for a link to an iOS tool for reading metadata)&lt;br /&gt;
&lt;br /&gt;
[[Category:Microsoft]]&lt;br /&gt;
[[Category:Windows]]&lt;br /&gt;
[[Category:OS/2]]&lt;/div&gt;</summary>
		<author><name>Cypherpunks</name></author>	</entry>

	<entry>
		<id>http://fileformats.archiveteam.org/wiki/RAR</id>
		<title>RAR</title>
		<link rel="alternate" type="text/html" href="http://fileformats.archiveteam.org/wiki/RAR"/>
				<updated>2020-12-22T22:42:34Z</updated>
		
		<summary type="html">&lt;p&gt;Cypherpunks: The Unarchiver can read RAR files&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{FormatInfo&lt;br /&gt;
|formattype=electronic&lt;br /&gt;
|subcat=Archiving&lt;br /&gt;
|extensions={{ext|rar}}&lt;br /&gt;
|mimetypes={{mimetype|application/vnd.rar}}, {{mimetype|application/x-rar-compressed}}&lt;br /&gt;
|pronom={{PRONOM|x-fmt/264}}, {{PRONOM|fmt/411}}, {{PRONOM|fmt/613}}&lt;br /&gt;
|kaitai struct=rar&lt;br /&gt;
|released=1993&lt;br /&gt;
}}&lt;br /&gt;
'''R'''oshal '''AR'''chive ('''RAR''') is a proprietary file format used by the compression software WinRAR. They make the decompression code available for use in other programs and allow its distribution, but with a license provision that &amp;quot;You cannot use the unrar source to re-create the RAR compression algorithm, which is proprietary.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
== File identification ==&lt;br /&gt;
&lt;br /&gt;
Current versions start their files with (hex) {{magic|52 61 72 21 1A 07}}, followed by {{magic|00}} or {{magic|01}}. Early versions (for which no format documentation is known) start with {{magic|52 45 7E 5E}}.&lt;br /&gt;
&lt;br /&gt;
== Software ==&lt;br /&gt;
* [http://www.rarlab.com/ WinRAR website]&lt;br /&gt;
** [http://www.rarlab.com/rar/UnRARDLL.exe Free UnRAR.dll]&lt;br /&gt;
** [http://www.rarlab.com/rar/unrarsrc-4.2.4.tar.gz UnRAR source]&lt;br /&gt;
* [[Konvertor]]&lt;br /&gt;
* [[7-Zip]]&lt;br /&gt;
* [[The Unarchiver]]&lt;br /&gt;
&lt;br /&gt;
== Sample files ==&lt;br /&gt;
* http://cd.textfiles.com/ataricompendium/FILES/MISC/PRTFOLIO/&lt;br /&gt;
* http://cd.textfiles.com/thebbsorg/max_files/&lt;br /&gt;
* https://telparia.com/fileFormatSamples/archive/rar/ → *.rar&lt;br /&gt;
&lt;br /&gt;
== Links ==&lt;br /&gt;
* [[Wikipedia:RAR (file format)|Wikipedia article]]&lt;br /&gt;
* [http://www.forensicswiki.org/wiki/RAR Forensics Wiki article] (has lots of format details)&lt;br /&gt;
* [https://imgur.com/a/MtQZv#0 Mini RAR poster]&lt;/div&gt;</summary>
		<author><name>Cypherpunks</name></author>	</entry>

	<entry>
		<id>http://fileformats.archiveteam.org/wiki/Finance_and_Accounting</id>
		<title>Finance and Accounting</title>
		<link rel="alternate" type="text/html" href="http://fileformats.archiveteam.org/wiki/Finance_and_Accounting"/>
				<updated>2020-11-17T06:25:27Z</updated>
		
		<summary type="html">&lt;p&gt;Cypherpunks: /* Interchange formats: open */ link to Plain text accounting journals&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{FormatInfo&lt;br /&gt;
|formattype=electronic&lt;br /&gt;
|thiscat=Finance and Accounting&lt;br /&gt;
|image=Money grabber.png&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
==Accounting software==&lt;br /&gt;
&lt;br /&gt;
* [[Exact]]&lt;br /&gt;
* [[Peachtree]]&lt;br /&gt;
* [[QuickBooks]] (.qbo, .qbw)&lt;br /&gt;
* [[M.Y.O.B.]]&lt;br /&gt;
&lt;br /&gt;
==Interchange formats: open==&lt;br /&gt;
&lt;br /&gt;
* [[GnuCash XML Format]]&lt;br /&gt;
* [[OFX]]&lt;br /&gt;
* [[QIF]]&lt;br /&gt;
* [[Tax XML]] (used by various governmental entities for e-filing)&lt;br /&gt;
* [[TXF]] (Tax Interchange Format; used by TurboTax)&lt;br /&gt;
* [[Plain text accounting journal]] (a family of formats used by Ledger and &amp;quot;Ledger-likes&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
==Interchange formats: proprietary==&lt;br /&gt;
&lt;br /&gt;
* [[BACS Standard 18]]&lt;br /&gt;
* [[QFX]]&lt;br /&gt;
&lt;br /&gt;
== Market data ==&lt;br /&gt;
&lt;br /&gt;
* [[ITCH]] (NASDAQ)&lt;br /&gt;
&lt;br /&gt;
==Personal finance software==&lt;br /&gt;
&lt;br /&gt;
* [[Banktivity]]&lt;br /&gt;
* [[Budget (Apple II)]]&lt;br /&gt;
* [[GnuCash]]&lt;br /&gt;
* [[Lemon]] (app/website tracking cards and receipts)&lt;br /&gt;
* [[Microsoft Money]]&lt;br /&gt;
* [[MoneyTree]]&lt;br /&gt;
* [[Quicken]] (Creates .qdf, .qph, .qel, .qsd, Imports .qif, .qfx)&lt;br /&gt;
&lt;br /&gt;
==Tax software==&lt;br /&gt;
&lt;br /&gt;
* [[H&amp;amp;R Block]] (.t11, etc.; changes every year)&lt;br /&gt;
* [[TurboTax]] (.tax, .tax2010, etc.; changes every year)&lt;br /&gt;
&lt;br /&gt;
== Naming and numbering systems ==&lt;br /&gt;
&lt;br /&gt;
* [[Routing transit number]]&lt;br /&gt;
&lt;br /&gt;
== See also ==&lt;br /&gt;
&lt;br /&gt;
* [[Currency]]&lt;br /&gt;
&lt;br /&gt;
== Links ==&lt;br /&gt;
* [http://www.theguardian.com/politics/2014/apr/18/hmrc-to-sell-taxpayers-data HMRC to sell taxpayers' financial data]&lt;br /&gt;
* [https://www.federalreserve.gov/apps/fof/ Info on Federal Reserve download data]&lt;/div&gt;</summary>
		<author><name>Cypherpunks</name></author>	</entry>

	<entry>
		<id>http://fileformats.archiveteam.org/wiki/Plain_text_accounting_journal</id>
		<title>Plain text accounting journal</title>
		<link rel="alternate" type="text/html" href="http://fileformats.archiveteam.org/wiki/Plain_text_accounting_journal"/>
				<updated>2020-11-17T06:22:54Z</updated>
		
		<summary type="html">&lt;p&gt;Cypherpunks: add links to journal syntaxes&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{FormatInfo&lt;br /&gt;
|subcat=Finance and Accounting&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Plain text accounting journals are a method of encoding financial transactions, intended to be readable by humans and also parsable by various programs. The first such format was designed for Ledger by John Wiegley in 2003. Other tools now exist to deal with the same basic format, sometimes differing in details.&lt;br /&gt;
&lt;br /&gt;
== Links ==&lt;br /&gt;
* [https://plaintextaccounting.org/ Plain text accounting portal]&lt;br /&gt;
* [https://www.ledger-cli.org/3.0/doc/ledger3.html#Basic-format Ledger 3 basic format]&lt;br /&gt;
* [https://hledger.org/journal.html hledger journal format]&lt;br /&gt;
* [https://beancount.github.io/docs/beancount_language_syntax.html Beancount syntax]&lt;/div&gt;</summary>
		<author><name>Cypherpunks</name></author>	</entry>

	<entry>
		<id>http://fileformats.archiveteam.org/wiki/L5X</id>
		<title>L5X</title>
		<link rel="alternate" type="text/html" href="http://fileformats.archiveteam.org/wiki/L5X"/>
				<updated>2020-07-02T04:05:34Z</updated>
		
		<summary type="html">&lt;p&gt;Cypherpunks: link to reference manual&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{FormatInfo&lt;br /&gt;
|formattype=electronic&lt;br /&gt;
|subcat=Industrial&lt;br /&gt;
|extensions={{ext|l5x}}&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
L5X is an XML-based file format for configuring Logix 5000 programmable logic controllers from Allen-Bradley, now owned by Rockwell Automation. Their RSLogix 5000 software can import and export this format, or the equivalent non-XML text-based [[L5K|L5K format]].&lt;br /&gt;
&lt;br /&gt;
== Links ==&lt;br /&gt;
&lt;br /&gt;
* [https://literature.rockwellautomation.com/idc/groups/literature/documents/rm/1756-rm084_-en-p.pdf Allen-Bradley reference manual]&lt;/div&gt;</summary>
		<author><name>Cypherpunks</name></author>	</entry>

	<entry>
		<id>http://fileformats.archiveteam.org/wiki/L5K</id>
		<title>L5K</title>
		<link rel="alternate" type="text/html" href="http://fileformats.archiveteam.org/wiki/L5K"/>
				<updated>2020-07-02T04:04:29Z</updated>
		
		<summary type="html">&lt;p&gt;Cypherpunks: link to reference manual&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{FormatInfo&lt;br /&gt;
|formattype=electronic&lt;br /&gt;
|subcat=Industrial&lt;br /&gt;
|extensions={{ext|l5k}}&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
L5K is a custom text-based file format for configuring Logix 5000 programmable logic controllers from Allen-Bradley, now owned by Rockwell Automation. Their RSLogix 5000 software can import and export this format, or the equivalent XML-based [[L5X|L5X format]].&lt;br /&gt;
&lt;br /&gt;
== Links ==&lt;br /&gt;
&lt;br /&gt;
* [https://literature.rockwellautomation.com/idc/groups/literature/documents/rm/1756-rm084_-en-p.pdf Allen-Bradley reference manual]&lt;/div&gt;</summary>
		<author><name>Cypherpunks</name></author>	</entry>

	<entry>
		<id>http://fileformats.archiveteam.org/wiki/XDP</id>
		<title>XDP</title>
		<link rel="alternate" type="text/html" href="http://fileformats.archiveteam.org/wiki/XDP"/>
				<updated>2020-06-09T04:11:18Z</updated>
		
		<summary type="html">&lt;p&gt;Cypherpunks: link to specification&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{FormatInfo&lt;br /&gt;
|formattype=electronic&lt;br /&gt;
|extensions={{ext|xdp}}&lt;br /&gt;
|mimetypes={{mimetype|application/vnd.adobe.xdp+xml}}&lt;br /&gt;
}}&lt;br /&gt;
[[XDP]] ('''XML Data Package''') is an XML-based container for [[PDF]] and [[XFA]] data.&lt;br /&gt;
&lt;br /&gt;
== Specifications ==&lt;br /&gt;
* [https://web.archive.org/web/20160329143634if_/http://partners.adobe.com/public/developer/en/xml/xdp_2.0.pdf XML Data Package Specification, Version 2.0 (2003-10)]&lt;br /&gt;
&lt;br /&gt;
[[Category:XML based file formats]]&lt;br /&gt;
[[Category:Adobe]]&lt;/div&gt;</summary>
		<author><name>Cypherpunks</name></author>	</entry>

	<entry>
		<id>http://fileformats.archiveteam.org/wiki/XFDF</id>
		<title>XFDF</title>
		<link rel="alternate" type="text/html" href="http://fileformats.archiveteam.org/wiki/XFDF"/>
				<updated>2020-06-09T03:56:17Z</updated>
		
		<summary type="html">&lt;p&gt;Cypherpunks: link to other spec versions&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{FormatInfo&lt;br /&gt;
|formattype=electronic&lt;br /&gt;
|subcat=Serialization&lt;br /&gt;
|extensions={{ext|xfdf}}&lt;br /&gt;
|mimetypes={{mimetype|application/vnd.adobe.xfdf}}&lt;br /&gt;
}}&lt;br /&gt;
[[XFDF]] ('''XML Forms Data Format''') is a format for storing and transferring data entered into a form in a [[PDF]] file. It is an [[XML]]-based alternative to [[FDF]].&lt;br /&gt;
&lt;br /&gt;
== Specifications ==&lt;br /&gt;
* [https://web.archive.org/web/20160408204348if_/https://partners.adobe.com/public/developer/en/xml/XFDF_Spec_3.0.pdf XML Forms Data Format Specification, Version 3.0 (2009-08)]&lt;br /&gt;
* [https://web.archive.org/web/20160303233354if_/http://partners.adobe.com/public/developer/en/xml/xfdf_2.0.pdf XML Forms Data Format Specification, Version 2.0 (2007-09)]&lt;br /&gt;
* [https://web.archive.org/web/20091007170953if_/http://partners.adobe.com:80/public/developer/en/xml/xfdf_2.0_draft.pdf XML Forms Data Format Specification Version 2.0 draft (2003-07)]&lt;br /&gt;
* [https://web.archive.org/web/20120422084810if_/http://partners.adobe.com:80/public/developer/en/xml/xfdf.xsd XML schema]&lt;br /&gt;
&lt;br /&gt;
[[Category:XML based file formats]]&lt;br /&gt;
[[Category:Adobe]]&lt;/div&gt;</summary>
		<author><name>Cypherpunks</name></author>	</entry>

	<entry>
		<id>http://fileformats.archiveteam.org/wiki/XFA</id>
		<title>XFA</title>
		<link rel="alternate" type="text/html" href="http://fileformats.archiveteam.org/wiki/XFA"/>
				<updated>2020-06-09T03:46:16Z</updated>
		
		<summary type="html">&lt;p&gt;Cypherpunks: fix 2.1 draft 3 link&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{FormatInfo&lt;br /&gt;
|formattype=electronic&lt;br /&gt;
}}&lt;br /&gt;
[[XFA]] ('''XML Forms Architecture''') is a deprecated format used in [[PDF]] files. Most PDF viewers are incompatible and will show only a message such as &amp;quot;The document you are trying to load requires Adobe Reader 8 or higher.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
== Specifications ==&lt;br /&gt;
* [https://web.archive.org/web/20160329145223if_/http://partners.adobe.com/public/developer/en/xml/xfa_spec_3_3.pdf XML Forms Architecture (XFA) Specification, Version 3.3 (2012-01-09)]&lt;br /&gt;
* [https://web.archive.org/web/20160329152047/http://partners.adobe.com:80/public/developer/en/xml/xfa_spec_3_1.pdf XML Forms Architecture (XFA) Specification, Version 3.1 (2009-11-16)]&lt;br /&gt;
* [https://web.archive.org/web/20160329152422if_/http://partners.adobe.com/public/developer/en/xml/xfa_spec_3_0.pdf XML Forms Architecture (XFA) Specification, Version 3.0 (2009-03-12)]&lt;br /&gt;
* [https://web.archive.org/web/20160329150533if_/http://partners.adobe.com/public/developer/en/xml/xfa_spec_2_8.pdf XML Forms Architecture (XFA) Specification, Version 2.8 (2008-10-23)]&lt;br /&gt;
* [https://web.archive.org/web/20160329150908if_/http://partners.adobe.com/public/developer/en/xml/xfa_spec_2_7.pdf XML Forms Architecture (XFA) Specification, Version 2.7 (2008-02-29)]&lt;br /&gt;
* [https://web.archive.org/web/20160329150938if_/http://partners.adobe.com/public/developer/en/xml/xfa_spec_2_6.pdf XML Forms Architecture (XFA) Specification, Version 2.6 (2008-01-25)]&lt;br /&gt;
* [https://web.archive.org/web/20160329151210if_/http://partners.adobe.com/public/developer/en/xml/xfa_spec_2_5.pdf XML Forms Architecture (XFA) Specification, Version 2.5 (2007-06-08)]&lt;br /&gt;
* [https://web.archive.org/web/20160329152255if_/http://partners.adobe.com/public/developer/en/xml/xfa_spec_2_4.pdf XML Forms Architecture (XFA) Specification, Version 2.4 (2006-09-11)]&lt;br /&gt;
* [https://web.archive.org/web/20160329152024if_/http://partners.adobe.com/public/developer/en/xml/xfa_spec.2.2.pdf XML Forms Architecture (XFA) Specification, Version 2.2 (2005-06-07)]&lt;br /&gt;
* [https://web.archive.org/web/20160807001610if_/http://partners.adobe.com:80/public/developer/en/xml/xfapecification_2.2_draft.pdf XFA Specification, Version 2.2 draft (2004-10-01)]&lt;br /&gt;
* [https://web.archive.org/web/20150706043727if_/http://partners.adobe.com/public/developer/en/xml/xfapecification_2.1_draft3.pdf XFA Specification, Version 2.1 draft 3 (2004-07-01)]&lt;br /&gt;
&lt;br /&gt;
[[Category:XML based file formats]]&lt;br /&gt;
[[Category:Adobe]]&lt;/div&gt;</summary>
		<author><name>Cypherpunks</name></author>	</entry>

	<entry>
		<id>http://fileformats.archiveteam.org/wiki/XFA</id>
		<title>XFA</title>
		<link rel="alternate" type="text/html" href="http://fileformats.archiveteam.org/wiki/XFA"/>
				<updated>2020-06-09T03:43:45Z</updated>
		
		<summary type="html">&lt;p&gt;Cypherpunks: link to other spec versions&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{FormatInfo&lt;br /&gt;
|formattype=electronic&lt;br /&gt;
}}&lt;br /&gt;
[[XFA]] ('''XML Forms Architecture''') is a deprecated format used in [[PDF]] files. Most PDF viewers are incompatible and will show only a message such as &amp;quot;The document you are trying to load requires Adobe Reader 8 or higher.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
== Specifications ==&lt;br /&gt;
* [https://web.archive.org/web/20160329145223if_/http://partners.adobe.com/public/developer/en/xml/xfa_spec_3_3.pdf XML Forms Architecture (XFA) Specification, Version 3.3 (2012-01-09)]&lt;br /&gt;
* [https://web.archive.org/web/20160329152047/http://partners.adobe.com:80/public/developer/en/xml/xfa_spec_3_1.pdf XML Forms Architecture (XFA) Specification, Version 3.1 (2009-11-16)]&lt;br /&gt;
* [https://web.archive.org/web/20160329152422if_/http://partners.adobe.com/public/developer/en/xml/xfa_spec_3_0.pdf XML Forms Architecture (XFA) Specification, Version 3.0 (2009-03-12)]&lt;br /&gt;
* [https://web.archive.org/web/20160329150533if_/http://partners.adobe.com/public/developer/en/xml/xfa_spec_2_8.pdf XML Forms Architecture (XFA) Specification, Version 2.8 (2008-10-23)]&lt;br /&gt;
* [https://web.archive.org/web/20160329150908if_/http://partners.adobe.com/public/developer/en/xml/xfa_spec_2_7.pdf XML Forms Architecture (XFA) Specification, Version 2.7 (2008-02-29)]&lt;br /&gt;
* [https://web.archive.org/web/20160329150938if_/http://partners.adobe.com/public/developer/en/xml/xfa_spec_2_6.pdf XML Forms Architecture (XFA) Specification, Version 2.6 (2008-01-25)]&lt;br /&gt;
* [https://web.archive.org/web/20160329151210if_/http://partners.adobe.com/public/developer/en/xml/xfa_spec_2_5.pdf XML Forms Architecture (XFA) Specification, Version 2.5 (2007-06-08)]&lt;br /&gt;
* [https://web.archive.org/web/20160329152255if_/http://partners.adobe.com/public/developer/en/xml/xfa_spec_2_4.pdf XML Forms Architecture (XFA) Specification, Version 2.4 (2006-09-11)]&lt;br /&gt;
* [https://web.archive.org/web/20160329152024if_/http://partners.adobe.com/public/developer/en/xml/xfa_spec.2.2.pdf XML Forms Architecture (XFA) Specification, Version 2.2 (2005-06-07)]&lt;br /&gt;
* [https://web.archive.org/web/20160807001610if_/http://partners.adobe.com:80/public/developer/en/xml/xfapecification_2.2_draft.pdf XFA Specification, Version 2.2 draft (2004-10-01)]&lt;br /&gt;
* [https://web.archive.org/web/20150916221516if_/http://partners.adobe.com/public/developer/en/xml/xfapecification_2.1_draft3.pdF XFA Specification, Version 2.1 draft 3 (2004-07-01)]&lt;br /&gt;
&lt;br /&gt;
[[Category:XML based file formats]]&lt;br /&gt;
[[Category:Adobe]]&lt;/div&gt;</summary>
		<author><name>Cypherpunks</name></author>	</entry>

	<entry>
		<id>http://fileformats.archiveteam.org/wiki/XFA</id>
		<title>XFA</title>
		<link rel="alternate" type="text/html" href="http://fileformats.archiveteam.org/wiki/XFA"/>
				<updated>2020-06-09T03:12:24Z</updated>
		
		<summary type="html">&lt;p&gt;Cypherpunks: fix link to &amp;quot;PDF&amp;quot; page&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{FormatInfo&lt;br /&gt;
|formattype=electronic&lt;br /&gt;
}}&lt;br /&gt;
[[XFA]] ('''XML Forms Architecture''') is a deprecated format used in [[PDF]] files. Most PDF viewers are incompatible and will show only a message such as &amp;quot;The document you are trying to load requires Adobe Reader 8 or higher.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
== Specifications ==&lt;br /&gt;
* [https://web.archive.org/web/20160329151210if_/http://partners.adobe.com/public/developer/en/xml/xfa_spec_2_5.pdf XML Forms Architecture (XFA) Specification, Version 2.5]&lt;br /&gt;
&lt;br /&gt;
[[Category:XML based file formats]]&lt;br /&gt;
[[Category:Adobe]]&lt;/div&gt;</summary>
		<author><name>Cypherpunks</name></author>	</entry>

	<entry>
		<id>http://fileformats.archiveteam.org/wiki/XFA</id>
		<title>XFA</title>
		<link rel="alternate" type="text/html" href="http://fileformats.archiveteam.org/wiki/XFA"/>
				<updated>2020-06-09T03:11:40Z</updated>
		
		<summary type="html">&lt;p&gt;Cypherpunks: link to spec via archive.org&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{FormatInfo&lt;br /&gt;
|formattype=electronic&lt;br /&gt;
}}&lt;br /&gt;
[[XFA]] ('''XML Forms Architecture''') is a deprecated format used in [PDF] files. Most PDF viewers are incompatible and will show only a message such as &amp;quot;The document you are trying to load requires Adobe Reader 8 or higher.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
== Specifications ==&lt;br /&gt;
* [https://web.archive.org/web/20160329151210if_/http://partners.adobe.com/public/developer/en/xml/xfa_spec_2_5.pdf XML Forms Architecture (XFA) Specification, Version 2.5]&lt;br /&gt;
&lt;br /&gt;
[[Category:XML based file formats]]&lt;br /&gt;
[[Category:Adobe]]&lt;/div&gt;</summary>
		<author><name>Cypherpunks</name></author>	</entry>

	<entry>
		<id>http://fileformats.archiveteam.org/wiki/XFDF</id>
		<title>XFDF</title>
		<link rel="alternate" type="text/html" href="http://fileformats.archiveteam.org/wiki/XFDF"/>
				<updated>2020-06-09T02:48:12Z</updated>
		
		<summary type="html">&lt;p&gt;Cypherpunks: fix broken link&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{FormatInfo&lt;br /&gt;
|formattype=electronic&lt;br /&gt;
|subcat=Serialization&lt;br /&gt;
|extensions={{ext|xfdf}}&lt;br /&gt;
|mimetypes={{mimetype|application/vnd.adobe.xfdf}}&lt;br /&gt;
}}&lt;br /&gt;
[[XFDF]] ('''XML Forms Data Format''') is a format for storing and transferring data entered into a form in a [[PDF]] file. It is an [[XML]]-based alternative to [[FDF]].&lt;br /&gt;
&lt;br /&gt;
== Specifications ==&lt;br /&gt;
* [https://web.archive.org/web/20160408204348/https://partners.adobe.com/public/developer/en/xml/XFDF_Spec_3.0.pdf XML Forms Data Format Specification, Version 3.0]&lt;br /&gt;
&lt;br /&gt;
[[Category:XML based file formats]]&lt;br /&gt;
[[Category:Adobe]]&lt;/div&gt;</summary>
		<author><name>Cypherpunks</name></author>	</entry>

	<entry>
		<id>http://fileformats.archiveteam.org/wiki/SimTower_saved_game</id>
		<title>SimTower saved game</title>
		<link rel="alternate" type="text/html" href="http://fileformats.archiveteam.org/wiki/SimTower_saved_game"/>
				<updated>2016-09-27T03:03:09Z</updated>
		
		<summary type="html">&lt;p&gt;Cypherpunks: /* util.py */ remove trailing newline&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{FormatInfo&lt;br /&gt;
|formattype=electronic&lt;br /&gt;
|subcat=Saved Games&lt;br /&gt;
|extensions={{ext|tdt}}&lt;br /&gt;
|image=Simtower.png&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
== Links ==&lt;br /&gt;
&lt;br /&gt;
* [https://raw.githubusercontent.com/fabianschuiki/OpenSkyscraper/90e6e92a2d46869a4052332e48633dd1545256e4/doc/simtower/TDT_format.txt Format description from the OpenSkyscraper project]&lt;br /&gt;
* [[Wikipedia:SimTower|Wikipedia article on SimTower]]&lt;br /&gt;
&lt;br /&gt;
== Code ==&lt;br /&gt;
&lt;br /&gt;
The following code can parse the format; and even for those who don't know Python it should mostly be understandable as a format description.&lt;br /&gt;
&lt;br /&gt;
Integers are named as &amp;lt;code&amp;gt;(sign)(endian)Int(bits)&amp;lt;/code&amp;gt;, like &amp;lt;code&amp;gt;ULInt32&amp;lt;/code&amp;gt;. TDT uses little-endian. Exact size and signedness wasn't verified for most fields.&lt;br /&gt;
&lt;br /&gt;
* This requires the Construct package for Python (tested with Construct 2.5.2 and Python 3.5.2).&lt;br /&gt;
* It's meant to handle binary-identical roundtripping even with bad values.&lt;br /&gt;
&lt;br /&gt;
=== Usage example ===&lt;br /&gt;
&lt;br /&gt;
If both files below are installed to the current directory, you can run the following at the command line to make all elevators carry 42 people:&amp;lt;br clear=&amp;quot;all&amp;quot;&amp;gt;&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;$ python3&lt;br /&gt;
&amp;gt;&amp;gt;&amp;gt; import tdt_cons&lt;br /&gt;
&amp;gt;&amp;gt;&amp;gt; f = open('SIMTOWER/TDT/TOWER.TDT','rb')&lt;br /&gt;
&amp;gt;&amp;gt;&amp;gt; tower = tdt_cons.Tower_Struct.parse_stream(f)&lt;br /&gt;
&amp;gt;&amp;gt;&amp;gt; for el in tower.elevators: el.capacity = 42&lt;br /&gt;
... &lt;br /&gt;
&amp;gt;&amp;gt;&amp;gt; f = open('SIMTOWER/TDT/TOWEROUT.TDT','wb')&lt;br /&gt;
&amp;gt;&amp;gt;&amp;gt; tdt_cons.Tower_Struct.build_stream(tower, f)&lt;br /&gt;
&amp;gt;&amp;gt;&amp;gt; &amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== tdt_cons.py ===&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;# To the extent possible under law, the author(s) have dedicated all copyright&lt;br /&gt;
# and related and neighboring rights to this software to the public domain&lt;br /&gt;
# worldwide. This software is distributed without any warranty.&lt;br /&gt;
#&lt;br /&gt;
# See &amp;lt;http://creativecommons.org/publicdomain/zero/1.0/&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
import construct as _cns&lt;br /&gt;
import util as _util&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#### File header&lt;br /&gt;
&lt;br /&gt;
File_Header_Struct = _cns.Struct('file_header',&lt;br /&gt;
	# Anchor records the current file position, for sanity checks (Assert).&lt;br /&gt;
	# Put _cns.Probe() between fields to dump data for debugging.&lt;br /&gt;
	_cns.Anchor('hdr_start_'),&lt;br /&gt;
&lt;br /&gt;
	# SimTower doesn't seem to care about the first byte, but the second&lt;br /&gt;
	# must be 0x24. Larger values produce a &amp;quot;wrong version&amp;quot; warning.&lt;br /&gt;
	_cns.Padding(1),&lt;br /&gt;
	_cns.Const(_cns.ULInt8('version'), 0x24),&lt;br /&gt;
&lt;br /&gt;
	_cns.ULInt8('stars'),          # 1-5 stars, or 6 for &amp;quot;tower&amp;quot;&lt;br /&gt;
	_util.Unknown('_hdr3', 1),&lt;br /&gt;
	_cns.ULInt32('cash_balance'),  # units of $100&lt;br /&gt;
	_cns.ULInt32('other_income'),&lt;br /&gt;
	_cns.ULInt32('construction_costs'),&lt;br /&gt;
	_cns.ULInt32('last_quarter_cash'),&lt;br /&gt;
	_cns.ULInt16('frame_time'),&lt;br /&gt;
	_cns.ULInt32('day'),&lt;br /&gt;
	_util.Unknown('_hdr26', 2),&lt;br /&gt;
	_cns.ULInt8('lobby_height'),&lt;br /&gt;
	_util.Unknown('_hdr29', 9),&lt;br /&gt;
	_cns.ULInt16('viewport_x'),&lt;br /&gt;
	_cns.ULInt16('viewport_y'),&lt;br /&gt;
	_util.Unknown('_hdr42', 14),&lt;br /&gt;
	_cns.ULInt8('named_people_count'),&lt;br /&gt;
&lt;br /&gt;
	_util.Unknown('_hdr57', 503),&lt;br /&gt;
	_cns.Anchor('hdr_end_'),&lt;br /&gt;
	_util.Assert(lambda ctx: ctx.hdr_end_ == ctx.hdr_start_ + 560),&lt;br /&gt;
)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#### Tenants&lt;br /&gt;
&lt;br /&gt;
Tenant_Type = _util.NumToSym(_cns.ULInt8('type'), {&lt;br /&gt;
	 0:'floor',&lt;br /&gt;
	 3:'hotel_single',&lt;br /&gt;
	 4:'hotel_double',&lt;br /&gt;
	 5:'hotal_suite',&lt;br /&gt;
	 6:'restaurant',&lt;br /&gt;
	 7:'office',&lt;br /&gt;
	 9:'condo',&lt;br /&gt;
	10:'shop',&lt;br /&gt;
	11:'parking_space',&lt;br /&gt;
	12:'fast_food',&lt;br /&gt;
	13:'medical',&lt;br /&gt;
	14:'security',&lt;br /&gt;
	15:'housekeeping',&lt;br /&gt;
	18:'movie_theater_floor2', 19:'movie_theater',&lt;br /&gt;
	20:'recycling_floor2', 21:'recycling',&lt;br /&gt;
	24:'lobby',&lt;br /&gt;
	29:'hall_floor2', 30:'hall',&lt;br /&gt;
	33:'metro',&lt;br /&gt;
	34:'movie_screen_floor2', 35:'movie_screen',&lt;br /&gt;
	36:'cathedral_floor5', 37:'cathedral_floor4',&lt;br /&gt;
		38:'cathedral_floor3', 39:'cathedral_floor2',&lt;br /&gt;
		40:'cathedral',&lt;br /&gt;
	44:'parking_ramp',&lt;br /&gt;
	45:'metro_tunnel',&lt;br /&gt;
	48:'burned',&lt;br /&gt;
})&lt;br /&gt;
&lt;br /&gt;
Tenant_Struct = _cns.Struct('tenant',&lt;br /&gt;
	# Horizontal positions are given with half-open ranges [left,right)&lt;br /&gt;
	# in units of 8 pixels.&lt;br /&gt;
	_cns.ULInt16('left_edge'),&lt;br /&gt;
	_cns.ULInt16('right_edge'),&lt;br /&gt;
	_cns.Rename('type', Tenant_Type),&lt;br /&gt;
	_cns.ULInt8('status'),&lt;br /&gt;
	_cns.ULInt8('pertype_idx'),&lt;br /&gt;
	_util.Unknown('_unk7', 1),&lt;br /&gt;
	_cns.ULInt32('people_offset'),&lt;br /&gt;
	_cns.ULInt8('id'),&lt;br /&gt;
	_util.Unknown('_unk13', 3),&lt;br /&gt;
	_cns.ULInt8('rent_class'),&lt;br /&gt;
	_util.Unknown('_unk17', 1),&lt;br /&gt;
)&lt;br /&gt;
assert(Tenant_Struct.sizeof() == 18)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#### Floors&lt;br /&gt;
&lt;br /&gt;
def _floor_below_grade(raw_floor):&lt;br /&gt;
	return raw_floor &amp;lt; 10&lt;br /&gt;
&lt;br /&gt;
def floor_id_from_raw(raw_floor):&lt;br /&gt;
	# Raw floor values {0..9} are basements: {-10..-1} or {B10..B1}.&lt;br /&gt;
	# Values {10..119} are floors {1..110}.&lt;br /&gt;
	if _floor_below_grade(raw_floor):&lt;br /&gt;
		return raw_floor-10&lt;br /&gt;
	else:&lt;br /&gt;
		return raw_floor-9&lt;br /&gt;
&lt;br /&gt;
def _floor_could_be_lobby(raw_floor):&lt;br /&gt;
	return floor_id_from_raw(raw_floor) in (1, 15, 30, 45, 60, 75, 90)&lt;br /&gt;
&lt;br /&gt;
Floor_Struct = _cns.Struct('floor',&lt;br /&gt;
	_cns.ULInt16('tenant_count'),&lt;br /&gt;
	_cns.ULInt16('left_edge'),&lt;br /&gt;
	_cns.ULInt16('right_edge'),&lt;br /&gt;
	_cns.Rename('tenants',&lt;br /&gt;
		_cns.Array(lambda ctx: ctx.tenant_count, Tenant_Struct)),&lt;br /&gt;
	_cns.Array(94, _cns.ULInt16('tenant_id_to_index')),&lt;br /&gt;
)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#### People&lt;br /&gt;
&lt;br /&gt;
Person_Struct = _cns.Struct('person',&lt;br /&gt;
	_cns.ULInt8('tenant_floor'),&lt;br /&gt;
	_cns.ULInt8('tenant_index'),&lt;br /&gt;
	_cns.ULInt16('number_in_tenant'),&lt;br /&gt;
	_cns.Rename('tenant_type', Tenant_Type),&lt;br /&gt;
	_cns.ULInt8('status'),&lt;br /&gt;
	_cns.SLInt8('current_floor'),&lt;br /&gt;
	_util.Unknown('_unk6', 5),&lt;br /&gt;
	_cns.ULInt16('stress'),&lt;br /&gt;
	_cns.ULInt16('eval'),&lt;br /&gt;
)&lt;br /&gt;
assert(Person_Struct.sizeof() == 16)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#### Retail&lt;br /&gt;
&lt;br /&gt;
Retail_Struct = _cns.Struct('retail',&lt;br /&gt;
	_cns.ULInt8('floor'),&lt;br /&gt;
	_util.Unknown('_unk1', 10),&lt;br /&gt;
	_cns.ULInt8('type'),&lt;br /&gt;
	_util.Unknown('_unk12', 6),&lt;br /&gt;
)&lt;br /&gt;
assert(Retail_Struct.sizeof() == 18)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#### Stairs&lt;br /&gt;
&lt;br /&gt;
Stairs_Type = _util.NumToSym(_cns.ULInt8('type'),&lt;br /&gt;
	{0:'escalator', 1:'standard'})&lt;br /&gt;
&lt;br /&gt;
Stairs_Struct = _cns.Struct('stairs',&lt;br /&gt;
	_util.Bool(_cns.ULInt8('present')),&lt;br /&gt;
	_cns.Rename('type', Stairs_Type),&lt;br /&gt;
	_cns.ULInt16('xpos'),&lt;br /&gt;
	_cns.ULInt8('bottom_floor'),&lt;br /&gt;
	_util.Unknown('_unk5', 5),&lt;br /&gt;
)&lt;br /&gt;
assert(Stairs_Struct.sizeof() == 10)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#### Elevators&lt;br /&gt;
&lt;br /&gt;
Elevator_Type = _util.NumToSym(_cns.ULInt8('type'),&lt;br /&gt;
		{0:'express', 1:'standard', 2:'service'})&lt;br /&gt;
&lt;br /&gt;
def _potential_floors_served(ctx):&lt;br /&gt;
	if ctx.type == 'express':&lt;br /&gt;
		count = 0&lt;br /&gt;
		for i in range(ctx.bottom_floor, ctx.top_floor + 1):&lt;br /&gt;
			if _floor_below_grade(i) or _floor_could_be_lobby(i):&lt;br /&gt;
				count += 1&lt;br /&gt;
	else:&lt;br /&gt;
		count = 1 + (ctx.top_floor - ctx.bottom_floor)&lt;br /&gt;
	return count&lt;br /&gt;
&lt;br /&gt;
Elevator_Struct = _cns.Struct('elevator',&lt;br /&gt;
	_cns.Anchor('start_'),&lt;br /&gt;
&lt;br /&gt;
	_util.Bool(_cns.ULInt8('present')),&lt;br /&gt;
	_cns.Rename('type', Elevator_Type),&lt;br /&gt;
&lt;br /&gt;
	# Capacity &amp;gt; 42 may crash SimTower.&lt;br /&gt;
	# 42 seems to work for non-express elevators.&lt;br /&gt;
	_cns.ULInt8('capacity'),&lt;br /&gt;
	_cns.ULInt8('car_count'),&lt;br /&gt;
&lt;br /&gt;
	# There are 4 &amp;quot;schedule&amp;quot; arrays of size 14: 7 weekday periods, followed&lt;br /&gt;
	# by 7 weekend periods.  The GUI shows 6 periods per day; the 7th is&lt;br /&gt;
	# not used.  The entire first array looks unused too.  The regex&lt;br /&gt;
	# '\x01{14}......\x05......\x05' can reliably find elevator data.&lt;br /&gt;
	_cns.Array(14, _cns.ULInt8('#unknown_sched')),&lt;br /&gt;
	_cns.If(lambda ctx: ctx.present,&lt;br /&gt;
		_util.Assert(lambda ctx: ctx['#unknown_sched'] == [1]*14)),&lt;br /&gt;
	_cns.Array(14, _cns.ULInt8('response_distances')),&lt;br /&gt;
	_cns.Array(14, _cns.ULInt8('express_modes')),&lt;br /&gt;
	_cns.Array(14, _cns.ULInt8('departure_delays')),&lt;br /&gt;
&lt;br /&gt;
	_util.Bool(_cns.ULInt8('shaft_visible')),&lt;br /&gt;
	_util.Unknown('_unk60', 1),&lt;br /&gt;
	_cns.ULInt16('left_edge'),&lt;br /&gt;
	_cns.ULInt8('top_floor'),&lt;br /&gt;
	_cns.ULInt8('bottom_floor'),&lt;br /&gt;
	_cns.Value('potential_floors_served_', _potential_floors_served),&lt;br /&gt;
&lt;br /&gt;
	# For each of 120 floors, value is 1 if served, otherwise 0.&lt;br /&gt;
	# Adding express elevator stops on improper floors (above ground and&lt;br /&gt;
	# not a multiple of 15) may crash SimTower, probably because there's&lt;br /&gt;
	# an array of size potential_floors_served.&lt;br /&gt;
	_cns.Array(120, _cns.ULInt8('floor_stops')),&lt;br /&gt;
&lt;br /&gt;
	# Resting floor for each car.&lt;br /&gt;
	_cns.Array(8, _cns.ULInt8('resting_floors')),&lt;br /&gt;
&lt;br /&gt;
	_cns.Anchor('fixed_end_'),&lt;br /&gt;
	_util.Assert(lambda ctx: ctx.fixed_end_ == ctx.start_ + 194),&lt;br /&gt;
&lt;br /&gt;
	_cns.If(lambda ctx: ctx.present, _util.AnonEmbed(&lt;br /&gt;
		_util.Unknown('_unk194', 3488),&lt;br /&gt;
&lt;br /&gt;
		# Information about people waiting for elevators&lt;br /&gt;
		# is likely to be in the following array.&lt;br /&gt;
		_cns.Array(lambda ctx: ctx.potential_floors_served_,&lt;br /&gt;
			_util.Unknown('_unk3682', 324)),&lt;br /&gt;
	)),&lt;br /&gt;
	_cns.Anchor('end_'),&lt;br /&gt;
)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#### Finances/population block&lt;br /&gt;
&lt;br /&gt;
Finances_Struct = _cns.Struct('finances',&lt;br /&gt;
	_cns.Array(10, _cns.ULInt32('tenant_populations')),&lt;br /&gt;
	_cns.ULInt32('tower_population'),&lt;br /&gt;
	_cns.Array(10, _cns.ULInt32('tenant_incomes')),&lt;br /&gt;
	_cns.ULInt32('tower_income'),&lt;br /&gt;
	_cns.Array(10, _cns.ULInt32('tenant_maintenance')),&lt;br /&gt;
	_cns.ULInt32('tower_maintenance'),&lt;br /&gt;
)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#### Overall file structure&lt;br /&gt;
&lt;br /&gt;
Tower_Struct = _cns.Struct('tower',&lt;br /&gt;
	_cns.Embedded(File_Header_Struct),&lt;br /&gt;
&lt;br /&gt;
	_cns.Rename('floors', _cns.Array(120, Floor_Struct)),&lt;br /&gt;
&lt;br /&gt;
	_cns.ULInt32('people_count'),&lt;br /&gt;
	_cns.Rename('people',&lt;br /&gt;
		_cns.Array(lambda ctx: ctx.people_count, Person_Struct)),&lt;br /&gt;
&lt;br /&gt;
	_cns.Rename('retail', _cns.Array(512, Retail_Struct)),&lt;br /&gt;
&lt;br /&gt;
	_cns.Anchor('elevators_start_'),&lt;br /&gt;
	_cns.Rename('elevators', _cns.Array(24, Elevator_Struct)),&lt;br /&gt;
	_cns.Anchor('elevators_end_'),&lt;br /&gt;
&lt;br /&gt;
	_util.Unknown('_unk_after_elev', 88),&lt;br /&gt;
	_cns.Anchor('finances_start_'),&lt;br /&gt;
	_cns.Embedded(Finances_Struct),&lt;br /&gt;
	_cns.Anchor('finances_end_'),&lt;br /&gt;
&lt;br /&gt;
	_util.Unknown('_unk_after_finpop', 1102),&lt;br /&gt;
	_cns.Anchor('stairs_start_'),&lt;br /&gt;
	_cns.Rename('stairs', _cns.Array(64, Stairs_Struct)),&lt;br /&gt;
	_cns.Anchor('stairs_end_'),&lt;br /&gt;
&lt;br /&gt;
	_util.Unknown('_unk_after_stairs', 17242),&lt;br /&gt;
	_cns.Rename('named_people',&lt;br /&gt;
		_cns.Array(lambda ctx: ctx.named_people_count,&lt;br /&gt;
			_util.ZStr(None, 16))),&lt;br /&gt;
&lt;br /&gt;
	_cns.Terminator  # must reach end of file&lt;br /&gt;
)&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== util.py ===&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;# To the extent possible under law, the author(s) have dedicated all copyright&lt;br /&gt;
# and related and neighboring rights to this software to the public domain&lt;br /&gt;
# worldwide. This software is distributed without any warranty.&lt;br /&gt;
#&lt;br /&gt;
# See &amp;lt;http://creativecommons.org/publicdomain/zero/1.0/&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
import construct as _cns&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#### Utility functions&lt;br /&gt;
&lt;br /&gt;
Unknown = _cns.Field&lt;br /&gt;
&lt;br /&gt;
class Assert(_cns.Construct):&lt;br /&gt;
	def __init__(self, fn):&lt;br /&gt;
		_cns.Construct.__init__(self, None)&lt;br /&gt;
		self.fn = fn&lt;br /&gt;
	def _sizeof(self, context): return 0&lt;br /&gt;
	def _assert(self, stream, context): assert self.fn(context)&lt;br /&gt;
	def _parse(self, stream, context): self._assert(stream, context)&lt;br /&gt;
	def _build(self, obj, stream, context): self._assert(stream, context)&lt;br /&gt;
&lt;br /&gt;
def AnonEmbed(*subcons):&lt;br /&gt;
	return _cns.Embedded(_cns.Struct(None, *subcons))&lt;br /&gt;
&lt;br /&gt;
def NumToSym(subcon, decoding):&lt;br /&gt;
	return _cns.MappingAdapter(subcon, decoding = decoding,&lt;br /&gt;
		encoding = dict((v,k) for (k,v) in decoding.items()),&lt;br /&gt;
		decdefault = _cns.Pass, encdefault = _cns.Pass)&lt;br /&gt;
&lt;br /&gt;
def Bool(subcon):&lt;br /&gt;
	return NumToSym(subcon, {0:False, 1:True})&lt;br /&gt;
&lt;br /&gt;
class _PaddedBytes(bytes):&lt;br /&gt;
	def __new__(cls, raw=b'', padding=None):&lt;br /&gt;
		b = super(_PaddedBytes, cls).__new__(cls, raw)&lt;br /&gt;
		b.padding = padding&lt;br /&gt;
		return b&lt;br /&gt;
&lt;br /&gt;
class _ZStrAdapter(_cns.StringAdapter):&lt;br /&gt;
	def __init__(self, subcon):&lt;br /&gt;
		_cns.StringAdapter.__init__(self, subcon)&lt;br /&gt;
	def _decode(self, obj, context):&lt;br /&gt;
		obj = _PaddedBytes(*obj.split(b'\0', 1))&lt;br /&gt;
		return _cns.StringAdapter._decode(self, obj, context)&lt;br /&gt;
	def _encode(self, obj, context):&lt;br /&gt;
		out = _cns.StringAdapter._encode(self, obj, context)&lt;br /&gt;
		out += b'\0'&lt;br /&gt;
		try:&lt;br /&gt;
			if obj.padding is not None:&lt;br /&gt;
				out += obj.padding&lt;br /&gt;
		except AttributeError:&lt;br /&gt;
			pass&lt;br /&gt;
&lt;br /&gt;
		pad = self._sizeof(context) - len(out)&lt;br /&gt;
		if pad &amp;lt; 0:&lt;br /&gt;
			raise ValueError(&amp;quot;string too long&amp;quot;)&lt;br /&gt;
		out += b'\0' * pad&lt;br /&gt;
&lt;br /&gt;
		return out&lt;br /&gt;
&lt;br /&gt;
def ZStr(name, length, encoding=None):&lt;br /&gt;
	fld = _cns.Field(name, length)&lt;br /&gt;
	return _ZStrAdapter(_cns.StringAdapter(fld, encoding=encoding))&amp;lt;/nowiki&amp;gt;&lt;/div&gt;</summary>
		<author><name>Cypherpunks</name></author>	</entry>

	<entry>
		<id>http://fileformats.archiveteam.org/wiki/SimTower_saved_game</id>
		<title>SimTower saved game</title>
		<link rel="alternate" type="text/html" href="http://fileformats.archiveteam.org/wiki/SimTower_saved_game"/>
				<updated>2016-09-27T03:01:53Z</updated>
		
		<summary type="html">&lt;p&gt;Cypherpunks: /* File Format */ add image&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{FormatInfo&lt;br /&gt;
|formattype=electronic&lt;br /&gt;
|subcat=Saved Games&lt;br /&gt;
|extensions={{ext|tdt}}&lt;br /&gt;
|image=Simtower.png&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
== Links ==&lt;br /&gt;
&lt;br /&gt;
* [https://raw.githubusercontent.com/fabianschuiki/OpenSkyscraper/90e6e92a2d46869a4052332e48633dd1545256e4/doc/simtower/TDT_format.txt Format description from the OpenSkyscraper project]&lt;br /&gt;
* [[Wikipedia:SimTower|Wikipedia article on SimTower]]&lt;br /&gt;
&lt;br /&gt;
== Code ==&lt;br /&gt;
&lt;br /&gt;
The following code can parse the format; and even for those who don't know Python it should mostly be understandable as a format description.&lt;br /&gt;
&lt;br /&gt;
Integers are named as &amp;lt;code&amp;gt;(sign)(endian)Int(bits)&amp;lt;/code&amp;gt;, like &amp;lt;code&amp;gt;ULInt32&amp;lt;/code&amp;gt;. TDT uses little-endian. Exact size and signedness wasn't verified for most fields.&lt;br /&gt;
&lt;br /&gt;
* This requires the Construct package for Python (tested with Construct 2.5.2 and Python 3.5.2).&lt;br /&gt;
* It's meant to handle binary-identical roundtripping even with bad values.&lt;br /&gt;
&lt;br /&gt;
=== Usage example ===&lt;br /&gt;
&lt;br /&gt;
If both files below are installed to the current directory, you can run the following at the command line to make all elevators carry 42 people:&amp;lt;br clear=&amp;quot;all&amp;quot;&amp;gt;&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;$ python3&lt;br /&gt;
&amp;gt;&amp;gt;&amp;gt; import tdt_cons&lt;br /&gt;
&amp;gt;&amp;gt;&amp;gt; f = open('SIMTOWER/TDT/TOWER.TDT','rb')&lt;br /&gt;
&amp;gt;&amp;gt;&amp;gt; tower = tdt_cons.Tower_Struct.parse_stream(f)&lt;br /&gt;
&amp;gt;&amp;gt;&amp;gt; for el in tower.elevators: el.capacity = 42&lt;br /&gt;
... &lt;br /&gt;
&amp;gt;&amp;gt;&amp;gt; f = open('SIMTOWER/TDT/TOWEROUT.TDT','wb')&lt;br /&gt;
&amp;gt;&amp;gt;&amp;gt; tdt_cons.Tower_Struct.build_stream(tower, f)&lt;br /&gt;
&amp;gt;&amp;gt;&amp;gt; &amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== tdt_cons.py ===&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;# To the extent possible under law, the author(s) have dedicated all copyright&lt;br /&gt;
# and related and neighboring rights to this software to the public domain&lt;br /&gt;
# worldwide. This software is distributed without any warranty.&lt;br /&gt;
#&lt;br /&gt;
# See &amp;lt;http://creativecommons.org/publicdomain/zero/1.0/&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
import construct as _cns&lt;br /&gt;
import util as _util&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#### File header&lt;br /&gt;
&lt;br /&gt;
File_Header_Struct = _cns.Struct('file_header',&lt;br /&gt;
	# Anchor records the current file position, for sanity checks (Assert).&lt;br /&gt;
	# Put _cns.Probe() between fields to dump data for debugging.&lt;br /&gt;
	_cns.Anchor('hdr_start_'),&lt;br /&gt;
&lt;br /&gt;
	# SimTower doesn't seem to care about the first byte, but the second&lt;br /&gt;
	# must be 0x24. Larger values produce a &amp;quot;wrong version&amp;quot; warning.&lt;br /&gt;
	_cns.Padding(1),&lt;br /&gt;
	_cns.Const(_cns.ULInt8('version'), 0x24),&lt;br /&gt;
&lt;br /&gt;
	_cns.ULInt8('stars'),          # 1-5 stars, or 6 for &amp;quot;tower&amp;quot;&lt;br /&gt;
	_util.Unknown('_hdr3', 1),&lt;br /&gt;
	_cns.ULInt32('cash_balance'),  # units of $100&lt;br /&gt;
	_cns.ULInt32('other_income'),&lt;br /&gt;
	_cns.ULInt32('construction_costs'),&lt;br /&gt;
	_cns.ULInt32('last_quarter_cash'),&lt;br /&gt;
	_cns.ULInt16('frame_time'),&lt;br /&gt;
	_cns.ULInt32('day'),&lt;br /&gt;
	_util.Unknown('_hdr26', 2),&lt;br /&gt;
	_cns.ULInt8('lobby_height'),&lt;br /&gt;
	_util.Unknown('_hdr29', 9),&lt;br /&gt;
	_cns.ULInt16('viewport_x'),&lt;br /&gt;
	_cns.ULInt16('viewport_y'),&lt;br /&gt;
	_util.Unknown('_hdr42', 14),&lt;br /&gt;
	_cns.ULInt8('named_people_count'),&lt;br /&gt;
&lt;br /&gt;
	_util.Unknown('_hdr57', 503),&lt;br /&gt;
	_cns.Anchor('hdr_end_'),&lt;br /&gt;
	_util.Assert(lambda ctx: ctx.hdr_end_ == ctx.hdr_start_ + 560),&lt;br /&gt;
)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#### Tenants&lt;br /&gt;
&lt;br /&gt;
Tenant_Type = _util.NumToSym(_cns.ULInt8('type'), {&lt;br /&gt;
	 0:'floor',&lt;br /&gt;
	 3:'hotel_single',&lt;br /&gt;
	 4:'hotel_double',&lt;br /&gt;
	 5:'hotal_suite',&lt;br /&gt;
	 6:'restaurant',&lt;br /&gt;
	 7:'office',&lt;br /&gt;
	 9:'condo',&lt;br /&gt;
	10:'shop',&lt;br /&gt;
	11:'parking_space',&lt;br /&gt;
	12:'fast_food',&lt;br /&gt;
	13:'medical',&lt;br /&gt;
	14:'security',&lt;br /&gt;
	15:'housekeeping',&lt;br /&gt;
	18:'movie_theater_floor2', 19:'movie_theater',&lt;br /&gt;
	20:'recycling_floor2', 21:'recycling',&lt;br /&gt;
	24:'lobby',&lt;br /&gt;
	29:'hall_floor2', 30:'hall',&lt;br /&gt;
	33:'metro',&lt;br /&gt;
	34:'movie_screen_floor2', 35:'movie_screen',&lt;br /&gt;
	36:'cathedral_floor5', 37:'cathedral_floor4',&lt;br /&gt;
		38:'cathedral_floor3', 39:'cathedral_floor2',&lt;br /&gt;
		40:'cathedral',&lt;br /&gt;
	44:'parking_ramp',&lt;br /&gt;
	45:'metro_tunnel',&lt;br /&gt;
	48:'burned',&lt;br /&gt;
})&lt;br /&gt;
&lt;br /&gt;
Tenant_Struct = _cns.Struct('tenant',&lt;br /&gt;
	# Horizontal positions are given with half-open ranges [left,right)&lt;br /&gt;
	# in units of 8 pixels.&lt;br /&gt;
	_cns.ULInt16('left_edge'),&lt;br /&gt;
	_cns.ULInt16('right_edge'),&lt;br /&gt;
	_cns.Rename('type', Tenant_Type),&lt;br /&gt;
	_cns.ULInt8('status'),&lt;br /&gt;
	_cns.ULInt8('pertype_idx'),&lt;br /&gt;
	_util.Unknown('_unk7', 1),&lt;br /&gt;
	_cns.ULInt32('people_offset'),&lt;br /&gt;
	_cns.ULInt8('id'),&lt;br /&gt;
	_util.Unknown('_unk13', 3),&lt;br /&gt;
	_cns.ULInt8('rent_class'),&lt;br /&gt;
	_util.Unknown('_unk17', 1),&lt;br /&gt;
)&lt;br /&gt;
assert(Tenant_Struct.sizeof() == 18)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#### Floors&lt;br /&gt;
&lt;br /&gt;
def _floor_below_grade(raw_floor):&lt;br /&gt;
	return raw_floor &amp;lt; 10&lt;br /&gt;
&lt;br /&gt;
def floor_id_from_raw(raw_floor):&lt;br /&gt;
	# Raw floor values {0..9} are basements: {-10..-1} or {B10..B1}.&lt;br /&gt;
	# Values {10..119} are floors {1..110}.&lt;br /&gt;
	if _floor_below_grade(raw_floor):&lt;br /&gt;
		return raw_floor-10&lt;br /&gt;
	else:&lt;br /&gt;
		return raw_floor-9&lt;br /&gt;
&lt;br /&gt;
def _floor_could_be_lobby(raw_floor):&lt;br /&gt;
	return floor_id_from_raw(raw_floor) in (1, 15, 30, 45, 60, 75, 90)&lt;br /&gt;
&lt;br /&gt;
Floor_Struct = _cns.Struct('floor',&lt;br /&gt;
	_cns.ULInt16('tenant_count'),&lt;br /&gt;
	_cns.ULInt16('left_edge'),&lt;br /&gt;
	_cns.ULInt16('right_edge'),&lt;br /&gt;
	_cns.Rename('tenants',&lt;br /&gt;
		_cns.Array(lambda ctx: ctx.tenant_count, Tenant_Struct)),&lt;br /&gt;
	_cns.Array(94, _cns.ULInt16('tenant_id_to_index')),&lt;br /&gt;
)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#### People&lt;br /&gt;
&lt;br /&gt;
Person_Struct = _cns.Struct('person',&lt;br /&gt;
	_cns.ULInt8('tenant_floor'),&lt;br /&gt;
	_cns.ULInt8('tenant_index'),&lt;br /&gt;
	_cns.ULInt16('number_in_tenant'),&lt;br /&gt;
	_cns.Rename('tenant_type', Tenant_Type),&lt;br /&gt;
	_cns.ULInt8('status'),&lt;br /&gt;
	_cns.SLInt8('current_floor'),&lt;br /&gt;
	_util.Unknown('_unk6', 5),&lt;br /&gt;
	_cns.ULInt16('stress'),&lt;br /&gt;
	_cns.ULInt16('eval'),&lt;br /&gt;
)&lt;br /&gt;
assert(Person_Struct.sizeof() == 16)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#### Retail&lt;br /&gt;
&lt;br /&gt;
Retail_Struct = _cns.Struct('retail',&lt;br /&gt;
	_cns.ULInt8('floor'),&lt;br /&gt;
	_util.Unknown('_unk1', 10),&lt;br /&gt;
	_cns.ULInt8('type'),&lt;br /&gt;
	_util.Unknown('_unk12', 6),&lt;br /&gt;
)&lt;br /&gt;
assert(Retail_Struct.sizeof() == 18)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#### Stairs&lt;br /&gt;
&lt;br /&gt;
Stairs_Type = _util.NumToSym(_cns.ULInt8('type'),&lt;br /&gt;
	{0:'escalator', 1:'standard'})&lt;br /&gt;
&lt;br /&gt;
Stairs_Struct = _cns.Struct('stairs',&lt;br /&gt;
	_util.Bool(_cns.ULInt8('present')),&lt;br /&gt;
	_cns.Rename('type', Stairs_Type),&lt;br /&gt;
	_cns.ULInt16('xpos'),&lt;br /&gt;
	_cns.ULInt8('bottom_floor'),&lt;br /&gt;
	_util.Unknown('_unk5', 5),&lt;br /&gt;
)&lt;br /&gt;
assert(Stairs_Struct.sizeof() == 10)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#### Elevators&lt;br /&gt;
&lt;br /&gt;
Elevator_Type = _util.NumToSym(_cns.ULInt8('type'),&lt;br /&gt;
		{0:'express', 1:'standard', 2:'service'})&lt;br /&gt;
&lt;br /&gt;
def _potential_floors_served(ctx):&lt;br /&gt;
	if ctx.type == 'express':&lt;br /&gt;
		count = 0&lt;br /&gt;
		for i in range(ctx.bottom_floor, ctx.top_floor + 1):&lt;br /&gt;
			if _floor_below_grade(i) or _floor_could_be_lobby(i):&lt;br /&gt;
				count += 1&lt;br /&gt;
	else:&lt;br /&gt;
		count = 1 + (ctx.top_floor - ctx.bottom_floor)&lt;br /&gt;
	return count&lt;br /&gt;
&lt;br /&gt;
Elevator_Struct = _cns.Struct('elevator',&lt;br /&gt;
	_cns.Anchor('start_'),&lt;br /&gt;
&lt;br /&gt;
	_util.Bool(_cns.ULInt8('present')),&lt;br /&gt;
	_cns.Rename('type', Elevator_Type),&lt;br /&gt;
&lt;br /&gt;
	# Capacity &amp;gt; 42 may crash SimTower.&lt;br /&gt;
	# 42 seems to work for non-express elevators.&lt;br /&gt;
	_cns.ULInt8('capacity'),&lt;br /&gt;
	_cns.ULInt8('car_count'),&lt;br /&gt;
&lt;br /&gt;
	# There are 4 &amp;quot;schedule&amp;quot; arrays of size 14: 7 weekday periods, followed&lt;br /&gt;
	# by 7 weekend periods.  The GUI shows 6 periods per day; the 7th is&lt;br /&gt;
	# not used.  The entire first array looks unused too.  The regex&lt;br /&gt;
	# '\x01{14}......\x05......\x05' can reliably find elevator data.&lt;br /&gt;
	_cns.Array(14, _cns.ULInt8('#unknown_sched')),&lt;br /&gt;
	_cns.If(lambda ctx: ctx.present,&lt;br /&gt;
		_util.Assert(lambda ctx: ctx['#unknown_sched'] == [1]*14)),&lt;br /&gt;
	_cns.Array(14, _cns.ULInt8('response_distances')),&lt;br /&gt;
	_cns.Array(14, _cns.ULInt8('express_modes')),&lt;br /&gt;
	_cns.Array(14, _cns.ULInt8('departure_delays')),&lt;br /&gt;
&lt;br /&gt;
	_util.Bool(_cns.ULInt8('shaft_visible')),&lt;br /&gt;
	_util.Unknown('_unk60', 1),&lt;br /&gt;
	_cns.ULInt16('left_edge'),&lt;br /&gt;
	_cns.ULInt8('top_floor'),&lt;br /&gt;
	_cns.ULInt8('bottom_floor'),&lt;br /&gt;
	_cns.Value('potential_floors_served_', _potential_floors_served),&lt;br /&gt;
&lt;br /&gt;
	# For each of 120 floors, value is 1 if served, otherwise 0.&lt;br /&gt;
	# Adding express elevator stops on improper floors (above ground and&lt;br /&gt;
	# not a multiple of 15) may crash SimTower, probably because there's&lt;br /&gt;
	# an array of size potential_floors_served.&lt;br /&gt;
	_cns.Array(120, _cns.ULInt8('floor_stops')),&lt;br /&gt;
&lt;br /&gt;
	# Resting floor for each car.&lt;br /&gt;
	_cns.Array(8, _cns.ULInt8('resting_floors')),&lt;br /&gt;
&lt;br /&gt;
	_cns.Anchor('fixed_end_'),&lt;br /&gt;
	_util.Assert(lambda ctx: ctx.fixed_end_ == ctx.start_ + 194),&lt;br /&gt;
&lt;br /&gt;
	_cns.If(lambda ctx: ctx.present, _util.AnonEmbed(&lt;br /&gt;
		_util.Unknown('_unk194', 3488),&lt;br /&gt;
&lt;br /&gt;
		# Information about people waiting for elevators&lt;br /&gt;
		# is likely to be in the following array.&lt;br /&gt;
		_cns.Array(lambda ctx: ctx.potential_floors_served_,&lt;br /&gt;
			_util.Unknown('_unk3682', 324)),&lt;br /&gt;
	)),&lt;br /&gt;
	_cns.Anchor('end_'),&lt;br /&gt;
)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#### Finances/population block&lt;br /&gt;
&lt;br /&gt;
Finances_Struct = _cns.Struct('finances',&lt;br /&gt;
	_cns.Array(10, _cns.ULInt32('tenant_populations')),&lt;br /&gt;
	_cns.ULInt32('tower_population'),&lt;br /&gt;
	_cns.Array(10, _cns.ULInt32('tenant_incomes')),&lt;br /&gt;
	_cns.ULInt32('tower_income'),&lt;br /&gt;
	_cns.Array(10, _cns.ULInt32('tenant_maintenance')),&lt;br /&gt;
	_cns.ULInt32('tower_maintenance'),&lt;br /&gt;
)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#### Overall file structure&lt;br /&gt;
&lt;br /&gt;
Tower_Struct = _cns.Struct('tower',&lt;br /&gt;
	_cns.Embedded(File_Header_Struct),&lt;br /&gt;
&lt;br /&gt;
	_cns.Rename('floors', _cns.Array(120, Floor_Struct)),&lt;br /&gt;
&lt;br /&gt;
	_cns.ULInt32('people_count'),&lt;br /&gt;
	_cns.Rename('people',&lt;br /&gt;
		_cns.Array(lambda ctx: ctx.people_count, Person_Struct)),&lt;br /&gt;
&lt;br /&gt;
	_cns.Rename('retail', _cns.Array(512, Retail_Struct)),&lt;br /&gt;
&lt;br /&gt;
	_cns.Anchor('elevators_start_'),&lt;br /&gt;
	_cns.Rename('elevators', _cns.Array(24, Elevator_Struct)),&lt;br /&gt;
	_cns.Anchor('elevators_end_'),&lt;br /&gt;
&lt;br /&gt;
	_util.Unknown('_unk_after_elev', 88),&lt;br /&gt;
	_cns.Anchor('finances_start_'),&lt;br /&gt;
	_cns.Embedded(Finances_Struct),&lt;br /&gt;
	_cns.Anchor('finances_end_'),&lt;br /&gt;
&lt;br /&gt;
	_util.Unknown('_unk_after_finpop', 1102),&lt;br /&gt;
	_cns.Anchor('stairs_start_'),&lt;br /&gt;
	_cns.Rename('stairs', _cns.Array(64, Stairs_Struct)),&lt;br /&gt;
	_cns.Anchor('stairs_end_'),&lt;br /&gt;
&lt;br /&gt;
	_util.Unknown('_unk_after_stairs', 17242),&lt;br /&gt;
	_cns.Rename('named_people',&lt;br /&gt;
		_cns.Array(lambda ctx: ctx.named_people_count,&lt;br /&gt;
			_util.ZStr(None, 16))),&lt;br /&gt;
&lt;br /&gt;
	_cns.Terminator  # must reach end of file&lt;br /&gt;
)&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== util.py ===&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;# To the extent possible under law, the author(s) have dedicated all copyright&lt;br /&gt;
# and related and neighboring rights to this software to the public domain&lt;br /&gt;
# worldwide. This software is distributed without any warranty.&lt;br /&gt;
#&lt;br /&gt;
# See &amp;lt;http://creativecommons.org/publicdomain/zero/1.0/&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
import construct as _cns&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#### Utility functions&lt;br /&gt;
&lt;br /&gt;
Unknown = _cns.Field&lt;br /&gt;
&lt;br /&gt;
class Assert(_cns.Construct):&lt;br /&gt;
	def __init__(self, fn):&lt;br /&gt;
		_cns.Construct.__init__(self, None)&lt;br /&gt;
		self.fn = fn&lt;br /&gt;
	def _sizeof(self, context): return 0&lt;br /&gt;
	def _assert(self, stream, context): assert self.fn(context)&lt;br /&gt;
	def _parse(self, stream, context): self._assert(stream, context)&lt;br /&gt;
	def _build(self, obj, stream, context): self._assert(stream, context)&lt;br /&gt;
&lt;br /&gt;
def AnonEmbed(*subcons):&lt;br /&gt;
	return _cns.Embedded(_cns.Struct(None, *subcons))&lt;br /&gt;
&lt;br /&gt;
def NumToSym(subcon, decoding):&lt;br /&gt;
	return _cns.MappingAdapter(subcon, decoding = decoding,&lt;br /&gt;
		encoding = dict((v,k) for (k,v) in decoding.items()),&lt;br /&gt;
		decdefault = _cns.Pass, encdefault = _cns.Pass)&lt;br /&gt;
&lt;br /&gt;
def Bool(subcon):&lt;br /&gt;
	return NumToSym(subcon, {0:False, 1:True})&lt;br /&gt;
&lt;br /&gt;
class _PaddedBytes(bytes):&lt;br /&gt;
	def __new__(cls, raw=b'', padding=None):&lt;br /&gt;
		b = super(_PaddedBytes, cls).__new__(cls, raw)&lt;br /&gt;
		b.padding = padding&lt;br /&gt;
		return b&lt;br /&gt;
&lt;br /&gt;
class _ZStrAdapter(_cns.StringAdapter):&lt;br /&gt;
	def __init__(self, subcon):&lt;br /&gt;
		_cns.StringAdapter.__init__(self, subcon)&lt;br /&gt;
	def _decode(self, obj, context):&lt;br /&gt;
		obj = _PaddedBytes(*obj.split(b'\0', 1))&lt;br /&gt;
		return _cns.StringAdapter._decode(self, obj, context)&lt;br /&gt;
	def _encode(self, obj, context):&lt;br /&gt;
		out = _cns.StringAdapter._encode(self, obj, context)&lt;br /&gt;
		out += b'\0'&lt;br /&gt;
		try:&lt;br /&gt;
			if obj.padding is not None:&lt;br /&gt;
				out += obj.padding&lt;br /&gt;
		except AttributeError:&lt;br /&gt;
			pass&lt;br /&gt;
&lt;br /&gt;
		pad = self._sizeof(context) - len(out)&lt;br /&gt;
		if pad &amp;lt; 0:&lt;br /&gt;
			raise ValueError(&amp;quot;string too long&amp;quot;)&lt;br /&gt;
		out += b'\0' * pad&lt;br /&gt;
&lt;br /&gt;
		return out&lt;br /&gt;
&lt;br /&gt;
def ZStr(name, length, encoding=None):&lt;br /&gt;
	fld = _cns.Field(name, length)&lt;br /&gt;
	return _ZStrAdapter(_cns.StringAdapter(fld, encoding=encoding))&lt;br /&gt;
&amp;lt;/nowiki&amp;gt;&lt;/div&gt;</summary>
		<author><name>Cypherpunks</name></author>	</entry>

	<entry>
		<id>http://fileformats.archiveteam.org/wiki/File:Simtower.png</id>
		<title>File:Simtower.png</title>
		<link rel="alternate" type="text/html" href="http://fileformats.archiveteam.org/wiki/File:Simtower.png"/>
				<updated>2016-09-27T03:00:04Z</updated>
		
		<summary type="html">&lt;p&gt;Cypherpunks: SimTower screenshot&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;SimTower screenshot&lt;/div&gt;</summary>
		<author><name>Cypherpunks</name></author>	</entry>

	<entry>
		<id>http://fileformats.archiveteam.org/wiki/SimTower_saved_game</id>
		<title>SimTower saved game</title>
		<link rel="alternate" type="text/html" href="http://fileformats.archiveteam.org/wiki/SimTower_saved_game"/>
				<updated>2016-09-27T01:53:54Z</updated>
		
		<summary type="html">&lt;p&gt;Cypherpunks: /* tdt_cons.py */ fix comment&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{FormatInfo&lt;br /&gt;
|formattype=electronic&lt;br /&gt;
|subcat=Saved Games&lt;br /&gt;
|extensions={{ext|tdt}}&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
== Links ==&lt;br /&gt;
&lt;br /&gt;
* [https://raw.githubusercontent.com/fabianschuiki/OpenSkyscraper/90e6e92a2d46869a4052332e48633dd1545256e4/doc/simtower/TDT_format.txt Format description from the OpenSkyscraper project]&lt;br /&gt;
* [[Wikipedia:SimTower|Wikipedia article on SimTower]]&lt;br /&gt;
&lt;br /&gt;
== Code ==&lt;br /&gt;
&lt;br /&gt;
The following code can parse the format; and even for those who don't know Python it should mostly be understandable as a format description.&lt;br /&gt;
&lt;br /&gt;
Integers are named as &amp;lt;code&amp;gt;(sign)(endian)Int(bits)&amp;lt;/code&amp;gt;, like &amp;lt;code&amp;gt;ULInt32&amp;lt;/code&amp;gt;. TDT uses little-endian. Exact size and signedness wasn't verified for most fields.&lt;br /&gt;
&lt;br /&gt;
* This requires the Construct package for Python (tested with Construct 2.5.2 and Python 3.5.2).&lt;br /&gt;
* It's meant to handle binary-identical roundtripping even with bad values.&lt;br /&gt;
&lt;br /&gt;
=== Usage example ===&lt;br /&gt;
&lt;br /&gt;
If both files below are installed to the current directory, you can run the following at the command line to make all elevators carry 42 people:&amp;lt;br clear=&amp;quot;all&amp;quot;&amp;gt;&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;$ python3&lt;br /&gt;
&amp;gt;&amp;gt;&amp;gt; import tdt_cons&lt;br /&gt;
&amp;gt;&amp;gt;&amp;gt; f = open('SIMTOWER/TDT/TOWER.TDT','rb')&lt;br /&gt;
&amp;gt;&amp;gt;&amp;gt; tower = tdt_cons.Tower_Struct.parse_stream(f)&lt;br /&gt;
&amp;gt;&amp;gt;&amp;gt; for el in tower.elevators: el.capacity = 42&lt;br /&gt;
... &lt;br /&gt;
&amp;gt;&amp;gt;&amp;gt; f = open('SIMTOWER/TDT/TOWEROUT.TDT','wb')&lt;br /&gt;
&amp;gt;&amp;gt;&amp;gt; tdt_cons.Tower_Struct.build_stream(tower, f)&lt;br /&gt;
&amp;gt;&amp;gt;&amp;gt; &amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== tdt_cons.py ===&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;# To the extent possible under law, the author(s) have dedicated all copyright&lt;br /&gt;
# and related and neighboring rights to this software to the public domain&lt;br /&gt;
# worldwide. This software is distributed without any warranty.&lt;br /&gt;
#&lt;br /&gt;
# See &amp;lt;http://creativecommons.org/publicdomain/zero/1.0/&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
import construct as _cns&lt;br /&gt;
import util as _util&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#### File header&lt;br /&gt;
&lt;br /&gt;
File_Header_Struct = _cns.Struct('file_header',&lt;br /&gt;
	# Anchor records the current file position, for sanity checks (Assert).&lt;br /&gt;
	# Put _cns.Probe() between fields to dump data for debugging.&lt;br /&gt;
	_cns.Anchor('hdr_start_'),&lt;br /&gt;
&lt;br /&gt;
	# SimTower doesn't seem to care about the first byte, but the second&lt;br /&gt;
	# must be 0x24. Larger values produce a &amp;quot;wrong version&amp;quot; warning.&lt;br /&gt;
	_cns.Padding(1),&lt;br /&gt;
	_cns.Const(_cns.ULInt8('version'), 0x24),&lt;br /&gt;
&lt;br /&gt;
	_cns.ULInt8('stars'),          # 1-5 stars, or 6 for &amp;quot;tower&amp;quot;&lt;br /&gt;
	_util.Unknown('_hdr3', 1),&lt;br /&gt;
	_cns.ULInt32('cash_balance'),  # units of $100&lt;br /&gt;
	_cns.ULInt32('other_income'),&lt;br /&gt;
	_cns.ULInt32('construction_costs'),&lt;br /&gt;
	_cns.ULInt32('last_quarter_cash'),&lt;br /&gt;
	_cns.ULInt16('frame_time'),&lt;br /&gt;
	_cns.ULInt32('day'),&lt;br /&gt;
	_util.Unknown('_hdr26', 2),&lt;br /&gt;
	_cns.ULInt8('lobby_height'),&lt;br /&gt;
	_util.Unknown('_hdr29', 9),&lt;br /&gt;
	_cns.ULInt16('viewport_x'),&lt;br /&gt;
	_cns.ULInt16('viewport_y'),&lt;br /&gt;
	_util.Unknown('_hdr42', 14),&lt;br /&gt;
	_cns.ULInt8('named_people_count'),&lt;br /&gt;
&lt;br /&gt;
	_util.Unknown('_hdr57', 503),&lt;br /&gt;
	_cns.Anchor('hdr_end_'),&lt;br /&gt;
	_util.Assert(lambda ctx: ctx.hdr_end_ == ctx.hdr_start_ + 560),&lt;br /&gt;
)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#### Tenants&lt;br /&gt;
&lt;br /&gt;
Tenant_Type = _util.NumToSym(_cns.ULInt8('type'), {&lt;br /&gt;
	 0:'floor',&lt;br /&gt;
	 3:'hotel_single',&lt;br /&gt;
	 4:'hotel_double',&lt;br /&gt;
	 5:'hotal_suite',&lt;br /&gt;
	 6:'restaurant',&lt;br /&gt;
	 7:'office',&lt;br /&gt;
	 9:'condo',&lt;br /&gt;
	10:'shop',&lt;br /&gt;
	11:'parking_space',&lt;br /&gt;
	12:'fast_food',&lt;br /&gt;
	13:'medical',&lt;br /&gt;
	14:'security',&lt;br /&gt;
	15:'housekeeping',&lt;br /&gt;
	18:'movie_theater_floor2', 19:'movie_theater',&lt;br /&gt;
	20:'recycling_floor2', 21:'recycling',&lt;br /&gt;
	24:'lobby',&lt;br /&gt;
	29:'hall_floor2', 30:'hall',&lt;br /&gt;
	33:'metro',&lt;br /&gt;
	34:'movie_screen_floor2', 35:'movie_screen',&lt;br /&gt;
	36:'cathedral_floor5', 37:'cathedral_floor4',&lt;br /&gt;
		38:'cathedral_floor3', 39:'cathedral_floor2',&lt;br /&gt;
		40:'cathedral',&lt;br /&gt;
	44:'parking_ramp',&lt;br /&gt;
	45:'metro_tunnel',&lt;br /&gt;
	48:'burned',&lt;br /&gt;
})&lt;br /&gt;
&lt;br /&gt;
Tenant_Struct = _cns.Struct('tenant',&lt;br /&gt;
	# Horizontal positions are given with half-open ranges [left,right)&lt;br /&gt;
	# in units of 8 pixels.&lt;br /&gt;
	_cns.ULInt16('left_edge'),&lt;br /&gt;
	_cns.ULInt16('right_edge'),&lt;br /&gt;
	_cns.Rename('type', Tenant_Type),&lt;br /&gt;
	_cns.ULInt8('status'),&lt;br /&gt;
	_cns.ULInt8('pertype_idx'),&lt;br /&gt;
	_util.Unknown('_unk7', 1),&lt;br /&gt;
	_cns.ULInt32('people_offset'),&lt;br /&gt;
	_cns.ULInt8('id'),&lt;br /&gt;
	_util.Unknown('_unk13', 3),&lt;br /&gt;
	_cns.ULInt8('rent_class'),&lt;br /&gt;
	_util.Unknown('_unk17', 1),&lt;br /&gt;
)&lt;br /&gt;
assert(Tenant_Struct.sizeof() == 18)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#### Floors&lt;br /&gt;
&lt;br /&gt;
def _floor_below_grade(raw_floor):&lt;br /&gt;
	return raw_floor &amp;lt; 10&lt;br /&gt;
&lt;br /&gt;
def floor_id_from_raw(raw_floor):&lt;br /&gt;
	# Raw floor values {0..9} are basements: {-10..-1} or {B10..B1}.&lt;br /&gt;
	# Values {10..119} are floors {1..110}.&lt;br /&gt;
	if _floor_below_grade(raw_floor):&lt;br /&gt;
		return raw_floor-10&lt;br /&gt;
	else:&lt;br /&gt;
		return raw_floor-9&lt;br /&gt;
&lt;br /&gt;
def _floor_could_be_lobby(raw_floor):&lt;br /&gt;
	return floor_id_from_raw(raw_floor) in (1, 15, 30, 45, 60, 75, 90)&lt;br /&gt;
&lt;br /&gt;
Floor_Struct = _cns.Struct('floor',&lt;br /&gt;
	_cns.ULInt16('tenant_count'),&lt;br /&gt;
	_cns.ULInt16('left_edge'),&lt;br /&gt;
	_cns.ULInt16('right_edge'),&lt;br /&gt;
	_cns.Rename('tenants',&lt;br /&gt;
		_cns.Array(lambda ctx: ctx.tenant_count, Tenant_Struct)),&lt;br /&gt;
	_cns.Array(94, _cns.ULInt16('tenant_id_to_index')),&lt;br /&gt;
)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#### People&lt;br /&gt;
&lt;br /&gt;
Person_Struct = _cns.Struct('person',&lt;br /&gt;
	_cns.ULInt8('tenant_floor'),&lt;br /&gt;
	_cns.ULInt8('tenant_index'),&lt;br /&gt;
	_cns.ULInt16('number_in_tenant'),&lt;br /&gt;
	_cns.Rename('tenant_type', Tenant_Type),&lt;br /&gt;
	_cns.ULInt8('status'),&lt;br /&gt;
	_cns.SLInt8('current_floor'),&lt;br /&gt;
	_util.Unknown('_unk6', 5),&lt;br /&gt;
	_cns.ULInt16('stress'),&lt;br /&gt;
	_cns.ULInt16('eval'),&lt;br /&gt;
)&lt;br /&gt;
assert(Person_Struct.sizeof() == 16)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#### Retail&lt;br /&gt;
&lt;br /&gt;
Retail_Struct = _cns.Struct('retail',&lt;br /&gt;
	_cns.ULInt8('floor'),&lt;br /&gt;
	_util.Unknown('_unk1', 10),&lt;br /&gt;
	_cns.ULInt8('type'),&lt;br /&gt;
	_util.Unknown('_unk12', 6),&lt;br /&gt;
)&lt;br /&gt;
assert(Retail_Struct.sizeof() == 18)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#### Stairs&lt;br /&gt;
&lt;br /&gt;
Stairs_Type = _util.NumToSym(_cns.ULInt8('type'),&lt;br /&gt;
	{0:'escalator', 1:'standard'})&lt;br /&gt;
&lt;br /&gt;
Stairs_Struct = _cns.Struct('stairs',&lt;br /&gt;
	_util.Bool(_cns.ULInt8('present')),&lt;br /&gt;
	_cns.Rename('type', Stairs_Type),&lt;br /&gt;
	_cns.ULInt16('xpos'),&lt;br /&gt;
	_cns.ULInt8('bottom_floor'),&lt;br /&gt;
	_util.Unknown('_unk5', 5),&lt;br /&gt;
)&lt;br /&gt;
assert(Stairs_Struct.sizeof() == 10)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#### Elevators&lt;br /&gt;
&lt;br /&gt;
Elevator_Type = _util.NumToSym(_cns.ULInt8('type'),&lt;br /&gt;
		{0:'express', 1:'standard', 2:'service'})&lt;br /&gt;
&lt;br /&gt;
def _potential_floors_served(ctx):&lt;br /&gt;
	if ctx.type == 'express':&lt;br /&gt;
		count = 0&lt;br /&gt;
		for i in range(ctx.bottom_floor, ctx.top_floor + 1):&lt;br /&gt;
			if _floor_below_grade(i) or _floor_could_be_lobby(i):&lt;br /&gt;
				count += 1&lt;br /&gt;
	else:&lt;br /&gt;
		count = 1 + (ctx.top_floor - ctx.bottom_floor)&lt;br /&gt;
	return count&lt;br /&gt;
&lt;br /&gt;
Elevator_Struct = _cns.Struct('elevator',&lt;br /&gt;
	_cns.Anchor('start_'),&lt;br /&gt;
&lt;br /&gt;
	_util.Bool(_cns.ULInt8('present')),&lt;br /&gt;
	_cns.Rename('type', Elevator_Type),&lt;br /&gt;
&lt;br /&gt;
	# Capacity &amp;gt; 42 may crash SimTower.&lt;br /&gt;
	# 42 seems to work for non-express elevators.&lt;br /&gt;
	_cns.ULInt8('capacity'),&lt;br /&gt;
	_cns.ULInt8('car_count'),&lt;br /&gt;
&lt;br /&gt;
	# There are 4 &amp;quot;schedule&amp;quot; arrays of size 14: 7 weekday periods, followed&lt;br /&gt;
	# by 7 weekend periods.  The GUI shows 6 periods per day; the 7th is&lt;br /&gt;
	# not used.  The entire first array looks unused too.  The regex&lt;br /&gt;
	# '\x01{14}......\x05......\x05' can reliably find elevator data.&lt;br /&gt;
	_cns.Array(14, _cns.ULInt8('#unknown_sched')),&lt;br /&gt;
	_cns.If(lambda ctx: ctx.present,&lt;br /&gt;
		_util.Assert(lambda ctx: ctx['#unknown_sched'] == [1]*14)),&lt;br /&gt;
	_cns.Array(14, _cns.ULInt8('response_distances')),&lt;br /&gt;
	_cns.Array(14, _cns.ULInt8('express_modes')),&lt;br /&gt;
	_cns.Array(14, _cns.ULInt8('departure_delays')),&lt;br /&gt;
&lt;br /&gt;
	_util.Bool(_cns.ULInt8('shaft_visible')),&lt;br /&gt;
	_util.Unknown('_unk60', 1),&lt;br /&gt;
	_cns.ULInt16('left_edge'),&lt;br /&gt;
	_cns.ULInt8('top_floor'),&lt;br /&gt;
	_cns.ULInt8('bottom_floor'),&lt;br /&gt;
	_cns.Value('potential_floors_served_', _potential_floors_served),&lt;br /&gt;
&lt;br /&gt;
	# For each of 120 floors, value is 1 if served, otherwise 0.&lt;br /&gt;
	# Adding express elevator stops on improper floors (above ground and&lt;br /&gt;
	# not a multiple of 15) may crash SimTower, probably because there's&lt;br /&gt;
	# an array of size potential_floors_served.&lt;br /&gt;
	_cns.Array(120, _cns.ULInt8('floor_stops')),&lt;br /&gt;
&lt;br /&gt;
	# Resting floor for each car.&lt;br /&gt;
	_cns.Array(8, _cns.ULInt8('resting_floors')),&lt;br /&gt;
&lt;br /&gt;
	_cns.Anchor('fixed_end_'),&lt;br /&gt;
	_util.Assert(lambda ctx: ctx.fixed_end_ == ctx.start_ + 194),&lt;br /&gt;
&lt;br /&gt;
	_cns.If(lambda ctx: ctx.present, _util.AnonEmbed(&lt;br /&gt;
		_util.Unknown('_unk194', 3488),&lt;br /&gt;
&lt;br /&gt;
		# Information about people waiting for elevators&lt;br /&gt;
		# is likely to be in the following array.&lt;br /&gt;
		_cns.Array(lambda ctx: ctx.potential_floors_served_,&lt;br /&gt;
			_util.Unknown('_unk3682', 324)),&lt;br /&gt;
	)),&lt;br /&gt;
	_cns.Anchor('end_'),&lt;br /&gt;
)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#### Finances/population block&lt;br /&gt;
&lt;br /&gt;
Finances_Struct = _cns.Struct('finances',&lt;br /&gt;
	_cns.Array(10, _cns.ULInt32('tenant_populations')),&lt;br /&gt;
	_cns.ULInt32('tower_population'),&lt;br /&gt;
	_cns.Array(10, _cns.ULInt32('tenant_incomes')),&lt;br /&gt;
	_cns.ULInt32('tower_income'),&lt;br /&gt;
	_cns.Array(10, _cns.ULInt32('tenant_maintenance')),&lt;br /&gt;
	_cns.ULInt32('tower_maintenance'),&lt;br /&gt;
)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#### Overall file structure&lt;br /&gt;
&lt;br /&gt;
Tower_Struct = _cns.Struct('tower',&lt;br /&gt;
	_cns.Embedded(File_Header_Struct),&lt;br /&gt;
&lt;br /&gt;
	_cns.Rename('floors', _cns.Array(120, Floor_Struct)),&lt;br /&gt;
&lt;br /&gt;
	_cns.ULInt32('people_count'),&lt;br /&gt;
	_cns.Rename('people',&lt;br /&gt;
		_cns.Array(lambda ctx: ctx.people_count, Person_Struct)),&lt;br /&gt;
&lt;br /&gt;
	_cns.Rename('retail', _cns.Array(512, Retail_Struct)),&lt;br /&gt;
&lt;br /&gt;
	_cns.Anchor('elevators_start_'),&lt;br /&gt;
	_cns.Rename('elevators', _cns.Array(24, Elevator_Struct)),&lt;br /&gt;
	_cns.Anchor('elevators_end_'),&lt;br /&gt;
&lt;br /&gt;
	_util.Unknown('_unk_after_elev', 88),&lt;br /&gt;
	_cns.Anchor('finances_start_'),&lt;br /&gt;
	_cns.Embedded(Finances_Struct),&lt;br /&gt;
	_cns.Anchor('finances_end_'),&lt;br /&gt;
&lt;br /&gt;
	_util.Unknown('_unk_after_finpop', 1102),&lt;br /&gt;
	_cns.Anchor('stairs_start_'),&lt;br /&gt;
	_cns.Rename('stairs', _cns.Array(64, Stairs_Struct)),&lt;br /&gt;
	_cns.Anchor('stairs_end_'),&lt;br /&gt;
&lt;br /&gt;
	_util.Unknown('_unk_after_stairs', 17242),&lt;br /&gt;
	_cns.Rename('named_people',&lt;br /&gt;
		_cns.Array(lambda ctx: ctx.named_people_count,&lt;br /&gt;
			_util.ZStr(None, 16))),&lt;br /&gt;
&lt;br /&gt;
	_cns.Terminator  # must reach end of file&lt;br /&gt;
)&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== util.py ===&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;# To the extent possible under law, the author(s) have dedicated all copyright&lt;br /&gt;
# and related and neighboring rights to this software to the public domain&lt;br /&gt;
# worldwide. This software is distributed without any warranty.&lt;br /&gt;
#&lt;br /&gt;
# See &amp;lt;http://creativecommons.org/publicdomain/zero/1.0/&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
import construct as _cns&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#### Utility functions&lt;br /&gt;
&lt;br /&gt;
Unknown = _cns.Field&lt;br /&gt;
&lt;br /&gt;
class Assert(_cns.Construct):&lt;br /&gt;
	def __init__(self, fn):&lt;br /&gt;
		_cns.Construct.__init__(self, None)&lt;br /&gt;
		self.fn = fn&lt;br /&gt;
	def _sizeof(self, context): return 0&lt;br /&gt;
	def _assert(self, stream, context): assert self.fn(context)&lt;br /&gt;
	def _parse(self, stream, context): self._assert(stream, context)&lt;br /&gt;
	def _build(self, obj, stream, context): self._assert(stream, context)&lt;br /&gt;
&lt;br /&gt;
def AnonEmbed(*subcons):&lt;br /&gt;
	return _cns.Embedded(_cns.Struct(None, *subcons))&lt;br /&gt;
&lt;br /&gt;
def NumToSym(subcon, decoding):&lt;br /&gt;
	return _cns.MappingAdapter(subcon, decoding = decoding,&lt;br /&gt;
		encoding = dict((v,k) for (k,v) in decoding.items()),&lt;br /&gt;
		decdefault = _cns.Pass, encdefault = _cns.Pass)&lt;br /&gt;
&lt;br /&gt;
def Bool(subcon):&lt;br /&gt;
	return NumToSym(subcon, {0:False, 1:True})&lt;br /&gt;
&lt;br /&gt;
class _PaddedBytes(bytes):&lt;br /&gt;
	def __new__(cls, raw=b'', padding=None):&lt;br /&gt;
		b = super(_PaddedBytes, cls).__new__(cls, raw)&lt;br /&gt;
		b.padding = padding&lt;br /&gt;
		return b&lt;br /&gt;
&lt;br /&gt;
class _ZStrAdapter(_cns.StringAdapter):&lt;br /&gt;
	def __init__(self, subcon):&lt;br /&gt;
		_cns.StringAdapter.__init__(self, subcon)&lt;br /&gt;
	def _decode(self, obj, context):&lt;br /&gt;
		obj = _PaddedBytes(*obj.split(b'\0', 1))&lt;br /&gt;
		return _cns.StringAdapter._decode(self, obj, context)&lt;br /&gt;
	def _encode(self, obj, context):&lt;br /&gt;
		out = _cns.StringAdapter._encode(self, obj, context)&lt;br /&gt;
		out += b'\0'&lt;br /&gt;
		try:&lt;br /&gt;
			if obj.padding is not None:&lt;br /&gt;
				out += obj.padding&lt;br /&gt;
		except AttributeError:&lt;br /&gt;
			pass&lt;br /&gt;
&lt;br /&gt;
		pad = self._sizeof(context) - len(out)&lt;br /&gt;
		if pad &amp;lt; 0:&lt;br /&gt;
			raise ValueError(&amp;quot;string too long&amp;quot;)&lt;br /&gt;
		out += b'\0' * pad&lt;br /&gt;
&lt;br /&gt;
		return out&lt;br /&gt;
&lt;br /&gt;
def ZStr(name, length, encoding=None):&lt;br /&gt;
	fld = _cns.Field(name, length)&lt;br /&gt;
	return _ZStrAdapter(_cns.StringAdapter(fld, encoding=encoding))&lt;br /&gt;
&amp;lt;/nowiki&amp;gt;&lt;/div&gt;</summary>
		<author><name>Cypherpunks</name></author>	</entry>

	<entry>
		<id>http://fileformats.archiveteam.org/wiki/SimTower_saved_game</id>
		<title>SimTower saved game</title>
		<link rel="alternate" type="text/html" href="http://fileformats.archiveteam.org/wiki/SimTower_saved_game"/>
				<updated>2016-09-27T01:36:58Z</updated>
		
		<summary type="html">&lt;p&gt;Cypherpunks: /* Usage example */ add section to change elevator capacity&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{FormatInfo&lt;br /&gt;
|formattype=electronic&lt;br /&gt;
|subcat=Saved Games&lt;br /&gt;
|extensions={{ext|tdt}}&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
== Links ==&lt;br /&gt;
&lt;br /&gt;
* [https://raw.githubusercontent.com/fabianschuiki/OpenSkyscraper/90e6e92a2d46869a4052332e48633dd1545256e4/doc/simtower/TDT_format.txt Format description from the OpenSkyscraper project]&lt;br /&gt;
* [[Wikipedia:SimTower|Wikipedia article on SimTower]]&lt;br /&gt;
&lt;br /&gt;
== Code ==&lt;br /&gt;
&lt;br /&gt;
The following code can parse the format; and even for those who don't know Python it should mostly be understandable as a format description.&lt;br /&gt;
&lt;br /&gt;
Integers are named as &amp;lt;code&amp;gt;(sign)(endian)Int(bits)&amp;lt;/code&amp;gt;, like &amp;lt;code&amp;gt;ULInt32&amp;lt;/code&amp;gt;. TDT uses little-endian. Exact size and signedness wasn't verified for most fields.&lt;br /&gt;
&lt;br /&gt;
* This requires the Construct package for Python (tested with Construct 2.5.2 and Python 3.5.2).&lt;br /&gt;
* It's meant to handle binary-identical roundtripping even with bad values.&lt;br /&gt;
&lt;br /&gt;
=== Usage example ===&lt;br /&gt;
&lt;br /&gt;
If both files below are installed to the current directory, you can run the following at the command line to make all elevators carry 42 people:&amp;lt;br clear=&amp;quot;all&amp;quot;&amp;gt;&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;$ python3&lt;br /&gt;
&amp;gt;&amp;gt;&amp;gt; import tdt_cons&lt;br /&gt;
&amp;gt;&amp;gt;&amp;gt; f = open('SIMTOWER/TDT/TOWER.TDT','rb')&lt;br /&gt;
&amp;gt;&amp;gt;&amp;gt; tower = tdt_cons.Tower_Struct.parse_stream(f)&lt;br /&gt;
&amp;gt;&amp;gt;&amp;gt; for el in tower.elevators: el.capacity = 42&lt;br /&gt;
... &lt;br /&gt;
&amp;gt;&amp;gt;&amp;gt; f = open('SIMTOWER/TDT/TOWEROUT.TDT','wb')&lt;br /&gt;
&amp;gt;&amp;gt;&amp;gt; tdt_cons.Tower_Struct.build_stream(tower, f)&lt;br /&gt;
&amp;gt;&amp;gt;&amp;gt; &amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== tdt_cons.py ===&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;# To the extent possible under law, the author(s) have dedicated all copyright&lt;br /&gt;
# and related and neighboring rights to this software to the public domain&lt;br /&gt;
# worldwide. This software is distributed without any warranty.&lt;br /&gt;
#&lt;br /&gt;
# See &amp;lt;http://creativecommons.org/publicdomain/zero/1.0/&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
import construct as _cns&lt;br /&gt;
import util as _util&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#### File header&lt;br /&gt;
&lt;br /&gt;
File_Header_Struct = _cns.Struct('file_header',&lt;br /&gt;
	_cns.Anchor('hdr_start_'),  # to debug, change Anchor to Probe&lt;br /&gt;
&lt;br /&gt;
	# SimTower doesn't seem to care about the first byte, but the second&lt;br /&gt;
	# must be 0x24. Larger values produce a &amp;quot;wrong version&amp;quot; warning.&lt;br /&gt;
	_cns.Padding(1),&lt;br /&gt;
	_cns.Const(_cns.ULInt8('version'), 0x24),&lt;br /&gt;
&lt;br /&gt;
	_cns.ULInt8('stars'),          # 1-5 stars, or 6 for &amp;quot;tower&amp;quot;&lt;br /&gt;
	_util.Unknown('_hdr3', 1),&lt;br /&gt;
	_cns.ULInt32('cash_balance'),  # units of $100&lt;br /&gt;
	_cns.ULInt32('other_income'),&lt;br /&gt;
	_cns.ULInt32('construction_costs'),&lt;br /&gt;
	_cns.ULInt32('last_quarter_cash'),&lt;br /&gt;
	_cns.ULInt16('frame_time'),&lt;br /&gt;
	_cns.ULInt32('day'),&lt;br /&gt;
	_util.Unknown('_hdr26', 2),&lt;br /&gt;
	_cns.ULInt8('lobby_height'),&lt;br /&gt;
	_util.Unknown('_hdr29', 9),&lt;br /&gt;
	_cns.ULInt16('viewport_x'),&lt;br /&gt;
	_cns.ULInt16('viewport_y'),&lt;br /&gt;
	_util.Unknown('_hdr42', 14),&lt;br /&gt;
	_cns.ULInt8('named_people_count'),&lt;br /&gt;
&lt;br /&gt;
	_util.Unknown('_hdr57', 503),&lt;br /&gt;
	_cns.Anchor('hdr_end_'),&lt;br /&gt;
	_util.Assert(lambda ctx: ctx.hdr_end_ == ctx.hdr_start_ + 560),&lt;br /&gt;
)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#### Tenants&lt;br /&gt;
&lt;br /&gt;
Tenant_Type = _util.NumToSym(_cns.ULInt8('type'), {&lt;br /&gt;
	 0:'floor',&lt;br /&gt;
	 3:'hotel_single',&lt;br /&gt;
	 4:'hotel_double',&lt;br /&gt;
	 5:'hotal_suite',&lt;br /&gt;
	 6:'restaurant',&lt;br /&gt;
	 7:'office',&lt;br /&gt;
	 9:'condo',&lt;br /&gt;
	10:'shop',&lt;br /&gt;
	11:'parking_space',&lt;br /&gt;
	12:'fast_food',&lt;br /&gt;
	13:'medical',&lt;br /&gt;
	14:'security',&lt;br /&gt;
	15:'housekeeping',&lt;br /&gt;
	18:'movie_theater_floor2', 19:'movie_theater',&lt;br /&gt;
	20:'recycling_floor2', 21:'recycling',&lt;br /&gt;
	24:'lobby',&lt;br /&gt;
	29:'hall_floor2', 30:'hall',&lt;br /&gt;
	33:'metro',&lt;br /&gt;
	34:'movie_screen_floor2', 35:'movie_screen',&lt;br /&gt;
	36:'cathedral_floor5', 37:'cathedral_floor4',&lt;br /&gt;
		38:'cathedral_floor3', 39:'cathedral_floor2',&lt;br /&gt;
		40:'cathedral',&lt;br /&gt;
	44:'parking_ramp',&lt;br /&gt;
	45:'metro_tunnel',&lt;br /&gt;
	48:'burned',&lt;br /&gt;
})&lt;br /&gt;
&lt;br /&gt;
Tenant_Struct = _cns.Struct('tenant',&lt;br /&gt;
	# Horizontal positions are given with half-open ranges [left,right)&lt;br /&gt;
	# in units of 8 pixels.&lt;br /&gt;
	_cns.ULInt16('left_edge'),&lt;br /&gt;
	_cns.ULInt16('right_edge'),&lt;br /&gt;
	_cns.Rename('type', Tenant_Type),&lt;br /&gt;
	_cns.ULInt8('status'),&lt;br /&gt;
	_cns.ULInt8('pertype_idx'),&lt;br /&gt;
	_util.Unknown('_unk7', 1),&lt;br /&gt;
	_cns.ULInt32('people_offset'),&lt;br /&gt;
	_cns.ULInt8('id'),&lt;br /&gt;
	_util.Unknown('_unk13', 3),&lt;br /&gt;
	_cns.ULInt8('rent_class'),&lt;br /&gt;
	_util.Unknown('_unk17', 1),&lt;br /&gt;
)&lt;br /&gt;
assert(Tenant_Struct.sizeof() == 18)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#### Floors&lt;br /&gt;
&lt;br /&gt;
def _floor_below_grade(raw_floor):&lt;br /&gt;
	return raw_floor &amp;lt; 10&lt;br /&gt;
&lt;br /&gt;
def floor_id_from_raw(raw_floor):&lt;br /&gt;
	# Raw floor values {0..9} are basements: {-10..-1} or {B10..B1}.&lt;br /&gt;
	# Values {10..119} are floors {1..110}.&lt;br /&gt;
	if _floor_below_grade(raw_floor):&lt;br /&gt;
		return raw_floor-10&lt;br /&gt;
	else:&lt;br /&gt;
		return raw_floor-9&lt;br /&gt;
&lt;br /&gt;
def _floor_could_be_lobby(raw_floor):&lt;br /&gt;
	return floor_id_from_raw(raw_floor) in (1, 15, 30, 45, 60, 75, 90)&lt;br /&gt;
&lt;br /&gt;
Floor_Struct = _cns.Struct('floor',&lt;br /&gt;
	_cns.ULInt16('tenant_count'),&lt;br /&gt;
	_cns.ULInt16('left_edge'),&lt;br /&gt;
	_cns.ULInt16('right_edge'),&lt;br /&gt;
	_cns.Rename('tenants',&lt;br /&gt;
		_cns.Array(lambda ctx: ctx.tenant_count, Tenant_Struct)),&lt;br /&gt;
	_cns.Array(94, _cns.ULInt16('tenant_id_to_index')),&lt;br /&gt;
)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#### People&lt;br /&gt;
&lt;br /&gt;
Person_Struct = _cns.Struct('person',&lt;br /&gt;
	_cns.ULInt8('tenant_floor'),&lt;br /&gt;
	_cns.ULInt8('tenant_index'),&lt;br /&gt;
	_cns.ULInt16('number_in_tenant'),&lt;br /&gt;
	_cns.Rename('tenant_type', Tenant_Type),&lt;br /&gt;
	_cns.ULInt8('status'),&lt;br /&gt;
	_cns.SLInt8('current_floor'),&lt;br /&gt;
	_util.Unknown('_unk6', 5),&lt;br /&gt;
	_cns.ULInt16('stress'),&lt;br /&gt;
	_cns.ULInt16('eval'),&lt;br /&gt;
)&lt;br /&gt;
assert(Person_Struct.sizeof() == 16)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#### Retail&lt;br /&gt;
&lt;br /&gt;
Retail_Struct = _cns.Struct('retail',&lt;br /&gt;
	_cns.ULInt8('floor'),&lt;br /&gt;
	_util.Unknown('_unk1', 10),&lt;br /&gt;
	_cns.ULInt8('type'),&lt;br /&gt;
	_util.Unknown('_unk12', 6),&lt;br /&gt;
)&lt;br /&gt;
assert(Retail_Struct.sizeof() == 18)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#### Stairs&lt;br /&gt;
&lt;br /&gt;
Stairs_Type = _util.NumToSym(_cns.ULInt8('type'),&lt;br /&gt;
	{0:'escalator', 1:'standard'})&lt;br /&gt;
&lt;br /&gt;
Stairs_Struct = _cns.Struct('stairs',&lt;br /&gt;
	_util.Bool(_cns.ULInt8('present')),&lt;br /&gt;
	_cns.Rename('type', Stairs_Type),&lt;br /&gt;
	_cns.ULInt16('xpos'),&lt;br /&gt;
	_cns.ULInt8('bottom_floor'),&lt;br /&gt;
	_util.Unknown('_unk5', 5),&lt;br /&gt;
)&lt;br /&gt;
assert(Stairs_Struct.sizeof() == 10)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#### Elevators&lt;br /&gt;
&lt;br /&gt;
Elevator_Type = _util.NumToSym(_cns.ULInt8('type'),&lt;br /&gt;
		{0:'express', 1:'standard', 2:'service'})&lt;br /&gt;
&lt;br /&gt;
def _potential_floors_served(ctx):&lt;br /&gt;
	if ctx.type == 'express':&lt;br /&gt;
		count = 0&lt;br /&gt;
		for i in range(ctx.bottom_floor, ctx.top_floor + 1):&lt;br /&gt;
			if _floor_below_grade(i) or _floor_could_be_lobby(i):&lt;br /&gt;
				count += 1&lt;br /&gt;
	else:&lt;br /&gt;
		count = 1 + (ctx.top_floor - ctx.bottom_floor)&lt;br /&gt;
	return count&lt;br /&gt;
&lt;br /&gt;
Elevator_Struct = _cns.Struct('elevator',&lt;br /&gt;
	_cns.Anchor('start_'),&lt;br /&gt;
&lt;br /&gt;
	_util.Bool(_cns.ULInt8('present')),&lt;br /&gt;
	_cns.Rename('type', Elevator_Type),&lt;br /&gt;
&lt;br /&gt;
	# Capacity &amp;gt; 42 may crash SimTower.&lt;br /&gt;
	# 42 seems to work for non-express elevators.&lt;br /&gt;
	_cns.ULInt8('capacity'),&lt;br /&gt;
	_cns.ULInt8('car_count'),&lt;br /&gt;
&lt;br /&gt;
	# There are 4 &amp;quot;schedule&amp;quot; arrays of size 14: 7 weekday periods, followed&lt;br /&gt;
	# by 7 weekend periods.  The GUI shows 6 periods per day; the 7th is&lt;br /&gt;
	# not used.  The entire first array looks unused too.  The regex&lt;br /&gt;
	# '\x01{14}......\x05......\x05' can reliably find elevator data.&lt;br /&gt;
	_cns.Array(14, _cns.ULInt8('#unknown_sched')),&lt;br /&gt;
	_cns.If(lambda ctx: ctx.present,&lt;br /&gt;
		_util.Assert(lambda ctx: ctx['#unknown_sched'] == [1]*14)),&lt;br /&gt;
	_cns.Array(14, _cns.ULInt8('response_distances')),&lt;br /&gt;
	_cns.Array(14, _cns.ULInt8('express_modes')),&lt;br /&gt;
	_cns.Array(14, _cns.ULInt8('departure_delays')),&lt;br /&gt;
&lt;br /&gt;
	_util.Bool(_cns.ULInt8('shaft_visible')),&lt;br /&gt;
	_util.Unknown('_unk60', 1),&lt;br /&gt;
	_cns.ULInt16('left_edge'),&lt;br /&gt;
	_cns.ULInt8('top_floor'),&lt;br /&gt;
	_cns.ULInt8('bottom_floor'),&lt;br /&gt;
	_cns.Value('potential_floors_served_', _potential_floors_served),&lt;br /&gt;
&lt;br /&gt;
	# For each of 120 floors, value is 1 if served, otherwise 0.&lt;br /&gt;
	# Adding express elevator stops on improper floors (above ground and&lt;br /&gt;
	# not a multiple of 15) may crash SimTower, probably because there's&lt;br /&gt;
	# an array of size potential_floors_served.&lt;br /&gt;
	_cns.Array(120, _cns.ULInt8('floor_stops')),&lt;br /&gt;
&lt;br /&gt;
	# Resting floor for each car.&lt;br /&gt;
	_cns.Array(8, _cns.ULInt8('resting_floors')),&lt;br /&gt;
&lt;br /&gt;
	_cns.Anchor('fixed_end_'),&lt;br /&gt;
	_util.Assert(lambda ctx: ctx.fixed_end_ == ctx.start_ + 194),&lt;br /&gt;
&lt;br /&gt;
	_cns.If(lambda ctx: ctx.present, _util.AnonEmbed(&lt;br /&gt;
		_util.Unknown('_unk194', 3488),&lt;br /&gt;
&lt;br /&gt;
		# Information about people waiting for elevators&lt;br /&gt;
		# is likely to be in the following array.&lt;br /&gt;
		_cns.Array(lambda ctx: ctx.potential_floors_served_,&lt;br /&gt;
			_util.Unknown('_unk3682', 324)),&lt;br /&gt;
	)),&lt;br /&gt;
	_cns.Anchor('end_'),&lt;br /&gt;
)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#### Finances/population block&lt;br /&gt;
&lt;br /&gt;
Finances_Struct = _cns.Struct('finances',&lt;br /&gt;
	_cns.Array(10, _cns.ULInt32('tenant_populations')),&lt;br /&gt;
	_cns.ULInt32('tower_population'),&lt;br /&gt;
	_cns.Array(10, _cns.ULInt32('tenant_incomes')),&lt;br /&gt;
	_cns.ULInt32('tower_income'),&lt;br /&gt;
	_cns.Array(10, _cns.ULInt32('tenant_maintenance')),&lt;br /&gt;
	_cns.ULInt32('tower_maintenance'),&lt;br /&gt;
)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#### Overall file structure&lt;br /&gt;
&lt;br /&gt;
Tower_Struct = _cns.Struct('tower',&lt;br /&gt;
	_cns.Embedded(File_Header_Struct),&lt;br /&gt;
&lt;br /&gt;
	_cns.Rename('floors', _cns.Array(120, Floor_Struct)),&lt;br /&gt;
&lt;br /&gt;
	_cns.ULInt32('people_count'),&lt;br /&gt;
	_cns.Rename('people',&lt;br /&gt;
		_cns.Array(lambda ctx: ctx.people_count, Person_Struct)),&lt;br /&gt;
&lt;br /&gt;
	_cns.Rename('retail', _cns.Array(512, Retail_Struct)),&lt;br /&gt;
&lt;br /&gt;
	_cns.Anchor('elevators_start_'),&lt;br /&gt;
	_cns.Rename('elevators', _cns.Array(24, Elevator_Struct)),&lt;br /&gt;
	_cns.Anchor('elevators_end_'),&lt;br /&gt;
&lt;br /&gt;
	_util.Unknown('_unk_after_elev', 88),&lt;br /&gt;
	_cns.Anchor('finances_start_'),&lt;br /&gt;
	_cns.Embedded(Finances_Struct),&lt;br /&gt;
	_cns.Anchor('finances_end_'),&lt;br /&gt;
&lt;br /&gt;
	_util.Unknown('_unk_after_finpop', 1102),&lt;br /&gt;
	_cns.Anchor('stairs_start_'),&lt;br /&gt;
	_cns.Rename('stairs', _cns.Array(64, Stairs_Struct)),&lt;br /&gt;
	_cns.Anchor('stairs_end_'),&lt;br /&gt;
&lt;br /&gt;
	_util.Unknown('_unk_after_stairs', 17242),&lt;br /&gt;
	_cns.Rename('named_people',&lt;br /&gt;
		_cns.Array(lambda ctx: ctx.named_people_count,&lt;br /&gt;
			_util.ZStr(None, 16))),&lt;br /&gt;
&lt;br /&gt;
	_cns.Terminator  # must reach end of file&lt;br /&gt;
)&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== util.py ===&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;# To the extent possible under law, the author(s) have dedicated all copyright&lt;br /&gt;
# and related and neighboring rights to this software to the public domain&lt;br /&gt;
# worldwide. This software is distributed without any warranty.&lt;br /&gt;
#&lt;br /&gt;
# See &amp;lt;http://creativecommons.org/publicdomain/zero/1.0/&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
import construct as _cns&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#### Utility functions&lt;br /&gt;
&lt;br /&gt;
Unknown = _cns.Field&lt;br /&gt;
&lt;br /&gt;
class Assert(_cns.Construct):&lt;br /&gt;
	def __init__(self, fn):&lt;br /&gt;
		_cns.Construct.__init__(self, None)&lt;br /&gt;
		self.fn = fn&lt;br /&gt;
	def _sizeof(self, context): return 0&lt;br /&gt;
	def _assert(self, stream, context): assert self.fn(context)&lt;br /&gt;
	def _parse(self, stream, context): self._assert(stream, context)&lt;br /&gt;
	def _build(self, obj, stream, context): self._assert(stream, context)&lt;br /&gt;
&lt;br /&gt;
def AnonEmbed(*subcons):&lt;br /&gt;
	return _cns.Embedded(_cns.Struct(None, *subcons))&lt;br /&gt;
&lt;br /&gt;
def NumToSym(subcon, decoding):&lt;br /&gt;
	return _cns.MappingAdapter(subcon, decoding = decoding,&lt;br /&gt;
		encoding = dict((v,k) for (k,v) in decoding.items()),&lt;br /&gt;
		decdefault = _cns.Pass, encdefault = _cns.Pass)&lt;br /&gt;
&lt;br /&gt;
def Bool(subcon):&lt;br /&gt;
	return NumToSym(subcon, {0:False, 1:True})&lt;br /&gt;
&lt;br /&gt;
class _PaddedBytes(bytes):&lt;br /&gt;
	def __new__(cls, raw=b'', padding=None):&lt;br /&gt;
		b = super(_PaddedBytes, cls).__new__(cls, raw)&lt;br /&gt;
		b.padding = padding&lt;br /&gt;
		return b&lt;br /&gt;
&lt;br /&gt;
class _ZStrAdapter(_cns.StringAdapter):&lt;br /&gt;
	def __init__(self, subcon):&lt;br /&gt;
		_cns.StringAdapter.__init__(self, subcon)&lt;br /&gt;
	def _decode(self, obj, context):&lt;br /&gt;
		obj = _PaddedBytes(*obj.split(b'\0', 1))&lt;br /&gt;
		return _cns.StringAdapter._decode(self, obj, context)&lt;br /&gt;
	def _encode(self, obj, context):&lt;br /&gt;
		out = _cns.StringAdapter._encode(self, obj, context)&lt;br /&gt;
		out += b'\0'&lt;br /&gt;
		try:&lt;br /&gt;
			if obj.padding is not None:&lt;br /&gt;
				out += obj.padding&lt;br /&gt;
		except AttributeError:&lt;br /&gt;
			pass&lt;br /&gt;
&lt;br /&gt;
		pad = self._sizeof(context) - len(out)&lt;br /&gt;
		if pad &amp;lt; 0:&lt;br /&gt;
			raise ValueError(&amp;quot;string too long&amp;quot;)&lt;br /&gt;
		out += b'\0' * pad&lt;br /&gt;
&lt;br /&gt;
		return out&lt;br /&gt;
&lt;br /&gt;
def ZStr(name, length, encoding=None):&lt;br /&gt;
	fld = _cns.Field(name, length)&lt;br /&gt;
	return _ZStrAdapter(_cns.StringAdapter(fld, encoding=encoding))&lt;br /&gt;
&amp;lt;/nowiki&amp;gt;&lt;/div&gt;</summary>
		<author><name>Cypherpunks</name></author>	</entry>

	<entry>
		<id>http://fileformats.archiveteam.org/wiki/SimTower_saved_game</id>
		<title>SimTower saved game</title>
		<link rel="alternate" type="text/html" href="http://fileformats.archiveteam.org/wiki/SimTower_saved_game"/>
				<updated>2016-09-27T01:23:24Z</updated>
		
		<summary type="html">&lt;p&gt;Cypherpunks: add notes&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{FormatInfo&lt;br /&gt;
|formattype=electronic&lt;br /&gt;
|subcat=Saved Games&lt;br /&gt;
|extensions={{ext|tdt}}&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
== Links ==&lt;br /&gt;
&lt;br /&gt;
* [https://raw.githubusercontent.com/fabianschuiki/OpenSkyscraper/90e6e92a2d46869a4052332e48633dd1545256e4/doc/simtower/TDT_format.txt Format description from the OpenSkyscraper project]&lt;br /&gt;
* [[Wikipedia:SimTower|Wikipedia article on SimTower]]&lt;br /&gt;
&lt;br /&gt;
== Code ==&lt;br /&gt;
&lt;br /&gt;
The following code can parse the format; and even for those who don't know Python it should mostly be understandable as a format description.&lt;br /&gt;
&lt;br /&gt;
Integers are named as &amp;lt;code&amp;gt;(sign)(endian)Int(bits)&amp;lt;/code&amp;gt;, like ULInt32. TDT uses little-endian. Exact size and signedness wasn't verified for most fields.&lt;br /&gt;
&lt;br /&gt;
* This requires the Construct package for Python (tested with Construct 2.5.2 and Python 3.5.2).&lt;br /&gt;
* It's meant to handle binary-identical roundtripping even with bad values.&lt;br /&gt;
&amp;lt;br clear=&amp;quot;all&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== tdt_cons.py ===&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;# To the extent possible under law, the author(s) have dedicated all copyright&lt;br /&gt;
# and related and neighboring rights to this software to the public domain&lt;br /&gt;
# worldwide. This software is distributed without any warranty.&lt;br /&gt;
#&lt;br /&gt;
# See &amp;lt;http://creativecommons.org/publicdomain/zero/1.0/&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
import construct as _cns&lt;br /&gt;
import util as _util&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#### File header&lt;br /&gt;
&lt;br /&gt;
File_Header_Struct = _cns.Struct('file_header',&lt;br /&gt;
	_cns.Anchor('hdr_start_'),  # to debug, change Anchor to Probe&lt;br /&gt;
&lt;br /&gt;
	# SimTower doesn't seem to care about the first byte, but the second&lt;br /&gt;
	# must be 0x24. Larger values produce a &amp;quot;wrong version&amp;quot; warning.&lt;br /&gt;
	_cns.Padding(1),&lt;br /&gt;
	_cns.Const(_cns.ULInt8('version'), 0x24),&lt;br /&gt;
&lt;br /&gt;
	_cns.ULInt8('stars'),          # 1-5 stars, or 6 for &amp;quot;tower&amp;quot;&lt;br /&gt;
	_util.Unknown('_hdr3', 1),&lt;br /&gt;
	_cns.ULInt32('cash_balance'),  # units of $100&lt;br /&gt;
	_cns.ULInt32('other_income'),&lt;br /&gt;
	_cns.ULInt32('construction_costs'),&lt;br /&gt;
	_cns.ULInt32('last_quarter_cash'),&lt;br /&gt;
	_cns.ULInt16('frame_time'),&lt;br /&gt;
	_cns.ULInt32('day'),&lt;br /&gt;
	_util.Unknown('_hdr26', 2),&lt;br /&gt;
	_cns.ULInt8('lobby_height'),&lt;br /&gt;
	_util.Unknown('_hdr29', 9),&lt;br /&gt;
	_cns.ULInt16('viewport_x'),&lt;br /&gt;
	_cns.ULInt16('viewport_y'),&lt;br /&gt;
	_util.Unknown('_hdr42', 14),&lt;br /&gt;
	_cns.ULInt8('named_people_count'),&lt;br /&gt;
&lt;br /&gt;
	_util.Unknown('_hdr57', 503),&lt;br /&gt;
	_cns.Anchor('hdr_end_'),&lt;br /&gt;
	_util.Assert(lambda ctx: ctx.hdr_end_ == ctx.hdr_start_ + 560),&lt;br /&gt;
)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#### Tenants&lt;br /&gt;
&lt;br /&gt;
Tenant_Type = _util.NumToSym(_cns.ULInt8('type'), {&lt;br /&gt;
	 0:'floor',&lt;br /&gt;
	 3:'hotel_single',&lt;br /&gt;
	 4:'hotel_double',&lt;br /&gt;
	 5:'hotal_suite',&lt;br /&gt;
	 6:'restaurant',&lt;br /&gt;
	 7:'office',&lt;br /&gt;
	 9:'condo',&lt;br /&gt;
	10:'shop',&lt;br /&gt;
	11:'parking_space',&lt;br /&gt;
	12:'fast_food',&lt;br /&gt;
	13:'medical',&lt;br /&gt;
	14:'security',&lt;br /&gt;
	15:'housekeeping',&lt;br /&gt;
	18:'movie_theater_floor2', 19:'movie_theater',&lt;br /&gt;
	20:'recycling_floor2', 21:'recycling',&lt;br /&gt;
	24:'lobby',&lt;br /&gt;
	29:'hall_floor2', 30:'hall',&lt;br /&gt;
	33:'metro',&lt;br /&gt;
	34:'movie_screen_floor2', 35:'movie_screen',&lt;br /&gt;
	36:'cathedral_floor5', 37:'cathedral_floor4',&lt;br /&gt;
		38:'cathedral_floor3', 39:'cathedral_floor2',&lt;br /&gt;
		40:'cathedral',&lt;br /&gt;
	44:'parking_ramp',&lt;br /&gt;
	45:'metro_tunnel',&lt;br /&gt;
	48:'burned',&lt;br /&gt;
})&lt;br /&gt;
&lt;br /&gt;
Tenant_Struct = _cns.Struct('tenant',&lt;br /&gt;
	# Horizontal positions are given with half-open ranges [left,right)&lt;br /&gt;
	# in units of 8 pixels.&lt;br /&gt;
	_cns.ULInt16('left_edge'),&lt;br /&gt;
	_cns.ULInt16('right_edge'),&lt;br /&gt;
	_cns.Rename('type', Tenant_Type),&lt;br /&gt;
	_cns.ULInt8('status'),&lt;br /&gt;
	_cns.ULInt8('pertype_idx'),&lt;br /&gt;
	_util.Unknown('_unk7', 1),&lt;br /&gt;
	_cns.ULInt32('people_offset'),&lt;br /&gt;
	_cns.ULInt8('id'),&lt;br /&gt;
	_util.Unknown('_unk13', 3),&lt;br /&gt;
	_cns.ULInt8('rent_class'),&lt;br /&gt;
	_util.Unknown('_unk17', 1),&lt;br /&gt;
)&lt;br /&gt;
assert(Tenant_Struct.sizeof() == 18)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#### Floors&lt;br /&gt;
&lt;br /&gt;
def _floor_below_grade(raw_floor):&lt;br /&gt;
	return raw_floor &amp;lt; 10&lt;br /&gt;
&lt;br /&gt;
def floor_id_from_raw(raw_floor):&lt;br /&gt;
	# Raw floor values {0..9} are basements: {-10..-1} or {B10..B1}.&lt;br /&gt;
	# Values {10..119} are floors {1..110}.&lt;br /&gt;
	if _floor_below_grade(raw_floor):&lt;br /&gt;
		return raw_floor-10&lt;br /&gt;
	else:&lt;br /&gt;
		return raw_floor-9&lt;br /&gt;
&lt;br /&gt;
def _floor_could_be_lobby(raw_floor):&lt;br /&gt;
	return floor_id_from_raw(raw_floor) in (1, 15, 30, 45, 60, 75, 90)&lt;br /&gt;
&lt;br /&gt;
Floor_Struct = _cns.Struct('floor',&lt;br /&gt;
	_cns.ULInt16('tenant_count'),&lt;br /&gt;
	_cns.ULInt16('left_edge'),&lt;br /&gt;
	_cns.ULInt16('right_edge'),&lt;br /&gt;
	_cns.Rename('tenants',&lt;br /&gt;
		_cns.Array(lambda ctx: ctx.tenant_count, Tenant_Struct)),&lt;br /&gt;
	_cns.Array(94, _cns.ULInt16('tenant_id_to_index')),&lt;br /&gt;
)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#### People&lt;br /&gt;
&lt;br /&gt;
Person_Struct = _cns.Struct('person',&lt;br /&gt;
	_cns.ULInt8('tenant_floor'),&lt;br /&gt;
	_cns.ULInt8('tenant_index'),&lt;br /&gt;
	_cns.ULInt16('number_in_tenant'),&lt;br /&gt;
	_cns.Rename('tenant_type', Tenant_Type),&lt;br /&gt;
	_cns.ULInt8('status'),&lt;br /&gt;
	_cns.SLInt8('current_floor'),&lt;br /&gt;
	_util.Unknown('_unk6', 5),&lt;br /&gt;
	_cns.ULInt16('stress'),&lt;br /&gt;
	_cns.ULInt16('eval'),&lt;br /&gt;
)&lt;br /&gt;
assert(Person_Struct.sizeof() == 16)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#### Retail&lt;br /&gt;
&lt;br /&gt;
Retail_Struct = _cns.Struct('retail',&lt;br /&gt;
	_cns.ULInt8('floor'),&lt;br /&gt;
	_util.Unknown('_unk1', 10),&lt;br /&gt;
	_cns.ULInt8('type'),&lt;br /&gt;
	_util.Unknown('_unk12', 6),&lt;br /&gt;
)&lt;br /&gt;
assert(Retail_Struct.sizeof() == 18)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#### Stairs&lt;br /&gt;
&lt;br /&gt;
Stairs_Type = _util.NumToSym(_cns.ULInt8('type'),&lt;br /&gt;
	{0:'escalator', 1:'standard'})&lt;br /&gt;
&lt;br /&gt;
Stairs_Struct = _cns.Struct('stairs',&lt;br /&gt;
	_util.Bool(_cns.ULInt8('present')),&lt;br /&gt;
	_cns.Rename('type', Stairs_Type),&lt;br /&gt;
	_cns.ULInt16('xpos'),&lt;br /&gt;
	_cns.ULInt8('bottom_floor'),&lt;br /&gt;
	_util.Unknown('_unk5', 5),&lt;br /&gt;
)&lt;br /&gt;
assert(Stairs_Struct.sizeof() == 10)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#### Elevators&lt;br /&gt;
&lt;br /&gt;
Elevator_Type = _util.NumToSym(_cns.ULInt8('type'),&lt;br /&gt;
		{0:'express', 1:'standard', 2:'service'})&lt;br /&gt;
&lt;br /&gt;
def _potential_floors_served(ctx):&lt;br /&gt;
	if ctx.type == 'express':&lt;br /&gt;
		count = 0&lt;br /&gt;
		for i in range(ctx.bottom_floor, ctx.top_floor + 1):&lt;br /&gt;
			if _floor_below_grade(i) or _floor_could_be_lobby(i):&lt;br /&gt;
				count += 1&lt;br /&gt;
	else:&lt;br /&gt;
		count = 1 + (ctx.top_floor - ctx.bottom_floor)&lt;br /&gt;
	return count&lt;br /&gt;
&lt;br /&gt;
Elevator_Struct = _cns.Struct('elevator',&lt;br /&gt;
	_cns.Anchor('start_'),&lt;br /&gt;
&lt;br /&gt;
	_util.Bool(_cns.ULInt8('present')),&lt;br /&gt;
	_cns.Rename('type', Elevator_Type),&lt;br /&gt;
&lt;br /&gt;
	# Capacity &amp;gt; 42 may crash SimTower.&lt;br /&gt;
	# 42 seems to work for non-express elevators.&lt;br /&gt;
	_cns.ULInt8('capacity'),&lt;br /&gt;
	_cns.ULInt8('car_count'),&lt;br /&gt;
&lt;br /&gt;
	# There are 4 &amp;quot;schedule&amp;quot; arrays of size 14: 7 weekday periods, followed&lt;br /&gt;
	# by 7 weekend periods.  The GUI shows 6 periods per day; the 7th is&lt;br /&gt;
	# not used.  The entire first array looks unused too.  The regex&lt;br /&gt;
	# '\x01{14}......\x05......\x05' can reliably find elevator data.&lt;br /&gt;
	_cns.Array(14, _cns.ULInt8('#unknown_sched')),&lt;br /&gt;
	_cns.If(lambda ctx: ctx.present,&lt;br /&gt;
		_util.Assert(lambda ctx: ctx['#unknown_sched'] == [1]*14)),&lt;br /&gt;
	_cns.Array(14, _cns.ULInt8('response_distances')),&lt;br /&gt;
	_cns.Array(14, _cns.ULInt8('express_modes')),&lt;br /&gt;
	_cns.Array(14, _cns.ULInt8('departure_delays')),&lt;br /&gt;
&lt;br /&gt;
	_util.Bool(_cns.ULInt8('shaft_visible')),&lt;br /&gt;
	_util.Unknown('_unk60', 1),&lt;br /&gt;
	_cns.ULInt16('left_edge'),&lt;br /&gt;
	_cns.ULInt8('top_floor'),&lt;br /&gt;
	_cns.ULInt8('bottom_floor'),&lt;br /&gt;
	_cns.Value('potential_floors_served_', _potential_floors_served),&lt;br /&gt;
&lt;br /&gt;
	# For each of 120 floors, value is 1 if served, otherwise 0.&lt;br /&gt;
	# Adding express elevator stops on improper floors (above ground and&lt;br /&gt;
	# not a multiple of 15) may crash SimTower, probably because there's&lt;br /&gt;
	# an array of size potential_floors_served.&lt;br /&gt;
	_cns.Array(120, _cns.ULInt8('floor_stops')),&lt;br /&gt;
&lt;br /&gt;
	# Resting floor for each car.&lt;br /&gt;
	_cns.Array(8, _cns.ULInt8('resting_floors')),&lt;br /&gt;
&lt;br /&gt;
	_cns.Anchor('fixed_end_'),&lt;br /&gt;
	_util.Assert(lambda ctx: ctx.fixed_end_ == ctx.start_ + 194),&lt;br /&gt;
&lt;br /&gt;
	_cns.If(lambda ctx: ctx.present, _util.AnonEmbed(&lt;br /&gt;
		_util.Unknown('_unk194', 3488),&lt;br /&gt;
&lt;br /&gt;
		# Information about people waiting for elevators&lt;br /&gt;
		# is likely to be in the following array.&lt;br /&gt;
		_cns.Array(lambda ctx: ctx.potential_floors_served_,&lt;br /&gt;
			_util.Unknown('_unk3682', 324)),&lt;br /&gt;
	)),&lt;br /&gt;
	_cns.Anchor('end_'),&lt;br /&gt;
)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#### Finances/population block&lt;br /&gt;
&lt;br /&gt;
Finances_Struct = _cns.Struct('finances',&lt;br /&gt;
	_cns.Array(10, _cns.ULInt32('tenant_populations')),&lt;br /&gt;
	_cns.ULInt32('tower_population'),&lt;br /&gt;
	_cns.Array(10, _cns.ULInt32('tenant_incomes')),&lt;br /&gt;
	_cns.ULInt32('tower_income'),&lt;br /&gt;
	_cns.Array(10, _cns.ULInt32('tenant_maintenance')),&lt;br /&gt;
	_cns.ULInt32('tower_maintenance'),&lt;br /&gt;
)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#### Overall file structure&lt;br /&gt;
&lt;br /&gt;
Tower_Struct = _cns.Struct('tower',&lt;br /&gt;
	_cns.Embedded(File_Header_Struct),&lt;br /&gt;
&lt;br /&gt;
	_cns.Rename('floors', _cns.Array(120, Floor_Struct)),&lt;br /&gt;
&lt;br /&gt;
	_cns.ULInt32('people_count'),&lt;br /&gt;
	_cns.Rename('people',&lt;br /&gt;
		_cns.Array(lambda ctx: ctx.people_count, Person_Struct)),&lt;br /&gt;
&lt;br /&gt;
	_cns.Rename('retail', _cns.Array(512, Retail_Struct)),&lt;br /&gt;
&lt;br /&gt;
	_cns.Anchor('elevators_start_'),&lt;br /&gt;
	_cns.Rename('elevators', _cns.Array(24, Elevator_Struct)),&lt;br /&gt;
	_cns.Anchor('elevators_end_'),&lt;br /&gt;
&lt;br /&gt;
	_util.Unknown('_unk_after_elev', 88),&lt;br /&gt;
	_cns.Anchor('finances_start_'),&lt;br /&gt;
	_cns.Embedded(Finances_Struct),&lt;br /&gt;
	_cns.Anchor('finances_end_'),&lt;br /&gt;
&lt;br /&gt;
	_util.Unknown('_unk_after_finpop', 1102),&lt;br /&gt;
	_cns.Anchor('stairs_start_'),&lt;br /&gt;
	_cns.Rename('stairs', _cns.Array(64, Stairs_Struct)),&lt;br /&gt;
	_cns.Anchor('stairs_end_'),&lt;br /&gt;
&lt;br /&gt;
	_util.Unknown('_unk_after_stairs', 17242),&lt;br /&gt;
	_cns.Rename('named_people',&lt;br /&gt;
		_cns.Array(lambda ctx: ctx.named_people_count,&lt;br /&gt;
			_util.ZStr(None, 16))),&lt;br /&gt;
&lt;br /&gt;
	_cns.Terminator  # must reach end of file&lt;br /&gt;
)&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== util.py ===&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;# To the extent possible under law, the author(s) have dedicated all copyright&lt;br /&gt;
# and related and neighboring rights to this software to the public domain&lt;br /&gt;
# worldwide. This software is distributed without any warranty.&lt;br /&gt;
#&lt;br /&gt;
# See &amp;lt;http://creativecommons.org/publicdomain/zero/1.0/&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
import construct as _cns&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#### Utility functions&lt;br /&gt;
&lt;br /&gt;
Unknown = _cns.Field&lt;br /&gt;
&lt;br /&gt;
class Assert(_cns.Construct):&lt;br /&gt;
	def __init__(self, fn):&lt;br /&gt;
		_cns.Construct.__init__(self, None)&lt;br /&gt;
		self.fn = fn&lt;br /&gt;
	def _sizeof(self, context): return 0&lt;br /&gt;
	def _assert(self, stream, context): assert self.fn(context)&lt;br /&gt;
	def _parse(self, stream, context): self._assert(stream, context)&lt;br /&gt;
	def _build(self, obj, stream, context): self._assert(stream, context)&lt;br /&gt;
&lt;br /&gt;
def AnonEmbed(*subcons):&lt;br /&gt;
	return _cns.Embedded(_cns.Struct(None, *subcons))&lt;br /&gt;
&lt;br /&gt;
def NumToSym(subcon, decoding):&lt;br /&gt;
	return _cns.MappingAdapter(subcon, decoding = decoding,&lt;br /&gt;
		encoding = dict((v,k) for (k,v) in decoding.items()),&lt;br /&gt;
		decdefault = _cns.Pass, encdefault = _cns.Pass)&lt;br /&gt;
&lt;br /&gt;
def Bool(subcon):&lt;br /&gt;
	return NumToSym(subcon, {0:False, 1:True})&lt;br /&gt;
&lt;br /&gt;
class _PaddedBytes(bytes):&lt;br /&gt;
	def __new__(cls, raw=b'', padding=None):&lt;br /&gt;
		b = super(_PaddedBytes, cls).__new__(cls, raw)&lt;br /&gt;
		b.padding = padding&lt;br /&gt;
		return b&lt;br /&gt;
&lt;br /&gt;
class _ZStrAdapter(_cns.StringAdapter):&lt;br /&gt;
	def __init__(self, subcon):&lt;br /&gt;
		_cns.StringAdapter.__init__(self, subcon)&lt;br /&gt;
	def _decode(self, obj, context):&lt;br /&gt;
		obj = _PaddedBytes(*obj.split(b'\0', 1))&lt;br /&gt;
		return _cns.StringAdapter._decode(self, obj, context)&lt;br /&gt;
	def _encode(self, obj, context):&lt;br /&gt;
		out = _cns.StringAdapter._encode(self, obj, context)&lt;br /&gt;
		out += b'\0'&lt;br /&gt;
		try:&lt;br /&gt;
			if obj.padding is not None:&lt;br /&gt;
				out += obj.padding&lt;br /&gt;
		except AttributeError:&lt;br /&gt;
			pass&lt;br /&gt;
&lt;br /&gt;
		pad = self._sizeof(context) - len(out)&lt;br /&gt;
		if pad &amp;lt; 0:&lt;br /&gt;
			raise ValueError(&amp;quot;string too long&amp;quot;)&lt;br /&gt;
		out += b'\0' * pad&lt;br /&gt;
&lt;br /&gt;
		return out&lt;br /&gt;
&lt;br /&gt;
def ZStr(name, length, encoding=None):&lt;br /&gt;
	fld = _cns.Field(name, length)&lt;br /&gt;
	return _ZStrAdapter(_cns.StringAdapter(fld, encoding=encoding))&lt;br /&gt;
&amp;lt;/nowiki&amp;gt;&lt;/div&gt;</summary>
		<author><name>Cypherpunks</name></author>	</entry>

	<entry>
		<id>http://fileformats.archiveteam.org/wiki/SimTower_saved_game</id>
		<title>SimTower saved game</title>
		<link rel="alternate" type="text/html" href="http://fileformats.archiveteam.org/wiki/SimTower_saved_game"/>
				<updated>2016-09-27T01:14:12Z</updated>
		
		<summary type="html">&lt;p&gt;Cypherpunks: add some code to parse the format (TODO: add usage notes)&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{FormatInfo&lt;br /&gt;
|formattype=electronic&lt;br /&gt;
|subcat=Saved Games&lt;br /&gt;
|extensions={{ext|tdt}}&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
== Links ==&lt;br /&gt;
&lt;br /&gt;
* [https://raw.githubusercontent.com/fabianschuiki/OpenSkyscraper/90e6e92a2d46869a4052332e48633dd1545256e4/doc/simtower/TDT_format.txt Format description from the OpenSkyscraper project]&lt;br /&gt;
* [[Wikipedia:SimTower|Wikipedia article on SimTower]]&lt;br /&gt;
&lt;br /&gt;
== Code ==&lt;br /&gt;
&amp;lt;br clear=&amp;quot;all&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== tdt_cons.py ===&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;# To the extent possible under law, the author(s) have dedicated all copyright&lt;br /&gt;
# and related and neighboring rights to this software to the public domain&lt;br /&gt;
# worldwide. This software is distributed without any warranty.&lt;br /&gt;
#&lt;br /&gt;
# See &amp;lt;http://creativecommons.org/publicdomain/zero/1.0/&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
import construct as _cns&lt;br /&gt;
import util as _util&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#### File header&lt;br /&gt;
&lt;br /&gt;
File_Header_Struct = _cns.Struct('file_header',&lt;br /&gt;
	_cns.Anchor('hdr_start_'),  # to debug, change Anchor to Probe&lt;br /&gt;
&lt;br /&gt;
	# SimTower doesn't seem to care about the first byte, but the second&lt;br /&gt;
	# must be 0x24. Larger values produce a &amp;quot;wrong version&amp;quot; warning.&lt;br /&gt;
	_cns.Padding(1),&lt;br /&gt;
	_cns.Const(_cns.ULInt8('version'), 0x24),&lt;br /&gt;
&lt;br /&gt;
	_cns.ULInt8('stars'),          # 1-5 stars, or 6 for &amp;quot;tower&amp;quot;&lt;br /&gt;
	_util.Unknown('_hdr3', 1),&lt;br /&gt;
	_cns.ULInt32('cash_balance'),  # units of $100&lt;br /&gt;
	_cns.ULInt32('other_income'),&lt;br /&gt;
	_cns.ULInt32('construction_costs'),&lt;br /&gt;
	_cns.ULInt32('last_quarter_cash'),&lt;br /&gt;
	_cns.ULInt16('frame_time'),&lt;br /&gt;
	_cns.ULInt32('day'),&lt;br /&gt;
	_util.Unknown('_hdr26', 2),&lt;br /&gt;
	_cns.ULInt8('lobby_height'),&lt;br /&gt;
	_util.Unknown('_hdr29', 9),&lt;br /&gt;
	_cns.ULInt16('viewport_x'),&lt;br /&gt;
	_cns.ULInt16('viewport_y'),&lt;br /&gt;
	_util.Unknown('_hdr42', 14),&lt;br /&gt;
	_cns.ULInt8('named_people_count'),&lt;br /&gt;
&lt;br /&gt;
	_util.Unknown('_hdr57', 503),&lt;br /&gt;
	_cns.Anchor('hdr_end_'),&lt;br /&gt;
	_util.Assert(lambda ctx: ctx.hdr_end_ == ctx.hdr_start_ + 560),&lt;br /&gt;
)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#### Tenants&lt;br /&gt;
&lt;br /&gt;
Tenant_Type = _util.NumToSym(_cns.ULInt8('type'), {&lt;br /&gt;
	 0:'floor',&lt;br /&gt;
	 3:'hotel_single',&lt;br /&gt;
	 4:'hotel_double',&lt;br /&gt;
	 5:'hotal_suite',&lt;br /&gt;
	 6:'restaurant',&lt;br /&gt;
	 7:'office',&lt;br /&gt;
	 9:'condo',&lt;br /&gt;
	10:'shop',&lt;br /&gt;
	11:'parking_space',&lt;br /&gt;
	12:'fast_food',&lt;br /&gt;
	13:'medical',&lt;br /&gt;
	14:'security',&lt;br /&gt;
	15:'housekeeping',&lt;br /&gt;
	18:'movie_theater_floor2', 19:'movie_theater',&lt;br /&gt;
	20:'recycling_floor2', 21:'recycling',&lt;br /&gt;
	24:'lobby',&lt;br /&gt;
	29:'hall_floor2', 30:'hall',&lt;br /&gt;
	33:'metro',&lt;br /&gt;
	34:'movie_screen_floor2', 35:'movie_screen',&lt;br /&gt;
	36:'cathedral_floor5', 37:'cathedral_floor4',&lt;br /&gt;
		38:'cathedral_floor3', 39:'cathedral_floor2',&lt;br /&gt;
		40:'cathedral',&lt;br /&gt;
	44:'parking_ramp',&lt;br /&gt;
	45:'metro_tunnel',&lt;br /&gt;
	48:'burned',&lt;br /&gt;
})&lt;br /&gt;
&lt;br /&gt;
Tenant_Struct = _cns.Struct('tenant',&lt;br /&gt;
	# Horizontal positions are given with half-open ranges [left,right)&lt;br /&gt;
	# in units of 8 pixels.&lt;br /&gt;
	_cns.ULInt16('left_edge'),&lt;br /&gt;
	_cns.ULInt16('right_edge'),&lt;br /&gt;
	_cns.Rename('type', Tenant_Type),&lt;br /&gt;
	_cns.ULInt8('status'),&lt;br /&gt;
	_cns.ULInt8('pertype_idx'),&lt;br /&gt;
	_util.Unknown('_unk7', 1),&lt;br /&gt;
	_cns.ULInt32('people_offset'),&lt;br /&gt;
	_cns.ULInt8('id'),&lt;br /&gt;
	_util.Unknown('_unk13', 3),&lt;br /&gt;
	_cns.ULInt8('rent_class'),&lt;br /&gt;
	_util.Unknown('_unk17', 1),&lt;br /&gt;
)&lt;br /&gt;
assert(Tenant_Struct.sizeof() == 18)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#### Floors&lt;br /&gt;
&lt;br /&gt;
def _floor_below_grade(raw_floor):&lt;br /&gt;
	return raw_floor &amp;lt; 10&lt;br /&gt;
&lt;br /&gt;
def floor_id_from_raw(raw_floor):&lt;br /&gt;
	# Raw floor values {0..9} are basements: {-10..-1} or {B10..B1}.&lt;br /&gt;
	# Values {10..119} are floors {1..110}.&lt;br /&gt;
	if _floor_below_grade(raw_floor):&lt;br /&gt;
		return raw_floor-10&lt;br /&gt;
	else:&lt;br /&gt;
		return raw_floor-9&lt;br /&gt;
&lt;br /&gt;
def _floor_could_be_lobby(raw_floor):&lt;br /&gt;
	return floor_id_from_raw(raw_floor) in (1, 15, 30, 45, 60, 75, 90)&lt;br /&gt;
&lt;br /&gt;
Floor_Struct = _cns.Struct('floor',&lt;br /&gt;
	_cns.ULInt16('tenant_count'),&lt;br /&gt;
	_cns.ULInt16('left_edge'),&lt;br /&gt;
	_cns.ULInt16('right_edge'),&lt;br /&gt;
	_cns.Rename('tenants',&lt;br /&gt;
		_cns.Array(lambda ctx: ctx.tenant_count, Tenant_Struct)),&lt;br /&gt;
	_cns.Array(94, _cns.ULInt16('tenant_id_to_index')),&lt;br /&gt;
)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#### People&lt;br /&gt;
&lt;br /&gt;
Person_Struct = _cns.Struct('person',&lt;br /&gt;
	_cns.ULInt8('tenant_floor'),&lt;br /&gt;
	_cns.ULInt8('tenant_index'),&lt;br /&gt;
	_cns.ULInt16('number_in_tenant'),&lt;br /&gt;
	_cns.Rename('tenant_type', Tenant_Type),&lt;br /&gt;
	_cns.ULInt8('status'),&lt;br /&gt;
	_cns.SLInt8('current_floor'),&lt;br /&gt;
	_util.Unknown('_unk6', 5),&lt;br /&gt;
	_cns.ULInt16('stress'),&lt;br /&gt;
	_cns.ULInt16('eval'),&lt;br /&gt;
)&lt;br /&gt;
assert(Person_Struct.sizeof() == 16)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#### Retail&lt;br /&gt;
&lt;br /&gt;
Retail_Struct = _cns.Struct('retail',&lt;br /&gt;
	_cns.ULInt8('floor'),&lt;br /&gt;
	_util.Unknown('_unk1', 10),&lt;br /&gt;
	_cns.ULInt8('type'),&lt;br /&gt;
	_util.Unknown('_unk12', 6),&lt;br /&gt;
)&lt;br /&gt;
assert(Retail_Struct.sizeof() == 18)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#### Stairs&lt;br /&gt;
&lt;br /&gt;
Stairs_Type = _util.NumToSym(_cns.ULInt8('type'),&lt;br /&gt;
	{0:'escalator', 1:'standard'})&lt;br /&gt;
&lt;br /&gt;
Stairs_Struct = _cns.Struct('stairs',&lt;br /&gt;
	_util.Bool(_cns.ULInt8('present')),&lt;br /&gt;
	_cns.Rename('type', Stairs_Type),&lt;br /&gt;
	_cns.ULInt16('xpos'),&lt;br /&gt;
	_cns.ULInt8('bottom_floor'),&lt;br /&gt;
	_util.Unknown('_unk5', 5),&lt;br /&gt;
)&lt;br /&gt;
assert(Stairs_Struct.sizeof() == 10)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#### Elevators&lt;br /&gt;
&lt;br /&gt;
Elevator_Type = _util.NumToSym(_cns.ULInt8('type'),&lt;br /&gt;
		{0:'express', 1:'standard', 2:'service'})&lt;br /&gt;
&lt;br /&gt;
def _potential_floors_served(ctx):&lt;br /&gt;
	if ctx.type == 'express':&lt;br /&gt;
		count = 0&lt;br /&gt;
		for i in range(ctx.bottom_floor, ctx.top_floor + 1):&lt;br /&gt;
			if _floor_below_grade(i) or _floor_could_be_lobby(i):&lt;br /&gt;
				count += 1&lt;br /&gt;
	else:&lt;br /&gt;
		count = 1 + (ctx.top_floor - ctx.bottom_floor)&lt;br /&gt;
	return count&lt;br /&gt;
&lt;br /&gt;
Elevator_Struct = _cns.Struct('elevator',&lt;br /&gt;
	_cns.Anchor('start_'),&lt;br /&gt;
&lt;br /&gt;
	_util.Bool(_cns.ULInt8('present')),&lt;br /&gt;
	_cns.Rename('type', Elevator_Type),&lt;br /&gt;
&lt;br /&gt;
	# Capacity &amp;gt; 42 may crash SimTower.&lt;br /&gt;
	# 42 seems to work for non-express elevators.&lt;br /&gt;
	_cns.ULInt8('capacity'),&lt;br /&gt;
	_cns.ULInt8('car_count'),&lt;br /&gt;
&lt;br /&gt;
	# There are 4 &amp;quot;schedule&amp;quot; arrays of size 14: 7 weekday periods, followed&lt;br /&gt;
	# by 7 weekend periods.  The GUI shows 6 periods per day; the 7th is&lt;br /&gt;
	# not used.  The entire first array looks unused too.  The regex&lt;br /&gt;
	# '\x01{14}......\x05......\x05' can reliably find elevator data.&lt;br /&gt;
	_cns.Array(14, _cns.ULInt8('#unknown_sched')),&lt;br /&gt;
	_cns.If(lambda ctx: ctx.present,&lt;br /&gt;
		_util.Assert(lambda ctx: ctx['#unknown_sched'] == [1]*14)),&lt;br /&gt;
	_cns.Array(14, _cns.ULInt8('response_distances')),&lt;br /&gt;
	_cns.Array(14, _cns.ULInt8('express_modes')),&lt;br /&gt;
	_cns.Array(14, _cns.ULInt8('departure_delays')),&lt;br /&gt;
&lt;br /&gt;
	_util.Bool(_cns.ULInt8('shaft_visible')),&lt;br /&gt;
	_util.Unknown('_unk60', 1),&lt;br /&gt;
	_cns.ULInt16('left_edge'),&lt;br /&gt;
	_cns.ULInt8('top_floor'),&lt;br /&gt;
	_cns.ULInt8('bottom_floor'),&lt;br /&gt;
	_cns.Value('potential_floors_served_', _potential_floors_served),&lt;br /&gt;
&lt;br /&gt;
	# For each of 120 floors, value is 1 if served, otherwise 0.&lt;br /&gt;
	# Adding express elevator stops on improper floors (above ground and&lt;br /&gt;
	# not a multiple of 15) may crash SimTower, probably because there's&lt;br /&gt;
	# an array of size potential_floors_served.&lt;br /&gt;
	_cns.Array(120, _cns.ULInt8('floor_stops')),&lt;br /&gt;
&lt;br /&gt;
	# Resting floor for each car.&lt;br /&gt;
	_cns.Array(8, _cns.ULInt8('resting_floors')),&lt;br /&gt;
&lt;br /&gt;
	_cns.Anchor('fixed_end_'),&lt;br /&gt;
	_util.Assert(lambda ctx: ctx.fixed_end_ == ctx.start_ + 194),&lt;br /&gt;
&lt;br /&gt;
	_cns.If(lambda ctx: ctx.present, _util.AnonEmbed(&lt;br /&gt;
		_util.Unknown('_unk194', 3488),&lt;br /&gt;
&lt;br /&gt;
		# Information about people waiting for elevators&lt;br /&gt;
		# is likely to be in the following array.&lt;br /&gt;
		_cns.Array(lambda ctx: ctx.potential_floors_served_,&lt;br /&gt;
			_util.Unknown('_unk3682', 324)),&lt;br /&gt;
	)),&lt;br /&gt;
	_cns.Anchor('end_'),&lt;br /&gt;
)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#### Finances/population block&lt;br /&gt;
&lt;br /&gt;
Finances_Struct = _cns.Struct('finances',&lt;br /&gt;
	_cns.Array(10, _cns.ULInt32('tenant_populations')),&lt;br /&gt;
	_cns.ULInt32('tower_population'),&lt;br /&gt;
	_cns.Array(10, _cns.ULInt32('tenant_incomes')),&lt;br /&gt;
	_cns.ULInt32('tower_income'),&lt;br /&gt;
	_cns.Array(10, _cns.ULInt32('tenant_maintenance')),&lt;br /&gt;
	_cns.ULInt32('tower_maintenance'),&lt;br /&gt;
)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#### Overall file structure&lt;br /&gt;
&lt;br /&gt;
Tower_Struct = _cns.Struct('tower',&lt;br /&gt;
	_cns.Embedded(File_Header_Struct),&lt;br /&gt;
&lt;br /&gt;
	_cns.Rename('floors', _cns.Array(120, Floor_Struct)),&lt;br /&gt;
&lt;br /&gt;
	_cns.ULInt32('people_count'),&lt;br /&gt;
	_cns.Rename('people',&lt;br /&gt;
		_cns.Array(lambda ctx: ctx.people_count, Person_Struct)),&lt;br /&gt;
&lt;br /&gt;
	_cns.Rename('retail', _cns.Array(512, Retail_Struct)),&lt;br /&gt;
&lt;br /&gt;
	_cns.Anchor('elevators_start_'),&lt;br /&gt;
	_cns.Rename('elevators', _cns.Array(24, Elevator_Struct)),&lt;br /&gt;
	_cns.Anchor('elevators_end_'),&lt;br /&gt;
&lt;br /&gt;
	_util.Unknown('_unk_after_elev', 88),&lt;br /&gt;
	_cns.Anchor('finances_start_'),&lt;br /&gt;
	_cns.Embedded(Finances_Struct),&lt;br /&gt;
	_cns.Anchor('finances_end_'),&lt;br /&gt;
&lt;br /&gt;
	_util.Unknown('_unk_after_finpop', 1102),&lt;br /&gt;
	_cns.Anchor('stairs_start_'),&lt;br /&gt;
	_cns.Rename('stairs', _cns.Array(64, Stairs_Struct)),&lt;br /&gt;
	_cns.Anchor('stairs_end_'),&lt;br /&gt;
&lt;br /&gt;
	_util.Unknown('_unk_after_stairs', 17242),&lt;br /&gt;
	_cns.Rename('named_people',&lt;br /&gt;
		_cns.Array(lambda ctx: ctx.named_people_count,&lt;br /&gt;
			_util.ZStr(None, 16))),&lt;br /&gt;
&lt;br /&gt;
	_cns.Terminator  # must reach end of file&lt;br /&gt;
)&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== util.py ===&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;# To the extent possible under law, the author(s) have dedicated all copyright&lt;br /&gt;
# and related and neighboring rights to this software to the public domain&lt;br /&gt;
# worldwide. This software is distributed without any warranty.&lt;br /&gt;
#&lt;br /&gt;
# See &amp;lt;http://creativecommons.org/publicdomain/zero/1.0/&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
import construct as _cns&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#### Utility functions&lt;br /&gt;
&lt;br /&gt;
Unknown = _cns.Field&lt;br /&gt;
&lt;br /&gt;
class Assert(_cns.Construct):&lt;br /&gt;
	def __init__(self, fn):&lt;br /&gt;
		_cns.Construct.__init__(self, None)&lt;br /&gt;
		self.fn = fn&lt;br /&gt;
	def _sizeof(self, context): return 0&lt;br /&gt;
	def _assert(self, stream, context): assert self.fn(context)&lt;br /&gt;
	def _parse(self, stream, context): self._assert(stream, context)&lt;br /&gt;
	def _build(self, obj, stream, context): self._assert(stream, context)&lt;br /&gt;
&lt;br /&gt;
def AnonEmbed(*subcons):&lt;br /&gt;
	return _cns.Embedded(_cns.Struct(None, *subcons))&lt;br /&gt;
&lt;br /&gt;
def NumToSym(subcon, decoding):&lt;br /&gt;
	return _cns.MappingAdapter(subcon, decoding = decoding,&lt;br /&gt;
		encoding = dict((v,k) for (k,v) in decoding.items()),&lt;br /&gt;
		decdefault = _cns.Pass, encdefault = _cns.Pass)&lt;br /&gt;
&lt;br /&gt;
def Bool(subcon):&lt;br /&gt;
	return NumToSym(subcon, {0:False, 1:True})&lt;br /&gt;
&lt;br /&gt;
class _PaddedBytes(bytes):&lt;br /&gt;
	def __new__(cls, raw=b'', padding=None):&lt;br /&gt;
		b = super(_PaddedBytes, cls).__new__(cls, raw)&lt;br /&gt;
		b.padding = padding&lt;br /&gt;
		return b&lt;br /&gt;
&lt;br /&gt;
class _ZStrAdapter(_cns.StringAdapter):&lt;br /&gt;
	def __init__(self, subcon):&lt;br /&gt;
		_cns.StringAdapter.__init__(self, subcon)&lt;br /&gt;
	def _decode(self, obj, context):&lt;br /&gt;
		obj = _PaddedBytes(*obj.split(b'\0', 1))&lt;br /&gt;
		return _cns.StringAdapter._decode(self, obj, context)&lt;br /&gt;
	def _encode(self, obj, context):&lt;br /&gt;
		out = _cns.StringAdapter._encode(self, obj, context)&lt;br /&gt;
		out += b'\0'&lt;br /&gt;
		try:&lt;br /&gt;
			if obj.padding is not None:&lt;br /&gt;
				out += obj.padding&lt;br /&gt;
		except AttributeError:&lt;br /&gt;
			pass&lt;br /&gt;
&lt;br /&gt;
		pad = self._sizeof(context) - len(out)&lt;br /&gt;
		if pad &amp;lt; 0:&lt;br /&gt;
			raise ValueError(&amp;quot;string too long&amp;quot;)&lt;br /&gt;
		out += b'\0' * pad&lt;br /&gt;
&lt;br /&gt;
		return out&lt;br /&gt;
&lt;br /&gt;
def ZStr(name, length, encoding=None):&lt;br /&gt;
	fld = _cns.Field(name, length)&lt;br /&gt;
	return _ZStrAdapter(_cns.StringAdapter(fld, encoding=encoding))&lt;br /&gt;
&amp;lt;/nowiki&amp;gt;&lt;/div&gt;</summary>
		<author><name>Cypherpunks</name></author>	</entry>

	<entry>
		<id>http://fileformats.archiveteam.org/wiki/Help:Editing</id>
		<title>Help:Editing</title>
		<link rel="alternate" type="text/html" href="http://fileformats.archiveteam.org/wiki/Help:Editing"/>
				<updated>2016-09-27T01:02:53Z</updated>
		
		<summary type="html">&lt;p&gt;Cypherpunks: link to mediawiki.org&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[https://www.mediawiki.org/wiki/Special:MyLanguage/Help:Formatting MediaWiki markup details]&lt;/div&gt;</summary>
		<author><name>Cypherpunks</name></author>	</entry>

	<entry>
		<id>http://fileformats.archiveteam.org/wiki/Ogg</id>
		<title>Ogg</title>
		<link rel="alternate" type="text/html" href="http://fileformats.archiveteam.org/wiki/Ogg"/>
				<updated>2016-09-24T05:27:23Z</updated>
		
		<summary type="html">&lt;p&gt;Cypherpunks: s/OGG/ogg/ «Ogg is not an acronym and should not be mentioned as &amp;quot;OGG&amp;quot;.»&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{FormatInfo&lt;br /&gt;
|subcat=Audio and Music&lt;br /&gt;
|extensions={{ext|ogg}}, {{ext|ogx}}, {{ext|ogv}}, {{ext|oga}}, {{ext|spx}}, {{ext|ogm}}, {{ext|opus}}&lt;br /&gt;
|mimetypes={{mimetype|application/ogg}}&amp;lt;br&amp;gt;{{mimetype|audio/ogg}}&amp;lt;br&amp;gt;{{mimetype|video/ogg}}&lt;br /&gt;
|released=1993&lt;br /&gt;
}}&lt;br /&gt;
'''Ogg''' is a multimedia container format, most commonly used with [[Vorbis]] and other codecs developed by the Xiph.Org Foundation.  Ogg files start with the magic number {{magic|&amp;quot;OggS&amp;quot;}}.&lt;br /&gt;
&lt;br /&gt;
Although the initial specification and IANA registration called for the .ogg extension and application/ogg MIME type, regardless of the type of media in the container, the September 2008 RFC 5334 changed that recommendation and registered audio/ogg and video/ogg MIME types with corresponding .oga and .ogv extensions for content that is primarily audio or video respectively.  The .ogx extension was introduced for use with content that incorporated the Ogg Skeleton and for which application/ogg remained appropriate.  The .ogg extension was grandfathered to refer to Ogg audio with a Vorbis audio encoding.  The .spx extension should be used for an Ogg audio file using the Speex codec.&lt;br /&gt;
&lt;br /&gt;
Because Ogg formats are free and open-source, not proprietary as many other formats are, they are preferred by many &amp;quot;free-media&amp;quot; projects including Wikipedia, but this causes some issues for people attempting to view/listen to them, since some devices (e.g., Apple's iOS devices) don't support the Ogg formats, and others (e.g., Windows PCs) don't have &amp;quot;out-of-the-box&amp;quot; support until you install codecs, plug-ins, or software for it. Some of the proprietary formats have wider support in consumer devices in their default configurations.&lt;br /&gt;
&lt;br /&gt;
==Streams that can be placed in Ogg==&lt;br /&gt;
* Audio&lt;br /&gt;
** [[Speex]]&lt;br /&gt;
** [[Vorbis]]&lt;br /&gt;
** [[FLAC]]&lt;br /&gt;
* Video&lt;br /&gt;
** [[Dirac]]&lt;br /&gt;
** [[Theora]]&lt;br /&gt;
* Other&lt;br /&gt;
** [[Kate]]&lt;br /&gt;
&lt;br /&gt;
== Software ==&lt;br /&gt;
* [[Konvertor]]&lt;br /&gt;
* [http://www.xiph.org/dshow/ Windows Media Player codecs for some Ogg formats]&lt;br /&gt;
* [http://xiph.org/quicktime/ Ogg QuickTime components (OSX, Windows)]&lt;br /&gt;
* [http://www.mirovideoconverter.com/ Miro Video Converter] (watch out for attempts to install annoying toolbars in installer, as is regretfully common these days)&lt;br /&gt;
&lt;br /&gt;
== Utilities ==&lt;br /&gt;
* [http://www.oggconvert.com/ Online audio format converter]&lt;br /&gt;
 &lt;br /&gt;
== References ==&lt;br /&gt;
* [http://www.xiph.org/ogg/doc/ Ogg documentation from xiph.org]&lt;br /&gt;
* [https://wiki.xiph.org/Ogg xiph.org wiki page for Ogg]&lt;br /&gt;
* [http://www.xiph.org/ogg/doc/rfc3533.txt RFC 3533: The Ogg Encapsulation Format Version 0]&lt;br /&gt;
* [http://www.xiph.org/ogg/doc/rfc5334.txt RFC 5334: Ogg Media types] Redefines application/ogg and registers video/ogg and audio/ogg.&lt;br /&gt;
* [[Wikipedia: Ogg]]&lt;br /&gt;
* [http://www.digitalpreservation.gov/formats/fdd/fdd000026.shtml Ogg File Format, from Library of Congress resource on Sustainability of Digital Formats]&lt;br /&gt;
* [http://hardwarebug.org/2010/03/03/ogg-objections/ Ogg objections] and [https://people.xiph.org/~xiphmont/lj-pseudocut/o-response-1.html Chris Montgomery's response]&lt;br /&gt;
&lt;br /&gt;
[[Category:Video]]&lt;/div&gt;</summary>
		<author><name>Cypherpunks</name></author>	</entry>

	<entry>
		<id>http://fileformats.archiveteam.org/wiki/Ogg</id>
		<title>Ogg</title>
		<link rel="alternate" type="text/html" href="http://fileformats.archiveteam.org/wiki/Ogg"/>
				<updated>2016-09-24T05:25:34Z</updated>
		
		<summary type="html">&lt;p&gt;Cypherpunks: /* References */ link to xiph wiki&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{FormatInfo&lt;br /&gt;
|subcat=Audio and Music&lt;br /&gt;
|extensions={{ext|ogg}}, {{ext|ogx}}, {{ext|ogv}}, {{ext|oga}}, {{ext|spx}}, {{ext|ogm}}, {{ext|opus}}&lt;br /&gt;
|mimetypes={{mimetype|application/ogg}}&amp;lt;br&amp;gt;{{mimetype|audio/ogg}}&amp;lt;br&amp;gt;{{mimetype|video/ogg}}&lt;br /&gt;
|released=1993&lt;br /&gt;
}}&lt;br /&gt;
'''Ogg''' is a multimedia container format, most commonly used with [[Vorbis]] and other codecs developed by the Xiph.Org Foundation.  Ogg files start with the magic number {{magic|&amp;quot;OggS&amp;quot;}}.&lt;br /&gt;
&lt;br /&gt;
Although the initial specification and IANA registration called for the .ogg extension and application/ogg MIME type, regardless of the type of media in the container, the September 2008 RFC 5334 changed that recommendation and registered audio/ogg and video/ogg MIME types with corresponding .oga and .ogv extensions for content that is primarily audio or video respectively.  The .ogx extension was introduced for use with content that incorporated the OGG Skeleton and for which application/ogg remained appropriate.  The .ogg extension was grandfathered to refer to OGG audio with a Vorbis audio encoding.  The .spx extension should be used for an Ogg audio file using the Speex codec.&lt;br /&gt;
&lt;br /&gt;
Because OGG formats are free and open-source, not proprietary as many other formats are, they are preferred by many &amp;quot;free-media&amp;quot; projects including Wikipedia, but this causes some issues for people attempting to view/listen to them, since some devices (e.g., Apple's iOS devices) don't support the OGG formats, and others (e.g., Windows PCs) don't have &amp;quot;out-of-the-box&amp;quot; support until you install codecs, plug-ins, or software for it. Some of the proprietary formats have wider support in consumer devices in their default configurations.&lt;br /&gt;
&lt;br /&gt;
==Streams that can be placed in Ogg==&lt;br /&gt;
* Audio&lt;br /&gt;
** [[Speex]]&lt;br /&gt;
** [[Vorbis]]&lt;br /&gt;
** [[FLAC]]&lt;br /&gt;
* Video&lt;br /&gt;
** [[Dirac]]&lt;br /&gt;
** [[Theora]]&lt;br /&gt;
* Other&lt;br /&gt;
** [[Kate]]&lt;br /&gt;
&lt;br /&gt;
== Software ==&lt;br /&gt;
* [[Konvertor]]&lt;br /&gt;
* [http://www.xiph.org/dshow/ Windows Media Player codecs for some OGG formats]&lt;br /&gt;
* [http://xiph.org/quicktime/ OGG QuickTime components (OSX, Windows)]&lt;br /&gt;
* [http://www.mirovideoconverter.com/ Miro Video Converter] (watch out for attempts to install annoying toolbars in installer, as is regretfully common these days)&lt;br /&gt;
&lt;br /&gt;
== Utilities ==&lt;br /&gt;
* [http://www.oggconvert.com/ Online audio format converter]&lt;br /&gt;
 &lt;br /&gt;
== References ==&lt;br /&gt;
* [http://www.xiph.org/ogg/doc/ Ogg documentation from xiph.org]&lt;br /&gt;
* [https://wiki.xiph.org/Ogg xiph.org wiki page for Ogg]&lt;br /&gt;
* [http://www.xiph.org/ogg/doc/rfc3533.txt RFC 3533: The Ogg Encapsulation Format Version 0]&lt;br /&gt;
* [http://www.xiph.org/ogg/doc/rfc5334.txt RFC 5334: Ogg Media types] Redefines application/ogg and registers video/ogg and audio/ogg.&lt;br /&gt;
* [[Wikipedia: Ogg]]&lt;br /&gt;
* [http://www.digitalpreservation.gov/formats/fdd/fdd000026.shtml Ogg File Format, from Library of Congress resource on Sustainability of Digital Formats]&lt;br /&gt;
* [http://hardwarebug.org/2010/03/03/ogg-objections/ Ogg objections] and [https://people.xiph.org/~xiphmont/lj-pseudocut/o-response-1.html Chris Montgomery's response]&lt;br /&gt;
&lt;br /&gt;
[[Category:Video]]&lt;/div&gt;</summary>
		<author><name>Cypherpunks</name></author>	</entry>

	<entry>
		<id>http://fileformats.archiveteam.org/wiki/TDT</id>
		<title>TDT</title>
		<link rel="alternate" type="text/html" href="http://fileformats.archiveteam.org/wiki/TDT"/>
				<updated>2016-09-24T05:09:23Z</updated>
		
		<summary type="html">&lt;p&gt;Cypherpunks: redirect to SimTower saved game&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;#REDIRECT [[SimTower saved game]]&lt;/div&gt;</summary>
		<author><name>Cypherpunks</name></author>	</entry>

	<entry>
		<id>http://fileformats.archiveteam.org/wiki/SimTower_saved_game</id>
		<title>SimTower saved game</title>
		<link rel="alternate" type="text/html" href="http://fileformats.archiveteam.org/wiki/SimTower_saved_game"/>
				<updated>2016-09-24T05:07:29Z</updated>
		
		<summary type="html">&lt;p&gt;Cypherpunks: link to OpenSkyscraper document&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{FormatInfo&lt;br /&gt;
|formattype=electronic&lt;br /&gt;
|subcat=Saved Games&lt;br /&gt;
|extensions={{ext|tdt}}&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
== Links ==&lt;br /&gt;
&lt;br /&gt;
* [https://raw.githubusercontent.com/fabianschuiki/OpenSkyscraper/90e6e92a2d46869a4052332e48633dd1545256e4/doc/simtower/TDT_format.txt Format description from the OpenSkyscraper project]&lt;br /&gt;
* [[Wikipedia:SimTower|Wikipedia article on SimTower]]&lt;/div&gt;</summary>
		<author><name>Cypherpunks</name></author>	</entry>

	</feed>