<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en-US">
	<id>https://wiki.stunts.hu/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Dstien</id>
	<title>Stunts Wiki - User contributions [en-us]</title>
	<link rel="self" type="application/atom+xml" href="https://wiki.stunts.hu/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Dstien"/>
	<link rel="alternate" type="text/html" href="https://wiki.stunts.hu/wiki/Special:Contributions/Dstien"/>
	<updated>2026-04-21T09:05:10Z</updated>
	<subtitle>User contributions</subtitle>
	<generator>MediaWiki 1.43.3</generator>
	<entry>
		<id>https://wiki.stunts.hu/index.php?title=Debug_symbols&amp;diff=7042</id>
		<title>Debug symbols</title>
		<link rel="alternate" type="text/html" href="https://wiki.stunts.hu/index.php?title=Debug_symbols&amp;diff=7042"/>
		<updated>2026-03-06T07:04:22Z</updated>

		<summary type="html">&lt;p&gt;Dstien: FM Towns builds debug symbols.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;&#039;Debug symbols&#039;&#039;&#039; are fragments of a program&#039;s original source code used to annotate the binary produced by a compiler in order to provide context to otherwise hard-to-read disassembled machine code. Since it provides intimate details of a program&#039;s inner workings it is usually stripped from the release version of proprietary software.&lt;br /&gt;
&lt;br /&gt;
==FM Towns==&lt;br /&gt;
The [[Game_versions#FM_Towns_version|FM Towns and FM Towns Marty]] builds of 4D Driving were shipped with debug symbols embedded in the &#039;&#039;[https://en.wikipedia.org/wiki/Phar_Lap_Software Phar Lap 386|DOS-Extender]&#039;&#039; payloads. Since the symbols and the executable code are stored in the same file this was most likely a mistake that went unnoticed. It also went unnoticed by the Stunts community until 2025. These symbols are a simple list of names for functions and global variables and the corresponding addresses, and they can therefore easily be converted to formats used by other debugging tools.&lt;br /&gt;
&lt;br /&gt;
This is the structure of the &amp;lt;tt&amp;gt;SYM1&amp;lt;/tt&amp;gt; chunk found in Phar Lap&#039;s &amp;lt;tt&amp;gt;.EXP&amp;lt;/tt&amp;gt; files:&lt;br /&gt;
&lt;br /&gt;
 struct SEGMENT {&lt;br /&gt;
     uint8  name_length&lt;br /&gt;
     char   name[name_length]&lt;br /&gt;
     uint32 unknown0&lt;br /&gt;
     uint32 unknown1&lt;br /&gt;
     uint32 selector &lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 struct SYMBOL {&lt;br /&gt;
     uint8  name_length&lt;br /&gt;
     char   name[name_length]&lt;br /&gt;
     uint32 address&lt;br /&gt;
     uint16 unk == 1&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 char   magic[4] == &amp;quot;SYM1&amp;quot;&lt;br /&gt;
 uint16 unknown0 == 14&lt;br /&gt;
 uint32 unknown1 == 44&lt;br /&gt;
 uint32 sym_data_length&lt;br /&gt;
 &lt;br /&gt;
 SEGMENT segments[2]&lt;br /&gt;
 &lt;br /&gt;
 SYMBOL syms[...] // Until end-of-chunk&lt;br /&gt;
&lt;br /&gt;
===All found symbols===&lt;br /&gt;
{| class=&amp;quot;wikitable mw-collapsible mw-collapsed&amp;quot; data-expandtext=&amp;quot;Show full list&amp;quot; data-collapsetext=&amp;quot;Hide list&amp;quot; style=&amp;quot;width:100%&amp;quot;&lt;br /&gt;
! colspan=&amp;quot;2&amp;quot; | Extracted debug symbols&lt;br /&gt;
|-&lt;br /&gt;
! FM Towns&amp;lt;br&amp;gt;4DDFMT.EXT (1993-02-16)&lt;br /&gt;
! FM Towns Marty&amp;lt;br&amp;gt;4DDFMTM.EXP (1993-06-11)&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;vertical-align:top; width:50%;&amp;quot; |&lt;br /&gt;
 01a19c: ADD_OBJECT_TO_BUFFER&lt;br /&gt;
 03b83c: BARR_LIST&lt;br /&gt;
 03b3f0: BLTR_LIST&lt;br /&gt;
 038d78: BOTButcol&lt;br /&gt;
 03b36c: BSTR_LIST&lt;br /&gt;
 038d30: Blue&lt;br /&gt;
 038d3a: Brown&lt;br /&gt;
 038d82: CBlue&lt;br /&gt;
 03afc0: CHI1_LIST&lt;br /&gt;
 03b094: CHI2_LIST&lt;br /&gt;
 038d84: CRed&lt;br /&gt;
 016f9c: ConfirmMessage&lt;br /&gt;
 038d66: CredArtCol&lt;br /&gt;
 038d68: CredArtCols&lt;br /&gt;
 038d5a: CredCreCol&lt;br /&gt;
 038d5c: CredCreCols&lt;br /&gt;
 038d5e: CredDesCol&lt;br /&gt;
 038d60: CredDesCols&lt;br /&gt;
 038d6a: CredMusCol&lt;br /&gt;
 038d6c: CredMusCols&lt;br /&gt;
 038d62: CredProCol&lt;br /&gt;
 038d64: CredProCols&lt;br /&gt;
 038d56: CredTxtCol&lt;br /&gt;
 038d58: CredTxtCols&lt;br /&gt;
 038d50: Cursorcol1&lt;br /&gt;
 038d52: Cursorcol2&lt;br /&gt;
 038d34: Cyan&lt;br /&gt;
 01b6ac: DRAW_OBJECTS&lt;br /&gt;
 03dce0: DSK_filename&lt;br /&gt;
 038d3e: Darkgrey&lt;br /&gt;
 016fec: DriveAorB&lt;br /&gt;
 022c98: DriveRetry&lt;br /&gt;
 045874: Dso&lt;br /&gt;
 046948: Dtrackmatrix&lt;br /&gt;
 038d86: EBoxcol&lt;br /&gt;
 051378: EGBWork&lt;br /&gt;
 03831c: EGB_displayPage&lt;br /&gt;
 0382b8: EGB_displayStart&lt;br /&gt;
 038258: EGB_init&lt;br /&gt;
 038288: EGB_resolution&lt;br /&gt;
 0382f0: EGB_writePage&lt;br /&gt;
 03df46: ErrorCS&lt;br /&gt;
 03df48: ErrorIP&lt;br /&gt;
 038d54: Evalcol2&lt;br /&gt;
 03b398: FLBSTR_LIST&lt;br /&gt;
 03adc0: FLTRR_LIST&lt;br /&gt;
 03acec: FLTR_LIST&lt;br /&gt;
 038800: FMC_popclient&lt;br /&gt;
 0387e0: FMC_pushclient&lt;br /&gt;
 022390: FMTFREEMEMORY&lt;br /&gt;
 0223b8: FMTPURGEMEMORY&lt;br /&gt;
 0482b0: FMT_cheading&lt;br /&gt;
 03a7e0: FMT_index&lt;br /&gt;
 0482a4: FMT_inpoint&lt;br /&gt;
 020928: FMT_loadshape&lt;br /&gt;
 02097c: FMT_loadshapez&lt;br /&gt;
 0482ac: FMT_outplace&lt;br /&gt;
 048294: FMT_point&lt;br /&gt;
 04829c: FMT_point2&lt;br /&gt;
 019db8: FMT_printpoly&lt;br /&gt;
 0482b4: FMT_render2_matrix&lt;br /&gt;
 0209d0: FMT_scalecfxy&lt;br /&gt;
 03b3c4: FRBSTR_LIST&lt;br /&gt;
 03882c: FRB_getclient&lt;br /&gt;
 038848: FRB_popclient&lt;br /&gt;
 038818: FRB_setclient&lt;br /&gt;
 03abc8: FSTRI_LIST&lt;br /&gt;
 03abf4: FSTRL_LIST&lt;br /&gt;
 03ac2c: FSTRR_LIST&lt;br /&gt;
 03aaf8: FSTR_LIST&lt;br /&gt;
 03aca8: FTURR_LIST&lt;br /&gt;
 03ac64: FTUR_LIST&lt;br /&gt;
 03df4e: FontColor&lt;br /&gt;
 03df50: FontColor2&lt;br /&gt;
 03df4c: FontHeight&lt;br /&gt;
 03df52: FontStyle&lt;br /&gt;
 03df4a: FontWidth&lt;br /&gt;
 045890: FullName&lt;br /&gt;
 03b78c: GHWY1_LIST&lt;br /&gt;
 03b7b8: GHWY2_LIST&lt;br /&gt;
 038d32: Green&lt;br /&gt;
 03aeec: HLTR_LIST&lt;br /&gt;
 03b874: HPIPE_LIST&lt;br /&gt;
 03aec0: HSTRI_LIST&lt;br /&gt;
 03ae94: HSTR_LIST&lt;br /&gt;
 03b7e4: HWY1_LIST&lt;br /&gt;
 03b810: HWY2_LIST&lt;br /&gt;
 047a3e: HighIndex&lt;br /&gt;
 01a0b0: INIT_BUFFERS&lt;br /&gt;
 01a028: INIT_MATRIX&lt;br /&gt;
 01a0d8: INIT_OBJECTS_BUFFER&lt;br /&gt;
 01a080: INIT_PALETTE&lt;br /&gt;
 022290: InitRamDrive&lt;br /&gt;
 038768: KYB_clic&lt;br /&gt;
 038774: KYB_clrbuf&lt;br /&gt;
 038748: KYB_init&lt;br /&gt;
 03877c: KYB_inpchk&lt;br /&gt;
 0387b8: KYB_matrix&lt;br /&gt;
 03879c: KYB_read&lt;br /&gt;
 038750: KYB_setbuf&lt;br /&gt;
 03875c: KYB_setcode&lt;br /&gt;
 03e144: KanjiFont&lt;br /&gt;
 03df54: KanjiShape&lt;br /&gt;
 038b7c: KimG_getclient&lt;br /&gt;
 038b98: KimG_popclient&lt;br /&gt;
 038b68: KimG_setclient&lt;br /&gt;
 03b4c4: LCOR_LIST&lt;br /&gt;
 03b194: LOOP_LIST&lt;br /&gt;
 038d40: Lightblue&lt;br /&gt;
 038d44: Lightcyan&lt;br /&gt;
 038d42: Lightgreen&lt;br /&gt;
 038d3c: Lightgrey&lt;br /&gt;
 038d48: Lightmagenta&lt;br /&gt;
 038d46: Lightred&lt;br /&gt;
 038d88: MBoxcol&lt;br /&gt;
 038d7a: MIDButcol&lt;br /&gt;
 0502ec: MOSWork&lt;br /&gt;
 038634: MOS_disp&lt;br /&gt;
 03851c: MOS_end&lt;br /&gt;
 0386c4: MOS_horizon&lt;br /&gt;
 03865c: MOS_rdpos&lt;br /&gt;
 038724: MOS_resolution&lt;br /&gt;
 038694: MOS_setpos&lt;br /&gt;
 038390: MOS_start&lt;br /&gt;
 0386f4: MOS_vertical&lt;br /&gt;
 038d38: Magenta&lt;br /&gt;
 03a7e4: NP&lt;br /&gt;
 047a30: NewSI&lt;br /&gt;
 038d7c: OptColor&lt;br /&gt;
 03ab9c: PIPE_LIST&lt;br /&gt;
 03a7f4: PT&lt;br /&gt;
 0482c8: P_firstiplc&lt;br /&gt;
 0482cc: P_insertlen&lt;br /&gt;
 0482ca: P_iplc&lt;br /&gt;
 0482d0: P_listend&lt;br /&gt;
 0482c6: P_numpoints&lt;br /&gt;
 0482ce: P_pindex&lt;br /&gt;
 047a10: PlayerName&lt;br /&gt;
 04fc78: RAM_file&lt;br /&gt;
 03dcf0: RAM_filename&lt;br /&gt;
 03dcd8: RAM_filesize&lt;br /&gt;
 04fc88: RAM_saved&lt;br /&gt;
 038d7e: RBBoxcol&lt;br /&gt;
 038d80: RBCursorcol&lt;br /&gt;
 03b628: RCOR_LIST&lt;br /&gt;
 039a80: RPath&lt;br /&gt;
 0137b4: RayNullFunction&lt;br /&gt;
 038d36: Red&lt;br /&gt;
 039ad4: ReplayName&lt;br /&gt;
 038d8c: SDPAL_mcgacol1&lt;br /&gt;
 039098: SDPAL_mcgacol2&lt;br /&gt;
 038f94: SDPAL_mcgadither&lt;br /&gt;
 038e90: SDPAL_mcgatype&lt;br /&gt;
 051b98: SNDWork&lt;br /&gt;
 033d74: SND_driver&lt;br /&gt;
 033e04: SND_elevol_all_mute&lt;br /&gt;
 033df4: SND_elevol_mute&lt;br /&gt;
 033ddc: SND_elevol_set&lt;br /&gt;
 034028: SND_end&lt;br /&gt;
 033e28: SND_fm_timer_a_set&lt;br /&gt;
 033f20: SND_init&lt;br /&gt;
 033d18: SND_inst_change&lt;br /&gt;
 033db0: SND_inst_write&lt;br /&gt;
 033ed4: SND_int_timer_a_get&lt;br /&gt;
 033e90: SND_int_timer_a_set&lt;br /&gt;
 033ce4: SND_joy_in_1&lt;br /&gt;
 033d54: SND_key_abort&lt;br /&gt;
 033d00: SND_key_on&lt;br /&gt;
 033e14: SND_pan_set&lt;br /&gt;
 034140: SND_pcm_bank_load&lt;br /&gt;
 033e3c: SND_pcm_mode_set&lt;br /&gt;
 033e4c: SND_pcm_play&lt;br /&gt;
 033e6c: SND_pcm_play_stop&lt;br /&gt;
 033d64: SND_pcm_sound_delete&lt;br /&gt;
 033dcc: SND_pcm_sound_set&lt;br /&gt;
 033e7c: SND_pcm_status&lt;br /&gt;
 033d2c: SND_pitch_change&lt;br /&gt;
 033d40: SND_volume_change&lt;br /&gt;
 03ab70: SPIPE_LIST&lt;br /&gt;
 055b98: SaveTimer&lt;br /&gt;
 047a2c: Scores&lt;br /&gt;
 00f12c: ShowTitle&lt;br /&gt;
 00f1f8: ShowTitle2&lt;br /&gt;
 051978: SystemMemory&lt;br /&gt;
 043acc: TBIOSSTK_bottom&lt;br /&gt;
 038d76: TOPButcol&lt;br /&gt;
 039a2c: TPath&lt;br /&gt;
 03ab50: TUN_LIST&lt;br /&gt;
 039ae0: TerName&lt;br /&gt;
 038d6e: TrackBoxCol1&lt;br /&gt;
 038d70: TrackBoxCol2&lt;br /&gt;
 038d72: TrackBoxCol3&lt;br /&gt;
 038d74: TrackCursorCol&lt;br /&gt;
 03b168: USTR_LIST&lt;br /&gt;
 03b2bc: VCORK_LIST&lt;br /&gt;
 016f38: WarningMessage&lt;br /&gt;
 038d4c: White&lt;br /&gt;
 03ab24: XFSTR_LIST&lt;br /&gt;
 038d4a: Yellow&lt;br /&gt;
 016ee8: YesOrNoMessage&lt;br /&gt;
 042f14: __onexit_termination&lt;br /&gt;
 042c20: _base&lt;br /&gt;
 042e68: _bufsiz&lt;br /&gt;
 042af4: _ctype&lt;br /&gt;
 034ad4: _dos_findfirst&lt;br /&gt;
 034b04: _dos_findnext&lt;br /&gt;
 032418: _dos_getdiskfree&lt;br /&gt;
 042fd4: _doserr&lt;br /&gt;
 0430d4: _doserrno&lt;br /&gt;
 044ed8: _edata&lt;br /&gt;
 055d10: _end&lt;br /&gt;
 034d88: _exit&lt;br /&gt;
 032854: _fdopen&lt;br /&gt;
 042f04: _fmode&lt;br /&gt;
 042ecc: _fopen_max&lt;br /&gt;
 038d20: _fsoftonly&lt;br /&gt;
 032870: _fsopen&lt;br /&gt;
 042c28: _gda&lt;br /&gt;
 043468: _heapptr&lt;br /&gt;
 042c74: _iob&lt;br /&gt;
 034d9c: _itoa&lt;br /&gt;
 042c49: _mw1167&lt;br /&gt;
 038d20: _mw1167required&lt;br /&gt;
 038d20: _mw1167used&lt;br /&gt;
 038d20: _mw3167used&lt;br /&gt;
 042c47: _mw387&lt;br /&gt;
 038d20: _mw387used&lt;br /&gt;
 042c43: _mw8087&lt;br /&gt;
 038d20: _mw87only&lt;br /&gt;
 038d20: _mw87required&lt;br /&gt;
 038d20: _mw87used&lt;br /&gt;
 042c14: _mwCPU&lt;br /&gt;
 0328f0: _mwINIT&lt;br /&gt;
 042c15: _mwOS&lt;br /&gt;
 0378a8: _mw_87_f2add&lt;br /&gt;
 0378d2: _mw_87_f2compare&lt;br /&gt;
 0378cb: _mw_87_f2div&lt;br /&gt;
 0378c4: _mw_87_f2mpy&lt;br /&gt;
 037996: _mw_87_fbld&lt;br /&gt;
 03798c: _mw_87_fbstp&lt;br /&gt;
 0378e8: _mw_87_fflt&lt;br /&gt;
 037928: _mw_87_flload&lt;br /&gt;
 03790e: _mw_87_fload&lt;br /&gt;
 037915: _mw_87_flret&lt;br /&gt;
 037942: _mw_87_fpop&lt;br /&gt;
 037901: _mw_87_fret&lt;br /&gt;
 037939: _mw_87_ftload&lt;br /&gt;
 03792f: _mw_87_ftret&lt;br /&gt;
 037983: _mw_87_fxam&lt;br /&gt;
 037978: _mw_87_round&lt;br /&gt;
 03795c: _mw_87_trunc&lt;br /&gt;
 0378ef: _mw_87_ufflt&lt;br /&gt;
 033474: _mw_errnoset&lt;br /&gt;
 0381e4: _mwabort&lt;br /&gt;
 037b60: _mwaddmany&lt;br /&gt;
 036094: _mwaprintf&lt;br /&gt;
 042c38: _mwarglen&lt;br /&gt;
 042c2c: _mwargp&lt;br /&gt;
 038d20: _mwargregs&lt;br /&gt;
 038d20: _mwargstack&lt;br /&gt;
 042c32: _mwargvp&lt;br /&gt;
 0371dc: _mwbcd_to_real&lt;br /&gt;
 033240: _mwc_create&lt;br /&gt;
 033220: _mwc_dos_name&lt;br /&gt;
 033268: _mwc_open&lt;br /&gt;
 033298: _mwc_unlink&lt;br /&gt;
 0334c4: _mwcall_onexit_fcns&lt;br /&gt;
 033b78: _mwcalldos&lt;br /&gt;
 0321bc: _mwcfclose_all&lt;br /&gt;
 032f4c: _mwcfinit&lt;br /&gt;
 032f94: _mwcfterm&lt;br /&gt;
 033b58: _mwcheck_heap_integrity&lt;br /&gt;
 033450: _mwcmp&lt;br /&gt;
 0381b4: _mwdisplay&lt;br /&gt;
 033130: _mwdos&lt;br /&gt;
 0331e8: _mwdos_exit&lt;br /&gt;
 037ca1: _mwdshl&lt;br /&gt;
 033c5c: _mwdump_heap&lt;br /&gt;
 0335c4: _mweach_allocated_item&lt;br /&gt;
 033550: _mweach_free_item&lt;br /&gt;
 0334f8: _mweach_item&lt;br /&gt;
 042c4b: _mwemc87&lt;br /&gt;
 0332ac: _mwend&lt;br /&gt;
 042c54: _mwenv&lt;br /&gt;
 043460: _mwenvip&lt;br /&gt;
 042c3c: _mwenvp&lt;br /&gt;
 042c16: _mwes&lt;br /&gt;
 032ecb: _mwexpand_heap&lt;br /&gt;
 0374b8: _mwfabs&lt;br /&gt;
 0371f4: _mwfadd&lt;br /&gt;
 037e40: _mwfbld&lt;br /&gt;
 037f38: _mwfbstp&lt;br /&gt;
 03783c: _mwfcmp&lt;br /&gt;
 037824: _mwfcompare&lt;br /&gt;
 037788: _mwfcomparend&lt;br /&gt;
 037638: _mwfdiv&lt;br /&gt;
 03762c: _mwfdivr&lt;br /&gt;
 0374d8: _mwfdup&lt;br /&gt;
 033c08: _mwferr&lt;br /&gt;
 0333c4: _mwfileclass&lt;br /&gt;
 033114: _mwfinit&lt;br /&gt;
 037348: _mwflload&lt;br /&gt;
 03730c: _mwfload&lt;br /&gt;
 038d20: _mwfltused&lt;br /&gt;
 0374f4: _mwfmpy&lt;br /&gt;
 03745c: _mwfneg&lt;br /&gt;
 037cf0: _mwfpop&lt;br /&gt;
 037cb4: _mwfpstackoflo&lt;br /&gt;
 033a9e: _mwfree&lt;br /&gt;
 03748c: _mwfsub&lt;br /&gt;
 037480: _mwfsubr&lt;br /&gt;
 033114: _mwfterm&lt;br /&gt;
 037384: _mwftload&lt;br /&gt;
 0373e4: _mwftret&lt;br /&gt;
 035444: _mwfwrite_&lt;br /&gt;
 037d80: _mwfxam&lt;br /&gt;
 037424: _mwfxch&lt;br /&gt;
 0371a0: _mwget_exponent&lt;br /&gt;
 0324c0: _mwget_file_handle_and_info&lt;br /&gt;
 032f34: _mwgetds&lt;br /&gt;
 034d38: _mwgetenv2&lt;br /&gt;
 04345c: _mwgetenvbufnum&lt;br /&gt;
 0332ec: _mwhalt&lt;br /&gt;
 042c5a: _mwheap_expansion_enabled&lt;br /&gt;
 032eac: _mwheaphi&lt;br /&gt;
 032ea0: _mwheaplo&lt;br /&gt;
 033a00: _mwhmalloc&lt;br /&gt;
 037cd4: _mwinc_tos&lt;br /&gt;
 0357e8: _mwinit_buf&lt;br /&gt;
 042c10: _mwinput&lt;br /&gt;
 03368c: _mwinsert_into_free_chain&lt;br /&gt;
 042c42: _mwis_286&lt;br /&gt;
 033cbc: _mwkbnewline&lt;br /&gt;
 033ca0: _mwkbputs&lt;br /&gt;
 038d20: _mwldouble10&lt;br /&gt;
 0337c4: _mwleast_free_memory&lt;br /&gt;
 0331a4: _mwload_ds_dx&lt;br /&gt;
 033170: _mwload_ptr&lt;br /&gt;
 038d2c: _mwloc&lt;br /&gt;
 03340c: _mwlseek&lt;br /&gt;
 0379a0: _mwltox&lt;br /&gt;
 033a64: _mwmalloc&lt;br /&gt;
 0338e8: _mwmalloc2&lt;br /&gt;
 037bde: _mwnegmany&lt;br /&gt;
 043464: _mwnextenv&lt;br /&gt;
 037cf8: _mwnormalize&lt;br /&gt;
 036768: _mwout_convert_dreal&lt;br /&gt;
 036e94: _mwout_convert_real&lt;br /&gt;
 042c12: _mwoutput&lt;br /&gt;
 035918: _mwpad_to_field_width&lt;br /&gt;
 042c4e: _mwprognamep&lt;br /&gt;
 0371c4: _mwreal_to_bcd&lt;br /&gt;
 032901: _mwrestore_interrupts&lt;br /&gt;
 037a98: _mwrtox&lt;br /&gt;
 0358d0: _mwsend_pad&lt;br /&gt;
 03787e: _mwset_flags_after_compare&lt;br /&gt;
 0326c4: _mwset_flags_etc&lt;br /&gt;
 03785c: _mwset_rounding_proc&lt;br /&gt;
 032f2e: _mwset_stack_limits&lt;br /&gt;
 033018: _mwset_up_args&lt;br /&gt;
 0370e0: _mwspecial_number_msg&lt;br /&gt;
 032f31: _mwss&lt;br /&gt;
 042bfc: _mwstack_limit&lt;br /&gt;
 03822c: _mwstack_overflow&lt;br /&gt;
 033c8c: _mwstackdump&lt;br /&gt;
 038220: _mwstkerr&lt;br /&gt;
 037b89: _mwsubmany112&lt;br /&gt;
 037bb2: _mwsubmany121&lt;br /&gt;
 037060: _mwten_to_the_power&lt;br /&gt;
 04325c: _mwtmp_env_buf&lt;br /&gt;
 0332d4: _mwvsretcode&lt;br /&gt;
 03811c: _mwxdiv&lt;br /&gt;
 0380d0: _mwxmpy&lt;br /&gt;
 037c03: _mwxnormalize&lt;br /&gt;
 037c38: _mwxshl&lt;br /&gt;
 037c48: _mwxshr&lt;br /&gt;
 037c54: _mwxshrcnt&lt;br /&gt;
 037a15: _mwxtol&lt;br /&gt;
 037afd: _mwxtor&lt;br /&gt;
 0331c8: _mwzclose&lt;br /&gt;
 033338: _mwzread&lt;br /&gt;
 0333b0: _mwztrunc&lt;br /&gt;
 033364: _mwzwrite&lt;br /&gt;
 042c04: _osmajor&lt;br /&gt;
 042c05: _osminor&lt;br /&gt;
 042c04: _osversion&lt;br /&gt;
 042c16: _psp&lt;br /&gt;
 034e14: _strcmpi&lt;br /&gt;
 034e14: _stricmp&lt;br /&gt;
 038bb4: _strnicmp&lt;br /&gt;
 038cb0: _strrev&lt;br /&gt;
 042ed0: _temp_file_chain&lt;br /&gt;
 042c1c: _top&lt;br /&gt;
 041809: _zclipvalue&lt;br /&gt;
 03a0b0: abbrname&lt;br /&gt;
 03a569: abortbox&lt;br /&gt;
 023cbc: abortmessage&lt;br /&gt;
 021538: accelerate&lt;br /&gt;
 040034: activeflag&lt;br /&gt;
 04181c: adderr&lt;br /&gt;
 024e34: addexit&lt;br /&gt;
 03e200: addexiterr&lt;br /&gt;
 011cd4: addhighs&lt;br /&gt;
 02f9b4: addtimer&lt;br /&gt;
 020e38: addtotextbuf&lt;br /&gt;
 01bcc4: addzone&lt;br /&gt;
 023d28: adrtoseg&lt;br /&gt;
 047a78: allcarobject1&lt;br /&gt;
 047b78: allcarobject2&lt;br /&gt;
 02291c: allexist&lt;br /&gt;
 047b90: alloppresfile&lt;br /&gt;
 039b25: allowabort&lt;br /&gt;
 028cbb: andcf&lt;br /&gt;
 028ee2: andcfxy&lt;br /&gt;
 028f1a: andcfxya&lt;br /&gt;
 026ffa: andcline&lt;br /&gt;
 0284a4: andf&lt;br /&gt;
 02858b: andfxy&lt;br /&gt;
 0285c3: andfxya&lt;br /&gt;
 02769c: andline&lt;br /&gt;
 02a6a2: andpackcf&lt;br /&gt;
 02a900: andpackcfxy&lt;br /&gt;
 02a938: andpackcfxya&lt;br /&gt;
 0299ef: andpackf&lt;br /&gt;
 029abb: andpackfxy&lt;br /&gt;
 029af3: andpackfxya&lt;br /&gt;
 026ce5: andpixel&lt;br /&gt;
 026bf6: andpixelc&lt;br /&gt;
 027861: andrect&lt;br /&gt;
 027b7d: andrectc&lt;br /&gt;
 02157c: anim_car&lt;br /&gt;
 02181c: anim_champ&lt;br /&gt;
 0212fc: anim_finish&lt;br /&gt;
 011ff8: animateopponent&lt;br /&gt;
 00ee08: animcarsmk&lt;br /&gt;
 047bb6: animdelay&lt;br /&gt;
 00ea34: animhelmet1&lt;br /&gt;
 00ec90: animhelmet2&lt;br /&gt;
 047bae: animindex&lt;br /&gt;
 047bb4: animnum&lt;br /&gt;
 047bba: animx&lt;br /&gt;
 047bbc: animy&lt;br /&gt;
 0456ad: askfull&lt;br /&gt;
 033494: atexit&lt;br /&gt;
 000594: availmem&lt;br /&gt;
 047ba8: backfile&lt;br /&gt;
 025144: background&lt;br /&gt;
 019dbc: benprojectp&lt;br /&gt;
 0479fe: between&lt;br /&gt;
 03bc9c: bew11&lt;br /&gt;
 055bbc: biosticks&lt;br /&gt;
 04188c: biostickset&lt;br /&gt;
 047990: bitplanes&lt;br /&gt;
 03d7f4: blackpal&lt;br /&gt;
 03fea0: blknotfound&lt;br /&gt;
 046960: blocklistsign&lt;br /&gt;
 0205c4: blowengine&lt;br /&gt;
 03fe2c: bmem&lt;br /&gt;
 03bd00: bne22&lt;br /&gt;
 03bc88: bns11&lt;br /&gt;
 03bd14: bnw22&lt;br /&gt;
 0400a2: botfire&lt;br /&gt;
 00d378: boxcheck&lt;br /&gt;
 04798e: bpix&lt;br /&gt;
 0479eb: brakecolor&lt;br /&gt;
 03c10c: brew11&lt;br /&gt;
 03c0f8: brns11&lt;br /&gt;
 03bcd8: bse22&lt;br /&gt;
 03bcb0: bsn11&lt;br /&gt;
 03bcec: bsw22&lt;br /&gt;
 047b7c: buttfile&lt;br /&gt;
 03bcc4: bwe11&lt;br /&gt;
 00c760: calccoll&lt;br /&gt;
 0237cc: calcrpm&lt;br /&gt;
 039910: camerasizeinfo&lt;br /&gt;
 039b18: camheading&lt;br /&gt;
 039b16: camlen&lt;br /&gt;
 039b1f: cammode&lt;br /&gt;
 039b1a: campitch&lt;br /&gt;
 023d04: cap&lt;br /&gt;
 045604: car1&lt;br /&gt;
 047936: car1handle&lt;br /&gt;
 0477c4: car1ltires&lt;br /&gt;
 04786c: car1tcenter&lt;br /&gt;
 0477dc: car1toffsets&lt;br /&gt;
 047938: car2handle&lt;br /&gt;
 0477d0: car2ltires&lt;br /&gt;
 047908: car2tcenter&lt;br /&gt;
 047878: car2toffsets&lt;br /&gt;
 020778: carbubble&lt;br /&gt;
 02067c: carbump&lt;br /&gt;
 020620: carcrash&lt;br /&gt;
 04630c: cari&lt;br /&gt;
 046614: cari2&lt;br /&gt;
 020d68: carmovesfx&lt;br /&gt;
 04799c: carname&lt;br /&gt;
 048b00: carobjects1&lt;br /&gt;
 048b04: carobjects2&lt;br /&gt;
 039b38: carresname&lt;br /&gt;
 0206d0: carscrape&lt;br /&gt;
 020724: carsplash&lt;br /&gt;
 03dcb4: ccmsg&lt;br /&gt;
 0208f8: cdfade&lt;br /&gt;
 030844: cdfadeto&lt;br /&gt;
 030948: cdisbusy&lt;br /&gt;
 03dcac: cdmsg&lt;br /&gt;
 030928: cdpause&lt;br /&gt;
 030a78: cdplay&lt;br /&gt;
 030970: cdplaysection&lt;br /&gt;
 0389cc: cdr_cdinfo&lt;br /&gt;
 038a88: cdr_continue&lt;br /&gt;
 038ad4: cdr_exit1&lt;br /&gt;
 03894c: cdr_mphase&lt;br /&gt;
 038938: cdr_mstop&lt;br /&gt;
 0388d4: cdr_mtplay&lt;br /&gt;
 038a74: cdr_pause&lt;br /&gt;
 038b50: cdr_popclient&lt;br /&gt;
 038b30: cdr_pushclient&lt;br /&gt;
 038864: cdr_sdrvmd&lt;br /&gt;
 043b49: cdr_stat&lt;br /&gt;
 0388a0: cdr_status&lt;br /&gt;
 03086c: cdreadtoc&lt;br /&gt;
 030938: cdresume&lt;br /&gt;
 0208e4: cdsnddone&lt;br /&gt;
 03090c: cdstart&lt;br /&gt;
 030918: cdstop&lt;br /&gt;
 0307d8: cdupdatefade&lt;br /&gt;
 025c6c: centertext&lt;br /&gt;
 0413f5: centerx&lt;br /&gt;
 041401: centerxpix&lt;br /&gt;
 0413f7: centery&lt;br /&gt;
 041403: centerypix&lt;br /&gt;
 0413ed: cenxpix&lt;br /&gt;
 0413ef: cenypix&lt;br /&gt;
 047c2c: cfcount&lt;br /&gt;
 03dcb0: cfmsg&lt;br /&gt;
 03be04: ch1ew21&lt;br /&gt;
 03be18: ch1ns21&lt;br /&gt;
 03be2c: ch2ew21&lt;br /&gt;
 03bdf0: ch2ns21&lt;br /&gt;
 021ee0: champion&lt;br /&gt;
 02118c: change_palette&lt;br /&gt;
 00e2f4: changedrive&lt;br /&gt;
 00e3e0: checkcarname&lt;br /&gt;
 0171c4: checkdisk&lt;br /&gt;
 022a24: checkinstall&lt;br /&gt;
 025468: checkmodule&lt;br /&gt;
 01c260: checkobjtypes&lt;br /&gt;
 019ac4: checktracksyntax&lt;br /&gt;
 03db14: chmpname&lt;br /&gt;
 0259bc: chooseone&lt;br /&gt;
 042230: circles&lt;br /&gt;
 042234: circletbls&lt;br /&gt;
 04795c: cjoystate&lt;br /&gt;
 047c2e: clastcolor&lt;br /&gt;
 047999: clastx&lt;br /&gt;
 04799a: clastz&lt;br /&gt;
 01653c: clear_keyboardbuffer&lt;br /&gt;
 0000c4: clearinterpretsubs&lt;br /&gt;
 034530: clearscreen&lt;br /&gt;
 0245bc: clearwindow&lt;br /&gt;
 01356c: clearzone&lt;br /&gt;
 0248d0: clip&lt;br /&gt;
 04797a: clipby&lt;br /&gt;
 02e054: clipline&lt;br /&gt;
 024770: clippix&lt;br /&gt;
 024740: clippixwindow&lt;br /&gt;
 047978: clipty&lt;br /&gt;
 0248e0: clipwindow&lt;br /&gt;
 01bc2c: clipzone&lt;br /&gt;
 015e30: closeresource&lt;br /&gt;
 047976: cloudfudge&lt;br /&gt;
 0479fa: cmps&lt;br /&gt;
 03c15c: colew22&lt;br /&gt;
 03c120: colns22&lt;br /&gt;
 048a48: color1&lt;br /&gt;
 048a4c: color2&lt;br /&gt;
 04f678: colorbak&lt;br /&gt;
 04f978: colorcur&lt;br /&gt;
 048a54: colordither&lt;br /&gt;
 048a58: colorrnds&lt;br /&gt;
 048a50: colorstat&lt;br /&gt;
 03c148: colsn22&lt;br /&gt;
 03c134: colwe22&lt;br /&gt;
 01ed30: compiletrack&lt;br /&gt;
 025ec0: convertjoy&lt;br /&gt;
 03d7b8: coord1&lt;br /&gt;
 03d7c0: coord2&lt;br /&gt;
 01c1fc: copyobj&lt;br /&gt;
 01c214: copyobjtypes&lt;br /&gt;
 0227c0: copyq2a&lt;br /&gt;
 03c1ac: corew22&lt;br /&gt;
 03c170: corns22&lt;br /&gt;
 03c198: corsn22&lt;br /&gt;
 03c184: corwe22&lt;br /&gt;
 0479d4: countdown&lt;br /&gt;
 03dcb8: cpmsg&lt;br /&gt;
 019d60: cpycoord&lt;br /&gt;
 019d98: cpymatrix&lt;br /&gt;
 019d80: cpyscoord&lt;br /&gt;
 00445c: crack&lt;br /&gt;
 023db0: crcbyte&lt;br /&gt;
 00f2a0: credit1&lt;br /&gt;
 00f348: credit2&lt;br /&gt;
 030d8f: criterr&lt;br /&gt;
 04188a: critflag&lt;br /&gt;
 041884: critfunc&lt;br /&gt;
 030d26: crithandler&lt;br /&gt;
 030e27: ctrlc&lt;br /&gt;
 030e17: ctrlchandler&lt;br /&gt;
 03a558: curfname&lt;br /&gt;
 0475d8: curplane&lt;br /&gt;
 047a76: currcar&lt;br /&gt;
 03d7b0: currchannel&lt;br /&gt;
 03d7e2: currentbuf&lt;br /&gt;
 04016a: currentfont&lt;br /&gt;
 025e00: currentkeysub&lt;br /&gt;
 041894: currentwindow&lt;br /&gt;
 04b2e2: currpm&lt;br /&gt;
 051364: cursmask&lt;br /&gt;
 051360: cursshape&lt;br /&gt;
 0456c4: cusedash&lt;br /&gt;
 0479e5: cusereplay&lt;br /&gt;
 014fa8: cutpath&lt;br /&gt;
 045e90: cv&lt;br /&gt;
 0462f0: cvx&lt;br /&gt;
 044edc: cz&lt;br /&gt;
 047a02: czoneflag&lt;br /&gt;
 03dd02: datadrive&lt;br /&gt;
 04580c: dcar_matrix&lt;br /&gt;
 04796e: dclip&lt;br /&gt;
 039a28: deffont&lt;br /&gt;
 02009c: deinitenginesfx&lt;br /&gt;
 021114: delaykey&lt;br /&gt;
 02f9e8: deltimer&lt;br /&gt;
 0479cf: demomode&lt;br /&gt;
 0399d4: demoplane&lt;br /&gt;
 047920: demotime&lt;br /&gt;
 0479d0: didrace&lt;br /&gt;
 0210b0: disabletextbuf&lt;br /&gt;
 022670: diskaexist&lt;br /&gt;
 0224a0: diskexist&lt;br /&gt;
 022310: diskfile&lt;br /&gt;
 022524: diskfileerror&lt;br /&gt;
 0224e0: diskfileexist&lt;br /&gt;
 024e98: diskfree&lt;br /&gt;
 03a534: diskmsgs&lt;br /&gt;
 03a544: disknames&lt;br /&gt;
 03dd00: diskop&lt;br /&gt;
 022648: diskspace&lt;br /&gt;
 022fa0: disolve_entirememwindow&lt;br /&gt;
 022dcc: disolve_hiddenwindow&lt;br /&gt;
 022ea0: disolve_memwindow&lt;br /&gt;
 0257c0: displayall&lt;br /&gt;
 025768: displayone&lt;br /&gt;
 02458c: displayshapes&lt;br /&gt;
 024730: displaywindow&lt;br /&gt;
 02fbc4: ditheredpoly&lt;br /&gt;
 02fbd4: ditheredpolyf&lt;br /&gt;
 02fbe4: ditheredpolyi&lt;br /&gt;
 02fbf4: ditheredpolyip&lt;br /&gt;
 02fc04: ditheredpolyipt&lt;br /&gt;
 02fc14: ditheredpolyit&lt;br /&gt;
 02fc24: ditheredpolyp&lt;br /&gt;
 02fc34: ditheredpolypt&lt;br /&gt;
 02fc44: ditheredpolyt&lt;br /&gt;
 0208cc: docdplay&lt;br /&gt;
 0167e0: docursor&lt;br /&gt;
 0167c8: docursorinit&lt;br /&gt;
 006748: dodash&lt;br /&gt;
 00bcbc: doengine&lt;br /&gt;
 00c250: dohandling&lt;br /&gt;
 0162d4: dohidemouse&lt;br /&gt;
 0074a0: doreplay&lt;br /&gt;
 0267e0: dosexit&lt;br /&gt;
 00c8b8: doshock&lt;br /&gt;
 016328: doshowmouse&lt;br /&gt;
 015e98: doslider&lt;br /&gt;
 00ca14: dosteering&lt;br /&gt;
 014c28: draw3dboxin&lt;br /&gt;
 014b00: draw3dboxout&lt;br /&gt;
 014d54: draw3dbutton&lt;br /&gt;
 003a58: drawblimpworld&lt;br /&gt;
 02fb44: drawbox&lt;br /&gt;
 034360: drawcircle&lt;br /&gt;
 026de3: drawcline&lt;br /&gt;
 011950: drawhighs&lt;br /&gt;
 0030c0: drawhorizon&lt;br /&gt;
 002f04: drawhorizone&lt;br /&gt;
 02764b: drawline&lt;br /&gt;
 004e64: drawlogo&lt;br /&gt;
 0479d2: drawmode&lt;br /&gt;
 0135a0: drawmode4box&lt;br /&gt;
 011f78: drawopponent&lt;br /&gt;
 019398: drawpiecebox&lt;br /&gt;
 0345e0: drawpolyf&lt;br /&gt;
 02fd68: drawpolyp&lt;br /&gt;
 02fd54: drawpolypt&lt;br /&gt;
 02778f: drawrect&lt;br /&gt;
 027ad1: drawrectc&lt;br /&gt;
 0039f4: drawsort&lt;br /&gt;
 003f80: drawtext&lt;br /&gt;
 019514: drawtrackbox&lt;br /&gt;
 00082c: drawworld&lt;br /&gt;
 0005b0: drawworldflipzones&lt;br /&gt;
 024ea8: drive&lt;br /&gt;
 0169dc: drnd&lt;br /&gt;
 024e6c: dsiexit&lt;br /&gt;
 03dcbc: dsmsg&lt;br /&gt;
 0455b0: dtempzone&lt;br /&gt;
 023d30: dump&lt;br /&gt;
 025874: dumpone&lt;br /&gt;
 047964: ebufend&lt;br /&gt;
 047962: ebufstart&lt;br /&gt;
 047960: ebuftime&lt;br /&gt;
 02fa40: elapsedticks&lt;br /&gt;
 031ea0: ellipse&lt;br /&gt;
 031b4c: ellipseh&lt;br /&gt;
 0171f8: elticks&lt;br /&gt;
 0210bc: enabletextbuf&lt;br /&gt;
 039ba0: endgame&lt;br /&gt;
 039600: eng&lt;br /&gt;
 039640: eng2&lt;br /&gt;
 045940: enginebuffer&lt;br /&gt;
 020354: engineoff&lt;br /&gt;
 020280: engineon&lt;br /&gt;
 0208a4: enginesfxover&lt;br /&gt;
 020fc8: erasetext&lt;br /&gt;
 042eda: errno&lt;br /&gt;
 047bb8: et&lt;br /&gt;
 012084: evaluation&lt;br /&gt;
 034d70: exit&lt;br /&gt;
 03e1d8: exitsub&lt;br /&gt;
 03ff00: exmemerr&lt;br /&gt;
 03fed0: expanderr&lt;br /&gt;
 04558c: explbmapsdiam&lt;br /&gt;
 03dd34: ext&lt;br /&gt;
 051a7c: extkeysubs&lt;br /&gt;
 048a5c: facedir&lt;br /&gt;
 022fb4: fade_display&lt;br /&gt;
 023084: fade_displays&lt;br /&gt;
 032118: fclose&lt;br /&gt;
 04b2dc: fcolor&lt;br /&gt;
 04b2de: fcolor2&lt;br /&gt;
 03b938: few11&lt;br /&gt;
 032040: fflush&lt;br /&gt;
 034790: fgetc&lt;br /&gt;
 024960: filename&lt;br /&gt;
 03e1cc: filerrtxt&lt;br /&gt;
 024e04: fileselector&lt;br /&gt;
 024ce0: filesize&lt;br /&gt;
 024d00: filesizea&lt;br /&gt;
 024cf0: filesizez&lt;br /&gt;
 00ba20: findcar&lt;br /&gt;
 024e14: findfile&lt;br /&gt;
 024998: findfirst&lt;br /&gt;
 0249c0: findnext&lt;br /&gt;
 00d92c: finishgame&lt;br /&gt;
 016884: finishsong&lt;br /&gt;
 047bac: firstone&lt;br /&gt;
 0479e2: firsttime&lt;br /&gt;
 030e50: fixedmult&lt;br /&gt;
 03bc74: flbew11&lt;br /&gt;
 03bc60: flbns11&lt;br /&gt;
 03bc38: flbsn11&lt;br /&gt;
 03bc4c: flbwe11&lt;br /&gt;
 015014: floadreq&lt;br /&gt;
 017200: fluffyload&lt;br /&gt;
 02cec2: fmtandcf&lt;br /&gt;
 02d0cc: fmtandcfxy&lt;br /&gt;
 02d0f5: fmtandcfxya&lt;br /&gt;
 02c8aa: fmtandf&lt;br /&gt;
 02c967: fmtandfxy&lt;br /&gt;
 02c990: fmtandfxya&lt;br /&gt;
 031248: fmtandpackcf&lt;br /&gt;
 031288: fmtandpackcfxy&lt;br /&gt;
 0312c8: fmtandpackcfxya&lt;br /&gt;
 02d8f2: fmtandpackf&lt;br /&gt;
 02d9c0: fmtandpackfxy&lt;br /&gt;
 02d9e9: fmtandpackfxya&lt;br /&gt;
 0315d2: fmtandrect&lt;br /&gt;
 031975: fmtandrectc&lt;br /&gt;
 03455f: fmtclearscreen&lt;br /&gt;
 0311f8: fmtdisolvefast&lt;br /&gt;
 031208: fmtdisolvefastxya&lt;br /&gt;
 031218: fmtdisolveslow&lt;br /&gt;
 031228: fmtdisolveslowxya&lt;br /&gt;
 0314dc: fmtdrawrect&lt;br /&gt;
 0318d8: fmtdrawrectc&lt;br /&gt;
 0250f4: fmtenlargescreen&lt;br /&gt;
 03e1a4: fmtexten&lt;br /&gt;
 026b20: fmtgetpalette&lt;br /&gt;
 034590: fmthtclear&lt;br /&gt;
 024fd8: fmtinitgraphics&lt;br /&gt;
 02cc8e: fmtmovcf&lt;br /&gt;
 02ce78: fmtmovcfxy&lt;br /&gt;
 02cea1: fmtmovcfxya&lt;br /&gt;
 02c7bb: fmtmovf&lt;br /&gt;
 02c860: fmtmovfxy&lt;br /&gt;
 02c889: fmtmovfxya&lt;br /&gt;
 031238: fmtmovpackcf&lt;br /&gt;
 031278: fmtmovpackcfxy&lt;br /&gt;
 0312b8: fmtmovpackcfxya&lt;br /&gt;
 02d7e6: fmtmovpackf&lt;br /&gt;
 02d8a8: fmtmovpackfxy&lt;br /&gt;
 02d8d1: fmtmovpackfxya&lt;br /&gt;
 02d116: fmtorcf&lt;br /&gt;
 02d320: fmtorcfxy&lt;br /&gt;
 02d349: fmtorcfxya&lt;br /&gt;
 02c9b1: fmtorf&lt;br /&gt;
 02ca6e: fmtorfxy&lt;br /&gt;
 02ca97: fmtorfxya&lt;br /&gt;
 031258: fmtorpackcf&lt;br /&gt;
 031298: fmtorpackcfxy&lt;br /&gt;
 0312d8: fmtorpackcfxya&lt;br /&gt;
 02da0a: fmtorpackf&lt;br /&gt;
 02dad8: fmtorpackfxy&lt;br /&gt;
 02db01: fmtorpackfxya&lt;br /&gt;
 0316d4: fmtorrect&lt;br /&gt;
 031a12: fmtorrectc&lt;br /&gt;
 026ac9: fmtpalette&lt;br /&gt;
 026b60: fmtpaltocol&lt;br /&gt;
 02df77: fmtreadf&lt;br /&gt;
 02dfeb: fmtreadfxy&lt;br /&gt;
 02e011: fmtreadfxya&lt;br /&gt;
 0312f8: fmtscalecf&lt;br /&gt;
 031308: fmtscalecfxy&lt;br /&gt;
 031318: fmtscalecfxya&lt;br /&gt;
 031328: fmtscalef&lt;br /&gt;
 031338: fmtscalefxy&lt;br /&gt;
 031348: fmtscalefxya&lt;br /&gt;
 0313f8: fmtscalereccf&lt;br /&gt;
 031408: fmtscalereccfxy&lt;br /&gt;
 031418: fmtscalereccfxya&lt;br /&gt;
 0313c8: fmtscalerecf&lt;br /&gt;
 0313d8: fmtscalerecfxy&lt;br /&gt;
 0313e8: fmtscalerecfxya&lt;br /&gt;
 024ff4: fmtscreenmode&lt;br /&gt;
 031358: fmtsetcolortranslate&lt;br /&gt;
 031161: fmtsetscreen&lt;br /&gt;
 027ff4: fmtspeed&lt;br /&gt;
 02d5be: fmttmaskcf&lt;br /&gt;
 02d79c: fmttmaskcfxy&lt;br /&gt;
 02d7c5: fmttmaskcfxya&lt;br /&gt;
 02cbbf: fmttmaskf&lt;br /&gt;
 02cc44: fmttmaskfxy&lt;br /&gt;
 02cc6d: fmttmaskfxya&lt;br /&gt;
 031368: fmttmaskhpackcf&lt;br /&gt;
 031378: fmttmaskhpackcfxy&lt;br /&gt;
 031388: fmttmaskhpackcfxya&lt;br /&gt;
 02ddcc: fmttmaskhpackf&lt;br /&gt;
 02df2a: fmttmaskhpackfxy&lt;br /&gt;
 02df56: fmttmaskhpackfxya&lt;br /&gt;
 031398: fmttmaskpackcf&lt;br /&gt;
 0313a8: fmttmaskpackcfxy&lt;br /&gt;
 0313b8: fmttmaskpackcfxya&lt;br /&gt;
 02dc3a: fmttmaskpackf&lt;br /&gt;
 02dd82: fmttmaskpackfxy&lt;br /&gt;
 02ddab: fmttmaskpackfxya&lt;br /&gt;
 03e1c8: fmtwindotxt&lt;br /&gt;
 0247e4: fmtwindowdef&lt;br /&gt;
 02d36a: fmtxorcf&lt;br /&gt;
 02d574: fmtxorcfxy&lt;br /&gt;
 02d59d: fmtxorcfxya&lt;br /&gt;
 02cab8: fmtxorf&lt;br /&gt;
 02cb75: fmtxorfxy&lt;br /&gt;
 02cb9e: fmtxorfxya&lt;br /&gt;
 031268: fmtxorpackcf&lt;br /&gt;
 0312a8: fmtxorpackcfxy&lt;br /&gt;
 0312e8: fmtxorpackcfxya&lt;br /&gt;
 02db22: fmtxorpackf&lt;br /&gt;
 02dbf0: fmtxorpackfxy&lt;br /&gt;
 02dc19: fmtxorpackfxya&lt;br /&gt;
 0317d6: fmtxorrect&lt;br /&gt;
 031aaf: fmtxorrectc&lt;br /&gt;
 03b9c0: fne11&lt;br /&gt;
 03ba10: fne22&lt;br /&gt;
 03b924: fns11&lt;br /&gt;
 03b9d4: fnw11&lt;br /&gt;
 03ba24: fnw22&lt;br /&gt;
 024a04: fo&lt;br /&gt;
 04795e: fontheight&lt;br /&gt;
 039b14: fontwidest&lt;br /&gt;
 032838: fopen&lt;br /&gt;
 02813b: fortext&lt;br /&gt;
 028117: fortextxy&lt;br /&gt;
 034a30: fprintf&lt;br /&gt;
 03bc24: frbew11&lt;br /&gt;
 03bc10: frbns11&lt;br /&gt;
 03bbe8: frbsn11&lt;br /&gt;
 03bbfc: frbwe11&lt;br /&gt;
 0353b4: fread&lt;br /&gt;
 032fd8: free&lt;br /&gt;
 010b98: freealloppres&lt;br /&gt;
 004658: freeallscene&lt;br /&gt;
 010c58: freeallselopp&lt;br /&gt;
 03fe20: freebotidx&lt;br /&gt;
 025470: freememory&lt;br /&gt;
 025464: freepack&lt;br /&gt;
 03fe24: freetopidx&lt;br /&gt;
 025480: freetotop&lt;br /&gt;
 0267c0: frenchjoycal&lt;br /&gt;
 022cac: fromram&lt;br /&gt;
 01b65c: front_facing&lt;br /&gt;
 03bbd4: fruew11&lt;br /&gt;
 03bbac: fruns11&lt;br /&gt;
 03bb98: frusn11&lt;br /&gt;
 03bbc0: fruwe11&lt;br /&gt;
 0158a0: fsavereq&lt;br /&gt;
 0479de: fscrn&lt;br /&gt;
 03b998: fse11&lt;br /&gt;
 03b9e8: fse22&lt;br /&gt;
 0347f4: fseek&lt;br /&gt;
 04b2e0: fstyle&lt;br /&gt;
 03b9ac: fsw11&lt;br /&gt;
 03b9fc: fsw22&lt;br /&gt;
 0348d8: ftell&lt;br /&gt;
 047992: fts&lt;br /&gt;
 035730: fwrite&lt;br /&gt;
 0479d5: gabort&lt;br /&gt;
 005184: game&lt;br /&gt;
 005d78: gameint&lt;br /&gt;
 005d40: gameintinit&lt;br /&gt;
 048af8: gameobjects1&lt;br /&gt;
 048afc: gameobjects2&lt;br /&gt;
 03a5aa: gamepauseflag&lt;br /&gt;
 04584c: gameres&lt;br /&gt;
 011bc0: genhline&lt;br /&gt;
 0208c4: getanimcounter&lt;br /&gt;
 0310c0: getbiostick&lt;br /&gt;
 0347c0: getc&lt;br /&gt;
 0347d8: getchar&lt;br /&gt;
 022218: getcurrentpalette&lt;br /&gt;
 0229fc: getdrive&lt;br /&gt;
 022a74: getdriveacd&lt;br /&gt;
 022a9c: getdriveq&lt;br /&gt;
 027fef: getds&lt;br /&gt;
 034b2c: getenv&lt;br /&gt;
 0117cc: getmodelname&lt;br /&gt;
 023f60: getmousepos&lt;br /&gt;
 0256ec: getnum&lt;br /&gt;
 022078: getoppfilename&lt;br /&gt;
 01b610: getoutcode&lt;br /&gt;
 026a58: getpalette&lt;br /&gt;
 026a58: getpalettefar&lt;br /&gt;
 01c31c: getpinfo&lt;br /&gt;
 0133f4: getprotection&lt;br /&gt;
 0233d8: getpstring&lt;br /&gt;
 015e40: getres&lt;br /&gt;
 015e50: getresl&lt;br /&gt;
 00e0a8: getsimdata&lt;br /&gt;
 025cb4: getstring&lt;br /&gt;
 025cc4: getstringi&lt;br /&gt;
 02fa2c: gettick&lt;br /&gt;
 00d020: gettlistpoint&lt;br /&gt;
 01e0a0: getwpinfo&lt;br /&gt;
 03bb84: gew11&lt;br /&gt;
 03c0e4: ghyew11&lt;br /&gt;
 03c0bc: ghyns11&lt;br /&gt;
 03c0a8: ghysn11&lt;br /&gt;
 03c0d0: ghywe11&lt;br /&gt;
 03bb5c: gns11&lt;br /&gt;
 046990: go&lt;br /&gt;
 00b03c: gotosim&lt;br /&gt;
 045220: gpbmaps&lt;br /&gt;
 03e214: graphicmode&lt;br /&gt;
 039930: gravity&lt;br /&gt;
 0479d6: grip&lt;br /&gt;
 047980: ground&lt;br /&gt;
 0462f4: gs&lt;br /&gt;
 03bb48: gsn11&lt;br /&gt;
 03bb70: gwe11&lt;br /&gt;
 03947c: headingzones&lt;br /&gt;
 03ba4c: hew11&lt;br /&gt;
 0248f0: hiddenwindow&lt;br /&gt;
 023f14: hidemouse&lt;br /&gt;
 024ed8: hideprint&lt;br /&gt;
 047974: highestsceneryheight&lt;br /&gt;
 03fe30: highwater&lt;br /&gt;
 03e216: hirestext&lt;br /&gt;
 03bad0: hne22&lt;br /&gt;
 03ba38: hns11&lt;br /&gt;
 03bae4: hnw22&lt;br /&gt;
 025154: horizsync&lt;br /&gt;
 03bd8c: hpew11&lt;br /&gt;
 03bd78: hpns11&lt;br /&gt;
 03baa8: hse22&lt;br /&gt;
 03babc: hsw22&lt;br /&gt;
 025164: hsyncstate&lt;br /&gt;
 03ba84: huew11&lt;br /&gt;
 03ba60: huns11&lt;br /&gt;
 015dbc: hurrykey&lt;br /&gt;
 03c094: hyew11&lt;br /&gt;
 03c080: hyns11&lt;br /&gt;
 0392cc: hzoneEN&lt;br /&gt;
 039314: hzoneES&lt;br /&gt;
 039284: hzoneNE&lt;br /&gt;
 03923c: hzoneNW&lt;br /&gt;
 03935c: hzoneSE&lt;br /&gt;
 0393a4: hzoneSW&lt;br /&gt;
 039434: hzoneWN&lt;br /&gt;
 0393ec: hzoneWS&lt;br /&gt;
 02546c: ifmodule&lt;br /&gt;
 0456b8: inint&lt;br /&gt;
 01e62c: init_3dcars&lt;br /&gt;
 01e410: init_3dpieces&lt;br /&gt;
 00de48: init_explode&lt;br /&gt;
 047a74: initallcar&lt;br /&gt;
 00a9a4: initcar&lt;br /&gt;
 020d48: initcarmovesfx&lt;br /&gt;
 02f8f0: initctimer&lt;br /&gt;
 0007b0: initdrawworld&lt;br /&gt;
 02f8e0: initdtimer&lt;br /&gt;
 0200e8: initengine&lt;br /&gt;
 020044: initenginesfx&lt;br /&gt;
 024f98: initgraphics&lt;br /&gt;
 000078: initinterpretsubs&lt;br /&gt;
 025e68: initjoy&lt;br /&gt;
 025f44: initjoyl&lt;br /&gt;
 025f4c: initjoyr&lt;br /&gt;
 00d774: initlogo&lt;br /&gt;
 025224: initmemmax&lt;br /&gt;
 025204: initmemory&lt;br /&gt;
 025234: initmemsize&lt;br /&gt;
 0000f4: initmodes&lt;br /&gt;
 023e04: initmouse&lt;br /&gt;
 0073a4: initmousedrive&lt;br /&gt;
 01bb60: initnm&lt;br /&gt;
 024ee8: initprofile&lt;br /&gt;
 024ef8: initprofsect&lt;br /&gt;
 00468c: initscenery&lt;br /&gt;
 01352c: initselections&lt;br /&gt;
 00ab40: initsim&lt;br /&gt;
 030ac4: initsound&lt;br /&gt;
 025cf4: initstatekey&lt;br /&gt;
 02f948: initstimer&lt;br /&gt;
 024fa4: inittext&lt;br /&gt;
 02f8d0: inittimer&lt;br /&gt;
 005d10: initworld&lt;br /&gt;
 025e08: inkey&lt;br /&gt;
 02284c: installa&lt;br /&gt;
 02280c: installhigtrk&lt;br /&gt;
 0137b8: instringz&lt;br /&gt;
 0268f0: int3dhypot&lt;br /&gt;
 02ecae: intatan&lt;br /&gt;
 02ec98: intcos&lt;br /&gt;
 03b974: inte11&lt;br /&gt;
 026778: interpretclear&lt;br /&gt;
 0266b8: interpretkey&lt;br /&gt;
 026724: interpretsub&lt;br /&gt;
 02ed9a: inthypot&lt;br /&gt;
 0479e7: intraffic&lt;br /&gt;
 02ec10: intsin&lt;br /&gt;
 03e1d4: invalid&lt;br /&gt;
 0455b8: inwater&lt;br /&gt;
 03bd64: ipew11&lt;br /&gt;
 03bd50: ipns11&lt;br /&gt;
 033cd4: itoa&lt;br /&gt;
 02641c: joybuttons&lt;br /&gt;
 026640: joybuttonsb&lt;br /&gt;
 0267bc: joycal&lt;br /&gt;
 039b52: joycaled&lt;br /&gt;
 04003c: joycalib&lt;br /&gt;
 0267c4: joycall&lt;br /&gt;
 0267cc: joycallo&lt;br /&gt;
 0267d0: joycalo&lt;br /&gt;
 0267c8: joycalr&lt;br /&gt;
 0267d4: joycalro&lt;br /&gt;
 040040: joyclock&lt;br /&gt;
 026028: joycos&lt;br /&gt;
 0260ac: joycosb&lt;br /&gt;
 0260fc: joycosbi&lt;br /&gt;
 02605c: joycosi&lt;br /&gt;
 0400ae: joydown&lt;br /&gt;
 0400b2: joyleft&lt;br /&gt;
 0400b0: joyleftdown&lt;br /&gt;
 0400a4: joyleftup&lt;br /&gt;
 0267ac: joyoffl&lt;br /&gt;
 0267b4: joyoffr&lt;br /&gt;
 0267f0: joyon&lt;br /&gt;
 0400aa: joyright&lt;br /&gt;
 0400ac: joyrightdown&lt;br /&gt;
 0400a8: joyrightup&lt;br /&gt;
 026254: joystate&lt;br /&gt;
 026458: joystateb&lt;br /&gt;
 025e70: joystick&lt;br /&gt;
 025f54: joystickb&lt;br /&gt;
 0400a6: joyup&lt;br /&gt;
 025ed4: joyxpot&lt;br /&gt;
 025fb0: joyxpotl&lt;br /&gt;
 026020: joyxpotr&lt;br /&gt;
 025f0c: joyypot&lt;br /&gt;
 025fe8: joyypotl&lt;br /&gt;
 026024: joyypotr&lt;br /&gt;
 026150: kbdjoystate&lt;br /&gt;
 038a9c: kcdr_status&lt;br /&gt;
 026800: keybiosticks&lt;br /&gt;
 026810: keyon&lt;br /&gt;
 040038: keyprog&lt;br /&gt;
 025d24: keystate&lt;br /&gt;
 025df4: keysub&lt;br /&gt;
 03ff34: keysubs&lt;br /&gt;
 025e1c: keyticks&lt;br /&gt;
 025e3c: keywait&lt;br /&gt;
 026820: keywaitbios&lt;br /&gt;
 0479d1: lang&lt;br /&gt;
 0479e0: lastdash&lt;br /&gt;
 0479df: lastdrawmode&lt;br /&gt;
 0479e8: lastintraffic&lt;br /&gt;
 0479e9: lastrbox&lt;br /&gt;
 0479e4: lastreplay&lt;br /&gt;
 0479e6: lastrpause&lt;br /&gt;
 0479ec: lastscenery&lt;br /&gt;
 0400ca: lbotfire&lt;br /&gt;
 04797c: lclipby&lt;br /&gt;
 03dca8: ldmsg&lt;br /&gt;
 045850: ledfont&lt;br /&gt;
 01bb9c: lgabs&lt;br /&gt;
 051374: library&lt;br /&gt;
 020fb0: limity&lt;br /&gt;
 04222c: linefunct&lt;br /&gt;
 0400d6: ljoydown&lt;br /&gt;
 0400da: ljoyleft&lt;br /&gt;
 0400d8: ljoyleftdown&lt;br /&gt;
 0400cc: ljoyleftup&lt;br /&gt;
 0400d2: ljoyright&lt;br /&gt;
 0400d4: ljoyrightdown&lt;br /&gt;
 0400d0: ljoyrightup&lt;br /&gt;
 0400ce: ljoyup&lt;br /&gt;
 0220d4: loadalloppfile&lt;br /&gt;
 010b38: loadalloppres&lt;br /&gt;
 004618: loadallscene&lt;br /&gt;
 010be0: loadallselopp&lt;br /&gt;
 0242b0: loadandshapepack&lt;br /&gt;
 0242d0: loadandshapepacka&lt;br /&gt;
 0242c0: loadandshapepackz&lt;br /&gt;
 004844: loaddrawbits&lt;br /&gt;
 022d80: loaddrivefile&lt;br /&gt;
 022ce4: loaddrivefileatz&lt;br /&gt;
 022d34: loaddrivefilez&lt;br /&gt;
 024ad8: loadfile&lt;br /&gt;
 024af8: loadfilea&lt;br /&gt;
 0249dc: loadfileat&lt;br /&gt;
 024a50: loadfileata&lt;br /&gt;
 0249f0: loadfileatz&lt;br /&gt;
 024ae8: loadfilez&lt;br /&gt;
 0070f4: loadgamefiles&lt;br /&gt;
 0166dc: loading&lt;br /&gt;
 022090: loadoppfile&lt;br /&gt;
 024b44: loadpack&lt;br /&gt;
 024b64: loadpacka&lt;br /&gt;
 024ca8: loadpackat&lt;br /&gt;
 024cd0: loadpackata&lt;br /&gt;
 024cbc: loadpackatz&lt;br /&gt;
 024b54: loadpackz&lt;br /&gt;
 0003b8: loadpalandmouse&lt;br /&gt;
 022438: loadram&lt;br /&gt;
 00669c: loadreplay&lt;br /&gt;
 023fbc: loadshape&lt;br /&gt;
 023fdc: loadshapea&lt;br /&gt;
 023fcc: loadshapez&lt;br /&gt;
 00658c: loadtornamenttog&lt;br /&gt;
 047954: loady&lt;br /&gt;
 024080: locateshape&lt;br /&gt;
 0241bc: locateshapes&lt;br /&gt;
 0241f0: locateshapesz&lt;br /&gt;
 024124: locateshapez&lt;br /&gt;
 03fe18: lockbotidx&lt;br /&gt;
 0252c4: lockedmemory&lt;br /&gt;
 03fe1c: locktopidx&lt;br /&gt;
 03bfcc: loflen22&lt;br /&gt;
 03bf60: loflnw22&lt;br /&gt;
 03bfa8: loflse22&lt;br /&gt;
 03bf84: loflws22&lt;br /&gt;
 03c05c: lofres22&lt;br /&gt;
 03bff0: lofrne22&lt;br /&gt;
 03c038: lofrsw22&lt;br /&gt;
 03c014: lofrwn22&lt;br /&gt;
 004898: logo&lt;br /&gt;
 0455d4: logo1&lt;br /&gt;
 0455ec: logo2&lt;br /&gt;
 0455d0: logo_ticks&lt;br /&gt;
 04561c: logoclip&lt;br /&gt;
 047972: lowestsceneryheight&lt;br /&gt;
 03bd3c: lpew21&lt;br /&gt;
 03bd28: lpns21&lt;br /&gt;
 047968: lrndtime&lt;br /&gt;
 0400c8: ltopfire&lt;br /&gt;
 00e448: main&lt;br /&gt;
 005b50: mainkey&lt;br /&gt;
 039a24: mainres&lt;br /&gt;
 01e5f8: makecarname&lt;br /&gt;
 01b868: makematrix&lt;br /&gt;
 015824: makename&lt;br /&gt;
 019df0: makeobjdef&lt;br /&gt;
 016910: maketime&lt;br /&gt;
 01c0c4: makezonelist&lt;br /&gt;
 032ff4: malloc&lt;br /&gt;
 0456ae: maskdash&lt;br /&gt;
 0456b0: maskshapes&lt;br /&gt;
 051b88: matrix&lt;br /&gt;
 0418a6: maxx&lt;br /&gt;
 0418aa: maxy&lt;br /&gt;
 047b80: mboxfile&lt;br /&gt;
 047c0c: mboxzone&lt;br /&gt;
 0502e8: mbuttons&lt;br /&gt;
 042124: mcgacolorxlate&lt;br /&gt;
 0311a8: mcgatranslation&lt;br /&gt;
 0311cd: mcgatransrange&lt;br /&gt;
 045804: mch&lt;br /&gt;
 045806: mchit&lt;br /&gt;
 045808: mchithdg&lt;br /&gt;
 045800: mcp&lt;br /&gt;
 045802: mcr&lt;br /&gt;
 0457f4: mcx&lt;br /&gt;
 0457f8: mcy&lt;br /&gt;
 0457fc: mcz&lt;br /&gt;
 016e5c: mdosexit&lt;br /&gt;
 0171c8: memerr&lt;br /&gt;
 0256c4: memmovef&lt;br /&gt;
 0259ec: memsizedisplay&lt;br /&gt;
 045848: memwindow&lt;br /&gt;
 01bbac: mergezones&lt;br /&gt;
 013824: messagebox&lt;br /&gt;
 048ac0: mheading_matrix&lt;br /&gt;
 0418a4: minx&lt;br /&gt;
 0418a8: miny&lt;br /&gt;
 047a28: miscres&lt;br /&gt;
 045628: miscshapes&lt;br /&gt;
 04521c: miscshapes2&lt;br /&gt;
 016bd0: mjoycal&lt;br /&gt;
 016be0: mjoycalx&lt;br /&gt;
 016c3c: mkeyon&lt;br /&gt;
 000000: mloadmcgaz&lt;br /&gt;
 047b88: mm_but&lt;br /&gt;
 020b74: mm_drawbox&lt;br /&gt;
 020b14: mm_drawcursor&lt;br /&gt;
 020a58: mm_drawline&lt;br /&gt;
 020a80: mm_drawrect&lt;br /&gt;
 020aec: mm_drawrectc&lt;br /&gt;
 020bb0: mm_fortextxy&lt;br /&gt;
 020c30: mm_fshadowtext&lt;br /&gt;
 020bf0: mm_movtxy&lt;br /&gt;
 048ad4: mmatrix&lt;br /&gt;
 016ca0: mmouseon&lt;br /&gt;
 016d64: mmusictog&lt;br /&gt;
 016cfc: mnullfunc&lt;br /&gt;
 044ed8: mnumzones&lt;br /&gt;
 03e218: moddir&lt;br /&gt;
 021270: mode1off&lt;br /&gt;
 021218: mode1on&lt;br /&gt;
 03a268: modelname&lt;br /&gt;
 04f620: modematrix&lt;br /&gt;
 0005a0: modsize&lt;br /&gt;
 0254fc: modulesize&lt;br /&gt;
 023dc0: monocursor&lt;br /&gt;
 043ad4: mos_control_flg&lt;br /&gt;
 043ad0: mos_event_adr&lt;br /&gt;
 043ad8: moswork_adr&lt;br /&gt;
 043adc: moswork_seg&lt;br /&gt;
 039b22: mouseactive&lt;br /&gt;
 04795a: mouseb&lt;br /&gt;
 0164d8: mousecursor&lt;br /&gt;
 039b1c: mousedrive&lt;br /&gt;
 03e19c: mouseflag&lt;br /&gt;
 047944: mousemaskw&lt;br /&gt;
 0162b8: mouseoff&lt;br /&gt;
 016294: mouseon&lt;br /&gt;
 039b23: mouseonscreen&lt;br /&gt;
 039b21: mouseonstat&lt;br /&gt;
 047940: mouseshapew&lt;br /&gt;
 03e1a0: mouseshown&lt;br /&gt;
 0073e8: mousesteer&lt;br /&gt;
 04793c: mouseunderw&lt;br /&gt;
 047956: mousex&lt;br /&gt;
 047958: mousey&lt;br /&gt;
 028a4e: movcf&lt;br /&gt;
 028c53: movcfxy&lt;br /&gt;
 028c8b: movcfxya&lt;br /&gt;
 00dfac: move_explode&lt;br /&gt;
 00db94: move_on_plane&lt;br /&gt;
 008e30: movecar&lt;br /&gt;
 005f5c: moveeverything&lt;br /&gt;
 006308: movehelicopters&lt;br /&gt;
 00d924: movelogo&lt;br /&gt;
 00873c: moveopponent&lt;br /&gt;
 00b310: moveplayer&lt;br /&gt;
 00b100: movesim&lt;br /&gt;
 028372: movf&lt;br /&gt;
 025cd4: movftxy&lt;br /&gt;
 02843c: movfxy&lt;br /&gt;
 028474: movfxya&lt;br /&gt;
 0475c0: movp&lt;br /&gt;
 02a3e3: movpackcf&lt;br /&gt;
 02a63a: movpackcfxy&lt;br /&gt;
 02a672: movpackcfxya&lt;br /&gt;
 0298c2: movpackf&lt;br /&gt;
 029987: movpackfxy&lt;br /&gt;
 0299bf: movpackfxya&lt;br /&gt;
 02827a: movt&lt;br /&gt;
 028256: movtxy&lt;br /&gt;
 047c38: mpactive&lt;br /&gt;
 048aac: mpitch_matrix&lt;br /&gt;
 047c30: mpstat&lt;br /&gt;
 03a61c: mpush&lt;br /&gt;
 0171bc: mretryhandler&lt;br /&gt;
 048a98: mroll_matrix&lt;br /&gt;
 01703c: msetrender&lt;br /&gt;
 046940: msong&lt;br /&gt;
 016de0: msoundtog&lt;br /&gt;
 04562c: msteerx&lt;br /&gt;
 04566c: msteerxvalid&lt;br /&gt;
 016d00: msystempause&lt;br /&gt;
 039b1d: musicon&lt;br /&gt;
 026830: musictog&lt;br /&gt;
 04693c: mvoice&lt;br /&gt;
 0502e4: mx&lt;br /&gt;
 0502e6: my&lt;br /&gt;
 014f88: mycenter&lt;br /&gt;
 0168b8: myclearfont&lt;br /&gt;
 0456bc: myclipzone&lt;br /&gt;
 000074: myfinddone&lt;br /&gt;
 000010: myfindfirst&lt;br /&gt;
 00006c: myfindnext&lt;br /&gt;
 023839: mygetseeds&lt;br /&gt;
 016724: myitoa&lt;br /&gt;
 015ac0: mykey&lt;br /&gt;
 016658: mykeywait&lt;br /&gt;
 016a04: myload&lt;br /&gt;
 016ac4: myloadat&lt;br /&gt;
 01c22c: mymemcmp&lt;br /&gt;
 048b08: myobj&lt;br /&gt;
 023854: myrandom&lt;br /&gt;
 039b28: myseed&lt;br /&gt;
 016898: mysetfont&lt;br /&gt;
 02381e: mysetseeds&lt;br /&gt;
 00cb20: myupdatesfx&lt;br /&gt;
 00cfbc: myupdatesfx1&lt;br /&gt;
 00cf80: myupdatesfx2&lt;br /&gt;
 045054: mz&lt;br /&gt;
 0451bc: mzkey&lt;br /&gt;
 0159d4: namecopy&lt;br /&gt;
 022aec: namedrive&lt;br /&gt;
 03dcc8: ndmsg&lt;br /&gt;
 025320: negblockmove&lt;br /&gt;
 025dac: nextkey&lt;br /&gt;
 03dcd0: nlmsg&lt;br /&gt;
 0479fc: nmps&lt;br /&gt;
 03fe6c: noblkerr&lt;br /&gt;
 039b1e: nohandling&lt;br /&gt;
 03fe34: nomemerr&lt;br /&gt;
 03a554: noreadpacket&lt;br /&gt;
 01ba90: norm_zone&lt;br /&gt;
 025d64: normkey&lt;br /&gt;
 026090: normkeyi&lt;br /&gt;
 05197c: normkeysubs&lt;br /&gt;
 03e1c0: norowspc&lt;br /&gt;
 03e1d0: notpack&lt;br /&gt;
 04798c: npix&lt;br /&gt;
 03dcd4: nrmsg&lt;br /&gt;
 03dccc: nsmsg&lt;br /&gt;
 023da8: nullfunction&lt;br /&gt;
 023dac: nullprint&lt;br /&gt;
 03a8ac: nullzone&lt;br /&gt;
 038d4e: numcolors&lt;br /&gt;
 0267d8: numlockclear&lt;br /&gt;
 026840: numlockset&lt;br /&gt;
 04791c: numroadblocks&lt;br /&gt;
 047994: numtrkcameras&lt;br /&gt;
 047995: numtrksigns&lt;br /&gt;
 047a00: nzoneflag&lt;br /&gt;
 048b0c: objtype1&lt;br /&gt;
 049e94: objtype2&lt;br /&gt;
 03c1c0: objtypes&lt;br /&gt;
 03beac: oflen11&lt;br /&gt;
 03be40: oflnw11&lt;br /&gt;
 03be88: oflse11&lt;br /&gt;
 03be64: oflws11&lt;br /&gt;
 03bf3c: ofres11&lt;br /&gt;
 03bed0: ofrne11&lt;br /&gt;
 03bf18: ofrsw11&lt;br /&gt;
 03bef4: ofrwn11&lt;br /&gt;
 039a20: oldlist&lt;br /&gt;
 015dcc: openresource&lt;br /&gt;
 022110: oppanim&lt;br /&gt;
 04f65c: oppfile&lt;br /&gt;
 03dc88: oppfilename&lt;br /&gt;
 0479cc: oppinit&lt;br /&gt;
 039b30: oppname&lt;br /&gt;
 01fd50: opponentcompile&lt;br /&gt;
 04696c: opponentlist&lt;br /&gt;
 04692c: oppspeeds&lt;br /&gt;
 005f30: optimizejoystick&lt;br /&gt;
 005efc: optimizejoyxpot&lt;br /&gt;
 0114f8: options&lt;br /&gt;
 028f4a: orcf&lt;br /&gt;
 029171: orcfxy&lt;br /&gt;
 0291a9: orcfxya&lt;br /&gt;
 027215: orcline&lt;br /&gt;
 0285f3: orf&lt;br /&gt;
 0286da: orfxy&lt;br /&gt;
 028712: orfxya&lt;br /&gt;
 0276ed: orline&lt;br /&gt;
 02a968: orpackcf&lt;br /&gt;
 02abc6: orpackcfxy&lt;br /&gt;
 02abfe: orpackcfxya&lt;br /&gt;
 029b23: orpackf&lt;br /&gt;
 029bef: orpackfxy&lt;br /&gt;
 029c27: orpackfxya&lt;br /&gt;
 026d16: orpixel&lt;br /&gt;
 026c30: orpixelc&lt;br /&gt;
 027931: orrect&lt;br /&gt;
 027c29: orrectc&lt;br /&gt;
 02561c: packmemory&lt;br /&gt;
 041890: pagedwindow&lt;br /&gt;
 024900: pageflip&lt;br /&gt;
 03919c: palcol1&lt;br /&gt;
 0391a0: palcol2&lt;br /&gt;
 0391a8: paldither&lt;br /&gt;
 025174: palettecolor&lt;br /&gt;
 0391a4: palstat&lt;br /&gt;
 020a38: paltocol&lt;br /&gt;
 0479dc: passed&lt;br /&gt;
 051368: pauseflag&lt;br /&gt;
 030bf8: pausesound&lt;br /&gt;
 030c7c: pcmdone&lt;br /&gt;
 030c10: pcmstart&lt;br /&gt;
 030c6c: pcmstop&lt;br /&gt;
 00de0c: pdist&lt;br /&gt;
 047988: penalty&lt;br /&gt;
 04799b: penaltytime&lt;br /&gt;
 047993: pflip&lt;br /&gt;
 04f61c: pict&lt;br /&gt;
 04798a: pix&lt;br /&gt;
 0418b4: pixmaxx&lt;br /&gt;
 0418b2: pixminx&lt;br /&gt;
 00dd7c: plane_distance&lt;br /&gt;
 046924: planes&lt;br /&gt;
 016870: playsong&lt;br /&gt;
 041880: pm_ceoff&lt;br /&gt;
 041888: pm_cesel&lt;br /&gt;
 047922: pnum&lt;br /&gt;
 047924: pobjx&lt;br /&gt;
 047926: pobjy&lt;br /&gt;
 047928: pobjz&lt;br /&gt;
 039928: pointsizeinfo&lt;br /&gt;
 0436c8: polling_sub_int&lt;br /&gt;
 02fdb9: poly&lt;br /&gt;
 02fdbc: polycmn&lt;br /&gt;
 042226: polycolor2&lt;br /&gt;
 042228: polyfunct&lt;br /&gt;
 042224: polymask&lt;br /&gt;
 02fd8e: polyp&lt;br /&gt;
 01b518: polysort&lt;br /&gt;
 0252ac: poolmemory&lt;br /&gt;
 0252f4: posblockmove&lt;br /&gt;
 027dc4: print&lt;br /&gt;
 027f54: printattribute&lt;br /&gt;
 027f73: printbyte&lt;br /&gt;
 027f92: printbytexy&lt;br /&gt;
 027fb1: printchar&lt;br /&gt;
 027fd0: printcharxy&lt;br /&gt;
 027d81: printclear&lt;br /&gt;
 024eb8: printdivby0&lt;br /&gt;
 034a0c: printf&lt;br /&gt;
 027f35: printscroll&lt;br /&gt;
 023150: printsjis&lt;br /&gt;
 027f16: printxy&lt;br /&gt;
 024f08: profileoff&lt;br /&gt;
 024f18: profileon&lt;br /&gt;
 024f28: profsectoff&lt;br /&gt;
 024f38: profsecton&lt;br /&gt;
 02f53d: projectc&lt;br /&gt;
 02f162: projectorgp&lt;br /&gt;
 02f30a: projectp&lt;br /&gt;
 016b98: pullmouse&lt;br /&gt;
 0220f8: purgealloppfile&lt;br /&gt;
 025e14: purgekey&lt;br /&gt;
 025490: purgememory&lt;br /&gt;
 0220bc: purgeoppfile&lt;br /&gt;
 030a90: purgesound&lt;br /&gt;
 016b70: pushmouse&lt;br /&gt;
 0238db: putsjis&lt;br /&gt;
 025214: quitmemory&lt;br /&gt;
 023e8c: quitmouse&lt;br /&gt;
 03a556: r_bgcolor&lt;br /&gt;
 047a6e: raceresult&lt;br /&gt;
 032220: rand&lt;br /&gt;
 030758: random&lt;br /&gt;
 02fc54: randompoly&lt;br /&gt;
 02fc64: randompolyf&lt;br /&gt;
 02fc74: randompolyi&lt;br /&gt;
 02fc84: randompolyip&lt;br /&gt;
 02fc94: randompolyipt&lt;br /&gt;
 02fca4: randompolyit&lt;br /&gt;
 02fcb4: randompolyp&lt;br /&gt;
 02fcc4: randompolypt&lt;br /&gt;
 02fcd4: randompolyt&lt;br /&gt;
 0400b6: rbotfire&lt;br /&gt;
 02c6c3: readf&lt;br /&gt;
 02c743: readfxy&lt;br /&gt;
 02c77b: readfxya&lt;br /&gt;
 025184: readhiddenscreen&lt;br /&gt;
 01181c: readhighs&lt;br /&gt;
 023de0: readmonoatt&lt;br /&gt;
 023dd0: readmonochar&lt;br /&gt;
 023eb8: readmouse&lt;br /&gt;
 026d78: readpixel&lt;br /&gt;
 025194: readscreen&lt;br /&gt;
 0251a4: redshift&lt;br /&gt;
 01eae4: remove_3dcars&lt;br /&gt;
 01e5c4: remove_3dpieces&lt;br /&gt;
 004888: removedrawbits&lt;br /&gt;
 007338: removegamefiles&lt;br /&gt;
 005d60: removegameint&lt;br /&gt;
 004818: removescenery&lt;br /&gt;
 0246f8: removewindow&lt;br /&gt;
 048280: render_matrix&lt;br /&gt;
 039b24: renderlevel&lt;br /&gt;
 047bcc: replay_flag&lt;br /&gt;
 0475dc: replaybuff&lt;br /&gt;
 045624: replaybuflen&lt;br /&gt;
 0475e0: replayso&lt;br /&gt;
 025350: reservememory&lt;br /&gt;
 020e1c: resetalltextbuf&lt;br /&gt;
 030de0: resetcriterr&lt;br /&gt;
 024e94: resetdivby0&lt;br /&gt;
 024f48: resetprofile&lt;br /&gt;
 024f58: resetprofsect&lt;br /&gt;
 025d1c: resetstatekey&lt;br /&gt;
 020df4: resettextbuf&lt;br /&gt;
 02fa54: resettick&lt;br /&gt;
 025544: resizememory&lt;br /&gt;
 000574: resmem&lt;br /&gt;
 01498c: restoreboxwindow&lt;br /&gt;
 025b78: restorefont&lt;br /&gt;
 020cd0: restorefont4&lt;br /&gt;
 02224c: restorepalette&lt;br /&gt;
 020f44: restoretext&lt;br /&gt;
 0210c8: restoretextbox&lt;br /&gt;
 020f00: restoretextgraphic&lt;br /&gt;
 021020: restoretextwindow&lt;br /&gt;
 02f9a0: restoretimer&lt;br /&gt;
 0247c8: restorewindow&lt;br /&gt;
 030c04: resumesound&lt;br /&gt;
 034944: rewind&lt;br /&gt;
 031450: ring&lt;br /&gt;
 0400c2: rjoydown&lt;br /&gt;
 0400c6: rjoyleft&lt;br /&gt;
 0400c4: rjoyleftdown&lt;br /&gt;
 0400b8: rjoyleftup&lt;br /&gt;
 0400be: rjoyright&lt;br /&gt;
 0400c0: rjoyrightdown&lt;br /&gt;
 0400bc: rjoyrightup&lt;br /&gt;
 0400ba: rjoyup&lt;br /&gt;
 04187c: rm_cevec&lt;br /&gt;
 04691c: rndseed&lt;br /&gt;
 04791a: rndtime&lt;br /&gt;
 046950: roadlistc&lt;br /&gt;
 046954: roadlistld&lt;br /&gt;
 046964: roadlistp1&lt;br /&gt;
 046968: roadlistp2&lt;br /&gt;
 046958: roadlistx&lt;br /&gt;
 04695c: roadlistz&lt;br /&gt;
 01ff48: roadupcheck&lt;br /&gt;
 0418a0: rowtbl&lt;br /&gt;
 0479d3: rpause&lt;br /&gt;
 0479f8: rpfxrate&lt;br /&gt;
 0479da: rspeed&lt;br /&gt;
 0400b4: rtopfire&lt;br /&gt;
 047620: rtzline&lt;br /&gt;
 03bb0c: ruew11&lt;br /&gt;
 03baf8: runs11&lt;br /&gt;
 03bb20: rusn11&lt;br /&gt;
 03bb34: ruwe11&lt;br /&gt;
 0300b1: s1linex&lt;br /&gt;
 02ffef: s1linexc&lt;br /&gt;
 03020b: s2linex&lt;br /&gt;
 022358: sameext&lt;br /&gt;
 039680: samplefile&lt;br /&gt;
 014898: saveboxwindow&lt;br /&gt;
 020f2c: savecurrenttextwindow&lt;br /&gt;
 022c08: savedrivefile&lt;br /&gt;
 022b78: savedrivefilez&lt;br /&gt;
 02f76c: savefile&lt;br /&gt;
 02f780: savefilez&lt;br /&gt;
 022680: savefloppy&lt;br /&gt;
 025b68: savefont&lt;br /&gt;
 020c9c: savefont4&lt;br /&gt;
 011ee8: savehighs&lt;br /&gt;
 017264: saveobject&lt;br /&gt;
 022234: savepalette&lt;br /&gt;
 024f68: saveprofile&lt;br /&gt;
 024f78: saveprofsect&lt;br /&gt;
 0223e0: saveram&lt;br /&gt;
 0228f4: saveramfiles&lt;br /&gt;
 0066fc: savereplay&lt;br /&gt;
 020ee8: savetextgraphic&lt;br /&gt;
 020ebc: savetextwindow&lt;br /&gt;
 020f08: savetextzone&lt;br /&gt;
 0247ac: savewindow&lt;br /&gt;
 02bf3f: scalecf&lt;br /&gt;
 02c0c8: scalecfxy&lt;br /&gt;
 02c0fd: scalecfxya&lt;br /&gt;
 02bdba: scalef&lt;br /&gt;
 02bee9: scalefxy&lt;br /&gt;
 02bf1e: scalefxya&lt;br /&gt;
 02c358: scalereccf&lt;br /&gt;
 02c646: scalereccfxy&lt;br /&gt;
 02c6a2: scalereccfxya&lt;br /&gt;
 02c11e: scalerecf&lt;br /&gt;
 02c2db: scalerecfxy&lt;br /&gt;
 02c337: scalerecfxya&lt;br /&gt;
 030cae: scalethicknessxp&lt;br /&gt;
 030cca: scalethicknessyp&lt;br /&gt;
 026850: scancode&lt;br /&gt;
 0479c4: scarname&lt;br /&gt;
 0455bc: scenefile&lt;br /&gt;
 039582: sceneloaded&lt;br /&gt;
 045598: scenery&lt;br /&gt;
 0455a8: sceneryh&lt;br /&gt;
 039b20: sceneryloaded&lt;br /&gt;
 045594: sceneshapes&lt;br /&gt;
 0418ac: scrbyts&lt;br /&gt;
 0251c4: screenorigin&lt;br /&gt;
 0251b4: screensnap&lt;br /&gt;
 0418b6: screenwindow&lt;br /&gt;
 051318: screenwindowsec&lt;br /&gt;
 05133c: screenwindowvga&lt;br /&gt;
 016694: screenwipe&lt;br /&gt;
 041894: scrfrm&lt;br /&gt;
 047914: scriptindex&lt;br /&gt;
 047916: scriptindexend&lt;br /&gt;
 0479dd: scrn&lt;br /&gt;
 047b84: scrnfile&lt;br /&gt;
 039a1c: scrnlist&lt;br /&gt;
 0251d4: scrolldown&lt;br /&gt;
 0251e4: scrollup&lt;br /&gt;
 041898: scrseg&lt;br /&gt;
 0418b0: scrxpixels&lt;br /&gt;
 051376: sectionnumber&lt;br /&gt;
 04184c: seed&lt;br /&gt;
 000348: seedrandom&lt;br /&gt;
 023d20: segtoadr&lt;br /&gt;
 00f588: select&lt;br /&gt;
 00fdac: selectcar&lt;br /&gt;
 010c94: selectopponent&lt;br /&gt;
 020de8: selecttextbuf&lt;br /&gt;
 047a40: selofile&lt;br /&gt;
 047a44: seloshapes&lt;br /&gt;
 0310d8: setbiosticks&lt;br /&gt;
 021174: setblackpal&lt;br /&gt;
 022264: setblacktext&lt;br /&gt;
 024e90: setdivby0&lt;br /&gt;
 025b88: setfont&lt;br /&gt;
 026860: setjoykeys&lt;br /&gt;
 026870: setjoykeysl&lt;br /&gt;
 026880: setjoykeysr&lt;br /&gt;
 023e94: setmousebounds&lt;br /&gt;
 023f38: setmousepos&lt;br /&gt;
 023e00: setmouseratio&lt;br /&gt;
 023f94: setmousex&lt;br /&gt;
 023fa8: setmousey&lt;br /&gt;
 030a8c: setmusicabort&lt;br /&gt;
 02f47a: setprojectc&lt;br /&gt;
 02f1c3: setprojectp&lt;br /&gt;
 02f1a1: setprojectpb&lt;br /&gt;
 02fce4: setrandompix&lt;br /&gt;
 02fa60: setticks&lt;br /&gt;
 01eb78: settires&lt;br /&gt;
 0267dc: settypeahead&lt;br /&gt;
 02f751: setzclip&lt;br /&gt;
 039920: sfpostsizeinfo&lt;br /&gt;
 047a08: sfxfile&lt;br /&gt;
 030b18: sfxoff&lt;br /&gt;
 030b38: sfxon&lt;br /&gt;
 0479ed: sfxstat&lt;br /&gt;
 0479ee: sfxstat1&lt;br /&gt;
 0479ef: sfxstat2&lt;br /&gt;
 030b58: sfxtoggle&lt;br /&gt;
 0237fd: sgn&lt;br /&gt;
 0165d8: shadowtext&lt;br /&gt;
 024224: shapecount&lt;br /&gt;
 024284: shapename&lt;br /&gt;
 024334: shapepack&lt;br /&gt;
 024230: shapepointer&lt;br /&gt;
 023be0: shellsort&lt;br /&gt;
 0251f4: shiftscreen&lt;br /&gt;
 023ef0: showmouse&lt;br /&gt;
 024f88: showprint&lt;br /&gt;
 03e1b8: shperrmsg&lt;br /&gt;
 039918: signsizeinfo&lt;br /&gt;
 00438c: sink&lt;br /&gt;
 03de40: sjistable&lt;br /&gt;
 043acc: skb_event_adr&lt;br /&gt;
 04797e: sky&lt;br /&gt;
 02e042: slopeline&lt;br /&gt;
 045854: smallfont&lt;br /&gt;
 0479db: smdelay&lt;br /&gt;
 03e1bc: snderrmsg&lt;br /&gt;
 045858: so&lt;br /&gt;
 0479d7: solid&lt;br /&gt;
 031428: solidellipseh&lt;br /&gt;
 030ec0: solidtire&lt;br /&gt;
 047a0c: songfile&lt;br /&gt;
 030b7c: songoff&lt;br /&gt;
 030ba4: songon&lt;br /&gt;
 030be8: songover&lt;br /&gt;
 030bcc: songtoggle&lt;br /&gt;
 01c19c: sortzonelist&lt;br /&gt;
 033d74: sound_bios&lt;br /&gt;
 033d98: sound_bios2&lt;br /&gt;
 026890: soundoff&lt;br /&gt;
 0268a0: soundon&lt;br /&gt;
 0268b0: soundtog&lt;br /&gt;
 047984: speedocol&lt;br /&gt;
 03bddc: spew11&lt;br /&gt;
 03bdb4: spns11&lt;br /&gt;
 034abc: sprintf&lt;br /&gt;
 03bda0: spsn11&lt;br /&gt;
 03bdc8: spwe11&lt;br /&gt;
 032248: srand&lt;br /&gt;
 02fa24: sseqds&lt;br /&gt;
 0479d9: staging&lt;br /&gt;
 0268c0: standardkeys&lt;br /&gt;
 04016e: standfont&lt;br /&gt;
 04791e: startblockhdg&lt;br /&gt;
 047996: startblockx&lt;br /&gt;
 047998: startblocky&lt;br /&gt;
 047997: startblockz&lt;br /&gt;
 020d04: startcarsfx&lt;br /&gt;
 0205a4: startengine&lt;br /&gt;
 0207cc: startskid&lt;br /&gt;
 020828: startskid2&lt;br /&gt;
 040060: statekey&lt;br /&gt;
 040080: statekeyb&lt;br /&gt;
 0456c8: status&lt;br /&gt;
 0479f4: steerval&lt;br /&gt;
 0205b4: stopengine&lt;br /&gt;
 020884: stopskid&lt;br /&gt;
 032318: strcat&lt;br /&gt;
 0323dc: strchr&lt;br /&gt;
 032254: strcpy&lt;br /&gt;
 015e80: strcpyfar&lt;br /&gt;
 033cdc: stricmp&lt;br /&gt;
 032380: strncmp&lt;br /&gt;
 032298: strncpy&lt;br /&gt;
 038248: strnicmp&lt;br /&gt;
 038250: strrev&lt;br /&gt;
 023df0: structshellsortup&lt;br /&gt;
 0400dc: suppressprint&lt;br /&gt;
 03dca4: svmsg&lt;br /&gt;
 047bd0: sw&lt;br /&gt;
 041874: swSFX&lt;br /&gt;
 041878: swSong&lt;br /&gt;
 039b26: swindowindex&lt;br /&gt;
 0211d8: switch_palette&lt;br /&gt;
 047bf0: swmemerror&lt;br /&gt;
 03dcc0: swmsg&lt;br /&gt;
 047bf4: swwindow&lt;br /&gt;
 0479f0: swwindowtbl&lt;br /&gt;
 019e90: symTransf&lt;br /&gt;
 0268d0: systempause&lt;br /&gt;
 044f54: sz&lt;br /&gt;
 044fcc: szalt&lt;br /&gt;
 045218: szheading&lt;br /&gt;
 047986: tcamlen&lt;br /&gt;
 04580a: tclipy&lt;br /&gt;
 0452d0: td&lt;br /&gt;
 0452d4: tdraw&lt;br /&gt;
 045294: tdrawindex&lt;br /&gt;
 045234: tdrawnum&lt;br /&gt;
 045238: tdrawobj&lt;br /&gt;
 045258: tdrawsvalue&lt;br /&gt;
 00f790: teditmain&lt;br /&gt;
 047bb0: tempshape&lt;br /&gt;
 0458f0: tempstring&lt;br /&gt;
 039b10: terheight&lt;br /&gt;
 04694c: terrain&lt;br /&gt;
 031114: testbiosticks&lt;br /&gt;
 025d5c: testkey&lt;br /&gt;
 02fa84: testticks&lt;br /&gt;
 04b2ec: textbuf&lt;br /&gt;
 040168: textchr&lt;br /&gt;
 028222: textchrxy&lt;br /&gt;
 025b34: textcolor&lt;br /&gt;
 03d7e4: textend&lt;br /&gt;
 025b94: textnpixels&lt;br /&gt;
 025c10: textpixels&lt;br /&gt;
 025b4c: textposition&lt;br /&gt;
 03d7e0: textwindowoff&lt;br /&gt;
 04b2e4: textzone&lt;br /&gt;
 03b960: tfew11&lt;br /&gt;
 03b94c: tfns11&lt;br /&gt;
 04774c: tfzs&lt;br /&gt;
 047788: tfzsh&lt;br /&gt;
 030c94: thickness&lt;br /&gt;
 030ce6: thicknessxp&lt;br /&gt;
 030d06: thicknessyp&lt;br /&gt;
 02fa34: tickcount&lt;br /&gt;
 055b9c: ticks&lt;br /&gt;
 055ba0: tickset&lt;br /&gt;
 055ba4: tickval&lt;br /&gt;
 0268e0: timedmessage&lt;br /&gt;
 02faa0: timedwait&lt;br /&gt;
 0436bc: timer_a_int&lt;br /&gt;
 0436c0: timer_b_int&lt;br /&gt;
 0436c4: timer_sub_int&lt;br /&gt;
 02f844: timerint&lt;br /&gt;
 02f888: timerintb&lt;br /&gt;
 030e68: tire&lt;br /&gt;
 047a70: titlefile&lt;br /&gt;
 047a24: titleptr&lt;br /&gt;
 00f3f0: titles&lt;br /&gt;
 029468: tmaskcf&lt;br /&gt;
 02963c: tmaskcfxy&lt;br /&gt;
 029674: tmaskcfxya&lt;br /&gt;
 028891: tmaskf&lt;br /&gt;
 02891b: tmaskfxy&lt;br /&gt;
 028953: tmaskfxya&lt;br /&gt;
 02b641: tmaskhpackcf&lt;br /&gt;
 02b99c: tmaskhpackcfxy&lt;br /&gt;
 02b9d7: tmaskhpackcfxya&lt;br /&gt;
 02a0a6: tmaskhpackf&lt;br /&gt;
 02a1e6: tmaskhpackfxy&lt;br /&gt;
 02a221: tmaskhpackfxya&lt;br /&gt;
 02aef4: tmaskpackcf&lt;br /&gt;
 02b23a: tmaskpackcfxy&lt;br /&gt;
 02b272: tmaskpackcfxya&lt;br /&gt;
 029d8b: tmaskpackf&lt;br /&gt;
 029ebd: tmaskpackfxy&lt;br /&gt;
 029ef5: tmaskpackfxya&lt;br /&gt;
 0296a4: tmaskxcf&lt;br /&gt;
 029878: tmaskxcfxy&lt;br /&gt;
 0298a1: tmaskxcfxya&lt;br /&gt;
 028983: tmaskxf&lt;br /&gt;
 028a04: tmaskxfxy&lt;br /&gt;
 028a2d: tmaskxfxya&lt;br /&gt;
 02ba07: tmaskxhpackcf&lt;br /&gt;
 02bd6d: tmaskxhpackcfxy&lt;br /&gt;
 02bd99: tmaskxhpackcfxya&lt;br /&gt;
 02a251: tmaskxhpackf&lt;br /&gt;
 02a396: tmaskxhpackfxy&lt;br /&gt;
 02a3c2: tmaskxhpackfxya&lt;br /&gt;
 02b2a2: tmaskxpackcf&lt;br /&gt;
 02b5f7: tmaskxpackcfxy&lt;br /&gt;
 02b620: tmaskxpackcfxya&lt;br /&gt;
 029f25: tmaskxpackf&lt;br /&gt;
 02a05c: tmaskxpackfxy&lt;br /&gt;
 02a085: tmaskxpackfxya&lt;br /&gt;
 03fe28: tmem&lt;br /&gt;
 055ba8: tmrsub&lt;br /&gt;
 022ac4: togdrive&lt;br /&gt;
 022b48: toobig&lt;br /&gt;
 0400a0: topfire&lt;br /&gt;
 039b40: tornamentflag&lt;br /&gt;
 00e198: tornamentload&lt;br /&gt;
 039b42: tornamentmode&lt;br /&gt;
 021f3c: tornamentmodecheck&lt;br /&gt;
 00e1b0: tornamenttog&lt;br /&gt;
 039690: tournamentcontinue&lt;br /&gt;
 03dcc4: tqmsg&lt;br /&gt;
 022008: trackdataupdate&lt;br /&gt;
 017390: trackedit&lt;br /&gt;
 046944: trackmatrix&lt;br /&gt;
 047a6c: tracknum&lt;br /&gt;
 019c20: trackoverlapcheck&lt;br /&gt;
 02ee48: transform&lt;br /&gt;
 02eff8: transmult&lt;br /&gt;
 03468b: transparentpf&lt;br /&gt;
 02fcf4: transparentpoly&lt;br /&gt;
 034678: transparentpolyf&lt;br /&gt;
 02fd04: transparentpolyi&lt;br /&gt;
 02fd14: transparentpolyip&lt;br /&gt;
 02fd24: transparentpolyipt&lt;br /&gt;
 02fd34: transparentpolyit&lt;br /&gt;
 03473b: transparentpolyp&lt;br /&gt;
 034720: transparentpolypt&lt;br /&gt;
 02fd44: transparentpolyt&lt;br /&gt;
 02f0d2: transpose&lt;br /&gt;
 046988: trkcamera&lt;br /&gt;
 04697c: trkcamerag&lt;br /&gt;
 046978: trkcamerah&lt;br /&gt;
 04698c: trksign&lt;br /&gt;
 046984: trksignh&lt;br /&gt;
 046980: trksignt&lt;br /&gt;
 047966: truckdoor&lt;br /&gt;
 0476d4: txs&lt;br /&gt;
 047710: txsh&lt;br /&gt;
 0475e4: tzline&lt;br /&gt;
 04765c: tzs&lt;br /&gt;
 047698: tzsh&lt;br /&gt;
 02459c: unflip&lt;br /&gt;
 024e24: unhuff&lt;br /&gt;
 0252dc: unlockedmemory&lt;br /&gt;
 024d60: unpacksize&lt;br /&gt;
 024d80: unpacksizea&lt;br /&gt;
 024d70: unpacksizez&lt;br /&gt;
 024df4: unrunpack&lt;br /&gt;
 0204d8: updateengine&lt;br /&gt;
 016440: updatemouseunder&lt;br /&gt;
 0165b0: usebuffer&lt;br /&gt;
 0165c0: usebufferc&lt;br /&gt;
 0479e1: usedash&lt;br /&gt;
 0479e3: usereplay&lt;br /&gt;
 016598: usescreen&lt;br /&gt;
 0165a0: usescreenc&lt;br /&gt;
 0233b4: validchar&lt;br /&gt;
 024ec8: validdrive&lt;br /&gt;
 03b8c0: vcew21&lt;br /&gt;
 03b8ac: vcns21&lt;br /&gt;
 0245ac: vertflip&lt;br /&gt;
 026aa1: vertsync&lt;br /&gt;
 026ab0: vertsyncend&lt;br /&gt;
 026aa1: vertsyncstart&lt;br /&gt;
 0349b0: vfprintf&lt;br /&gt;
 0269f8: vgapalette&lt;br /&gt;
 0269f8: vgapalettefar&lt;br /&gt;
 051370: videopage&lt;br /&gt;
 05136c: videowindow&lt;br /&gt;
 024910: videowindowdef&lt;br /&gt;
 047970: viewheading&lt;br /&gt;
 047a04: voicefile&lt;br /&gt;
 0349ec: vprintf&lt;br /&gt;
 034a88: vsprintf&lt;br /&gt;
 026abf: vsyncstate&lt;br /&gt;
 03113b: waitbios&lt;br /&gt;
 0310f6: waitbiosticks&lt;br /&gt;
 01657c: waitforkey&lt;br /&gt;
 02fa74: waitticks&lt;br /&gt;
 04792a: wall&lt;br /&gt;
 0479d8: wall2sided&lt;br /&gt;
 047930: wallh&lt;br /&gt;
 047934: wallhgtb&lt;br /&gt;
 047932: wallhgtt&lt;br /&gt;
 046928: walls&lt;br /&gt;
 04792c: wallx&lt;br /&gt;
 04792e: wallz&lt;br /&gt;
 0456ac: watch&lt;br /&gt;
 047982: water&lt;br /&gt;
 0455ba: watercar&lt;br /&gt;
 024920: whichpage&lt;br /&gt;
 024930: whichwindow&lt;br /&gt;
 00e37c: wincheck&lt;br /&gt;
 046970: winddrag1&lt;br /&gt;
 046974: winddrag2&lt;br /&gt;
 03e1c4: windotxt&lt;br /&gt;
 024714: window&lt;br /&gt;
 04796c: windowbottom&lt;br /&gt;
 0245f0: windowdef&lt;br /&gt;
 051372: windowpage&lt;br /&gt;
 04796a: windowtop&lt;br /&gt;
 025af8: wordfill&lt;br /&gt;
 025b20: wordfillf&lt;br /&gt;
 026cb4: writepixel&lt;br /&gt;
 026ba2: writepixelc&lt;br /&gt;
 0413fd: xbangle&lt;br /&gt;
 03b910: xfew11&lt;br /&gt;
 03b8fc: xfns11&lt;br /&gt;
 026910: xformx&lt;br /&gt;
 02695c: xformy&lt;br /&gt;
 0269ac: xformz&lt;br /&gt;
 03b8d4: xfsn11&lt;br /&gt;
 03b8e8: xfwe11&lt;br /&gt;
 047950: xmousemaskw&lt;br /&gt;
 04794c: xmouseshapew&lt;br /&gt;
 047948: xmouseunderw&lt;br /&gt;
 02fabc: xorbox&lt;br /&gt;
 0291d9: xorcf&lt;br /&gt;
 029400: xorcfxy&lt;br /&gt;
 029438: xorcfxya&lt;br /&gt;
 027430: xorcline&lt;br /&gt;
 025ce4: xorcursor&lt;br /&gt;
 028742: xorf&lt;br /&gt;
 028829: xorfxy&lt;br /&gt;
 028861: xorfxya&lt;br /&gt;
 02773e: xorline&lt;br /&gt;
 02ac2e: xorpackcf&lt;br /&gt;
 02ae8c: xorpackcfxy&lt;br /&gt;
 02aec4: xorpackcfxya&lt;br /&gt;
 029c57: xorpackf&lt;br /&gt;
 029d23: xorpackfxy&lt;br /&gt;
 029d5b: xorpackfxya&lt;br /&gt;
 026d47: xorpixel&lt;br /&gt;
 026c6a: xorpixelc&lt;br /&gt;
 027a01: xorrect&lt;br /&gt;
 027cd5: xorrectc&lt;br /&gt;
 041405: xproject&lt;br /&gt;
 0413f9: xscale&lt;br /&gt;
 024940: xscroll&lt;br /&gt;
 024950: xscrollwindow&lt;br /&gt;
 03e19e: xshiftflag&lt;br /&gt;
 0413ff: ybangle&lt;br /&gt;
 041607: yproject&lt;br /&gt;
 0413fb: yscale&lt;br /&gt;
 02f6cb: zclip&lt;br /&gt;
 02f6df: zclipline&lt;br /&gt;
 047918: zerotime&lt;br /&gt;
 047c04: zone4&lt;br /&gt;
 01c04c: zoneadjacent&lt;br /&gt;
 01ba44: zonecheck&lt;br /&gt;
 01c014: zoneinside&lt;br /&gt;
 01bfdc: zoneoverlap&lt;br /&gt;
 045044: zv&lt;br /&gt;
&lt;br /&gt;
| style=&amp;quot;vertical-align:top; width:50%;&amp;quot; |&lt;br /&gt;
 01a318: ADD_OBJECT_TO_BUFFER&lt;br /&gt;
 03f938: ALLOW_MODE_CHANGE&lt;br /&gt;
 03d1c4: BARR_LIST&lt;br /&gt;
 03cd78: BLTR_LIST&lt;br /&gt;
 03a6a8: BOTButcol&lt;br /&gt;
 03ccf4: BSTR_LIST&lt;br /&gt;
 03a660: Blue&lt;br /&gt;
 03a66a: Brown&lt;br /&gt;
 03a6b2: CBlue&lt;br /&gt;
 03c948: CHI1_LIST&lt;br /&gt;
 03ca1c: CHI2_LIST&lt;br /&gt;
 03a6b4: CRed&lt;br /&gt;
 017130: ConfirmMessage&lt;br /&gt;
 03a696: CredArtCol&lt;br /&gt;
 03a698: CredArtCols&lt;br /&gt;
 03a68a: CredCreCol&lt;br /&gt;
 03a68c: CredCreCols&lt;br /&gt;
 03a68e: CredDesCol&lt;br /&gt;
 03a690: CredDesCols&lt;br /&gt;
 03a69a: CredMusCol&lt;br /&gt;
 03a69c: CredMusCols&lt;br /&gt;
 03a692: CredProCol&lt;br /&gt;
 03a694: CredProCols&lt;br /&gt;
 03a686: CredTxtCol&lt;br /&gt;
 03a688: CredTxtCols&lt;br /&gt;
 03a680: Cursorcol1&lt;br /&gt;
 03a682: Cursorcol2&lt;br /&gt;
 03a664: Cyan&lt;br /&gt;
 01b828: DRAW_OBJECTS&lt;br /&gt;
 03f668: DSK_filename&lt;br /&gt;
 03a66e: Darkgrey&lt;br /&gt;
 017180: DriveAorB&lt;br /&gt;
 0230e0: DriveRetry&lt;br /&gt;
 0476f8: Dso&lt;br /&gt;
 0487cc: Dtrackmatrix&lt;br /&gt;
 03a6b6: EBoxcol&lt;br /&gt;
 053b00: EGBWork&lt;br /&gt;
 039cf8: EGB_displayPage&lt;br /&gt;
 039c94: EGB_displayStart&lt;br /&gt;
 039c34: EGB_init&lt;br /&gt;
 039c64: EGB_resolution&lt;br /&gt;
 039ccc: EGB_writePage&lt;br /&gt;
 03f942: ErrorCS&lt;br /&gt;
 03f944: ErrorIP&lt;br /&gt;
 03a684: Evalcol2&lt;br /&gt;
 03cd20: FLBSTR_LIST&lt;br /&gt;
 03c748: FLTRR_LIST&lt;br /&gt;
 03c674: FLTR_LIST&lt;br /&gt;
 0227d8: FMTFREEMEMORY&lt;br /&gt;
 022800: FMTPURGEMEMORY&lt;br /&gt;
 04a134: FMT_cheading&lt;br /&gt;
 03c168: FMT_index&lt;br /&gt;
 04a128: FMT_inpoint&lt;br /&gt;
 020d70: FMT_loadshape&lt;br /&gt;
 020dc4: FMT_loadshapez&lt;br /&gt;
 04a130: FMT_outplace&lt;br /&gt;
 04a118: FMT_point&lt;br /&gt;
 04a120: FMT_point2&lt;br /&gt;
 019f34: FMT_printpoly&lt;br /&gt;
 04a138: FMT_render2_matrix&lt;br /&gt;
 020e18: FMT_scalecfxy&lt;br /&gt;
 03cd4c: FRBSTR_LIST&lt;br /&gt;
 03c550: FSTRI_LIST&lt;br /&gt;
 03c57c: FSTRL_LIST&lt;br /&gt;
 03c5b4: FSTRR_LIST&lt;br /&gt;
 03c480: FSTR_LIST&lt;br /&gt;
 03c630: FTURR_LIST&lt;br /&gt;
 03c5ec: FTUR_LIST&lt;br /&gt;
 03f94a: FontColor&lt;br /&gt;
 03f94c: FontColor2&lt;br /&gt;
 03f948: FontHeight&lt;br /&gt;
 03f94e: FontStyle&lt;br /&gt;
 03f946: FontWidth&lt;br /&gt;
 047714: FullName&lt;br /&gt;
 03d114: GHWY1_LIST&lt;br /&gt;
 03d140: GHWY2_LIST&lt;br /&gt;
 03a662: Green&lt;br /&gt;
 03c874: HLTR_LIST&lt;br /&gt;
 03d1fc: HPIPE_LIST&lt;br /&gt;
 03c848: HSTRI_LIST&lt;br /&gt;
 03c81c: HSTR_LIST&lt;br /&gt;
 03d16c: HWY1_LIST&lt;br /&gt;
 03d198: HWY2_LIST&lt;br /&gt;
 0498c2: HighIndex&lt;br /&gt;
 01a22c: INIT_BUFFERS&lt;br /&gt;
 01a1a4: INIT_MATRIX&lt;br /&gt;
 01a254: INIT_OBJECTS_BUFFER&lt;br /&gt;
 01a1fc: INIT_PALETTE&lt;br /&gt;
 0226d8: InitRamDrive&lt;br /&gt;
 052168: Joyport1&lt;br /&gt;
 05216c: Joyport2&lt;br /&gt;
 03a168: KYB_clic&lt;br /&gt;
 03a180: KYB_clrbuf&lt;br /&gt;
 03a124: KYB_init&lt;br /&gt;
 03a194: KYB_inpchk&lt;br /&gt;
 03a1e8: KYB_matrix&lt;br /&gt;
 03a1c0: KYB_read&lt;br /&gt;
 03a138: KYB_setbuf&lt;br /&gt;
 03a150: KYB_setcode&lt;br /&gt;
 03fc18: KanaFont16&lt;br /&gt;
 03fc78: KanaFont8&lt;br /&gt;
 03fb80: KanaFontColor16&lt;br /&gt;
 03fb86: KanaFontColor8&lt;br /&gt;
 03fb7e: KanaFontHeight16&lt;br /&gt;
 03fb84: KanaFontHeight8&lt;br /&gt;
 03fb7c: KanaFontWidth16&lt;br /&gt;
 03fb82: KanaFontWidth8&lt;br /&gt;
 03fb88: KanaShape16&lt;br /&gt;
 03fc28: KanaShape8&lt;br /&gt;
 03fb40: KanjiFont&lt;br /&gt;
 03f950: KanjiShape&lt;br /&gt;
 03a51c: KimG_getclient&lt;br /&gt;
 03a538: KimG_popclient&lt;br /&gt;
 03a508: KimG_setclient&lt;br /&gt;
 03ce4c: LCOR_LIST&lt;br /&gt;
 03fc8a: LOOPC&lt;br /&gt;
 03cb1c: LOOP_LIST&lt;br /&gt;
 03a670: Lightblue&lt;br /&gt;
 03a674: Lightcyan&lt;br /&gt;
 03a672: Lightgreen&lt;br /&gt;
 03a66c: Lightgrey&lt;br /&gt;
 03a678: Lightmagenta&lt;br /&gt;
 03a676: Lightred&lt;br /&gt;
 03a6b8: MBoxcol&lt;br /&gt;
 03a6aa: MIDButcol&lt;br /&gt;
 052a74: MOSWork&lt;br /&gt;
 03a010: MOS_disp&lt;br /&gt;
 039ef8: MOS_end&lt;br /&gt;
 03a0a0: MOS_horizon&lt;br /&gt;
 03a038: MOS_rdpos&lt;br /&gt;
 03a100: MOS_resolution&lt;br /&gt;
 03a070: MOS_setpos&lt;br /&gt;
 039d6c: MOS_start&lt;br /&gt;
 03a0d0: MOS_vertical&lt;br /&gt;
 03a668: Magenta&lt;br /&gt;
 05215c: Mosport0&lt;br /&gt;
 052160: Mosport1&lt;br /&gt;
 052164: Mosport2&lt;br /&gt;
 0239b8: MoveCurrent&lt;br /&gt;
 03c16c: NP&lt;br /&gt;
 0498b4: NewSI&lt;br /&gt;
 03a6ac: OptColor&lt;br /&gt;
 03c524: PIPE_LIST&lt;br /&gt;
 03c17c: PT&lt;br /&gt;
 04a14c: P_firstiplc&lt;br /&gt;
 04a150: P_insertlen&lt;br /&gt;
 04a14e: P_iplc&lt;br /&gt;
 04a154: P_listend&lt;br /&gt;
 04a14a: P_numpoints&lt;br /&gt;
 04a152: P_pindex&lt;br /&gt;
 049894: PlayerName&lt;br /&gt;
 051afc: RAM_file&lt;br /&gt;
 03f678: RAM_filename&lt;br /&gt;
 03f660: RAM_filesize&lt;br /&gt;
 051b0c: RAM_saved&lt;br /&gt;
 03a6ae: RBBoxcol&lt;br /&gt;
 03a6b0: RBCursorcol&lt;br /&gt;
 03cfb0: RCOR_LIST&lt;br /&gt;
 03b3c0: RPath&lt;br /&gt;
 013958: RayNullFunction&lt;br /&gt;
 03a666: Red&lt;br /&gt;
 03b414: ReplayName&lt;br /&gt;
 03fc82: SBIGINAD&lt;br /&gt;
 03a6bc: SDPAL_mcgacol1&lt;br /&gt;
 03a9c8: SDPAL_mcgacol2&lt;br /&gt;
 03a8c4: SDPAL_mcgadither&lt;br /&gt;
 03a7c0: SDPAL_mcgatype&lt;br /&gt;
 03fc86: SLINEPIX&lt;br /&gt;
 034e70: SMALL?&lt;br /&gt;
 054320: SNDWork&lt;br /&gt;
 03567c: SND_driver&lt;br /&gt;
 03570c: SND_elevol_all_mute&lt;br /&gt;
 0356fc: SND_elevol_mute&lt;br /&gt;
 0356e4: SND_elevol_set&lt;br /&gt;
 035868: SND_end&lt;br /&gt;
 035994: SND_fm_timer_a_set&lt;br /&gt;
 035760: SND_init&lt;br /&gt;
 035620: SND_inst_change&lt;br /&gt;
 0356b8: SND_inst_write&lt;br /&gt;
 035a44: SND_int_timer_a_get&lt;br /&gt;
 035a00: SND_int_timer_a_set&lt;br /&gt;
 0355ec: SND_joy_in_1&lt;br /&gt;
 03565c: SND_key_abort&lt;br /&gt;
 035608: SND_key_on&lt;br /&gt;
 035980: SND_pan_set&lt;br /&gt;
 035a4c: SND_pcm_bank_load&lt;br /&gt;
 0359a8: SND_pcm_mode_set&lt;br /&gt;
 0359b8: SND_pcm_play&lt;br /&gt;
 0359d8: SND_pcm_play_stop&lt;br /&gt;
 03566c: SND_pcm_sound_delete&lt;br /&gt;
 0356d4: SND_pcm_sound_set&lt;br /&gt;
 0359e8: SND_pcm_status&lt;br /&gt;
 035634: SND_pitch_change&lt;br /&gt;
 035648: SND_volume_change&lt;br /&gt;
 03c4f8: SPIPE_LIST&lt;br /&gt;
 058320: SaveTimer&lt;br /&gt;
 0498b0: Scores&lt;br /&gt;
 023ce8: ScreenKeybord&lt;br /&gt;
 023670: SetArray&lt;br /&gt;
 023944: SetCurrent&lt;br /&gt;
 00f1f0: ShowTitle&lt;br /&gt;
 00f2bc: ShowTitle2&lt;br /&gt;
 054100: SystemMemory&lt;br /&gt;
 045704: TBIOSSTK_bottom&lt;br /&gt;
 03a6a6: TOPButcol&lt;br /&gt;
 03b36c: TPath&lt;br /&gt;
 03c4d8: TUN_LIST&lt;br /&gt;
 03b420: TerName&lt;br /&gt;
 03a69e: TrackBoxCol1&lt;br /&gt;
 03a6a0: TrackBoxCol2&lt;br /&gt;
 03a6a2: TrackBoxCol3&lt;br /&gt;
 03a6a4: TrackCursorCol&lt;br /&gt;
 03caf0: USTR_LIST&lt;br /&gt;
 03cc44: VCORK_LIST&lt;br /&gt;
 0170cc: WarningMessage&lt;br /&gt;
 03a67c: White&lt;br /&gt;
 03c4ac: XFSTR_LIST&lt;br /&gt;
 03a67a: Yellow&lt;br /&gt;
 01707c: YesOrNoMessage&lt;br /&gt;
 044724: __mwdfc&lt;br /&gt;
 044724: __mwdlc&lt;br /&gt;
 044a34: __onexit_termination&lt;br /&gt;
 044734: _base&lt;br /&gt;
 044988: _bufsiz&lt;br /&gt;
 04460c: _ctype&lt;br /&gt;
 03694c: _dos_findfirst&lt;br /&gt;
 036980: _dos_findnext&lt;br /&gt;
 03406c: _dos_getdiskfree&lt;br /&gt;
 044b00: _doserr&lt;br /&gt;
 044afc: _doserrno&lt;br /&gt;
 046d54: _edata&lt;br /&gt;
 058490: _end&lt;br /&gt;
 036938: _exit&lt;br /&gt;
 033fd0: _fdopen&lt;br /&gt;
 044a24: _fmode&lt;br /&gt;
 0449ec: _fopen_max&lt;br /&gt;
 03a650: _fsoftonly&lt;br /&gt;
 033fec: _fsopen&lt;br /&gt;
 044748: _gda&lt;br /&gt;
 044794: _iob&lt;br /&gt;
 036a7c: _itoa&lt;br /&gt;
 044769: _mw1167&lt;br /&gt;
 03a650: _mw1167required&lt;br /&gt;
 03a650: _mw1167used&lt;br /&gt;
 03a650: _mw3167used&lt;br /&gt;
 044767: _mw387&lt;br /&gt;
 03a650: _mw387used&lt;br /&gt;
 044763: _mw8087&lt;br /&gt;
 03a650: _mw87only&lt;br /&gt;
 03a650: _mw87required&lt;br /&gt;
 03a650: _mw87used&lt;br /&gt;
 044728: _mwCPU&lt;br /&gt;
 0340a4: _mwINIT&lt;br /&gt;
 044729: _mwOS&lt;br /&gt;
 03928c: _mw_87_f2add&lt;br /&gt;
 0392b6: _mw_87_f2compare&lt;br /&gt;
 0392af: _mw_87_f2div&lt;br /&gt;
 0392a8: _mw_87_f2mpy&lt;br /&gt;
 03937a: _mw_87_fbld&lt;br /&gt;
 039370: _mw_87_fbstp&lt;br /&gt;
 0392cc: _mw_87_fflt&lt;br /&gt;
 03930c: _mw_87_flload&lt;br /&gt;
 0392f2: _mw_87_fload&lt;br /&gt;
 0392f9: _mw_87_flret&lt;br /&gt;
 039326: _mw_87_fpop&lt;br /&gt;
 0392e5: _mw_87_fret&lt;br /&gt;
 03931d: _mw_87_ftload&lt;br /&gt;
 039313: _mw_87_ftret&lt;br /&gt;
 039367: _mw_87_fxam&lt;br /&gt;
 03935c: _mw_87_round&lt;br /&gt;
 039340: _mw_87_trunc&lt;br /&gt;
 0392d3: _mw_87_ufflt&lt;br /&gt;
 034e74: _mw_errnoset&lt;br /&gt;
 044d90: _mw_findnext_uses_attrib&lt;br /&gt;
 039bc8: _mwabort&lt;br /&gt;
 039544: _mwaddmany&lt;br /&gt;
 037a10: _mwaprintf&lt;br /&gt;
 044758: _mwarglen&lt;br /&gt;
 04474c: _mwargp&lt;br /&gt;
 03a650: _mwargregs&lt;br /&gt;
 03a650: _mwargstack&lt;br /&gt;
 044752: _mwargvp&lt;br /&gt;
 038bc0: _mwbcd_to_real&lt;br /&gt;
 034c34: _mwc_create&lt;br /&gt;
 034c14: _mwc_dos_name&lt;br /&gt;
 034c5c: _mwc_open&lt;br /&gt;
 034c8c: _mwc_unlink&lt;br /&gt;
 034ec4: _mwcall_onexit_fcns&lt;br /&gt;
 03547c: _mwcalldos&lt;br /&gt;
 033974: _mwcfclose_all&lt;br /&gt;
 034940: _mwcfinit&lt;br /&gt;
 034988: _mwcfterm&lt;br /&gt;
 03545c: _mwcheck_heap_integrity&lt;br /&gt;
 034e44: _mwcmp&lt;br /&gt;
 039b98: _mwdisplay&lt;br /&gt;
 0369d8: _mwdo_itoa&lt;br /&gt;
 034b24: _mwdos&lt;br /&gt;
 034bdc: _mwdos_exit&lt;br /&gt;
 039685: _mwdshl&lt;br /&gt;
 035564: _mwdump_heap&lt;br /&gt;
 034fe8: _mweach_allocated_item&lt;br /&gt;
 034f6c: _mweach_free_item&lt;br /&gt;
 034ef8: _mweach_item&lt;br /&gt;
 04476b: _mwemc87&lt;br /&gt;
 034ca0: _mwend&lt;br /&gt;
 044774: _mwenv&lt;br /&gt;
 044fa0: _mwenvip&lt;br /&gt;
 04475c: _mwenvp&lt;br /&gt;
 04472a: _mwes&lt;br /&gt;
 0347f4: _mwexpand_heap&lt;br /&gt;
 038e9c: _mwfabs&lt;br /&gt;
 038bd8: _mwfadd&lt;br /&gt;
 039824: _mwfbld&lt;br /&gt;
 03991c: _mwfbstp&lt;br /&gt;
 039220: _mwfcmp&lt;br /&gt;
 039208: _mwfcompare&lt;br /&gt;
 03916c: _mwfcomparend&lt;br /&gt;
 03901c: _mwfdiv&lt;br /&gt;
 039010: _mwfdivr&lt;br /&gt;
 038ebc: _mwfdup&lt;br /&gt;
 035510: _mwferr&lt;br /&gt;
 034db8: _mwfileclass&lt;br /&gt;
 034b08: _mwfinit&lt;br /&gt;
 038d2c: _mwflload&lt;br /&gt;
 038cf0: _mwfload&lt;br /&gt;
 03a650: _mwfltused&lt;br /&gt;
 038ed8: _mwfmpy&lt;br /&gt;
 038e40: _mwfneg&lt;br /&gt;
 0396d4: _mwfpop&lt;br /&gt;
 039698: _mwfpstackoflo&lt;br /&gt;
 0353e3: _mwfree&lt;br /&gt;
 038e70: _mwfsub&lt;br /&gt;
 038e64: _mwfsubr&lt;br /&gt;
 034b08: _mwfterm&lt;br /&gt;
 038d68: _mwftload&lt;br /&gt;
 038dc8: _mwftret&lt;br /&gt;
 036dc0: _mwfwrite_&lt;br /&gt;
 039764: _mwfxam&lt;br /&gt;
 038e08: _mwfxch&lt;br /&gt;
 038b84: _mwget_exponent&lt;br /&gt;
 033c3c: _mwget_file_handle_and_info&lt;br /&gt;
 034926: _mwgetds&lt;br /&gt;
 036d84: _mwgetenv2&lt;br /&gt;
 034ce0: _mwhalt&lt;br /&gt;
 044779: _mwheap_expansion_enabled&lt;br /&gt;
 035350: _mwhmalloc&lt;br /&gt;
 0396b8: _mwinc_tos&lt;br /&gt;
 037164: _mwinit_buf&lt;br /&gt;
 0347b4: _mwinit_const&lt;br /&gt;
 044777: _mwinit_ver&lt;br /&gt;
 044724: _mwinput&lt;br /&gt;
 03505c: _mwinsert_into_free_chain&lt;br /&gt;
 034e70: _mwint21&lt;br /&gt;
 044762: _mwis_286&lt;br /&gt;
 0355c4: _mwkbnewline&lt;br /&gt;
 0355a8: _mwkbputs&lt;br /&gt;
 03a650: _mwldouble10&lt;br /&gt;
 03519c: _mwleast_free_memory&lt;br /&gt;
 034b98: _mwload_ds_dx&lt;br /&gt;
 034b64: _mwload_ptr&lt;br /&gt;
 03a65c: _mwloc&lt;br /&gt;
 034e00: _mwlseek&lt;br /&gt;
 039384: _mwltox&lt;br /&gt;
 0353ac: _mwmalloc&lt;br /&gt;
 03521c: _mwmalloc2&lt;br /&gt;
 0395c2: _mwnegmany&lt;br /&gt;
 0396dc: _mwnormalize&lt;br /&gt;
 03814c: _mwout_convert_dreal&lt;br /&gt;
 038878: _mwout_convert_real&lt;br /&gt;
 044726: _mwoutput&lt;br /&gt;
 037294: _mwpad_to_field_width&lt;br /&gt;
 044776: _mwprintnochipmsg&lt;br /&gt;
 04476e: _mwprognamep&lt;br /&gt;
 038ba8: _mwreal_to_bcd&lt;br /&gt;
 0340b8: _mwrestore_interrupts&lt;br /&gt;
 03947c: _mwrtox&lt;br /&gt;
 03724c: _mwsend_pad&lt;br /&gt;
 039262: _mwset_flags_after_compare&lt;br /&gt;
 033e40: _mwset_flags_etc&lt;br /&gt;
 039240: _mwset_rounding_proc&lt;br /&gt;
 034a0c: _mwset_up_args&lt;br /&gt;
 038ac4: _mwspecial_number_msg&lt;br /&gt;
 034923: _mwss&lt;br /&gt;
 044714: _mwstack_limit&lt;br /&gt;
 039c10: _mwstack_overflow&lt;br /&gt;
 035594: _mwstackdump&lt;br /&gt;
 039c04: _mwstkerr&lt;br /&gt;
 03956d: _mwsubmany112&lt;br /&gt;
 039596: _mwsubmany121&lt;br /&gt;
 038a44: _mwten_to_the_power&lt;br /&gt;
 034cc8: _mwvsretcode&lt;br /&gt;
 044775: _mwwind&lt;br /&gt;
 039b00: _mwxdiv&lt;br /&gt;
 039ab4: _mwxmpy&lt;br /&gt;
 0395e7: _mwxnormalize&lt;br /&gt;
 03961c: _mwxshl&lt;br /&gt;
 03962c: _mwxshr&lt;br /&gt;
 039638: _mwxshrcnt&lt;br /&gt;
 0393f9: _mwxtol&lt;br /&gt;
 0394e1: _mwxtor&lt;br /&gt;
 034bbc: _mwzclose&lt;br /&gt;
 034d2c: _mwzread&lt;br /&gt;
 034da4: _mwztrunc&lt;br /&gt;
 034d58: _mwzwrite&lt;br /&gt;
 03fc94: _osmajor&lt;br /&gt;
 03fc95: _osminor&lt;br /&gt;
 03fc94: _osversion&lt;br /&gt;
 04472a: _psp&lt;br /&gt;
 036a98: _strcmpi&lt;br /&gt;
 036a98: _stricmp&lt;br /&gt;
 03a554: _strnicmp&lt;br /&gt;
 037d04: _strrev&lt;br /&gt;
 0449f0: _temp_file_chain&lt;br /&gt;
 044730: _top&lt;br /&gt;
 043bb5: _zclipvalue&lt;br /&gt;
 03ba18: abbrname&lt;br /&gt;
 03bee1: abortbox&lt;br /&gt;
 02545c: abortmessage&lt;br /&gt;
 021980: accelerate&lt;br /&gt;
 041b4c: activeflag&lt;br /&gt;
 043bc8: adderr&lt;br /&gt;
 026598: addexit&lt;br /&gt;
 03fd18: addexiterr&lt;br /&gt;
 011e40: addhighs&lt;br /&gt;
 031188: addtimer&lt;br /&gt;
 021280: addtotextbuf&lt;br /&gt;
 01be40: addzone&lt;br /&gt;
 0254c8: adrtoseg&lt;br /&gt;
 052188: all&lt;br /&gt;
 0498fc: allcarobject1&lt;br /&gt;
 0499fc: allcarobject2&lt;br /&gt;
 022d64: allexist&lt;br /&gt;
 049a14: alloppresfile&lt;br /&gt;
 03b465: allowabort&lt;br /&gt;
 052154: alphashp&lt;br /&gt;
 02a44b: andcf&lt;br /&gt;
 02a672: andcfxy&lt;br /&gt;
 02a6aa: andcfxya&lt;br /&gt;
 02878a: andcline&lt;br /&gt;
 029c34: andf&lt;br /&gt;
 029d1b: andfxy&lt;br /&gt;
 029d53: andfxya&lt;br /&gt;
 028e2c: andline&lt;br /&gt;
 02be32: andpackcf&lt;br /&gt;
 02c090: andpackcfxy&lt;br /&gt;
 02c0c8: andpackcfxya&lt;br /&gt;
 02b17f: andpackf&lt;br /&gt;
 02b24b: andpackfxy&lt;br /&gt;
 02b283: andpackfxya&lt;br /&gt;
 028475: andpixel&lt;br /&gt;
 028386: andpixelc&lt;br /&gt;
 028ff1: andrect&lt;br /&gt;
 02930d: andrectc&lt;br /&gt;
 0219c4: anim_car&lt;br /&gt;
 021c64: anim_champ&lt;br /&gt;
 021744: anim_finish&lt;br /&gt;
 012164: animateopponent&lt;br /&gt;
 00eecc: animcarsmk&lt;br /&gt;
 049a3a: animdelay&lt;br /&gt;
 00eaf8: animhelmet1&lt;br /&gt;
 00ed54: animhelmet2&lt;br /&gt;
 049a32: animindex&lt;br /&gt;
 049a38: animnum&lt;br /&gt;
 049a3e: animx&lt;br /&gt;
 049a40: animy&lt;br /&gt;
 047529: askfull&lt;br /&gt;
 034e94: atexit&lt;br /&gt;
 0005a8: availmem&lt;br /&gt;
 049a2c: backfile&lt;br /&gt;
 0268a8: background&lt;br /&gt;
 019f38: benprojectp&lt;br /&gt;
 049882: between&lt;br /&gt;
 03d624: bew11&lt;br /&gt;
 058344: biosticks&lt;br /&gt;
 043c38: biostickset&lt;br /&gt;
 049814: bitplanes&lt;br /&gt;
 03f17c: blackpal&lt;br /&gt;
 0419b8: blknotfound&lt;br /&gt;
 0487e4: blocklistsign&lt;br /&gt;
 020740: blowengine&lt;br /&gt;
 041944: bmem&lt;br /&gt;
 03d688: bne22&lt;br /&gt;
 03d610: bns11&lt;br /&gt;
 03d69c: bnw22&lt;br /&gt;
 041bba: botfire&lt;br /&gt;
 00d438: boxcheck&lt;br /&gt;
 049812: bpix&lt;br /&gt;
 04986f: brakecolor&lt;br /&gt;
 03da94: brew11&lt;br /&gt;
 03da80: brns11&lt;br /&gt;
 03d660: bse22&lt;br /&gt;
 03d638: bsn11&lt;br /&gt;
 03d674: bsw22&lt;br /&gt;
 049a00: buttfile&lt;br /&gt;
 03d64c: bwe11&lt;br /&gt;
 00c820: calccoll&lt;br /&gt;
 024a2c: calcrpm&lt;br /&gt;
 03b250: camerasizeinfo&lt;br /&gt;
 03b458: camheading&lt;br /&gt;
 03b456: camlen&lt;br /&gt;
 03b45f: cammode&lt;br /&gt;
 03b45a: campitch&lt;br /&gt;
 052158: canncel_flag&lt;br /&gt;
 0254a4: cap&lt;br /&gt;
 047480: car1&lt;br /&gt;
 0497ba: car1handle&lt;br /&gt;
 049648: car1ltires&lt;br /&gt;
 0496f0: car1tcenter&lt;br /&gt;
 049660: car1toffsets&lt;br /&gt;
 0497bc: car2handle&lt;br /&gt;
 049654: car2ltires&lt;br /&gt;
 04978c: car2tcenter&lt;br /&gt;
 0496fc: car2toffsets&lt;br /&gt;
 0208f4: carbubble&lt;br /&gt;
 0207f8: carbump&lt;br /&gt;
 02079c: carcrash&lt;br /&gt;
 048190: cari&lt;br /&gt;
 048498: cari2&lt;br /&gt;
 0211b0: carmovesfx&lt;br /&gt;
 049820: carname&lt;br /&gt;
 04a984: carobjects1&lt;br /&gt;
 04a988: carobjects2&lt;br /&gt;
 03b478: carresname&lt;br /&gt;
 02084c: carscrape&lt;br /&gt;
 0208a0: carsplash&lt;br /&gt;
 03f63c: ccmsg&lt;br /&gt;
 020d40: cdfade&lt;br /&gt;
 032018: cdfadeto&lt;br /&gt;
 0321d4: cdisbusy&lt;br /&gt;
 03f634: cdmsg&lt;br /&gt;
 0321b4: cdpause&lt;br /&gt;
 0324d0: cdplay&lt;br /&gt;
 0321fc: cdplaysection&lt;br /&gt;
 032364: cdplaysector&lt;br /&gt;
 0320e8: cdprinttoc&lt;br /&gt;
 03a36c: cdr_cdinfo&lt;br /&gt;
 03a428: cdr_continue&lt;br /&gt;
 03a474: cdr_exit1&lt;br /&gt;
 03a2ec: cdr_mphase&lt;br /&gt;
 03a2d8: cdr_mstop&lt;br /&gt;
 03a274: cdr_mtplay&lt;br /&gt;
 03a414: cdr_pause&lt;br /&gt;
 03a4f0: cdr_popclient&lt;br /&gt;
 03a4d0: cdr_pushclient&lt;br /&gt;
 03a204: cdr_sdrvmd&lt;br /&gt;
 045781: cdr_stat&lt;br /&gt;
 03a240: cdr_status&lt;br /&gt;
 032040: cdreadtoc&lt;br /&gt;
 0321c4: cdresume&lt;br /&gt;
 020d2c: cdsnddone&lt;br /&gt;
 032198: cdstart&lt;br /&gt;
 0321a4: cdstop&lt;br /&gt;
 031fac: cdupdatefade&lt;br /&gt;
 0273d4: centertext&lt;br /&gt;
 0437a1: centerx&lt;br /&gt;
 0437ad: centerxpix&lt;br /&gt;
 0437a3: centery&lt;br /&gt;
 0437af: centerypix&lt;br /&gt;
 043799: cenxpix&lt;br /&gt;
 04379b: cenypix&lt;br /&gt;
 049ab0: cfcount&lt;br /&gt;
 03f638: cfmsg&lt;br /&gt;
 03d78c: ch1ew21&lt;br /&gt;
 03d7a0: ch1ns21&lt;br /&gt;
 03d7b4: ch2ew21&lt;br /&gt;
 03d778: ch2ns21&lt;br /&gt;
 022328: champion&lt;br /&gt;
 0215d4: change_palette&lt;br /&gt;
 0250d6: changeareacolor&lt;br /&gt;
 00e3b4: changedrive&lt;br /&gt;
 00e4a0: checkcarname&lt;br /&gt;
 017358: checkdisk&lt;br /&gt;
 022e6c: checkinstall&lt;br /&gt;
 026bcc: checkmodule&lt;br /&gt;
 01c3dc: checkobjtypes&lt;br /&gt;
 019c40: checktracksyntax&lt;br /&gt;
 03f49c: chmpname&lt;br /&gt;
 027124: chooseone&lt;br /&gt;
 043d48: circles&lt;br /&gt;
 043d4c: circletbls&lt;br /&gt;
 0497e0: cjoystate&lt;br /&gt;
 049ab2: clastcolor&lt;br /&gt;
 04981d: clastx&lt;br /&gt;
 04981e: clastz&lt;br /&gt;
 0166d0: clear_keyboardbuffer&lt;br /&gt;
 0000c4: clearinterpretsubs&lt;br /&gt;
 035e3c: clearscreen&lt;br /&gt;
 025d5c: clearwindow&lt;br /&gt;
 013710: clearzone&lt;br /&gt;
 026070: clip&lt;br /&gt;
 0497fe: clipby&lt;br /&gt;
 02f82b: clipline&lt;br /&gt;
 025f10: clippix&lt;br /&gt;
 025ee0: clippixwindow&lt;br /&gt;
 0497fc: clipty&lt;br /&gt;
 026080: clipwindow&lt;br /&gt;
 01bda8: clipzone&lt;br /&gt;
 015fc4: closeresource&lt;br /&gt;
 0497fa: cloudfudge&lt;br /&gt;
 04987e: cmps&lt;br /&gt;
 03dae4: colew22&lt;br /&gt;
 03daa8: colns22&lt;br /&gt;
 04a8cc: color1&lt;br /&gt;
 04a8d0: color2&lt;br /&gt;
 0514fc: colorbak&lt;br /&gt;
 0517fc: colorcur&lt;br /&gt;
 04a8d8: colordither&lt;br /&gt;
 04a8dc: colorrnds&lt;br /&gt;
 04a8d4: colorstat&lt;br /&gt;
 03dad0: colsn22&lt;br /&gt;
 03dabc: colwe22&lt;br /&gt;
 01eeac: compiletrack&lt;br /&gt;
 027628: convertjoy&lt;br /&gt;
 03f140: coord1&lt;br /&gt;
 03f148: coord2&lt;br /&gt;
 01c378: copyobj&lt;br /&gt;
 01c390: copyobjtypes&lt;br /&gt;
 022c08: copyq2a&lt;br /&gt;
 03db34: corew22&lt;br /&gt;
 03daf8: corns22&lt;br /&gt;
 03db20: corsn22&lt;br /&gt;
 03db0c: corwe22&lt;br /&gt;
 049858: countdown&lt;br /&gt;
 03f640: cpmsg&lt;br /&gt;
 019edc: cpycoord&lt;br /&gt;
 019f14: cpymatrix&lt;br /&gt;
 019efc: cpyscoord&lt;br /&gt;
 004470: crack&lt;br /&gt;
 025550: crcbyte&lt;br /&gt;
 00f364: credit1&lt;br /&gt;
 00f40c: credit2&lt;br /&gt;
 0327e7: criterr&lt;br /&gt;
 043c36: critflag&lt;br /&gt;
 043c30: critfunc&lt;br /&gt;
 03277e: crithandler&lt;br /&gt;
 03287f: ctrlc&lt;br /&gt;
 03286f: ctrlchandler&lt;br /&gt;
 03bed0: curfname&lt;br /&gt;
 04945c: curplane&lt;br /&gt;
 0498fa: currcar&lt;br /&gt;
 03f138: currchannel&lt;br /&gt;
 052a48: current&lt;br /&gt;
 03f16a: currentbuf&lt;br /&gt;
 041c82: currentfont&lt;br /&gt;
 027568: currentkeysub&lt;br /&gt;
 04220a: currentwindow&lt;br /&gt;
 04d166: currpm&lt;br /&gt;
 053aec: cursmask&lt;br /&gt;
 053ae8: cursshape&lt;br /&gt;
 047540: cusedash&lt;br /&gt;
 049869: cusereplay&lt;br /&gt;
 015140: cutpath&lt;br /&gt;
 047d14: cv&lt;br /&gt;
 048174: cvx&lt;br /&gt;
 046d58: cz&lt;br /&gt;
 049886: czoneflag&lt;br /&gt;
 03f68a: datadrive&lt;br /&gt;
 047690: dcar_matrix&lt;br /&gt;
 0497f2: dclip&lt;br /&gt;
 03b368: deffont&lt;br /&gt;
 020218: deinitenginesfx&lt;br /&gt;
 02155c: delaykey&lt;br /&gt;
 0311bc: deltimer&lt;br /&gt;
 049853: demomode&lt;br /&gt;
 03b314: demoplane&lt;br /&gt;
 0497a4: demotime&lt;br /&gt;
 049854: didrace&lt;br /&gt;
 0214f8: disabletextbuf&lt;br /&gt;
 022ab8: diskaexist&lt;br /&gt;
 0228e8: diskexist&lt;br /&gt;
 022758: diskfile&lt;br /&gt;
 02296c: diskfileerror&lt;br /&gt;
 022928: diskfileexist&lt;br /&gt;
 0265fc: diskfree&lt;br /&gt;
 03beac: diskmsgs&lt;br /&gt;
 03bebc: disknames&lt;br /&gt;
 03f688: diskop&lt;br /&gt;
 022a90: diskspace&lt;br /&gt;
 0233e8: disolve_entirememwindow&lt;br /&gt;
 023214: disolve_hiddenwindow&lt;br /&gt;
 0232e8: disolve_memwindow&lt;br /&gt;
 026f28: displayall&lt;br /&gt;
 026ed0: displayone&lt;br /&gt;
 025d2c: displayshapes&lt;br /&gt;
 025ed0: displaywindow&lt;br /&gt;
 031398: ditheredpoly&lt;br /&gt;
 0313a8: ditheredpolyf&lt;br /&gt;
 0313b8: ditheredpolyi&lt;br /&gt;
 0313c8: ditheredpolyip&lt;br /&gt;
 0313d8: ditheredpolyipt&lt;br /&gt;
 0313e8: ditheredpolyit&lt;br /&gt;
 0313f8: ditheredpolyp&lt;br /&gt;
 031408: ditheredpolypt&lt;br /&gt;
 031418: ditheredpolyt&lt;br /&gt;
 020d14: docdplay&lt;br /&gt;
 016974: docursor&lt;br /&gt;
 01695c: docursorinit&lt;br /&gt;
 0067d4: dodash&lt;br /&gt;
 00bd7c: doengine&lt;br /&gt;
 00c310: dohandling&lt;br /&gt;
 016468: dohidemouse&lt;br /&gt;
 007564: doreplay&lt;br /&gt;
 027f70: dosexit&lt;br /&gt;
 00c978: doshock&lt;br /&gt;
 0164bc: doshowmouse&lt;br /&gt;
 01602c: doslider&lt;br /&gt;
 00cad4: dosteering&lt;br /&gt;
 014dc0: draw3dboxin&lt;br /&gt;
 014c98: draw3dboxout&lt;br /&gt;
 014eec: draw3dbutton&lt;br /&gt;
 003a6c: drawblimpworld&lt;br /&gt;
 031318: drawbox&lt;br /&gt;
 035c6c: drawcircle&lt;br /&gt;
 028573: drawcline&lt;br /&gt;
 011abc: drawhighs&lt;br /&gt;
 0030d4: drawhorizon&lt;br /&gt;
 002f18: drawhorizone&lt;br /&gt;
 028ddb: drawline&lt;br /&gt;
 004e78: drawlogo&lt;br /&gt;
 049856: drawmode&lt;br /&gt;
 013744: drawmode4box&lt;br /&gt;
 0120e4: drawopponent&lt;br /&gt;
 019514: drawpiecebox&lt;br /&gt;
 035eec: drawpolyf&lt;br /&gt;
 03153c: drawpolyp&lt;br /&gt;
 031528: drawpolypt&lt;br /&gt;
 028f1f: drawrect&lt;br /&gt;
 029261: drawrectc&lt;br /&gt;
 003a08: drawsort&lt;br /&gt;
 003f94: drawtext&lt;br /&gt;
 019690: drawtrackbox&lt;br /&gt;
 000840: drawworld&lt;br /&gt;
 0005c4: drawworldflipzones&lt;br /&gt;
 02660c: drive&lt;br /&gt;
 016b70: drnd&lt;br /&gt;
 0265d0: dsiexit&lt;br /&gt;
 03f644: dsmsg&lt;br /&gt;
 04742c: dtempzone&lt;br /&gt;
 0254d0: dump&lt;br /&gt;
 026fdc: dumpone&lt;br /&gt;
 0497e8: ebufend&lt;br /&gt;
 0497e6: ebufstart&lt;br /&gt;
 0497e4: ebuftime&lt;br /&gt;
 031214: elapsedticks&lt;br /&gt;
 032c6c: ellipse&lt;br /&gt;
 033490: ellipseh&lt;br /&gt;
 01738c: elticks&lt;br /&gt;
 021504: enabletextbuf&lt;br /&gt;
 03b4e0: endgame&lt;br /&gt;
 03af30: eng&lt;br /&gt;
 03af70: eng2&lt;br /&gt;
 0477c4: enginebuffer&lt;br /&gt;
 0204d0: engineoff&lt;br /&gt;
 0203fc: engineon&lt;br /&gt;
 020a20: enginesfxover&lt;br /&gt;
 021410: erasetext&lt;br /&gt;
 0449fa: errno&lt;br /&gt;
 049a3c: et&lt;br /&gt;
 0121f0: evaluation&lt;br /&gt;
 036920: exit&lt;br /&gt;
 03fcf0: exitsub&lt;br /&gt;
 041a18: exmemerr&lt;br /&gt;
 0419e8: expanderr&lt;br /&gt;
 047408: explbmapsdiam&lt;br /&gt;
 03f6bc: ext&lt;br /&gt;
 054204: extkeysubs&lt;br /&gt;
 04a8e0: facedir&lt;br /&gt;
 0233fc: fade_display&lt;br /&gt;
 0234cc: fade_displays&lt;br /&gt;
 0338d0: fclose&lt;br /&gt;
 04d160: fcolor&lt;br /&gt;
 04d162: fcolor2&lt;br /&gt;
 03d2c0: few11&lt;br /&gt;
 0337f8: fflush&lt;br /&gt;
 0365cc: fgetc&lt;br /&gt;
 026100: filename&lt;br /&gt;
 03fce4: filerrtxt&lt;br /&gt;
 02658c: fileselector&lt;br /&gt;
 026474: filesize&lt;br /&gt;
 026494: filesizea&lt;br /&gt;
 026484: filesizez&lt;br /&gt;
 00bae0: findcar&lt;br /&gt;
 026590: findfile&lt;br /&gt;
 026138: findfirst&lt;br /&gt;
 026160: findnext&lt;br /&gt;
 00d9ec: finishgame&lt;br /&gt;
 016a18: finishsong&lt;br /&gt;
 049a30: firstone&lt;br /&gt;
 049866: firsttime&lt;br /&gt;
 0328a8: fixedmult&lt;br /&gt;
 03d5fc: flbew11&lt;br /&gt;
 03d5e8: flbns11&lt;br /&gt;
 03d5c0: flbsn11&lt;br /&gt;
 03d5d4: flbwe11&lt;br /&gt;
 0151ac: floadreq&lt;br /&gt;
 017394: fluffyload&lt;br /&gt;
 02e699: fmtandcf&lt;br /&gt;
 02e8a3: fmtandcfxy&lt;br /&gt;
 02e8cc: fmtandcfxya&lt;br /&gt;
 02e081: fmtandf&lt;br /&gt;
 02e13e: fmtandfxy&lt;br /&gt;
 02e167: fmtandfxya&lt;br /&gt;
 032a8c: fmtandpackcf&lt;br /&gt;
 032acc: fmtandpackcfxy&lt;br /&gt;
 032b0c: fmtandpackcfxya&lt;br /&gt;
 02f0c9: fmtandpackf&lt;br /&gt;
 02f197: fmtandpackfxy&lt;br /&gt;
 02f1c0: fmtandpackfxya&lt;br /&gt;
 032f16: fmtandrect&lt;br /&gt;
 0332b9: fmtandrectc&lt;br /&gt;
 035e6b: fmtclearscreen&lt;br /&gt;
 032a3c: fmtdisolvefast&lt;br /&gt;
 032a4c: fmtdisolvefastxya&lt;br /&gt;
 032a5c: fmtdisolveslow&lt;br /&gt;
 032a6c: fmtdisolveslowxya&lt;br /&gt;
 032e20: fmtdrawrect&lt;br /&gt;
 03321c: fmtdrawrectc&lt;br /&gt;
 026858: fmtenlargescreen&lt;br /&gt;
 03fcbc: fmtexten&lt;br /&gt;
 0282b0: fmtgetpalette&lt;br /&gt;
 035e9c: fmthtclear&lt;br /&gt;
 02673c: fmtinitgraphics&lt;br /&gt;
 02e465: fmtmovcf&lt;br /&gt;
 02e64f: fmtmovcfxy&lt;br /&gt;
 02e678: fmtmovcfxya&lt;br /&gt;
 02df92: fmtmovf&lt;br /&gt;
 02e037: fmtmovfxy&lt;br /&gt;
 02e060: fmtmovfxya&lt;br /&gt;
 032a7c: fmtmovpackcf&lt;br /&gt;
 032abc: fmtmovpackcfxy&lt;br /&gt;
 032afc: fmtmovpackcfxya&lt;br /&gt;
 02efbd: fmtmovpackf&lt;br /&gt;
 02f07f: fmtmovpackfxy&lt;br /&gt;
 02f0a8: fmtmovpackfxya&lt;br /&gt;
 02e8ed: fmtorcf&lt;br /&gt;
 02eaf7: fmtorcfxy&lt;br /&gt;
 02eb20: fmtorcfxya&lt;br /&gt;
 02e188: fmtorf&lt;br /&gt;
 02e245: fmtorfxy&lt;br /&gt;
 02e26e: fmtorfxya&lt;br /&gt;
 032a9c: fmtorpackcf&lt;br /&gt;
 032adc: fmtorpackcfxy&lt;br /&gt;
 032b1c: fmtorpackcfxya&lt;br /&gt;
 02f1e1: fmtorpackf&lt;br /&gt;
 02f2af: fmtorpackfxy&lt;br /&gt;
 02f2d8: fmtorpackfxya&lt;br /&gt;
 033018: fmtorrect&lt;br /&gt;
 033356: fmtorrectc&lt;br /&gt;
 028259: fmtpalette&lt;br /&gt;
 0282f0: fmtpaltocol&lt;br /&gt;
 02f74e: fmtreadf&lt;br /&gt;
 02f7c2: fmtreadfxy&lt;br /&gt;
 02f7e8: fmtreadfxya&lt;br /&gt;
 032b3c: fmtscalecf&lt;br /&gt;
 032b4c: fmtscalecfxy&lt;br /&gt;
 032b5c: fmtscalecfxya&lt;br /&gt;
 032b6c: fmtscalef&lt;br /&gt;
 032b7c: fmtscalefxy&lt;br /&gt;
 032b8c: fmtscalefxya&lt;br /&gt;
 032c3c: fmtscalereccf&lt;br /&gt;
 032c4c: fmtscalereccfxy&lt;br /&gt;
 032c5c: fmtscalereccfxya&lt;br /&gt;
 032c0c: fmtscalerecf&lt;br /&gt;
 032c1c: fmtscalerecfxy&lt;br /&gt;
 032c2c: fmtscalerecfxya&lt;br /&gt;
 026758: fmtscreenmode&lt;br /&gt;
 032b9c: fmtsetcolortranslate&lt;br /&gt;
 02df4b: fmtsetscreen&lt;br /&gt;
 029784: fmtspeed&lt;br /&gt;
 02ed95: fmttmaskcf&lt;br /&gt;
 02ef73: fmttmaskcfxy&lt;br /&gt;
 02ef9c: fmttmaskcfxya&lt;br /&gt;
 02e396: fmttmaskf&lt;br /&gt;
 02e41b: fmttmaskfxy&lt;br /&gt;
 02e444: fmttmaskfxya&lt;br /&gt;
 032bac: fmttmaskhpackcf&lt;br /&gt;
 032bbc: fmttmaskhpackcfxy&lt;br /&gt;
 032bcc: fmttmaskhpackcfxya&lt;br /&gt;
 02f5a3: fmttmaskhpackf&lt;br /&gt;
 02f701: fmttmaskhpackfxy&lt;br /&gt;
 02f72d: fmttmaskhpackfxya&lt;br /&gt;
 032bdc: fmttmaskpackcf&lt;br /&gt;
 032bec: fmttmaskpackcfxy&lt;br /&gt;
 032bfc: fmttmaskpackcfxya&lt;br /&gt;
 02f411: fmttmaskpackf&lt;br /&gt;
 02f559: fmttmaskpackfxy&lt;br /&gt;
 02f582: fmttmaskpackfxya&lt;br /&gt;
 03fce0: fmtwindotxt&lt;br /&gt;
 025f84: fmtwindowdef&lt;br /&gt;
 02eb41: fmtxorcf&lt;br /&gt;
 02ed4b: fmtxorcfxy&lt;br /&gt;
 02ed74: fmtxorcfxya&lt;br /&gt;
 02e28f: fmtxorf&lt;br /&gt;
 02e34c: fmtxorfxy&lt;br /&gt;
 02e375: fmtxorfxya&lt;br /&gt;
 032aac: fmtxorpackcf&lt;br /&gt;
 032aec: fmtxorpackcfxy&lt;br /&gt;
 032b2c: fmtxorpackcfxya&lt;br /&gt;
 02f2f9: fmtxorpackf&lt;br /&gt;
 02f3c7: fmtxorpackfxy&lt;br /&gt;
 02f3f0: fmtxorpackfxya&lt;br /&gt;
 03311a: fmtxorrect&lt;br /&gt;
 0333f3: fmtxorrectc&lt;br /&gt;
 03d348: fne11&lt;br /&gt;
 03d398: fne22&lt;br /&gt;
 03d2ac: fns11&lt;br /&gt;
 03d35c: fnw11&lt;br /&gt;
 03d3ac: fnw22&lt;br /&gt;
 0261a4: fo&lt;br /&gt;
 0497e2: fontheight&lt;br /&gt;
 03b454: fontwidest&lt;br /&gt;
 033fb4: fopen&lt;br /&gt;
 0298cb: fortext&lt;br /&gt;
 0298a7: fortextxy&lt;br /&gt;
 03686c: fprintf&lt;br /&gt;
 03d5ac: frbew11&lt;br /&gt;
 03d598: frbns11&lt;br /&gt;
 03d570: frbsn11&lt;br /&gt;
 03d584: frbwe11&lt;br /&gt;
 036540: fread&lt;br /&gt;
 0349cc: free&lt;br /&gt;
 010cd4: freealloppres&lt;br /&gt;
 00466c: freeallscene&lt;br /&gt;
 010d94: freeallselopp&lt;br /&gt;
 041938: freebotidx&lt;br /&gt;
 026bd4: freememory&lt;br /&gt;
 026bc8: freepack&lt;br /&gt;
 04193c: freetopidx&lt;br /&gt;
 026be4: freetotop&lt;br /&gt;
 027f50: frenchjoycal&lt;br /&gt;
 0230f4: fromram&lt;br /&gt;
 01b7d8: front_facing&lt;br /&gt;
 03d55c: fruew11&lt;br /&gt;
 03d534: fruns11&lt;br /&gt;
 03d520: frusn11&lt;br /&gt;
 03d548: fruwe11&lt;br /&gt;
 015a34: fsavereq&lt;br /&gt;
 049862: fscrn&lt;br /&gt;
 03d320: fse11&lt;br /&gt;
 03d370: fse22&lt;br /&gt;
 036630: fseek&lt;br /&gt;
 04d164: fstyle&lt;br /&gt;
 03d334: fsw11&lt;br /&gt;
 03d384: fsw22&lt;br /&gt;
 036714: ftell&lt;br /&gt;
 049816: fts&lt;br /&gt;
 0370ac: fwrite&lt;br /&gt;
 058358: gCDTrackTime&lt;br /&gt;
 049859: gabort&lt;br /&gt;
 0051d0: game&lt;br /&gt;
 005df8: gameint&lt;br /&gt;
 005dc0: gameintinit&lt;br /&gt;
 04a97c: gameobjects1&lt;br /&gt;
 04a980: gameobjects2&lt;br /&gt;
 03bf22: gamepauseflag&lt;br /&gt;
 0476d0: gameres&lt;br /&gt;
 011d2c: genhline&lt;br /&gt;
 0245b4: get_pstring&lt;br /&gt;
 020d0c: getanimcounter&lt;br /&gt;
 03294c: getbiostick&lt;br /&gt;
 0365fc: getc&lt;br /&gt;
 036614: getchar&lt;br /&gt;
 022660: getcurrentpalette&lt;br /&gt;
 022e44: getdrive&lt;br /&gt;
 022ebc: getdriveacd&lt;br /&gt;
 022ee4: getdriveq&lt;br /&gt;
 02977f: getds&lt;br /&gt;
 036b68: getenv&lt;br /&gt;
 032310: getframeoffset&lt;br /&gt;
 011938: getmodelname&lt;br /&gt;
 025700: getmousepos&lt;br /&gt;
 026e54: getnum&lt;br /&gt;
 0224c0: getoppfilename&lt;br /&gt;
 01b78c: getoutcode&lt;br /&gt;
 0281e8: getpalette&lt;br /&gt;
 0281e8: getpalettefar&lt;br /&gt;
 01c498: getpinfo&lt;br /&gt;
 013598: getprotection&lt;br /&gt;
 015fd4: getres&lt;br /&gt;
 015fe4: getresl&lt;br /&gt;
 00e168: getsimdata&lt;br /&gt;
 02741c: getstring&lt;br /&gt;
 02742c: getstringi&lt;br /&gt;
 031200: gettick&lt;br /&gt;
 00d0e0: gettlistpoint&lt;br /&gt;
 01e21c: getwpinfo&lt;br /&gt;
 03d50c: gew11&lt;br /&gt;
 03da6c: ghyew11&lt;br /&gt;
 03da44: ghyns11&lt;br /&gt;
 03da30: ghysn11&lt;br /&gt;
 03da58: ghywe11&lt;br /&gt;
 03d4e4: gns11&lt;br /&gt;
 048814: go&lt;br /&gt;
 00b0fc: gotosim&lt;br /&gt;
 04709c: gpbmaps&lt;br /&gt;
 03fd2c: graphicmode&lt;br /&gt;
 03b270: gravity&lt;br /&gt;
 04985a: grip&lt;br /&gt;
 049804: ground&lt;br /&gt;
 048178: gs&lt;br /&gt;
 03d4d0: gsn11&lt;br /&gt;
 03d4f8: gwe11&lt;br /&gt;
 03adac: headingzones&lt;br /&gt;
 03d3d4: hew11&lt;br /&gt;
 026090: hiddenwindow&lt;br /&gt;
 0256b4: hidemouse&lt;br /&gt;
 02663c: hideprint&lt;br /&gt;
 0497f8: highestsceneryheight&lt;br /&gt;
 041948: highwater&lt;br /&gt;
 03fd2e: hirestext&lt;br /&gt;
 03d458: hne22&lt;br /&gt;
 03d3c0: hns11&lt;br /&gt;
 03d46c: hnw22&lt;br /&gt;
 0268b8: horizsync&lt;br /&gt;
 03d714: hpew11&lt;br /&gt;
 03d700: hpns11&lt;br /&gt;
 03d430: hse22&lt;br /&gt;
 03d444: hsw22&lt;br /&gt;
 0268c8: hsyncstate&lt;br /&gt;
 03d40c: huew11&lt;br /&gt;
 03d3e8: huns11&lt;br /&gt;
 015f50: hurrykey&lt;br /&gt;
 03da1c: hyew11&lt;br /&gt;
 03da08: hyns11&lt;br /&gt;
 03abfc: hzoneEN&lt;br /&gt;
 03ac44: hzoneES&lt;br /&gt;
 03abb4: hzoneNE&lt;br /&gt;
 03ab6c: hzoneNW&lt;br /&gt;
 03ac8c: hzoneSE&lt;br /&gt;
 03acd4: hzoneSW&lt;br /&gt;
 03ad64: hzoneWN&lt;br /&gt;
 03ad1c: hzoneWS&lt;br /&gt;
 026bd0: ifmodule&lt;br /&gt;
 047534: inint&lt;br /&gt;
 01e7a8: init_3dcars&lt;br /&gt;
 01e58c: init_3dpieces&lt;br /&gt;
 00df08: init_explode&lt;br /&gt;
 0498f8: initallcar&lt;br /&gt;
 00aa64: initcar&lt;br /&gt;
 021190: initcarmovesfx&lt;br /&gt;
 0310c4: initctimer&lt;br /&gt;
 0007c4: initdrawworld&lt;br /&gt;
 0310b4: initdtimer&lt;br /&gt;
 020264: initengine&lt;br /&gt;
 0201c0: initenginesfx&lt;br /&gt;
 0266fc: initgraphics&lt;br /&gt;
 000078: initinterpretsubs&lt;br /&gt;
 0275d0: initjoy&lt;br /&gt;
 0276ac: initjoyl&lt;br /&gt;
 0276b4: initjoyr&lt;br /&gt;
 00d834: initlogo&lt;br /&gt;
 026988: initmemmax&lt;br /&gt;
 026968: initmemory&lt;br /&gt;
 026998: initmemsize&lt;br /&gt;
 0000f4: initmodes&lt;br /&gt;
 0255a4: initmouse&lt;br /&gt;
 00745c: initmousedrive&lt;br /&gt;
 01bcdc: initnm&lt;br /&gt;
 02664c: initprofile&lt;br /&gt;
 02665c: initprofsect&lt;br /&gt;
 0046a0: initscenery&lt;br /&gt;
 0136d0: initselections&lt;br /&gt;
 00ac00: initsim&lt;br /&gt;
 03251c: initsound&lt;br /&gt;
 02745c: initstatekey&lt;br /&gt;
 03111c: initstimer&lt;br /&gt;
 026708: inittext&lt;br /&gt;
 0310a4: inittimer&lt;br /&gt;
 005d90: initworld&lt;br /&gt;
 027570: inkey&lt;br /&gt;
 022c94: installa&lt;br /&gt;
 022c54: installhigtrk&lt;br /&gt;
 01395c: instringz&lt;br /&gt;
 028080: int3dhypot&lt;br /&gt;
 030485: intatan&lt;br /&gt;
 03046f: intcos&lt;br /&gt;
 03d2fc: inte11&lt;br /&gt;
 027f08: interpretclear&lt;br /&gt;
 027e48: interpretkey&lt;br /&gt;
 027eb4: interpretsub&lt;br /&gt;
 030571: inthypot&lt;br /&gt;
 04986b: intraffic&lt;br /&gt;
 0303e7: intsin&lt;br /&gt;
 03fcec: invalid&lt;br /&gt;
 047434: inwater&lt;br /&gt;
 03d6ec: ipew11&lt;br /&gt;
 03d6d8: ipns11&lt;br /&gt;
 0355dc: itoa&lt;br /&gt;
 027bac: joybuttons&lt;br /&gt;
 027dd0: joybuttonsb&lt;br /&gt;
 027f4c: joycal&lt;br /&gt;
 03b492: joycaled&lt;br /&gt;
 041b54: joycalib&lt;br /&gt;
 027f54: joycall&lt;br /&gt;
 027f5c: joycallo&lt;br /&gt;
 027f60: joycalo&lt;br /&gt;
 027f58: joycalr&lt;br /&gt;
 027f64: joycalro&lt;br /&gt;
 041b58: joyclock&lt;br /&gt;
 027790: joycos&lt;br /&gt;
 027814: joycosb&lt;br /&gt;
 027864: joycosbi&lt;br /&gt;
 0277c4: joycosi&lt;br /&gt;
 041bc6: joydown&lt;br /&gt;
 041bca: joyleft&lt;br /&gt;
 041bc8: joyleftdown&lt;br /&gt;
 041bbc: joyleftup&lt;br /&gt;
 027f3c: joyoffl&lt;br /&gt;
 027f44: joyoffr&lt;br /&gt;
 027f80: joyon&lt;br /&gt;
 047542: joypad_state&lt;br /&gt;
 041bc2: joyright&lt;br /&gt;
 041bc4: joyrightdown&lt;br /&gt;
 041bc0: joyrightup&lt;br /&gt;
 0279e4: joystate&lt;br /&gt;
 027be8: joystateb&lt;br /&gt;
 0275d8: joystick&lt;br /&gt;
 0276bc: joystickb&lt;br /&gt;
 041bbe: joyup&lt;br /&gt;
 02763c: joyxpot&lt;br /&gt;
 027718: joyxpotl&lt;br /&gt;
 027788: joyxpotr&lt;br /&gt;
 027674: joyypot&lt;br /&gt;
 027750: joyypotl&lt;br /&gt;
 02778c: joyypotr&lt;br /&gt;
 0278e0: kbdjoystate&lt;br /&gt;
 03a43c: kcdr_status&lt;br /&gt;
 027f90: keybiosticks&lt;br /&gt;
 0475e8: keybordf&lt;br /&gt;
 027fa0: keyon&lt;br /&gt;
 041b50: keyprog&lt;br /&gt;
 02748c: keystate&lt;br /&gt;
 0278b8: keystatefast&lt;br /&gt;
 02755c: keysub&lt;br /&gt;
 041a4c: keysubs&lt;br /&gt;
 027584: keyticks&lt;br /&gt;
 0275a4: keywait&lt;br /&gt;
 027fb0: keywaitbios&lt;br /&gt;
 049855: lang&lt;br /&gt;
 047544: last_joypad_state&lt;br /&gt;
 049864: lastdash&lt;br /&gt;
 049863: lastdrawmode&lt;br /&gt;
 04986c: lastintraffic&lt;br /&gt;
 04986d: lastrbox&lt;br /&gt;
 049868: lastreplay&lt;br /&gt;
 04986a: lastrpause&lt;br /&gt;
 049870: lastscenery&lt;br /&gt;
 041be2: lbotfire&lt;br /&gt;
 049800: lclipby&lt;br /&gt;
 03f630: ldmsg&lt;br /&gt;
 0476d4: ledfont&lt;br /&gt;
 01bd18: lgabs&lt;br /&gt;
 053afc: library&lt;br /&gt;
 0213f8: limity&lt;br /&gt;
 043d44: linefunct&lt;br /&gt;
 041bee: ljoydown&lt;br /&gt;
 041bf2: ljoyleft&lt;br /&gt;
 041bf0: ljoyleftdown&lt;br /&gt;
 041be4: ljoyleftup&lt;br /&gt;
 041bea: ljoyright&lt;br /&gt;
 041bec: ljoyrightdown&lt;br /&gt;
 041be8: ljoyrightup&lt;br /&gt;
 041be6: ljoyup&lt;br /&gt;
 02251c: loadalloppfile&lt;br /&gt;
 010c74: loadalloppres&lt;br /&gt;
 00462c: loadallscene&lt;br /&gt;
 010d1c: loadallselopp&lt;br /&gt;
 025a50: loadandshapepack&lt;br /&gt;
 025a70: loadandshapepacka&lt;br /&gt;
 025a60: loadandshapepackz&lt;br /&gt;
 004858: loaddrawbits&lt;br /&gt;
 0231c8: loaddrivefile&lt;br /&gt;
 02312c: loaddrivefileatz&lt;br /&gt;
 02317c: loaddrivefilez&lt;br /&gt;
 026278: loadfile&lt;br /&gt;
 026298: loadfilea&lt;br /&gt;
 02617c: loadfileat&lt;br /&gt;
 0261f0: loadfileata&lt;br /&gt;
 026190: loadfileatz&lt;br /&gt;
 026288: loadfilez&lt;br /&gt;
 007180: loadgamefiles&lt;br /&gt;
 016870: loading&lt;br /&gt;
 0224d8: loadoppfile&lt;br /&gt;
 0262e4: loadpack&lt;br /&gt;
 026304: loadpacka&lt;br /&gt;
 026448: loadpackat&lt;br /&gt;
 026470: loadpackata&lt;br /&gt;
 02645c: loadpackatz&lt;br /&gt;
 0262f4: loadpackz&lt;br /&gt;
 0003cc: loadpalandmouse&lt;br /&gt;
 022880: loadram&lt;br /&gt;
 006728: loadreplay&lt;br /&gt;
 02575c: loadshape&lt;br /&gt;
 02577c: loadshapea&lt;br /&gt;
 02576c: loadshapez&lt;br /&gt;
 006618: loadtornamenttog&lt;br /&gt;
 0497d8: loady&lt;br /&gt;
 025820: locateshape&lt;br /&gt;
 02595c: locateshapes&lt;br /&gt;
 025990: locateshapesz&lt;br /&gt;
 0258c4: locateshapez&lt;br /&gt;
 041930: lockbotidx&lt;br /&gt;
 026a28: lockedmemory&lt;br /&gt;
 041934: locktopidx&lt;br /&gt;
 03d954: loflen22&lt;br /&gt;
 03d8e8: loflnw22&lt;br /&gt;
 03d930: loflse22&lt;br /&gt;
 03d90c: loflws22&lt;br /&gt;
 03d9e4: lofres22&lt;br /&gt;
 03d978: lofrne22&lt;br /&gt;
 03d9c0: lofrsw22&lt;br /&gt;
 03d99c: lofrwn22&lt;br /&gt;
 0048ac: logo&lt;br /&gt;
 047450: logo1&lt;br /&gt;
 047468: logo2&lt;br /&gt;
 04744c: logo_ticks&lt;br /&gt;
 047498: logoclip&lt;br /&gt;
 0497f6: lowestsceneryheight&lt;br /&gt;
 03d6c4: lpew21&lt;br /&gt;
 03d6b0: lpns21&lt;br /&gt;
 0497ec: lrndtime&lt;br /&gt;
 041be0: ltopfire&lt;br /&gt;
 00e508: main&lt;br /&gt;
 005bd0: mainkey&lt;br /&gt;
 03b364: mainres&lt;br /&gt;
 01e774: makecarname&lt;br /&gt;
 01b9e4: makematrix&lt;br /&gt;
 0159b8: makename&lt;br /&gt;
 019f6c: makeobjdef&lt;br /&gt;
 016aa4: maketime&lt;br /&gt;
 01c240: makezonelist&lt;br /&gt;
 0349e8: malloc&lt;br /&gt;
 04752a: maskdash&lt;br /&gt;
 04752c: maskshapes&lt;br /&gt;
 054310: matrix&lt;br /&gt;
 04221c: maxx&lt;br /&gt;
 042220: maxy&lt;br /&gt;
 049a04: mboxfile&lt;br /&gt;
 049a90: mboxzone&lt;br /&gt;
 052a70: mbuttons&lt;br /&gt;
 043c3c: mcgacolorxlate&lt;br /&gt;
 0329ed: mcgatranslation&lt;br /&gt;
 032a12: mcgatransrange&lt;br /&gt;
 047688: mch&lt;br /&gt;
 04768a: mchit&lt;br /&gt;
 04768c: mchithdg&lt;br /&gt;
 047684: mcp&lt;br /&gt;
 047686: mcr&lt;br /&gt;
 047678: mcx&lt;br /&gt;
 04767c: mcy&lt;br /&gt;
 047680: mcz&lt;br /&gt;
 016ff0: mdosexit&lt;br /&gt;
 01735c: memerr&lt;br /&gt;
 026e2c: memmovef&lt;br /&gt;
 027154: memsizedisplay&lt;br /&gt;
 0476cc: memwindow&lt;br /&gt;
 01bd28: mergezones&lt;br /&gt;
 0139d0: messagebox&lt;br /&gt;
 04a944: mheading_matrix&lt;br /&gt;
 04221a: minx&lt;br /&gt;
 04221e: miny&lt;br /&gt;
 0498ac: miscres&lt;br /&gt;
 0474a4: miscshapes&lt;br /&gt;
 047098: miscshapes2&lt;br /&gt;
 016d64: mjoycal&lt;br /&gt;
 016d74: mjoycalx&lt;br /&gt;
 016dd0: mkeyon&lt;br /&gt;
 000000: mloadmcgaz&lt;br /&gt;
 049a0c: mm_but&lt;br /&gt;
 020fbc: mm_drawbox&lt;br /&gt;
 020f5c: mm_drawcursor&lt;br /&gt;
 020ea0: mm_drawline&lt;br /&gt;
 020ec8: mm_drawrect&lt;br /&gt;
 020f34: mm_drawrectc&lt;br /&gt;
 020ff8: mm_fortextxy&lt;br /&gt;
 021078: mm_fshadowtext&lt;br /&gt;
 021038: mm_movtxy&lt;br /&gt;
 04a958: mmatrix&lt;br /&gt;
 016e34: mmouseon&lt;br /&gt;
 016ef8: mmusictog&lt;br /&gt;
 016e90: mnullfunc&lt;br /&gt;
 046d54: mnumzones&lt;br /&gt;
 03fd30: moddir&lt;br /&gt;
 0216b8: mode1off&lt;br /&gt;
 021660: mode1on&lt;br /&gt;
 03bbd0: modelname&lt;br /&gt;
 0514a4: modematrix&lt;br /&gt;
 0005b4: modsize&lt;br /&gt;
 026c64: modulesize&lt;br /&gt;
 025560: monocursor&lt;br /&gt;
 04570c: mos_control_flg&lt;br /&gt;
 045708: mos_event_adr&lt;br /&gt;
 045710: moswork_adr&lt;br /&gt;
 045714: moswork_seg&lt;br /&gt;
 03b462: mouseactive&lt;br /&gt;
 0497de: mouseb&lt;br /&gt;
 01666c: mousecursor&lt;br /&gt;
 03b45c: mousedrive&lt;br /&gt;
 03fcb4: mouseflag&lt;br /&gt;
 0497c8: mousemaskw&lt;br /&gt;
 01644c: mouseoff&lt;br /&gt;
 016428: mouseon&lt;br /&gt;
 03b463: mouseonscreen&lt;br /&gt;
 03b461: mouseonstat&lt;br /&gt;
 0497c4: mouseshapew&lt;br /&gt;
 03fcb8: mouseshown&lt;br /&gt;
 0074ac: mousesteer&lt;br /&gt;
 0497c0: mouseunderw&lt;br /&gt;
 0497da: mousex&lt;br /&gt;
 0497dc: mousey&lt;br /&gt;
 02a1de: movcf&lt;br /&gt;
 02a3e3: movcfxy&lt;br /&gt;
 02a41b: movcfxya&lt;br /&gt;
 00e06c: move_explode&lt;br /&gt;
 00dc54: move_on_plane&lt;br /&gt;
 008ef0: movecar&lt;br /&gt;
 005fdc: moveeverything&lt;br /&gt;
 006394: movehelicopters&lt;br /&gt;
 00d9e4: movelogo&lt;br /&gt;
 0087fc: moveopponent&lt;br /&gt;
 00b3d0: moveplayer&lt;br /&gt;
 00b1c0: movesim&lt;br /&gt;
 029b02: movf&lt;br /&gt;
 02743c: movftxy&lt;br /&gt;
 029bcc: movfxy&lt;br /&gt;
 029c04: movfxya&lt;br /&gt;
 049444: movp&lt;br /&gt;
 02bb73: movpackcf&lt;br /&gt;
 02bdca: movpackcfxy&lt;br /&gt;
 02be02: movpackcfxya&lt;br /&gt;
 02b052: movpackf&lt;br /&gt;
 02b117: movpackfxy&lt;br /&gt;
 02b14f: movpackfxya&lt;br /&gt;
 029a0a: movt&lt;br /&gt;
 0299e6: movtxy&lt;br /&gt;
 049abc: mpactive&lt;br /&gt;
 04a930: mpitch_matrix&lt;br /&gt;
 049ab4: mpstat&lt;br /&gt;
 03bf94: mpush&lt;br /&gt;
 017350: mretryhandler&lt;br /&gt;
 04a91c: mroll_matrix&lt;br /&gt;
 0171d0: msetrender&lt;br /&gt;
 0487c4: msong&lt;br /&gt;
 016f74: msoundtog&lt;br /&gt;
 0474a8: msteerx&lt;br /&gt;
 0474e8: msteerxvalid&lt;br /&gt;
 016e94: msystempause&lt;br /&gt;
 03b45d: musicon&lt;br /&gt;
 027fc0: musictog&lt;br /&gt;
 0487c0: mvoice&lt;br /&gt;
 052a6c: mx&lt;br /&gt;
 052a6e: my&lt;br /&gt;
 015120: mycenter&lt;br /&gt;
 016a4c: myclearfont&lt;br /&gt;
 047538: myclipzone&lt;br /&gt;
 000074: myfinddone&lt;br /&gt;
 000010: myfindfirst&lt;br /&gt;
 00006c: myfindnext&lt;br /&gt;
 024a99: mygetseeds&lt;br /&gt;
 0168b8: myitoa&lt;br /&gt;
 015c54: mykey&lt;br /&gt;
 0167ec: mykeywait&lt;br /&gt;
 016b98: myload&lt;br /&gt;
 016c58: myloadat&lt;br /&gt;
 01c3a8: mymemcmp&lt;br /&gt;
 04a98c: myobj&lt;br /&gt;
 024ab4: myrandom&lt;br /&gt;
 03b468: myseed&lt;br /&gt;
 016a2c: mysetfont&lt;br /&gt;
 024a7e: mysetseeds&lt;br /&gt;
 00cbe0: myupdatesfx&lt;br /&gt;
 00d07c: myupdatesfx1&lt;br /&gt;
 00d040: myupdatesfx2&lt;br /&gt;
 046ed0: mz&lt;br /&gt;
 047038: mzkey&lt;br /&gt;
 015b68: namecopy&lt;br /&gt;
 022f34: namedrive&lt;br /&gt;
 03f650: ndmsg&lt;br /&gt;
 026a84: negblockmove&lt;br /&gt;
 027514: nextkey&lt;br /&gt;
 03f658: nlmsg&lt;br /&gt;
 049880: nmps&lt;br /&gt;
 041984: noblkerr&lt;br /&gt;
 03b45e: nohandling&lt;br /&gt;
 04194c: nomemerr&lt;br /&gt;
 03becc: noreadpacket&lt;br /&gt;
 01bc0c: norm_zone&lt;br /&gt;
 0274cc: normkey&lt;br /&gt;
 0277f8: normkeyi&lt;br /&gt;
 054104: normkeysubs&lt;br /&gt;
 03fcd8: norowspc&lt;br /&gt;
 03fce8: notpack&lt;br /&gt;
 049810: npix&lt;br /&gt;
 03f65c: nrmsg&lt;br /&gt;
 03f654: nsmsg&lt;br /&gt;
 025548: nullfunction&lt;br /&gt;
 02554c: nullprint&lt;br /&gt;
 03c234: nullzone&lt;br /&gt;
 03a67e: numcolors&lt;br /&gt;
 027f68: numlockclear&lt;br /&gt;
 027fd0: numlockset&lt;br /&gt;
 0497a0: numroadblocks&lt;br /&gt;
 049818: numtrkcameras&lt;br /&gt;
 049819: numtrksigns&lt;br /&gt;
 049884: nzoneflag&lt;br /&gt;
 04a990: objtype1&lt;br /&gt;
 04bd18: objtype2&lt;br /&gt;
 03db48: objtypes&lt;br /&gt;
 03d834: oflen11&lt;br /&gt;
 03d7c8: oflnw11&lt;br /&gt;
 03d810: oflse11&lt;br /&gt;
 03d7ec: oflws11&lt;br /&gt;
 03d8c4: ofres11&lt;br /&gt;
 03d858: ofrne11&lt;br /&gt;
 03d8a0: ofrsw11&lt;br /&gt;
 03d87c: ofrwn11&lt;br /&gt;
 03b360: oldlist&lt;br /&gt;
 015f60: openresource&lt;br /&gt;
 022558: oppanim&lt;br /&gt;
 0514e0: oppfile&lt;br /&gt;
 03f610: oppfilename&lt;br /&gt;
 049850: oppinit&lt;br /&gt;
 03b470: oppname&lt;br /&gt;
 01fecc: opponentcompile&lt;br /&gt;
 0487f0: opponentlist&lt;br /&gt;
 0487b0: oppspeeds&lt;br /&gt;
 005fb0: optimizejoystick&lt;br /&gt;
 005f7c: optimizejoyxpot&lt;br /&gt;
 01164c: options&lt;br /&gt;
 02a6da: orcf&lt;br /&gt;
 02a901: orcfxy&lt;br /&gt;
 02a939: orcfxya&lt;br /&gt;
 0289a5: orcline&lt;br /&gt;
 029d83: orf&lt;br /&gt;
 029e6a: orfxy&lt;br /&gt;
 029ea2: orfxya&lt;br /&gt;
 028e7d: orline&lt;br /&gt;
 02c0f8: orpackcf&lt;br /&gt;
 02c356: orpackcfxy&lt;br /&gt;
 02c38e: orpackcfxya&lt;br /&gt;
 02b2b3: orpackf&lt;br /&gt;
 02b37f: orpackfxy&lt;br /&gt;
 02b3b7: orpackfxya&lt;br /&gt;
 0284a6: orpixel&lt;br /&gt;
 0283c0: orpixelc&lt;br /&gt;
 0290c1: orrect&lt;br /&gt;
 0293b9: orrectc&lt;br /&gt;
 026d84: packmemory&lt;br /&gt;
 042206: pagedwindow&lt;br /&gt;
 0260a0: pageflip&lt;br /&gt;
 03aacc: palcol1&lt;br /&gt;
 03aad0: palcol2&lt;br /&gt;
 03aad8: paldither&lt;br /&gt;
 0268d8: palettecolor&lt;br /&gt;
 03aad4: palstat&lt;br /&gt;
 020e80: paltocol&lt;br /&gt;
 049860: passed&lt;br /&gt;
 053af0: pauseflag&lt;br /&gt;
 032650: pausesound&lt;br /&gt;
 0326d4: pcmdone&lt;br /&gt;
 032668: pcmstart&lt;br /&gt;
 0326c4: pcmstop&lt;br /&gt;
 00decc: pdist&lt;br /&gt;
 04980c: penalty&lt;br /&gt;
 04981f: penaltytime&lt;br /&gt;
 049817: pflip&lt;br /&gt;
 0514a0: pict&lt;br /&gt;
 04980e: pix&lt;br /&gt;
 04222a: pixmaxx&lt;br /&gt;
 042228: pixminx&lt;br /&gt;
 00de3c: plane_distance&lt;br /&gt;
 0487a8: planes&lt;br /&gt;
 016a04: playsong&lt;br /&gt;
 043c2c: pm_ceoff&lt;br /&gt;
 043c34: pm_cesel&lt;br /&gt;
 0497a6: pnum&lt;br /&gt;
 0497a8: pobjx&lt;br /&gt;
 0497aa: pobjy&lt;br /&gt;
 0497ac: pobjz&lt;br /&gt;
 023bf4: pointinarray&lt;br /&gt;
 023c30: pointsetarray&lt;br /&gt;
 03b268: pointsizeinfo&lt;br /&gt;
 045200: polling_sub_int&lt;br /&gt;
 03158d: poly&lt;br /&gt;
 031590: polycmn&lt;br /&gt;
 043d3e: polycolor2&lt;br /&gt;
 043d40: polyfunct&lt;br /&gt;
 043d3c: polymask&lt;br /&gt;
 031562: polyp&lt;br /&gt;
 01b694: polysort&lt;br /&gt;
 026a10: poolmemory&lt;br /&gt;
 026a58: posblockmove&lt;br /&gt;
 029554: print&lt;br /&gt;
 0296e4: printattribute&lt;br /&gt;
 029703: printbyte&lt;br /&gt;
 029722: printbytexy&lt;br /&gt;
 029741: printchar&lt;br /&gt;
 029760: printcharxy&lt;br /&gt;
 029511: printclear&lt;br /&gt;
 02661c: printdivby0&lt;br /&gt;
 036848: printf&lt;br /&gt;
 0296c5: printscroll&lt;br /&gt;
 023598: printsjis&lt;br /&gt;
 02361c: printsk8&lt;br /&gt;
 0296a6: printxy&lt;br /&gt;
 02666c: profileoff&lt;br /&gt;
 02667c: profileon&lt;br /&gt;
 02668c: profsectoff&lt;br /&gt;
 02669c: profsecton&lt;br /&gt;
 030d14: projectc&lt;br /&gt;
 030939: projectorgp&lt;br /&gt;
 030ae1: projectp&lt;br /&gt;
 016d2c: pullmouse&lt;br /&gt;
 022540: purgealloppfile&lt;br /&gt;
 02757c: purgekey&lt;br /&gt;
 026bf4: purgememory&lt;br /&gt;
 022504: purgeoppfile&lt;br /&gt;
 0324e8: purgesound&lt;br /&gt;
 016d04: pushmouse&lt;br /&gt;
 024b3b: putsjis&lt;br /&gt;
 025013: putsk8&lt;br /&gt;
 024e3e: putskana16&lt;br /&gt;
 024f01: putskana8&lt;br /&gt;
 026978: quitmemory&lt;br /&gt;
 02562c: quitmouse&lt;br /&gt;
 03bece: r_bgcolor&lt;br /&gt;
 0498f2: raceresult&lt;br /&gt;
 0339d8: rand&lt;br /&gt;
 031f2c: random&lt;br /&gt;
 031428: randompoly&lt;br /&gt;
 031438: randompolyf&lt;br /&gt;
 031448: randompolyi&lt;br /&gt;
 031458: randompolyip&lt;br /&gt;
 031468: randompolyipt&lt;br /&gt;
 031478: randompolyit&lt;br /&gt;
 031488: randompolyp&lt;br /&gt;
 031498: randompolypt&lt;br /&gt;
 0314a8: randompolyt&lt;br /&gt;
 041bce: rbotfire&lt;br /&gt;
 005198: read_joypad&lt;br /&gt;
 02de53: readf&lt;br /&gt;
 02ded3: readfxy&lt;br /&gt;
 02df0b: readfxya&lt;br /&gt;
 0268e8: readhiddenscreen&lt;br /&gt;
 011988: readhighs&lt;br /&gt;
 025580: readmonoatt&lt;br /&gt;
 025570: readmonochar&lt;br /&gt;
 025658: readmouse&lt;br /&gt;
 028508: readpixel&lt;br /&gt;
 0268f8: readscreen&lt;br /&gt;
 026908: redshift&lt;br /&gt;
 01ec60: remove_3dcars&lt;br /&gt;
 01e740: remove_3dpieces&lt;br /&gt;
 00489c: removedrawbits&lt;br /&gt;
 0073e4: removegamefiles&lt;br /&gt;
 005de0: removegameint&lt;br /&gt;
 00482c: removescenery&lt;br /&gt;
 025e98: removewindow&lt;br /&gt;
 04a104: render_matrix&lt;br /&gt;
 03b464: renderlevel&lt;br /&gt;
 049a50: replay_flag&lt;br /&gt;
 049460: replaybuff&lt;br /&gt;
 0474a0: replaybuflen&lt;br /&gt;
 049464: replayso&lt;br /&gt;
 026ab4: reservememory&lt;br /&gt;
 021264: resetalltextbuf&lt;br /&gt;
 032838: resetcriterr&lt;br /&gt;
 0265f8: resetdivby0&lt;br /&gt;
 0266ac: resetprofile&lt;br /&gt;
 0266bc: resetprofsect&lt;br /&gt;
 027484: resetstatekey&lt;br /&gt;
 02123c: resettextbuf&lt;br /&gt;
 031228: resettick&lt;br /&gt;
 026cac: resizememory&lt;br /&gt;
 000588: resmem&lt;br /&gt;
 014b24: restoreboxwindow&lt;br /&gt;
 0272e0: restorefont&lt;br /&gt;
 021118: restorefont4&lt;br /&gt;
 022694: restorepalette&lt;br /&gt;
 02138c: restoretext&lt;br /&gt;
 021510: restoretextbox&lt;br /&gt;
 021348: restoretextgraphic&lt;br /&gt;
 021468: restoretextwindow&lt;br /&gt;
 031174: restoretimer&lt;br /&gt;
 025f68: restorewindow&lt;br /&gt;
 03265c: resumesound&lt;br /&gt;
 023b44: reverse_edge&lt;br /&gt;
 036780: rewind&lt;br /&gt;
 0328c0: ring&lt;br /&gt;
 041bda: rjoydown&lt;br /&gt;
 041bde: rjoyleft&lt;br /&gt;
 041bdc: rjoyleftdown&lt;br /&gt;
 041bd0: rjoyleftup&lt;br /&gt;
 041bd6: rjoyright&lt;br /&gt;
 041bd8: rjoyrightdown&lt;br /&gt;
 041bd4: rjoyrightup&lt;br /&gt;
 041bd2: rjoyup&lt;br /&gt;
 043c28: rm_cevec&lt;br /&gt;
 0487a0: rndseed&lt;br /&gt;
 04979e: rndtime&lt;br /&gt;
 0487d4: roadlistc&lt;br /&gt;
 0487d8: roadlistld&lt;br /&gt;
 0487e8: roadlistp1&lt;br /&gt;
 0487ec: roadlistp2&lt;br /&gt;
 0487dc: roadlistx&lt;br /&gt;
 0487e0: roadlistz&lt;br /&gt;
 0200c4: roadupcheck&lt;br /&gt;
 042216: rowtbl&lt;br /&gt;
 049857: rpause&lt;br /&gt;
 04987c: rpfxrate&lt;br /&gt;
 04985e: rspeed&lt;br /&gt;
 041bcc: rtopfire&lt;br /&gt;
 0494a4: rtzline&lt;br /&gt;
 03d494: ruew11&lt;br /&gt;
 03d480: runs11&lt;br /&gt;
 03d4a8: rusn11&lt;br /&gt;
 03d4bc: ruwe11&lt;br /&gt;
 031885: s1linex&lt;br /&gt;
 0317c3: s1linexc&lt;br /&gt;
 0319df: s2linex&lt;br /&gt;
 0227a0: sameext&lt;br /&gt;
 03afb0: samplefile&lt;br /&gt;
 014a30: saveboxwindow&lt;br /&gt;
 021374: savecurrenttextwindow&lt;br /&gt;
 023050: savedrivefile&lt;br /&gt;
 022fc0: savedrivefilez&lt;br /&gt;
 030f43: savefile&lt;br /&gt;
 030f57: savefilez&lt;br /&gt;
 022ac8: savefloppy&lt;br /&gt;
 0272d0: savefont&lt;br /&gt;
 0210e4: savefont4&lt;br /&gt;
 012054: savehighs&lt;br /&gt;
 0173f8: saveobject&lt;br /&gt;
 02267c: savepalette&lt;br /&gt;
 0266cc: saveprofile&lt;br /&gt;
 0266dc: saveprofsect&lt;br /&gt;
 022828: saveram&lt;br /&gt;
 022d3c: saveramfiles&lt;br /&gt;
 006788: savereplay&lt;br /&gt;
 021330: savetextgraphic&lt;br /&gt;
 021304: savetextwindow&lt;br /&gt;
 021350: savetextzone&lt;br /&gt;
 025f4c: savewindow&lt;br /&gt;
 02d6cf: scalecf&lt;br /&gt;
 02d858: scalecfxy&lt;br /&gt;
 02d88d: scalecfxya&lt;br /&gt;
 02d54a: scalef&lt;br /&gt;
 02d679: scalefxy&lt;br /&gt;
 02d6ae: scalefxya&lt;br /&gt;
 02dae8: scalereccf&lt;br /&gt;
 02ddd6: scalereccfxy&lt;br /&gt;
 02de32: scalereccfxya&lt;br /&gt;
 02d8ae: scalerecf&lt;br /&gt;
 02da6b: scalerecfxy&lt;br /&gt;
 02dac7: scalerecfxya&lt;br /&gt;
 032706: scalethicknessxp&lt;br /&gt;
 032722: scalethicknessyp&lt;br /&gt;
 027fe0: scancode&lt;br /&gt;
 049848: scarname&lt;br /&gt;
 047438: scenefile&lt;br /&gt;
 03aeb2: sceneloaded&lt;br /&gt;
 047414: scenery&lt;br /&gt;
 047424: sceneryh&lt;br /&gt;
 03b460: sceneryloaded&lt;br /&gt;
 047410: sceneshapes&lt;br /&gt;
 042222: scrbyts&lt;br /&gt;
 026928: screenorigin&lt;br /&gt;
 026918: screensnap&lt;br /&gt;
 04222c: screenwindow&lt;br /&gt;
 053aa0: screenwindowsec&lt;br /&gt;
 053ac4: screenwindowvga&lt;br /&gt;
 016828: screenwipe&lt;br /&gt;
 04220a: scrfrm&lt;br /&gt;
 049798: scriptindex&lt;br /&gt;
 04979a: scriptindexend&lt;br /&gt;
 049861: scrn&lt;br /&gt;
 049a08: scrnfile&lt;br /&gt;
 03b35c: scrnlist&lt;br /&gt;
 026938: scrolldown&lt;br /&gt;
 026948: scrollup&lt;br /&gt;
 04220e: scrseg&lt;br /&gt;
 042226: scrxpixels&lt;br /&gt;
 053afe: sectionnumber&lt;br /&gt;
 043bf8: seed&lt;br /&gt;
 00035c: seedrandom&lt;br /&gt;
 0254c0: segtoadr&lt;br /&gt;
 00f64c: select&lt;br /&gt;
 00fe8c: selectcar&lt;br /&gt;
 010dd0: selectopponent&lt;br /&gt;
 021230: selecttextbuf&lt;br /&gt;
 0498c4: selofile&lt;br /&gt;
 0498c8: seloshapes&lt;br /&gt;
 032964: setbiosticks&lt;br /&gt;
 0215bc: setblackpal&lt;br /&gt;
 0226ac: setblacktext&lt;br /&gt;
 0265f4: setdivby0&lt;br /&gt;
 0272f0: setfont&lt;br /&gt;
 027ff0: setjoykeys&lt;br /&gt;
 028000: setjoykeysl&lt;br /&gt;
 028010: setjoykeysr&lt;br /&gt;
 025634: setmousebounds&lt;br /&gt;
 0256d8: setmousepos&lt;br /&gt;
 0255a0: setmouseratio&lt;br /&gt;
 025734: setmousex&lt;br /&gt;
 025748: setmousey&lt;br /&gt;
 0324e4: setmusicabort&lt;br /&gt;
 030c51: setprojectc&lt;br /&gt;
 03099a: setprojectp&lt;br /&gt;
 030978: setprojectpb&lt;br /&gt;
 0314b8: setrandompix&lt;br /&gt;
 031234: setticks&lt;br /&gt;
 01ecf4: settires&lt;br /&gt;
 027f6c: settypeahead&lt;br /&gt;
 030f28: setzclip&lt;br /&gt;
 03b260: sfpostsizeinfo&lt;br /&gt;
 04988c: sfxfile&lt;br /&gt;
 032570: sfxoff&lt;br /&gt;
 032590: sfxon&lt;br /&gt;
 049871: sfxstat&lt;br /&gt;
 049872: sfxstat1&lt;br /&gt;
 049873: sfxstat2&lt;br /&gt;
 0325b0: sfxtoggle&lt;br /&gt;
 024a5d: sgn&lt;br /&gt;
 01676c: shadowtext&lt;br /&gt;
 0259c4: shapecount&lt;br /&gt;
 025a24: shapename&lt;br /&gt;
 025ad4: shapepack&lt;br /&gt;
 0259d0: shapepointer&lt;br /&gt;
 025380: shellsort&lt;br /&gt;
 026958: shiftscreen&lt;br /&gt;
 025690: showmouse&lt;br /&gt;
 0266ec: showprint&lt;br /&gt;
 03fcd0: shperrmsg&lt;br /&gt;
 03b258: signsizeinfo&lt;br /&gt;
 0043a0: sink&lt;br /&gt;
 03f7c8: sjistable&lt;br /&gt;
 052170: sk_str&lt;br /&gt;
 045704: skb_event_adr&lt;br /&gt;
 049802: sky&lt;br /&gt;
 02f819: slopeline&lt;br /&gt;
 0476d8: smallfont&lt;br /&gt;
 04985f: smdelay&lt;br /&gt;
 03fcd4: snderrmsg&lt;br /&gt;
 0476dc: so&lt;br /&gt;
 04985b: solid&lt;br /&gt;
 032df8: solidellipseh&lt;br /&gt;
 020a98: solidtire&lt;br /&gt;
 049890: songfile&lt;br /&gt;
 0325d4: songoff&lt;br /&gt;
 0325fc: songon&lt;br /&gt;
 032640: songover&lt;br /&gt;
 032624: songtoggle&lt;br /&gt;
 01c318: sortzonelist&lt;br /&gt;
 03567c: sound_bios&lt;br /&gt;
 0356a0: sound_bios2&lt;br /&gt;
 028020: soundoff&lt;br /&gt;
 028030: soundon&lt;br /&gt;
 028040: soundtog&lt;br /&gt;
 049808: speedocol&lt;br /&gt;
 03d764: spew11&lt;br /&gt;
 03d73c: spns11&lt;br /&gt;
 0368f8: sprintf&lt;br /&gt;
 03d728: spsn11&lt;br /&gt;
 03d750: spwe11&lt;br /&gt;
 033a00: srand&lt;br /&gt;
 0311f8: sseqds&lt;br /&gt;
 04985d: staging&lt;br /&gt;
 028050: standardkeys&lt;br /&gt;
 041c86: standfont&lt;br /&gt;
 0497a2: startblockhdg&lt;br /&gt;
 04981a: startblockx&lt;br /&gt;
 04981c: startblocky&lt;br /&gt;
 04981b: startblockz&lt;br /&gt;
 02114c: startcarsfx&lt;br /&gt;
 020720: startengine&lt;br /&gt;
 020948: startskid&lt;br /&gt;
 0209a4: startskid2&lt;br /&gt;
 041b78: statekey&lt;br /&gt;
 041b98: statekeyb&lt;br /&gt;
 047548: status&lt;br /&gt;
 049878: steerval&lt;br /&gt;
 020730: stopengine&lt;br /&gt;
 020a00: stopskid&lt;br /&gt;
 033ad0: strcat&lt;br /&gt;
 033b94: strchr&lt;br /&gt;
 033a0c: strcpy&lt;br /&gt;
 016014: strcpyfar&lt;br /&gt;
 0355e4: stricmp&lt;br /&gt;
 033b38: strncmp&lt;br /&gt;
 033a50: strncpy&lt;br /&gt;
 039c2c: strnicmp&lt;br /&gt;
 025590: structshellsortup&lt;br /&gt;
 041bf4: suppressprint&lt;br /&gt;
 03f62c: svmsg&lt;br /&gt;
 049a54: sw&lt;br /&gt;
 043c20: swSFX&lt;br /&gt;
 043c24: swSong&lt;br /&gt;
 03b466: swindowindex&lt;br /&gt;
 021620: switch_palette&lt;br /&gt;
 049a74: swmemerror&lt;br /&gt;
 03f648: swmsg&lt;br /&gt;
 049a78: swwindow&lt;br /&gt;
 049874: swwindowtbl&lt;br /&gt;
 01a00c: symTransf&lt;br /&gt;
 028060: systempause&lt;br /&gt;
 046dd0: sz&lt;br /&gt;
 046e48: szalt&lt;br /&gt;
 047094: szheading&lt;br /&gt;
 04980a: tcamlen&lt;br /&gt;
 04768e: tclipy&lt;br /&gt;
 04714c: td&lt;br /&gt;
 047150: tdraw&lt;br /&gt;
 047110: tdrawindex&lt;br /&gt;
 0470b0: tdrawnum&lt;br /&gt;
 0470b4: tdrawobj&lt;br /&gt;
 0470d4: tdrawsvalue&lt;br /&gt;
 00f858: teditmain&lt;br /&gt;
 049a34: tempshape&lt;br /&gt;
 047774: tempstring&lt;br /&gt;
 03b450: terheight&lt;br /&gt;
 0487d0: terrain&lt;br /&gt;
 0329a0: testbiosticks&lt;br /&gt;
 0274c4: testkey&lt;br /&gt;
 031258: testticks&lt;br /&gt;
 04d170: textbuf&lt;br /&gt;
 041c80: textchr&lt;br /&gt;
 0299b2: textchrxy&lt;br /&gt;
 02729c: textcolor&lt;br /&gt;
 03f16c: textend&lt;br /&gt;
 0272fc: textnpixels&lt;br /&gt;
 027378: textpixels&lt;br /&gt;
 0272b4: textposition&lt;br /&gt;
 03f168: textwindowoff&lt;br /&gt;
 04d168: textzone&lt;br /&gt;
 03d2e8: tfew11&lt;br /&gt;
 03d2d4: tfns11&lt;br /&gt;
 0495d0: tfzs&lt;br /&gt;
 04960c: tfzsh&lt;br /&gt;
 0326ec: thickness&lt;br /&gt;
 03273e: thicknessxp&lt;br /&gt;
 03275e: thicknessyp&lt;br /&gt;
 031208: tickcount&lt;br /&gt;
 058324: ticks&lt;br /&gt;
 058328: tickset&lt;br /&gt;
 05832c: tickval&lt;br /&gt;
 028070: timedmessage&lt;br /&gt;
 031274: timedwait&lt;br /&gt;
 0451f4: timer_a_int&lt;br /&gt;
 0451f8: timer_b_int&lt;br /&gt;
 0451fc: timer_sub_int&lt;br /&gt;
 031018: timerint&lt;br /&gt;
 03105c: timerintb&lt;br /&gt;
 020a40: tire&lt;br /&gt;
 0498f4: titlefile&lt;br /&gt;
 0498a8: titleptr&lt;br /&gt;
 00f4b4: titles&lt;br /&gt;
 02abf8: tmaskcf&lt;br /&gt;
 02adcc: tmaskcfxy&lt;br /&gt;
 02ae04: tmaskcfxya&lt;br /&gt;
 02a021: tmaskf&lt;br /&gt;
 02a0ab: tmaskfxy&lt;br /&gt;
 02a0e3: tmaskfxya&lt;br /&gt;
 02cdd1: tmaskhpackcf&lt;br /&gt;
 02d12c: tmaskhpackcfxy&lt;br /&gt;
 02d167: tmaskhpackcfxya&lt;br /&gt;
 02b836: tmaskhpackf&lt;br /&gt;
 02b976: tmaskhpackfxy&lt;br /&gt;
 02b9b1: tmaskhpackfxya&lt;br /&gt;
 02c684: tmaskpackcf&lt;br /&gt;
 02c9ca: tmaskpackcfxy&lt;br /&gt;
 02ca02: tmaskpackcfxya&lt;br /&gt;
 02b51b: tmaskpackf&lt;br /&gt;
 02b64d: tmaskpackfxy&lt;br /&gt;
 02b685: tmaskpackfxya&lt;br /&gt;
 02ae34: tmaskxcf&lt;br /&gt;
 02b008: tmaskxcfxy&lt;br /&gt;
 02b031: tmaskxcfxya&lt;br /&gt;
 02a113: tmaskxf&lt;br /&gt;
 02a194: tmaskxfxy&lt;br /&gt;
 02a1bd: tmaskxfxya&lt;br /&gt;
 02d197: tmaskxhpackcf&lt;br /&gt;
 02d4fd: tmaskxhpackcfxy&lt;br /&gt;
 02d529: tmaskxhpackcfxya&lt;br /&gt;
 02b9e1: tmaskxhpackf&lt;br /&gt;
 02bb26: tmaskxhpackfxy&lt;br /&gt;
 02bb52: tmaskxhpackfxya&lt;br /&gt;
 02ca32: tmaskxpackcf&lt;br /&gt;
 02cd87: tmaskxpackcfxy&lt;br /&gt;
 02cdb0: tmaskxpackcfxya&lt;br /&gt;
 02b6b5: tmaskxpackf&lt;br /&gt;
 02b7ec: tmaskxpackfxy&lt;br /&gt;
 02b815: tmaskxpackfxya&lt;br /&gt;
 041940: tmem&lt;br /&gt;
 058330: tmrsub&lt;br /&gt;
 022f0c: togdrive&lt;br /&gt;
 022f90: toobig&lt;br /&gt;
 041bb8: topfire&lt;br /&gt;
 03b480: tornamentflag&lt;br /&gt;
 00e258: tornamentload&lt;br /&gt;
 03b482: tornamentmode&lt;br /&gt;
 022384: tornamentmodecheck&lt;br /&gt;
 00e270: tornamenttog&lt;br /&gt;
 03afc0: tournamentcontinue&lt;br /&gt;
 03f64c: tqmsg&lt;br /&gt;
 022450: trackdataupdate&lt;br /&gt;
 017524: trackedit&lt;br /&gt;
 0487c8: trackmatrix&lt;br /&gt;
 0498f0: tracknum&lt;br /&gt;
 019d9c: trackoverlapcheck&lt;br /&gt;
 03061f: transform&lt;br /&gt;
 0307cf: transmult&lt;br /&gt;
 035f97: transparentpf&lt;br /&gt;
 0314c8: transparentpoly&lt;br /&gt;
 035f84: transparentpolyf&lt;br /&gt;
 0314d8: transparentpolyi&lt;br /&gt;
 0314e8: transparentpolyip&lt;br /&gt;
 0314f8: transparentpolyipt&lt;br /&gt;
 031508: transparentpolyit&lt;br /&gt;
 036047: transparentpolyp&lt;br /&gt;
 03602c: transparentpolypt&lt;br /&gt;
 031518: transparentpolyt&lt;br /&gt;
 0308a9: transpose&lt;br /&gt;
 04880c: trkcamera&lt;br /&gt;
 048800: trkcamerag&lt;br /&gt;
 0487fc: trkcamerah&lt;br /&gt;
 048810: trksign&lt;br /&gt;
 048808: trksignh&lt;br /&gt;
 048804: trksignt&lt;br /&gt;
 0497ea: truckdoor&lt;br /&gt;
 02516e: twomicechk&lt;br /&gt;
 049558: txs&lt;br /&gt;
 049594: txsh&lt;br /&gt;
 049468: tzline&lt;br /&gt;
 0494e0: tzs&lt;br /&gt;
 04951c: tzsh&lt;br /&gt;
 025d3c: unflip&lt;br /&gt;
 026594: unhuff&lt;br /&gt;
 026a40: unlockedmemory&lt;br /&gt;
 0264f4: unpacksize&lt;br /&gt;
 026514: unpacksizea&lt;br /&gt;
 026504: unpacksizez&lt;br /&gt;
 026588: unrunpack&lt;br /&gt;
 020654: updateengine&lt;br /&gt;
 0165d4: updatemouseunder&lt;br /&gt;
 016744: usebuffer&lt;br /&gt;
 016754: usebufferc&lt;br /&gt;
 049865: usedash&lt;br /&gt;
 049867: usereplay&lt;br /&gt;
 01672c: usescreen&lt;br /&gt;
 016734: usescreenc&lt;br /&gt;
 024590: validchar&lt;br /&gt;
 02662c: validdrive&lt;br /&gt;
 03d248: vcew21&lt;br /&gt;
 03d234: vcns21&lt;br /&gt;
 025d4c: vertflip&lt;br /&gt;
 028231: vertsync&lt;br /&gt;
 028240: vertsyncend&lt;br /&gt;
 028231: vertsyncstart&lt;br /&gt;
 0367ec: vfprintf&lt;br /&gt;
 028188: vgapalette&lt;br /&gt;
 028188: vgapalettefar&lt;br /&gt;
 053af8: videopage&lt;br /&gt;
 053af4: videowindow&lt;br /&gt;
 0260b0: videowindowdef&lt;br /&gt;
 0497f4: viewheading&lt;br /&gt;
 049888: voicefile&lt;br /&gt;
 036828: vprintf&lt;br /&gt;
 0368c4: vsprintf&lt;br /&gt;
 02824f: vsyncstate&lt;br /&gt;
 0329c7: waitbios&lt;br /&gt;
 032982: waitbiosticks&lt;br /&gt;
 016710: waitforkey&lt;br /&gt;
 031248: waitticks&lt;br /&gt;
 0497ae: wall&lt;br /&gt;
 04985c: wall2sided&lt;br /&gt;
 0497b4: wallh&lt;br /&gt;
 0497b8: wallhgtb&lt;br /&gt;
 0497b6: wallhgtt&lt;br /&gt;
 0487ac: walls&lt;br /&gt;
 0497b0: wallx&lt;br /&gt;
 0497b2: wallz&lt;br /&gt;
 047528: watch&lt;br /&gt;
 049806: water&lt;br /&gt;
 047436: watercar&lt;br /&gt;
 0260c0: whichpage&lt;br /&gt;
 0260d0: whichwindow&lt;br /&gt;
 00e43c: wincheck&lt;br /&gt;
 0487f4: winddrag1&lt;br /&gt;
 0487f8: winddrag2&lt;br /&gt;
 03fcdc: windotxt&lt;br /&gt;
 025eb4: window&lt;br /&gt;
 0497f0: windowbottom&lt;br /&gt;
 025d90: windowdef&lt;br /&gt;
 053afa: windowpage&lt;br /&gt;
 0497ee: windowtop&lt;br /&gt;
 027260: wordfill&lt;br /&gt;
 027288: wordfillf&lt;br /&gt;
 028444: writepixel&lt;br /&gt;
 028332: writepixelc&lt;br /&gt;
 0437a9: xbangle&lt;br /&gt;
 03d298: xfew11&lt;br /&gt;
 03d284: xfns11&lt;br /&gt;
 0280a0: xformx&lt;br /&gt;
 0280ec: xformy&lt;br /&gt;
 02813c: xformz&lt;br /&gt;
 03d25c: xfsn11&lt;br /&gt;
 03d270: xfwe11&lt;br /&gt;
 0497d4: xmousemaskw&lt;br /&gt;
 0497d0: xmouseshapew&lt;br /&gt;
 0497cc: xmouseunderw&lt;br /&gt;
 031290: xorbox&lt;br /&gt;
 02a969: xorcf&lt;br /&gt;
 02ab90: xorcfxy&lt;br /&gt;
 02abc8: xorcfxya&lt;br /&gt;
 028bc0: xorcline&lt;br /&gt;
 02744c: xorcursor&lt;br /&gt;
 029ed2: xorf&lt;br /&gt;
 029fb9: xorfxy&lt;br /&gt;
 029ff1: xorfxya&lt;br /&gt;
 028ece: xorline&lt;br /&gt;
 02c3be: xorpackcf&lt;br /&gt;
 02c61c: xorpackcfxy&lt;br /&gt;
 02c654: xorpackcfxya&lt;br /&gt;
 02b3e7: xorpackf&lt;br /&gt;
 02b4b3: xorpackfxy&lt;br /&gt;
 02b4eb: xorpackfxya&lt;br /&gt;
 0284d7: xorpixel&lt;br /&gt;
 0283fa: xorpixelc&lt;br /&gt;
 029191: xorrect&lt;br /&gt;
 029465: xorrectc&lt;br /&gt;
 0437b1: xproject&lt;br /&gt;
 0437a5: xscale&lt;br /&gt;
 0260e0: xscroll&lt;br /&gt;
 0260f0: xscrollwindow&lt;br /&gt;
 03fcb6: xshiftflag&lt;br /&gt;
 0437ab: ybangle&lt;br /&gt;
 0439b3: yproject&lt;br /&gt;
 0437a7: yscale&lt;br /&gt;
 030ea2: zclip&lt;br /&gt;
 030eb6: zclipline&lt;br /&gt;
 04979c: zerotime&lt;br /&gt;
 049a88: zone4&lt;br /&gt;
 01c1c8: zoneadjacent&lt;br /&gt;
 01bbc0: zonecheck&lt;br /&gt;
 01c190: zoneinside&lt;br /&gt;
 01c158: zoneoverlap&lt;br /&gt;
 046ec0: zv&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
[[Category:Internals]]&lt;/div&gt;</summary>
		<author><name>Dstien</name></author>
	</entry>
	<entry>
		<id>https://wiki.stunts.hu/index.php?title=Compression&amp;diff=5814</id>
		<title>Compression</title>
		<link rel="alternate" type="text/html" href="https://wiki.stunts.hu/index.php?title=Compression&amp;diff=5814"/>
		<updated>2024-01-23T17:23:17Z</updated>

		<summary type="html">&lt;p&gt;Dstien: /* Huffman coding */ Emphasis on the codebook being canonical.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Stunts and its ports uses multiple compression formats for code and [[Resource_file_format|resource files]] to save disk space and, more importantly, the number of floppy disks used to distribute the game. &lt;br /&gt;
&lt;br /&gt;
== Formats by game version ==&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! rowspan=3 colspan=3 | Game version !! colspan=4 | DSI packing !! rowspan=2 colspan=2 | EAC packing !! rowspan=3 | RPck&lt;br /&gt;
|-&lt;br /&gt;
! rowspan=2 | RLE !! colspan=3 | Huffman&lt;br /&gt;
|-&lt;br /&gt;
! Supported !! Prefix table !! Code endianness !! Huffman !! BPE&lt;br /&gt;
|-&lt;br /&gt;
! rowspan=4 style=text-align:left | MS DOS !! rowspan=2 | BB 1.0 !! style=text-align:left | Game&lt;br /&gt;
| style=text-align:center | X || style=text-align:center | X || || Big || || ||&lt;br /&gt;
|-&lt;br /&gt;
! style=text-align:left | Loader&lt;br /&gt;
| || style=text-align:center | X || style=text-align:center | X || Little || || ||&lt;br /&gt;
|-&lt;br /&gt;
! rowspan=2 | BB 1.1/MS 1.1 !! style=text-align:left | Game&lt;br /&gt;
| style=text-align:center | X || style=text-align:center | X || style=text-align:center | X || Little || || ||&lt;br /&gt;
|-&lt;br /&gt;
! style=text-align:left | Loader&lt;br /&gt;
| || style=text-align:center | X || style=text-align:center | X || Little || || ||&lt;br /&gt;
|-&lt;br /&gt;
! colspan=3 style=text-align:left | Amiga&lt;br /&gt;
| || || || || style=text-align:center | X || style=text-align:center | X || style=text-align:center | X&lt;br /&gt;
|-&lt;br /&gt;
! colspan=3 style=text-align:left | PC98&lt;br /&gt;
| || || || || || style=text-align:center | X ||&lt;br /&gt;
|-&lt;br /&gt;
! colspan=3 style=text-align:left | FM Towns&lt;br /&gt;
| || || || || || ||&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== DSI packing ==&lt;br /&gt;
The original release of Stunts for MS DOS uses a custom data compression format not found in the ports to other platforms. The code may have been hand-crafted for 16-bit x86 since other options were favoured in the later ports. The format does not have any identification bytes, so we will refer to it as &#039;&#039;DSI packing&#039;&#039; as it appeared in several DSI games in the late 80&#039;s and early 90&#039;s.&lt;br /&gt;
&lt;br /&gt;
The data format supports both [https://en.wikipedia.org/wiki/Run-length_encoding run-length encoding] (RLE) and [https://en.wikipedia.org/wiki/Huffman_coding Huffman coding]. They can be combined in multiple passes. The data format and the decompression code don&#039;t require any particular order or combination of algorithms. Every compressed file shipped with the game use Huffman coding, and when combined with RLE, the RLE pass is applied before Huffman.&lt;br /&gt;
&lt;br /&gt;
=== File header ===&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;enum&amp;lt;/span&amp;gt; CompressionType &amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;{&amp;lt;/span&amp;gt;&lt;br /&gt;
     RLE     = 1&lt;br /&gt;
     Huffman = 2&lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;}&amp;lt;/span&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;struct&amp;lt;/span&amp;gt; Header &amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;{&amp;lt;/span&amp;gt;&lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;union&amp;lt;/span&amp;gt; &amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;{&amp;lt;/span&amp;gt;&lt;br /&gt;
         &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt; passes : 7&lt;br /&gt;
         &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt; compression_type : 7&lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;}&amp;lt;/span&amp;gt;&lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt;  multi_pass : 1&lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint32&amp;lt;/span&amp;gt; uncompressed_size : 24&lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;}&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
If the most significant bit of the first byte of the file is set, this is a multi-pass file and the remaining 7 bits are the number of passes to be processed recursively. If the &amp;lt;tt&amp;gt;multi_pass&amp;lt;/tt&amp;gt; flag is not set, we are only doing a single pass and the first byte is the compression type. The next three bytes make up the uncompressed size. If the &amp;lt;tt&amp;gt;multi_pass&amp;lt;/tt&amp;gt; flag was set, this is the final uncompressed size. When the &amp;lt;tt&amp;gt;multi_pass&amp;lt;/tt&amp;gt; flag is not set, this is the uncompressed size of the current pass. The remaining data is processed recursively. The &amp;lt;tt&amp;gt;compression_type&amp;lt;/tt&amp;gt; field decides how it is decoded.&lt;br /&gt;
&lt;br /&gt;
=== Run-length encoding ===&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;struct&amp;lt;/span&amp;gt; RLE &amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;{&amp;lt;/span&amp;gt;&lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint32&amp;lt;/span&amp;gt; compressed_size : 24&lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt;  reserved &amp;lt;span class=&amp;quot;hlC&amp;quot;&amp;gt;// Always 0x00, value is ignored by the game&amp;lt;/span&amp;gt;&lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt;  escape_length : 7&lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt;  no_sequence : 1&lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt;  escape_codes&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;[&amp;lt;/span&amp;gt;escape_length&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;]&amp;lt;/span&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt;  data&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;[&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;hlC&amp;quot;&amp;gt;...&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;]&amp;lt;/span&amp;gt;&lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;}&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
RLE is used to reduce the length of consecutively repeated bytes by using an escape code followed by a counter to signify how many times the next byte should be repeated. It is particularly useful for compressing images, as large areas with a single colour would be represented by many consecutive identical bytes.&lt;br /&gt;
&lt;br /&gt;
The RLE stage can itself have two passes if &amp;lt;tt&amp;gt;no_sequence&amp;lt;/tt&amp;gt; is not set. The first pass will then expand sequences of bytes in the data. &amp;lt;tt&amp;gt;escape_codes[1]&amp;lt;/tt&amp;gt; will mark the beginning and the end of a byte sequence. When the escape code is encountered in the data, the following bytes are considered a sequence until the escape code is hit again. After the end-marking escape code, a one byte length counter tells how many times the preceding byte sequence should be repeated in the output buffer. Because the escape code cannot itself be escaped, sequential byte runs can only be applied in files that have unused byte values to use as the first escape code.&lt;br /&gt;
&lt;br /&gt;
The main RLE pass is a traditional expansion of single-byte runs, but with a twist that allows for multiple types of escape codes. The escape code&#039;s position in the header&#039;s escape code list affects its properties. When the first escape code is encountered in the source buffer, the following byte has the number of repetitions, and the next byte will be copied that many times to the output buffer. When the third escape code is encountered, the number of repetitions is stored in the following &#039;&#039;two&#039;&#039; bytes as a 16-bit integer. Then the following byte is copied that many times. All other escape codes use its position in the escape code list as the number of repetitions, and have no additional counter bytes before the data byte to be repeated. This allows the second escape code reserved for sequences to serve as a no-op without the two passes interfering. Escape codes can themselves be escaped in single-byte runs by having them expanded to only one copy.&lt;br /&gt;
&lt;br /&gt;
All repetition counters have an off-by-one surplus, as the data byte itself counts as the first copy. For optimal compression, escape codes should be chosen from byte values that occur least frequently, or not at all, in the source data.&lt;br /&gt;
&lt;br /&gt;
==== RLE decoding optimisation ====&lt;br /&gt;
Escape codes are put in an &amp;lt;tt&amp;gt;escape[256]&amp;lt;/tt&amp;gt; array, where the code&#039;s byte value is the index and the escape code&#039;s position is the entry&#039;s value. This array is used to test incoming bytes for escape codes. Raw bytes will have the value 0, while other values corresponds to the escape code&#039;s property. This optimisation makes the decoding run O(1), as opposed to O(&#039;&#039;n&#039;&#039;), where &#039;&#039;n&#039;&#039; is the number of escape codes.&lt;br /&gt;
&lt;br /&gt;
=== Huffman coding ===&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;struct&amp;lt;/span&amp;gt; Huffman &amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;{&amp;lt;/span&amp;gt;&lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt; tree_levels : 7&lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt; delta_coding : 1&lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt; symbols_per_level&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;[&amp;lt;/span&amp;gt;tree_levels&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;]&amp;lt;/span&amp;gt;&lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt; alphabet&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;[&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;SUM&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;(&amp;lt;/span&amp;gt;symbols_per_level&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;)&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;]&amp;lt;/span&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint16&amp;lt;/span&amp;gt; codes : var &amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;[&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;hlC&amp;quot;&amp;gt;...&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;]&amp;lt;/span&amp;gt;&lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;}&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Huffman coding uses a binary tree to store data. When Huffman codes are read, each bit tells which branch to take when traversing the tree. If a leaf node is hit, we have found the code&#039;s symbol and can proceed with the next code. Frequently used symbols have shorter paths and thus takes up fewer bits in the source file.&lt;br /&gt;
&lt;br /&gt;
The tree is stored by having two lists, one with symbols per level, and one with the alphabet. The alphabet is every possible symbol in the order they appear in the tree. The tree is built by going through each &amp;lt;tt&amp;gt;symbols_per_level&amp;lt;/tt&amp;gt;. If there are symbols at the current level, consume them from &amp;lt;tt&amp;gt;alphabet&amp;lt;/tt&amp;gt; and create leaf nodes. If there are no symbols, and there still are more levels to create, proceed to create left and right children nodes for the next level. The codes are arranged [https://en.wikipedia.org/wiki/Canonical_Huffman_code canonically], meaning that the symbols in the alphabet are sorted by code length and symbol value. This makes it possible to decode the data without constructing and traversing the tree structure, instead relying on an offset table.&lt;br /&gt;
&lt;br /&gt;
The remaining data is the Huffman codes. Bit by bit is read to find leaf nodes in the Huffman tree whose symbols are appended to the output buffer. This is repeated until the output buffer has reached &amp;lt;tt&amp;gt;uncompressed_size&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
The maximum Huffman tree height is 16. While the data format allows for up to 127 levels, Stunts&#039; decompression function uses arrays with a fixed capacity of 16 for its level offset table.&lt;br /&gt;
&lt;br /&gt;
==== Delta coding ====&lt;br /&gt;
If the flag for [https://en.wikipedia.org/wiki/Delta_encoding delta coding] is set, each symbol is treated as the difference from the previous output byte instead of an independent final value. The last byte written to the output buffer is remembered and added to the next expanded symbol. While regular Huffman coding assigns shorter codes to frequently occurring values, this delta variant assigns shorter codes to differences that occurs frequently. This feature is not used by any shipped files, but the code is present in all versions that implements Huffman decoding. One can speculate that delta coding was outperformed by RLE combined with regular Huffman coding, making delta coding unnecessary.&lt;br /&gt;
&lt;br /&gt;
==== Huffman decoding optimisations ====&lt;br /&gt;
===== Prefix table =====&lt;br /&gt;
With Huffman codes being paths in a binary tree, they have the property of being prefix-free, meaning that one leaf node&#039;s code cannot be the prefix of another node&#039;s code. This allows for a decoding optimisation technique known as &#039;&#039;prefix tables&#039;&#039; or &#039;&#039;Huffman tables&#039;&#039;. By creating arrays of symbols and code widths where the indices are the Huffman codes, the codes can be looked up directly without traversing the tree. Every array index for non-leaf nodes between two leaf node entries are filled with data for the preceding leaf node. This way there&#039;s no need to filter out bits that belong to the next Huffman code, at the expense of common symbols taking up multiple entries in the lookup table during decompression.&lt;br /&gt;
&lt;br /&gt;
Stunts utilises this optimisation for Huffman codes that are up to 8 bits wide. The first byte of the code is checked in the &amp;lt;tt&amp;gt;widths[256]&amp;lt;/tt&amp;gt; array. If the code&#039;s width is 8 bits or less, the same code is looked up in the &amp;lt;tt&amp;gt;symbols[256]&amp;lt;/tt&amp;gt; array and written to the output buffer. To find the start of the next Huffman code, the source buffer is advanced by the code&#039;s bit width found in the &amp;lt;tt&amp;gt;widths&amp;lt;/tt&amp;gt; array.&lt;br /&gt;
&lt;br /&gt;
===== Offset table =====&lt;br /&gt;
As Stunts limits the prefix tables to 8 bit wide Huffman codes to save RAM, another optimisation is applied for codes that exceeds 8 bits. Prefixes for longer codes have the value &amp;lt;tt&amp;gt;0x40&amp;lt;/tt&amp;gt; in the &amp;lt;tt&amp;gt;widths&amp;lt;/tt&amp;gt; array, indicating that the current code is a prefix that needs further expansion. Benefiting from the canonical nature of the codebook, Stunts uses two additional helper arrays: &amp;lt;tt&amp;gt;total_codes[tree_levels]&amp;lt;/tt&amp;gt;, which has the total number of leaf nodes that exists in the tree up to each level, and &amp;lt;tt&amp;gt;code_offsets[tree_levels]&amp;lt;/tt&amp;gt;, which for each level has a value that is the level&#039;s offset in the alphabet minus the tree&#039;s total capacity up to each level, and thus can be added to a code with the same level in order to get its index in the alphabet. As a code&#039;s bit width corresponds to the code&#039;s level in the Huffman tree, the width can be used to compare the current code with the level&#039;s total by getting &amp;lt;tt&amp;gt;total_codes[current_width]&amp;lt;/tt&amp;gt; for each extra bit read. If the code is smaller than the total number of codes encountered, it is a leaf node, and we get the symbol by adding the level&#039;s code offset to the code with &amp;lt;tt&amp;gt;alphabet[code + code_offsets[width]]&amp;lt;/tt&amp;gt;. This is more laborious than the use of prefix tables for direct lookup, but it only applies to codes that are occurring less frequently in the input file, and it is still far more efficient than traversing a binary tree.&lt;br /&gt;
&lt;br /&gt;
==== Version differences ====&lt;br /&gt;
The Huffman decompression in the game code of Stunts 1.0 differs from the one in its LOAD.EXE and later versions of the game. The Huffman codes are written with the least significant bit first, as opposed to the other versions that has the codes written with the opposite orientation. The game code of Stunts 1.0 also does not use a prefix table, and the bit-stream orientation was likely changed with the introduction of this optimisation.&lt;br /&gt;
&lt;br /&gt;
== EAC packing ==&lt;br /&gt;
Pixel graphics in the PC98 port and non-3d shape resource files in the Amiga port uses another in-house format that is characterized by the identification byte &amp;lt;tt&amp;gt;0xFB&amp;lt;/tt&amp;gt;, assumed to be the initials of its author, [https://www.mobygames.com/person/7186/frank-barchard/ Frank Barchard]. This format supports a suite of different compression methods and it evolved through the 90&#039;s and early 2000&#039;s as a part of EA Canada&#039;s internal engine libraries. Whereas later games tended to use the [https://en.wikipedia.org/wiki/Lempel%E2%80%93Ziv%E2%80%93Storer%E2%80%93Szymanski LZSS]-based [https://github.com/lingeringwillx/Refpack-QFS-Resources RefPack] algorithm, the Stunts ports uses other methods. We will therefore refer to these compressions as &#039;&#039;EAC packing&#039;&#039; to distinguish them from the ubiquitous RefPack.&lt;br /&gt;
&lt;br /&gt;
This is the currently assumed header structure:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;struct&amp;lt;/span&amp;gt; Header &amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;{&amp;lt;/span&amp;gt;&lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt;  method_flags : 3&lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt;  method_type  : 4&lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt;  32bit_length : 1 &amp;lt;span class=&amp;quot;hlC&amp;quot;&amp;gt;// Not used by Stunts&amp;lt;/span&amp;gt;&lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt;  magic &amp;lt;span class=&amp;quot;hlC&amp;quot;&amp;gt;// Always 0xFB&amp;lt;/span&amp;gt;&lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint32&amp;lt;/span&amp;gt; uncompressed_size : 24&lt;br /&gt;
 &lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlC&amp;quot;&amp;gt;// Possibly more fields if indicated by method_flags&amp;lt;/span&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt;  data&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;[&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;hlC&amp;quot;&amp;gt;...&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;]&amp;lt;/span&amp;gt;&lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;}&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Below are the values of the first byte in the shipped files. Values from the DOS version of [https://www.mobygames.com/game/56474/mickeys-abcs-a-day-at-the-fair/ Mickey&#039;s ABC&#039;s: A Day at the Fair] are included, as this may be the first public incarnation of Barchard compression. The bitfield suspected to be the method is highlighted in red, the method flags in green.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Game                !! Hex  !! Bits&lt;br /&gt;
|-&lt;br /&gt;
| Mickey&#039;s ABC BPE      || &amp;lt;tt&amp;gt;0x44&amp;lt;/tt&amp;gt; || &amp;lt;tt&amp;gt;&amp;lt;span style=&amp;quot;color:lightgray&amp;quot;&amp;gt;0&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;1000&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt;100&amp;lt;/span&amp;gt;&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Stunts Amiga Huffman  || &amp;lt;tt&amp;gt;0x26&amp;lt;/tt&amp;gt; || &amp;lt;tt&amp;gt;&amp;lt;span style=&amp;quot;color:lightgray&amp;quot;&amp;gt;0&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;0100&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt;110&amp;lt;/span&amp;gt;&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Stunts Amiga Huffman  || &amp;lt;tt&amp;gt;0x27&amp;lt;/tt&amp;gt; || &amp;lt;tt&amp;gt;&amp;lt;span style=&amp;quot;color:lightgray&amp;quot;&amp;gt;0&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;0100&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt;111&amp;lt;/span&amp;gt;&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Stunts Amiga BPE      || &amp;lt;tt&amp;gt;0x42&amp;lt;/tt&amp;gt; || &amp;lt;tt&amp;gt;&amp;lt;span style=&amp;quot;color:lightgray&amp;quot;&amp;gt;0&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;1000&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt;010&amp;lt;/span&amp;gt;&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Stunts PC98 BPE       || &amp;lt;tt&amp;gt;0x46&amp;lt;/tt&amp;gt; || &amp;lt;tt&amp;gt;&amp;lt;span style=&amp;quot;color:lightgray&amp;quot;&amp;gt;0&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;1000&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt;110&amp;lt;/span&amp;gt;&amp;lt;/tt&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The game code appears to support several other methods that are not used by the shipped files.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Method !! Hex !! Bits !! Amiga !! PC98 !! Mickey&lt;br /&gt;
|-&lt;br /&gt;
| rowspan=2 | 0x4 Huffman coding&lt;br /&gt;
| &amp;lt;tt&amp;gt;0x26&amp;lt;/tt&amp;gt; || &amp;lt;tt&amp;gt;&amp;lt;span style=&amp;quot;color:lightgray&amp;quot;&amp;gt;0&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;0100&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt;110&amp;lt;/span&amp;gt;&amp;lt;/tt&amp;gt; || style=text-align:center | X || style=text-align:center |   || style=text-align:center | &lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;0x27&amp;lt;/tt&amp;gt; || &amp;lt;tt&amp;gt;&amp;lt;span style=&amp;quot;color:lightgray&amp;quot;&amp;gt;0&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;0100&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt;111&amp;lt;/span&amp;gt;&amp;lt;/tt&amp;gt; || style=text-align:center | X || style=text-align:center |   || style=text-align:center | &lt;br /&gt;
|-&lt;br /&gt;
| rowspan=7 | 0x8 Byte pair encoding&lt;br /&gt;
| &amp;lt;tt&amp;gt;0x40&amp;lt;/tt&amp;gt; || &amp;lt;tt&amp;gt;&amp;lt;span style=&amp;quot;color:lightgray&amp;quot;&amp;gt;0&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;1000&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt;000&amp;lt;/span&amp;gt;&amp;lt;/tt&amp;gt; || style=text-align:center | X || style=text-align:center |   || style=text-align:center | X&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;0x41&amp;lt;/tt&amp;gt; || &amp;lt;tt&amp;gt;&amp;lt;span style=&amp;quot;color:lightgray&amp;quot;&amp;gt;0&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;1000&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt;001&amp;lt;/span&amp;gt;&amp;lt;/tt&amp;gt; || style=text-align:center | X || style=text-align:center |   || style=text-align:center | X&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;0x42&amp;lt;/tt&amp;gt; || &amp;lt;tt&amp;gt;&amp;lt;span style=&amp;quot;color:lightgray&amp;quot;&amp;gt;0&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;1000&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt;010&amp;lt;/span&amp;gt;&amp;lt;/tt&amp;gt; || style=text-align:center | X || style=text-align:center |   || style=text-align:center | X&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;0x44&amp;lt;/tt&amp;gt; || &amp;lt;tt&amp;gt;&amp;lt;span style=&amp;quot;color:lightgray&amp;quot;&amp;gt;0&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;1000&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt;100&amp;lt;/span&amp;gt;&amp;lt;/tt&amp;gt; || style=text-align:center |   || style=text-align:center |   || style=text-align:center | X&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;0x45&amp;lt;/tt&amp;gt; || &amp;lt;tt&amp;gt;&amp;lt;span style=&amp;quot;color:lightgray&amp;quot;&amp;gt;0&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;1000&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt;101&amp;lt;/span&amp;gt;&amp;lt;/tt&amp;gt; || style=text-align:center |   || style=text-align:center |   || style=text-align:center | X&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;0x46&amp;lt;/tt&amp;gt; || &amp;lt;tt&amp;gt;&amp;lt;span style=&amp;quot;color:lightgray&amp;quot;&amp;gt;0&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;1000&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt;110&amp;lt;/span&amp;gt;&amp;lt;/tt&amp;gt; || style=text-align:center |   || style=text-align:center | X || style=text-align:center |&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;0x47&amp;lt;/tt&amp;gt; || &amp;lt;tt&amp;gt;&amp;lt;span style=&amp;quot;color:lightgray&amp;quot;&amp;gt;0&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;1000&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt;111&amp;lt;/span&amp;gt;&amp;lt;/tt&amp;gt; || style=text-align:center |   || style=text-align:center | X || style=text-align:center |&lt;br /&gt;
|-&lt;br /&gt;
| rowspan=3 | 0xC Obfuscation&lt;br /&gt;
| &amp;lt;tt&amp;gt;0x60&amp;lt;/tt&amp;gt; || &amp;lt;tt&amp;gt;&amp;lt;span style=&amp;quot;color:lightgray&amp;quot;&amp;gt;0&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;1100&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt;000&amp;lt;/span&amp;gt;&amp;lt;/tt&amp;gt; || style=text-align:center | X || style=text-align:center | X || style=text-align:center | X&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;0x62&amp;lt;/tt&amp;gt; || &amp;lt;tt&amp;gt;&amp;lt;span style=&amp;quot;color:lightgray&amp;quot;&amp;gt;0&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;1100&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt;010&amp;lt;/span&amp;gt;&amp;lt;/tt&amp;gt; || style=text-align:center | X || style=text-align:center | X || style=text-align:center | X&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;0x66&amp;lt;/tt&amp;gt; || &amp;lt;tt&amp;gt;&amp;lt;span style=&amp;quot;color:lightgray&amp;quot;&amp;gt;0&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;1100&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt;100&amp;lt;/span&amp;gt;&amp;lt;/tt&amp;gt; || style=text-align:center | X || style=text-align:center | X || style=text-align:center | X&lt;br /&gt;
|-&lt;br /&gt;
| 0xD Store&lt;br /&gt;
| &amp;lt;tt&amp;gt;0x6B || &amp;lt;tt&amp;gt;&amp;lt;span style=&amp;quot;color:lightgray&amp;quot;&amp;gt;0&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;1101&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt;011&amp;lt;/span&amp;gt;&amp;lt;/tt&amp;gt; || style=text-align:center |   || style=text-align:center | X || style=text-align:center | X&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== 0x4 Huffman coding ====&lt;br /&gt;
Similar to, but incompatible with the Huffman coding used in later EA games as method 0x6 and [https://problemkaputt.de/psxspx-cdrom-file-compression-ea-methods-huffman.htm documented by Martin Korth].&lt;br /&gt;
&lt;br /&gt;
==== 0x8 Byte pair encoding ====&lt;br /&gt;
[https://en.wikipedia.org/wiki/Byte_pair_encoding Byte pair encoding] replaces frequently occurring byte pairs with a single byte that is not used elsewhere in the data. The process is repeated recursively until there are no more repeated byte pairs or available code bytes. Appears to be the same format as [https://problemkaputt.de/psxspx-cdrom-file-compression-ea-methods-bpe.htm documented by Martin Korth].&lt;br /&gt;
&lt;br /&gt;
==== 0xC Obfuscation ====&lt;br /&gt;
Very simple data obfuscation scheme where each byte is subtracted from the previous. The process is reversed by adding running bytes as they are copied.&lt;br /&gt;
&lt;br /&gt;
==== 0xD Store ====&lt;br /&gt;
Data is embedded without any transformations.&lt;br /&gt;
&lt;br /&gt;
== RPck ==&lt;br /&gt;
3-d shapes in the Amiga port are compressed with RPck, a simple byte-oriented [https://en.wikipedia.org/wiki/Run-length_encoding RLE]-based format also found in earlier Amiga games from DSI. Compression ratio is inferior to EAC&#039;s BPE or Huffman compression. RPck may have been kept for performance reasons or deadline constraints.&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlC&amp;quot;&amp;gt;// Big endian byte ordering.&amp;lt;/span&amp;gt;&lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;struct&amp;lt;/span&amp;gt; Header &amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;{&amp;lt;/span&amp;gt;&lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;char&amp;lt;/span&amp;gt;   magic&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;[&amp;lt;/span&amp;gt;4&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;]&amp;lt;/span&amp;gt; &amp;lt;span class=&amp;quot;hlC&amp;quot;&amp;gt;// &amp;quot;RPck&amp;quot; or &amp;quot;Rpck&amp;quot;&amp;lt;/span&amp;gt;&lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint32&amp;lt;/span&amp;gt; uncompressed_size&lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint32&amp;lt;/span&amp;gt; bytes_saved&lt;br /&gt;
 &lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt;  data&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;[&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;hlC&amp;quot;&amp;gt;...&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;]&amp;lt;/span&amp;gt;&lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;}&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
After the header comes a one-byte control code treated as a signed integer. If the value is negative, it is negated and this number of bytes is read and copied directly to the output. Since the maximum length is 128, another control code is needed if there are more than 128 consecutive bytes without repetition. If the control byte value is positive, the following byte is copied to the output and then duplicated the number of times specified in the control byte. This is repeated until &amp;lt;tt&amp;gt;uncompressed_size&amp;lt;/tt&amp;gt; is reached or there is no more data in the source buffer.&lt;br /&gt;
&lt;br /&gt;
The game is also shipped with two files, &#039;&#039;stdapmin.psh&#039;&#039; and &#039;&#039;stdbaudi.psh&#039;&#039;, which appears to be wrapped in another variant of this format. The header is &amp;quot;&amp;lt;tt&amp;gt;PPkc&amp;lt;/tt&amp;gt;&amp;quot; [&#039;&#039;sic.&#039;&#039;] and the contents are stored without compression, but the length header is stripped from the wrapped resource files. Yet another possibly related format appears in the DSI game [https://www.mobygames.com/game/107/test-drive/ Test Drive] with the header &amp;quot;&amp;lt;tt&amp;gt;Pckd&amp;lt;/tt&amp;gt;&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
== FM Towns ==&lt;br /&gt;
The FM Towns and FM Towns Marty ports of the game were distributed on CD-ROM with ample storage and does not apply any compression to the game resource files.&lt;br /&gt;
&lt;br /&gt;
[[Category:Internals]]&lt;/div&gt;</summary>
		<author><name>Dstien</name></author>
	</entry>
	<entry>
		<id>https://wiki.stunts.hu/index.php?title=Compression&amp;diff=5813</id>
		<title>Compression</title>
		<link rel="alternate" type="text/html" href="https://wiki.stunts.hu/index.php?title=Compression&amp;diff=5813"/>
		<updated>2024-01-23T16:46:08Z</updated>

		<summary type="html">&lt;p&gt;Dstien: Rename formats to &amp;quot;DSI packing&amp;quot; and &amp;quot;EAC packing&amp;quot; as these specifications are valid for many DSI/EA games.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Stunts and its ports uses multiple compression formats for code and [[Resource_file_format|resource files]] to save disk space and, more importantly, the number of floppy disks used to distribute the game. &lt;br /&gt;
&lt;br /&gt;
== Formats by game version ==&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! rowspan=3 colspan=3 | Game version !! colspan=4 | DSI packing !! rowspan=2 colspan=2 | EAC packing !! rowspan=3 | RPck&lt;br /&gt;
|-&lt;br /&gt;
! rowspan=2 | RLE !! colspan=3 | Huffman&lt;br /&gt;
|-&lt;br /&gt;
! Supported !! Prefix table !! Code endianness !! Huffman !! BPE&lt;br /&gt;
|-&lt;br /&gt;
! rowspan=4 style=text-align:left | MS DOS !! rowspan=2 | BB 1.0 !! style=text-align:left | Game&lt;br /&gt;
| style=text-align:center | X || style=text-align:center | X || || Big || || ||&lt;br /&gt;
|-&lt;br /&gt;
! style=text-align:left | Loader&lt;br /&gt;
| || style=text-align:center | X || style=text-align:center | X || Little || || ||&lt;br /&gt;
|-&lt;br /&gt;
! rowspan=2 | BB 1.1/MS 1.1 !! style=text-align:left | Game&lt;br /&gt;
| style=text-align:center | X || style=text-align:center | X || style=text-align:center | X || Little || || ||&lt;br /&gt;
|-&lt;br /&gt;
! style=text-align:left | Loader&lt;br /&gt;
| || style=text-align:center | X || style=text-align:center | X || Little || || ||&lt;br /&gt;
|-&lt;br /&gt;
! colspan=3 style=text-align:left | Amiga&lt;br /&gt;
| || || || || style=text-align:center | X || style=text-align:center | X || style=text-align:center | X&lt;br /&gt;
|-&lt;br /&gt;
! colspan=3 style=text-align:left | PC98&lt;br /&gt;
| || || || || || style=text-align:center | X ||&lt;br /&gt;
|-&lt;br /&gt;
! colspan=3 style=text-align:left | FM Towns&lt;br /&gt;
| || || || || || ||&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== DSI packing ==&lt;br /&gt;
The original release of Stunts for MS DOS uses a custom data compression format not found in the ports to other platforms. The code may have been hand-crafted for 16-bit x86 since other options were favoured in the later ports. The format does not have any identification bytes, so we will refer to it as &#039;&#039;DSI packing&#039;&#039; as it appeared in several DSI games in the late 80&#039;s and early 90&#039;s.&lt;br /&gt;
&lt;br /&gt;
The data format supports both [https://en.wikipedia.org/wiki/Run-length_encoding run-length encoding] (RLE) and [https://en.wikipedia.org/wiki/Huffman_coding Huffman coding]. They can be combined in multiple passes. The data format and the decompression code don&#039;t require any particular order or combination of algorithms. Every compressed file shipped with the game use Huffman coding, and when combined with RLE, the RLE pass is applied before Huffman.&lt;br /&gt;
&lt;br /&gt;
=== File header ===&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;enum&amp;lt;/span&amp;gt; CompressionType &amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;{&amp;lt;/span&amp;gt;&lt;br /&gt;
     RLE     = 1&lt;br /&gt;
     Huffman = 2&lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;}&amp;lt;/span&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;struct&amp;lt;/span&amp;gt; Header &amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;{&amp;lt;/span&amp;gt;&lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;union&amp;lt;/span&amp;gt; &amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;{&amp;lt;/span&amp;gt;&lt;br /&gt;
         &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt; passes : 7&lt;br /&gt;
         &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt; compression_type : 7&lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;}&amp;lt;/span&amp;gt;&lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt;  multi_pass : 1&lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint32&amp;lt;/span&amp;gt; uncompressed_size : 24&lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;}&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
If the most significant bit of the first byte of the file is set, this is a multi-pass file and the remaining 7 bits are the number of passes to be processed recursively. If the &amp;lt;tt&amp;gt;multi_pass&amp;lt;/tt&amp;gt; flag is not set, we are only doing a single pass and the first byte is the compression type. The next three bytes make up the uncompressed size. If the &amp;lt;tt&amp;gt;multi_pass&amp;lt;/tt&amp;gt; flag was set, this is the final uncompressed size. When the &amp;lt;tt&amp;gt;multi_pass&amp;lt;/tt&amp;gt; flag is not set, this is the uncompressed size of the current pass. The remaining data is processed recursively. The &amp;lt;tt&amp;gt;compression_type&amp;lt;/tt&amp;gt; field decides how it is decoded.&lt;br /&gt;
&lt;br /&gt;
=== Run-length encoding ===&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;struct&amp;lt;/span&amp;gt; RLE &amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;{&amp;lt;/span&amp;gt;&lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint32&amp;lt;/span&amp;gt; compressed_size : 24&lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt;  reserved &amp;lt;span class=&amp;quot;hlC&amp;quot;&amp;gt;// Always 0x00, value is ignored by the game&amp;lt;/span&amp;gt;&lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt;  escape_length : 7&lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt;  no_sequence : 1&lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt;  escape_codes&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;[&amp;lt;/span&amp;gt;escape_length&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;]&amp;lt;/span&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt;  data&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;[&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;hlC&amp;quot;&amp;gt;...&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;]&amp;lt;/span&amp;gt;&lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;}&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
RLE is used to reduce the length of consecutively repeated bytes by using an escape code followed by a counter to signify how many times the next byte should be repeated. It is particularly useful for compressing images, as large areas with a single colour would be represented by many consecutive identical bytes.&lt;br /&gt;
&lt;br /&gt;
The RLE stage can itself have two passes if &amp;lt;tt&amp;gt;no_sequence&amp;lt;/tt&amp;gt; is not set. The first pass will then expand sequences of bytes in the data. &amp;lt;tt&amp;gt;escape_codes[1]&amp;lt;/tt&amp;gt; will mark the beginning and the end of a byte sequence. When the escape code is encountered in the data, the following bytes are considered a sequence until the escape code is hit again. After the end-marking escape code, a one byte length counter tells how many times the preceding byte sequence should be repeated in the output buffer. Because the escape code cannot itself be escaped, sequential byte runs can only be applied in files that have unused byte values to use as the first escape code.&lt;br /&gt;
&lt;br /&gt;
The main RLE pass is a traditional expansion of single-byte runs, but with a twist that allows for multiple types of escape codes. The escape code&#039;s position in the header&#039;s escape code list affects its properties. When the first escape code is encountered in the source buffer, the following byte has the number of repetitions, and the next byte will be copied that many times to the output buffer. When the third escape code is encountered, the number of repetitions is stored in the following &#039;&#039;two&#039;&#039; bytes as a 16-bit integer. Then the following byte is copied that many times. All other escape codes use its position in the escape code list as the number of repetitions, and have no additional counter bytes before the data byte to be repeated. This allows the second escape code reserved for sequences to serve as a no-op without the two passes interfering. Escape codes can themselves be escaped in single-byte runs by having them expanded to only one copy.&lt;br /&gt;
&lt;br /&gt;
All repetition counters have an off-by-one surplus, as the data byte itself counts as the first copy. For optimal compression, escape codes should be chosen from byte values that occur least frequently, or not at all, in the source data.&lt;br /&gt;
&lt;br /&gt;
==== RLE decoding optimisation ====&lt;br /&gt;
Escape codes are put in an &amp;lt;tt&amp;gt;escape[256]&amp;lt;/tt&amp;gt; array, where the code&#039;s byte value is the index and the escape code&#039;s position is the entry&#039;s value. This array is used to test incoming bytes for escape codes. Raw bytes will have the value 0, while other values corresponds to the escape code&#039;s property. This optimisation makes the decoding run O(1), as opposed to O(&#039;&#039;n&#039;&#039;), where &#039;&#039;n&#039;&#039; is the number of escape codes.&lt;br /&gt;
&lt;br /&gt;
=== Huffman coding ===&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;struct&amp;lt;/span&amp;gt; Huffman &amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;{&amp;lt;/span&amp;gt;&lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt; tree_levels : 7&lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt; delta_coding : 1&lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt; symbols_per_level&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;[&amp;lt;/span&amp;gt;tree_levels&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;]&amp;lt;/span&amp;gt;&lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt; alphabet&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;[&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;SUM&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;(&amp;lt;/span&amp;gt;symbols_per_level&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;)&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;]&amp;lt;/span&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint16&amp;lt;/span&amp;gt; codes : var &amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;[&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;hlC&amp;quot;&amp;gt;...&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;]&amp;lt;/span&amp;gt;&lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;}&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Huffman coding uses a binary tree to store data. When Huffman codes are read, each bit tells which branch to take when traversing the tree. If a leaf node is hit, we have found the code&#039;s symbol and can proceed with the next code. Frequently used symbols have shorter paths and thus takes up fewer bits in the source file.&lt;br /&gt;
&lt;br /&gt;
The tree is stored by having two lists, one with symbols per level, and one with the alphabet. The alphabet is every possible symbol in the order they appear in the tree. The tree is built by going through each &amp;lt;tt&amp;gt;symbols_per_level&amp;lt;/tt&amp;gt;. If there are symbols at the current level, consume them from &amp;lt;tt&amp;gt;alphabet&amp;lt;/tt&amp;gt; and create leaf nodes. If there are no symbols, and there still are more levels to create, proceed to create left and right children nodes for the next level.&lt;br /&gt;
&lt;br /&gt;
The remaining data is the Huffman codes. Bit by bit is read to find leaf nodes in the Huffman tree whose symbols are appended to the output buffer. This is repeated until the output buffer has reached &amp;lt;tt&amp;gt;uncompressed_size&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
The maximum Huffman tree height is 16. While the data format allows for up to 127 levels, Stunts&#039; decompression function uses arrays with a fixed capacity of 16 for its level offset table.&lt;br /&gt;
&lt;br /&gt;
==== Delta coding ====&lt;br /&gt;
If the flag for [https://en.wikipedia.org/wiki/Delta_encoding delta coding] is set, each symbol is treated as the difference from the previous output byte instead of an independent final value. The last byte written to the output buffer is remembered and added to the next expanded symbol. While regular Huffman coding assigns shorter codes to frequently occurring values, this delta variant assigns shorter codes to differences that occurs frequently. This feature is not used by any shipped files, but the code is present in all versions that implements Huffman decoding. One can speculate that delta coding was outperformed by RLE combined with regular Huffman coding, making delta coding unnecessary.&lt;br /&gt;
&lt;br /&gt;
==== Huffman decoding optimisations ====&lt;br /&gt;
===== Prefix table =====&lt;br /&gt;
With Huffman codes being paths in a binary tree, they have the property of being prefix-free, meaning that one leaf node&#039;s code cannot be the prefix of another node&#039;s code. This allows for a decoding optimisation technique known as &#039;&#039;prefix tables&#039;&#039; or &#039;&#039;Huffman tables&#039;&#039;. By creating arrays of symbols and code widths where the indices are the Huffman codes, the codes can be looked up directly without traversing the tree. Every array index for non-leaf nodes between two leaf node entries are filled with data for the preceding leaf node. This way there&#039;s no need to filter out bits that belong to the next Huffman code, at the expense of common symbols taking up multiple entries in the lookup table during decompression.&lt;br /&gt;
&lt;br /&gt;
Stunts utilises this optimisation for Huffman codes that are up to 8 bits wide. The first byte of the code is checked in the &amp;lt;tt&amp;gt;widths[256]&amp;lt;/tt&amp;gt; array. If the code&#039;s width is 8 bits or less, the same code is looked up in the &amp;lt;tt&amp;gt;symbols[256]&amp;lt;/tt&amp;gt; array and written to the output buffer. To find the start of the next Huffman code, the source buffer is advanced by the code&#039;s bit width found in the &amp;lt;tt&amp;gt;widths&amp;lt;/tt&amp;gt; array.&lt;br /&gt;
&lt;br /&gt;
===== Offset table =====&lt;br /&gt;
As Stunts limits the prefix tables to 8 bit wide Huffman codes to save RAM, another novel optimisation is applied for codes that exceeds 8 bits. Prefixes for longer codes have the value &amp;lt;tt&amp;gt;0x40&amp;lt;/tt&amp;gt; in the &amp;lt;tt&amp;gt;widths&amp;lt;/tt&amp;gt; array, indicating that the current code is a prefix that needs further expansion. For this purpose Stunts uses two additional helper arrays: &amp;lt;tt&amp;gt;total_codes[tree_levels]&amp;lt;/tt&amp;gt;, which has the total number of leaf nodes that exists in the tree up to each level, and &amp;lt;tt&amp;gt;code_offsets[tree_levels]&amp;lt;/tt&amp;gt;, which for each level has a value that can be added to a code with the same level in order to get its index in the alphabet. This works because the codes are arranged [https://en.wikipedia.org/wiki/Canonical_Huffman_code canonically]. As a code&#039;s bit width corresponds to the code&#039;s level in the Huffman tree, the width can be used to compare the current code with the level&#039;s total by getting &amp;lt;tt&amp;gt;total_codes[current_width]&amp;lt;/tt&amp;gt; for each extra bit read. If the code is smaller than the total number of codes encountered, it is a leaf node, and we get the symbol by adding the level&#039;s code offset to the code with &amp;lt;tt&amp;gt;alphabet[code + code_offsets[width]]&amp;lt;/tt&amp;gt;. This is more laborious than the use of prefix tables for direct lookup, but it only applies to codes that are occurring less frequently in the input file.&lt;br /&gt;
&lt;br /&gt;
==== Version differences ====&lt;br /&gt;
The Huffman decompression in the game code of Stunts 1.0 differs from the one in its LOAD.EXE and later versions of the game. The Huffman codes are written with the least significant bit first, as opposed to the other versions that has the codes written with the opposite orientation. The game code of Stunts 1.0 also does not use a prefix table, and the bit-stream orientation was likely changed with the introduction of this optimisation.&lt;br /&gt;
&lt;br /&gt;
== EAC packing ==&lt;br /&gt;
Pixel graphics in the PC98 port and non-3d shape resource files in the Amiga port uses another in-house format that is characterized by the identification byte &amp;lt;tt&amp;gt;0xFB&amp;lt;/tt&amp;gt;, assumed to be the initials of its author, [https://www.mobygames.com/person/7186/frank-barchard/ Frank Barchard]. This format supports a suite of different compression methods and it evolved through the 90&#039;s and early 2000&#039;s as a part of EA Canada&#039;s internal engine libraries. Whereas later games tended to use the [https://en.wikipedia.org/wiki/Lempel%E2%80%93Ziv%E2%80%93Storer%E2%80%93Szymanski LZSS]-based [https://github.com/lingeringwillx/Refpack-QFS-Resources RefPack] algorithm, the Stunts ports uses other methods. We will therefore refer to these compressions as &#039;&#039;EAC packing&#039;&#039; to distinguish them from the ubiquitous RefPack.&lt;br /&gt;
&lt;br /&gt;
This is the currently assumed header structure:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;struct&amp;lt;/span&amp;gt; Header &amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;{&amp;lt;/span&amp;gt;&lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt;  method_flags : 3&lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt;  method_type  : 4&lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt;  32bit_length : 1 &amp;lt;span class=&amp;quot;hlC&amp;quot;&amp;gt;// Not used by Stunts&amp;lt;/span&amp;gt;&lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt;  magic &amp;lt;span class=&amp;quot;hlC&amp;quot;&amp;gt;// Always 0xFB&amp;lt;/span&amp;gt;&lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint32&amp;lt;/span&amp;gt; uncompressed_size : 24&lt;br /&gt;
 &lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlC&amp;quot;&amp;gt;// Possibly more fields if indicated by method_flags&amp;lt;/span&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt;  data&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;[&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;hlC&amp;quot;&amp;gt;...&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;]&amp;lt;/span&amp;gt;&lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;}&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Below are the values of the first byte in the shipped files. Values from the DOS version of [https://www.mobygames.com/game/56474/mickeys-abcs-a-day-at-the-fair/ Mickey&#039;s ABC&#039;s: A Day at the Fair] are included, as this may be the first public incarnation of Barchard compression. The bitfield suspected to be the method is highlighted in red, the method flags in green.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Game                !! Hex  !! Bits&lt;br /&gt;
|-&lt;br /&gt;
| Mickey&#039;s ABC BPE      || &amp;lt;tt&amp;gt;0x44&amp;lt;/tt&amp;gt; || &amp;lt;tt&amp;gt;&amp;lt;span style=&amp;quot;color:lightgray&amp;quot;&amp;gt;0&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;1000&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt;100&amp;lt;/span&amp;gt;&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Stunts Amiga Huffman  || &amp;lt;tt&amp;gt;0x26&amp;lt;/tt&amp;gt; || &amp;lt;tt&amp;gt;&amp;lt;span style=&amp;quot;color:lightgray&amp;quot;&amp;gt;0&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;0100&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt;110&amp;lt;/span&amp;gt;&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Stunts Amiga Huffman  || &amp;lt;tt&amp;gt;0x27&amp;lt;/tt&amp;gt; || &amp;lt;tt&amp;gt;&amp;lt;span style=&amp;quot;color:lightgray&amp;quot;&amp;gt;0&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;0100&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt;111&amp;lt;/span&amp;gt;&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Stunts Amiga BPE      || &amp;lt;tt&amp;gt;0x42&amp;lt;/tt&amp;gt; || &amp;lt;tt&amp;gt;&amp;lt;span style=&amp;quot;color:lightgray&amp;quot;&amp;gt;0&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;1000&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt;010&amp;lt;/span&amp;gt;&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Stunts PC98 BPE       || &amp;lt;tt&amp;gt;0x46&amp;lt;/tt&amp;gt; || &amp;lt;tt&amp;gt;&amp;lt;span style=&amp;quot;color:lightgray&amp;quot;&amp;gt;0&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;1000&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt;110&amp;lt;/span&amp;gt;&amp;lt;/tt&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The game code appears to support several other methods that are not used by the shipped files.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Method !! Hex !! Bits !! Amiga !! PC98 !! Mickey&lt;br /&gt;
|-&lt;br /&gt;
| rowspan=2 | 0x4 Huffman coding&lt;br /&gt;
| &amp;lt;tt&amp;gt;0x26&amp;lt;/tt&amp;gt; || &amp;lt;tt&amp;gt;&amp;lt;span style=&amp;quot;color:lightgray&amp;quot;&amp;gt;0&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;0100&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt;110&amp;lt;/span&amp;gt;&amp;lt;/tt&amp;gt; || style=text-align:center | X || style=text-align:center |   || style=text-align:center | &lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;0x27&amp;lt;/tt&amp;gt; || &amp;lt;tt&amp;gt;&amp;lt;span style=&amp;quot;color:lightgray&amp;quot;&amp;gt;0&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;0100&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt;111&amp;lt;/span&amp;gt;&amp;lt;/tt&amp;gt; || style=text-align:center | X || style=text-align:center |   || style=text-align:center | &lt;br /&gt;
|-&lt;br /&gt;
| rowspan=7 | 0x8 Byte pair encoding&lt;br /&gt;
| &amp;lt;tt&amp;gt;0x40&amp;lt;/tt&amp;gt; || &amp;lt;tt&amp;gt;&amp;lt;span style=&amp;quot;color:lightgray&amp;quot;&amp;gt;0&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;1000&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt;000&amp;lt;/span&amp;gt;&amp;lt;/tt&amp;gt; || style=text-align:center | X || style=text-align:center |   || style=text-align:center | X&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;0x41&amp;lt;/tt&amp;gt; || &amp;lt;tt&amp;gt;&amp;lt;span style=&amp;quot;color:lightgray&amp;quot;&amp;gt;0&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;1000&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt;001&amp;lt;/span&amp;gt;&amp;lt;/tt&amp;gt; || style=text-align:center | X || style=text-align:center |   || style=text-align:center | X&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;0x42&amp;lt;/tt&amp;gt; || &amp;lt;tt&amp;gt;&amp;lt;span style=&amp;quot;color:lightgray&amp;quot;&amp;gt;0&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;1000&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt;010&amp;lt;/span&amp;gt;&amp;lt;/tt&amp;gt; || style=text-align:center | X || style=text-align:center |   || style=text-align:center | X&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;0x44&amp;lt;/tt&amp;gt; || &amp;lt;tt&amp;gt;&amp;lt;span style=&amp;quot;color:lightgray&amp;quot;&amp;gt;0&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;1000&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt;100&amp;lt;/span&amp;gt;&amp;lt;/tt&amp;gt; || style=text-align:center |   || style=text-align:center |   || style=text-align:center | X&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;0x45&amp;lt;/tt&amp;gt; || &amp;lt;tt&amp;gt;&amp;lt;span style=&amp;quot;color:lightgray&amp;quot;&amp;gt;0&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;1000&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt;101&amp;lt;/span&amp;gt;&amp;lt;/tt&amp;gt; || style=text-align:center |   || style=text-align:center |   || style=text-align:center | X&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;0x46&amp;lt;/tt&amp;gt; || &amp;lt;tt&amp;gt;&amp;lt;span style=&amp;quot;color:lightgray&amp;quot;&amp;gt;0&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;1000&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt;110&amp;lt;/span&amp;gt;&amp;lt;/tt&amp;gt; || style=text-align:center |   || style=text-align:center | X || style=text-align:center |&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;0x47&amp;lt;/tt&amp;gt; || &amp;lt;tt&amp;gt;&amp;lt;span style=&amp;quot;color:lightgray&amp;quot;&amp;gt;0&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;1000&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt;111&amp;lt;/span&amp;gt;&amp;lt;/tt&amp;gt; || style=text-align:center |   || style=text-align:center | X || style=text-align:center |&lt;br /&gt;
|-&lt;br /&gt;
| rowspan=3 | 0xC Obfuscation&lt;br /&gt;
| &amp;lt;tt&amp;gt;0x60&amp;lt;/tt&amp;gt; || &amp;lt;tt&amp;gt;&amp;lt;span style=&amp;quot;color:lightgray&amp;quot;&amp;gt;0&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;1100&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt;000&amp;lt;/span&amp;gt;&amp;lt;/tt&amp;gt; || style=text-align:center | X || style=text-align:center | X || style=text-align:center | X&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;0x62&amp;lt;/tt&amp;gt; || &amp;lt;tt&amp;gt;&amp;lt;span style=&amp;quot;color:lightgray&amp;quot;&amp;gt;0&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;1100&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt;010&amp;lt;/span&amp;gt;&amp;lt;/tt&amp;gt; || style=text-align:center | X || style=text-align:center | X || style=text-align:center | X&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;0x66&amp;lt;/tt&amp;gt; || &amp;lt;tt&amp;gt;&amp;lt;span style=&amp;quot;color:lightgray&amp;quot;&amp;gt;0&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;1100&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt;100&amp;lt;/span&amp;gt;&amp;lt;/tt&amp;gt; || style=text-align:center | X || style=text-align:center | X || style=text-align:center | X&lt;br /&gt;
|-&lt;br /&gt;
| 0xD Store&lt;br /&gt;
| &amp;lt;tt&amp;gt;0x6B || &amp;lt;tt&amp;gt;&amp;lt;span style=&amp;quot;color:lightgray&amp;quot;&amp;gt;0&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;1101&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt;011&amp;lt;/span&amp;gt;&amp;lt;/tt&amp;gt; || style=text-align:center |   || style=text-align:center | X || style=text-align:center | X&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== 0x4 Huffman coding ====&lt;br /&gt;
Similar to, but incompatible with the Huffman coding used in later EA games as method 0x6 and [https://problemkaputt.de/psxspx-cdrom-file-compression-ea-methods-huffman.htm documented by Martin Korth].&lt;br /&gt;
&lt;br /&gt;
==== 0x8 Byte pair encoding ====&lt;br /&gt;
[https://en.wikipedia.org/wiki/Byte_pair_encoding Byte pair encoding] replaces frequently occurring byte pairs with a single byte that is not used elsewhere in the data. The process is repeated recursively until there are no more repeated byte pairs or available code bytes. Appears to be the same format as [https://problemkaputt.de/psxspx-cdrom-file-compression-ea-methods-bpe.htm documented by Martin Korth].&lt;br /&gt;
&lt;br /&gt;
==== 0xC Obfuscation ====&lt;br /&gt;
Very simple data obfuscation scheme where each byte is subtracted from the previous. The process is reversed by adding running bytes as they are copied.&lt;br /&gt;
&lt;br /&gt;
==== 0xD Store ====&lt;br /&gt;
Data is embedded without any transformations.&lt;br /&gt;
&lt;br /&gt;
== RPck ==&lt;br /&gt;
3-d shapes in the Amiga port are compressed with RPck, a simple byte-oriented [https://en.wikipedia.org/wiki/Run-length_encoding RLE]-based format also found in earlier Amiga games from DSI. Compression ratio is inferior to EAC&#039;s BPE or Huffman compression. RPck may have been kept for performance reasons or deadline constraints.&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlC&amp;quot;&amp;gt;// Big endian byte ordering.&amp;lt;/span&amp;gt;&lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;struct&amp;lt;/span&amp;gt; Header &amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;{&amp;lt;/span&amp;gt;&lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;char&amp;lt;/span&amp;gt;   magic&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;[&amp;lt;/span&amp;gt;4&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;]&amp;lt;/span&amp;gt; &amp;lt;span class=&amp;quot;hlC&amp;quot;&amp;gt;// &amp;quot;RPck&amp;quot; or &amp;quot;Rpck&amp;quot;&amp;lt;/span&amp;gt;&lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint32&amp;lt;/span&amp;gt; uncompressed_size&lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint32&amp;lt;/span&amp;gt; bytes_saved&lt;br /&gt;
 &lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt;  data&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;[&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;hlC&amp;quot;&amp;gt;...&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;]&amp;lt;/span&amp;gt;&lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;}&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
After the header comes a one-byte control code treated as a signed integer. If the value is negative, it is negated and this number of bytes is read and copied directly to the output. Since the maximum length is 128, another control code is needed if there are more than 128 consecutive bytes without repetition. If the control byte value is positive, the following byte is copied to the output and then duplicated the number of times specified in the control byte. This is repeated until &amp;lt;tt&amp;gt;uncompressed_size&amp;lt;/tt&amp;gt; is reached or there is no more data in the source buffer.&lt;br /&gt;
&lt;br /&gt;
The game is also shipped with two files, &#039;&#039;stdapmin.psh&#039;&#039; and &#039;&#039;stdbaudi.psh&#039;&#039;, which appears to be wrapped in another variant of this format. The header is &amp;quot;&amp;lt;tt&amp;gt;PPkc&amp;lt;/tt&amp;gt;&amp;quot; [&#039;&#039;sic.&#039;&#039;] and the contents are stored without compression, but the length header is stripped from the wrapped resource files. Yet another possibly related format appears in the DSI game [https://www.mobygames.com/game/107/test-drive/ Test Drive] with the header &amp;quot;&amp;lt;tt&amp;gt;Pckd&amp;lt;/tt&amp;gt;&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
== FM Towns ==&lt;br /&gt;
The FM Towns and FM Towns Marty ports of the game were distributed on CD-ROM with ample storage and does not apply any compression to the game resource files.&lt;br /&gt;
&lt;br /&gt;
[[Category:Internals]]&lt;/div&gt;</summary>
		<author><name>Dstien</name></author>
	</entry>
	<entry>
		<id>https://wiki.stunts.hu/index.php?title=Compression&amp;diff=5798</id>
		<title>Compression</title>
		<link rel="alternate" type="text/html" href="https://wiki.stunts.hu/index.php?title=Compression&amp;diff=5798"/>
		<updated>2024-01-18T14:28:57Z</updated>

		<summary type="html">&lt;p&gt;Dstien: /* Barchard */ Identified Huffman method.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Stunts and its ports uses multiple compression formats for code and [[Resource_file_format|resource files]] to save disk space and, more importantly, the number of floppy disks used to distribute the game. &lt;br /&gt;
&lt;br /&gt;
== Formats by game version ==&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! rowspan=3 colspan=3 | Game version !! colspan=4 | Stunts packing !! rowspan=2 colspan=2 | Barchard !! rowspan=3 | RPck&lt;br /&gt;
|-&lt;br /&gt;
! rowspan=2 | RLE !! colspan=3 | Huffman&lt;br /&gt;
|-&lt;br /&gt;
! Supported !! Prefix table !! Code endianness !! Huffman !! BPE&lt;br /&gt;
|-&lt;br /&gt;
! rowspan=4 style=text-align:left | MS DOS !! rowspan=2 | BB 1.0 !! style=text-align:left | Game&lt;br /&gt;
| style=text-align:center | X || style=text-align:center | X || || Big || || ||&lt;br /&gt;
|-&lt;br /&gt;
! style=text-align:left | Loader&lt;br /&gt;
| || style=text-align:center | X || style=text-align:center | X || Little || || ||&lt;br /&gt;
|-&lt;br /&gt;
! rowspan=2 | BB 1.1/MS 1.1 !! style=text-align:left | Game&lt;br /&gt;
| style=text-align:center | X || style=text-align:center | X || style=text-align:center | X || Little || || ||&lt;br /&gt;
|-&lt;br /&gt;
! style=text-align:left | Loader&lt;br /&gt;
| || style=text-align:center | X || style=text-align:center | X || Little || || ||&lt;br /&gt;
|-&lt;br /&gt;
! colspan=3 style=text-align:left | Amiga&lt;br /&gt;
| || || || || style=text-align:center | X || style=text-align:center | X || style=text-align:center | X&lt;br /&gt;
|-&lt;br /&gt;
! colspan=3 style=text-align:left | PC98&lt;br /&gt;
| || || || || || style=text-align:center | X ||&lt;br /&gt;
|-&lt;br /&gt;
! colspan=3 style=text-align:left | FM Towns&lt;br /&gt;
| || || || || || ||&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== MS DOS ==&lt;br /&gt;
The original release of Stunts uses a custom data compression format not found in the ports to other platforms. The code may have been hand-crafted for 16-bit x86 since other options were favoured in the later ports.&lt;br /&gt;
&lt;br /&gt;
The data format supports both [https://en.wikipedia.org/wiki/Run-length_encoding run-length encoding] (RLE) and [https://en.wikipedia.org/wiki/Huffman_coding Huffman coding]. They can be combined in multiple passes. The data format and the decompression code don&#039;t require any particular order or combination of algorithms. Every compressed file shipped with the game use Huffman coding, and when combined with RLE, the RLE pass is applied before Huffman.&lt;br /&gt;
&lt;br /&gt;
=== File header ===&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;enum&amp;lt;/span&amp;gt; CompressionType &amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;{&amp;lt;/span&amp;gt;&lt;br /&gt;
     RLE     = 1&lt;br /&gt;
     Huffman = 2&lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;}&amp;lt;/span&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;struct&amp;lt;/span&amp;gt; Header &amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;{&amp;lt;/span&amp;gt;&lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;union&amp;lt;/span&amp;gt; &amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;{&amp;lt;/span&amp;gt;&lt;br /&gt;
         &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt; passes : 7&lt;br /&gt;
         &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt; compression_type : 7&lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;}&amp;lt;/span&amp;gt;&lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt;  multi_pass : 1&lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint32&amp;lt;/span&amp;gt; uncompressed_size : 24&lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;}&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
If the most significant bit of the first byte of the file is set, this is a multi-pass file and the remaining 7 bits are the number of passes to be processed recursively. If the &amp;lt;tt&amp;gt;multi_pass&amp;lt;/tt&amp;gt; flag is not set, we are only doing a single pass and the first byte is the compression type. The next three bytes make up the uncompressed size. If the &amp;lt;tt&amp;gt;multi_pass&amp;lt;/tt&amp;gt; flag was set, this is the final uncompressed size. When the &amp;lt;tt&amp;gt;multi_pass&amp;lt;/tt&amp;gt; flag is not set, this is the uncompressed size of the current pass. The remaining data is processed recursively. The &amp;lt;tt&amp;gt;compression_type&amp;lt;/tt&amp;gt; field decides how it is decoded.&lt;br /&gt;
&lt;br /&gt;
=== Run-length encoding ===&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;struct&amp;lt;/span&amp;gt; RLE &amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;{&amp;lt;/span&amp;gt;&lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint32&amp;lt;/span&amp;gt; compressed_size : 24&lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt;  reserved &amp;lt;span class=&amp;quot;hlC&amp;quot;&amp;gt;// Always 0x00, value is ignored by the game&amp;lt;/span&amp;gt;&lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt;  escape_length : 7&lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt;  no_sequence : 1&lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt;  escape_codes&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;[&amp;lt;/span&amp;gt;escape_length&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;]&amp;lt;/span&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt;  data&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;[&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;hlC&amp;quot;&amp;gt;...&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;]&amp;lt;/span&amp;gt;&lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;}&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
RLE is used to reduce the length of consecutively repeated bytes by using an escape code followed by a counter to signify how many times the next byte should be repeated. It is particularly useful for compressing images, as large areas with a single colour would be represented by many consecutive identical bytes.&lt;br /&gt;
&lt;br /&gt;
The RLE stage can itself have two passes if &amp;lt;tt&amp;gt;no_sequence&amp;lt;/tt&amp;gt; is not set. The first pass will then expand sequences of bytes in the data. &amp;lt;tt&amp;gt;escape_codes[1]&amp;lt;/tt&amp;gt; will mark the beginning and the end of a byte sequence. When the escape code is encountered in the data, the following bytes are considered a sequence until the escape code is hit again. After the end-marking escape code, a one byte length counter tells how many times the preceding byte sequence should be repeated in the output buffer. Because the escape code cannot itself be escaped, sequential byte runs can only be applied in files that have unused byte values to use as the first escape code.&lt;br /&gt;
&lt;br /&gt;
The main RLE pass is a traditional expansion of single-byte runs, but with a twist that allows for multiple types of escape codes. The escape code&#039;s position in the header&#039;s escape code list affects its properties. When the first escape code is encountered in the source buffer, the following byte has the number of repetitions, and the next byte will be copied that many times to the output buffer. When the third escape code is encountered, the number of repetitions is stored in the following &#039;&#039;two&#039;&#039; bytes as a 16-bit integer. Then the following byte is copied that many times. All other escape codes use its position in the escape code list as the number of repetitions, and have no additional counter bytes before the data byte to be repeated. This allows the second escape code reserved for sequences to serve as a no-op without the two passes interfering. Escape codes can themselves be escaped in single-byte runs by having them expanded to only one copy.&lt;br /&gt;
&lt;br /&gt;
All repetition counters have an off-by-one surplus, as the data byte itself counts as the first copy. For optimal compression, escape codes should be chosen from byte values that occur least frequently, or not at all, in the source data.&lt;br /&gt;
&lt;br /&gt;
==== RLE decoding optimisation ====&lt;br /&gt;
Escape codes are put in an &amp;lt;tt&amp;gt;escape[256]&amp;lt;/tt&amp;gt; array, where the code&#039;s byte value is the index and the escape code&#039;s position is the entry&#039;s value. This array is used to test incoming bytes for escape codes. Raw bytes will have the value 0, while other values corresponds to the escape code&#039;s property. This optimisation makes the decoding run O(1), as opposed to O(&#039;&#039;n&#039;&#039;), where &#039;&#039;n&#039;&#039; is the number of escape codes.&lt;br /&gt;
&lt;br /&gt;
=== Huffman coding ===&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;struct&amp;lt;/span&amp;gt; Huffman &amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;{&amp;lt;/span&amp;gt;&lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt; tree_levels : 7&lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt; delta_coding : 1&lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt; symbols_per_level&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;[&amp;lt;/span&amp;gt;tree_levels&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;]&amp;lt;/span&amp;gt;&lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt; alphabet&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;[&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;SUM&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;(&amp;lt;/span&amp;gt;symbols_per_level&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;)&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;]&amp;lt;/span&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint16&amp;lt;/span&amp;gt; codes : var &amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;[&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;hlC&amp;quot;&amp;gt;...&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;]&amp;lt;/span&amp;gt;&lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;}&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Huffman coding uses a binary tree to store data. When Huffman codes are read, each bit tells which branch to take when traversing the tree. If a leaf node is hit, we have found the code&#039;s symbol and can proceed with the next code. Frequently used symbols have shorter paths and thus takes up fewer bits in the source file.&lt;br /&gt;
&lt;br /&gt;
The tree is stored by having two lists, one with symbols per level, and one with the alphabet. The alphabet is every possible symbol in the order they appear in the tree. The tree is built by going through each &amp;lt;tt&amp;gt;symbols_per_level&amp;lt;/tt&amp;gt;. If there are symbols at the current level, consume them from &amp;lt;tt&amp;gt;alphabet&amp;lt;/tt&amp;gt; and create leaf nodes. If there are no symbols, and there still are more levels to create, proceed to create left and right children nodes for the next level.&lt;br /&gt;
&lt;br /&gt;
The remaining data is the Huffman codes. Bit by bit is read to find leaf nodes in the Huffman tree whose symbols are appended to the output buffer. This is repeated until the output buffer has reached &amp;lt;tt&amp;gt;uncompressed_size&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
The maximum Huffman tree height is 16. While the data format allows for up to 127 levels, Stunts&#039; decompression function uses arrays with a fixed capacity of 16 for its level offset table.&lt;br /&gt;
&lt;br /&gt;
==== Delta coding ====&lt;br /&gt;
If the flag for [https://en.wikipedia.org/wiki/Delta_encoding delta coding] is set, each symbol is treated as the difference from the previous output byte instead of an independent final value. The last byte written to the output buffer is remembered and added to the next expanded symbol. While regular Huffman coding assigns shorter codes to frequently occurring values, this delta variant assigns shorter codes to differences that occurs frequently. This feature is not used by any shipped files, but the code is present in all versions that implements Huffman decoding. One can speculate that delta coding was outperformed by RLE combined with regular Huffman coding, making delta coding unnecessary.&lt;br /&gt;
&lt;br /&gt;
==== Huffman decoding optimisations ====&lt;br /&gt;
===== Prefix table =====&lt;br /&gt;
With Huffman codes being paths in a binary tree, they have the property of being prefix-free, meaning that one leaf node&#039;s code cannot be the prefix of another node&#039;s code. This allows for a decoding optimisation technique known as &#039;&#039;prefix tables&#039;&#039; or &#039;&#039;Huffman tables&#039;&#039;. By creating arrays of symbols and code widths where the indices are the Huffman codes, the codes can be looked up directly without traversing the tree. Every array index for non-leaf nodes between two leaf node entries are filled with data for the preceding leaf node. This way there&#039;s no need to filter out bits that belong to the next Huffman code, at the expense of common symbols taking up multiple entries in the lookup table during decompression.&lt;br /&gt;
&lt;br /&gt;
Stunts utilises this optimisation for Huffman codes that are up to 8 bits wide. The first byte of the code is checked in the &amp;lt;tt&amp;gt;widths[256]&amp;lt;/tt&amp;gt; array. If the code&#039;s width is 8 bits or less, the same code is looked up in the &amp;lt;tt&amp;gt;symbols[256]&amp;lt;/tt&amp;gt; array and written to the output buffer. To find the start of the next Huffman code, the source buffer is advanced by the code&#039;s bit width found in the &amp;lt;tt&amp;gt;widths&amp;lt;/tt&amp;gt; array.&lt;br /&gt;
&lt;br /&gt;
===== Offset table =====&lt;br /&gt;
As Stunts limits the prefix tables to 8 bit wide Huffman codes to save RAM, another novel optimisation is applied for codes that exceeds 8 bits. Prefixes for longer codes have the value &amp;lt;tt&amp;gt;0x40&amp;lt;/tt&amp;gt; in the &amp;lt;tt&amp;gt;widths&amp;lt;/tt&amp;gt; array, indicating that the current code is a prefix that needs further expansion. For this purpose Stunts uses two additional helper arrays: &amp;lt;tt&amp;gt;total_codes[tree_levels]&amp;lt;/tt&amp;gt;, which has the total number of leaf nodes that exists in the tree up to each level, and &amp;lt;tt&amp;gt;code_offsets[tree_levels]&amp;lt;/tt&amp;gt;, which for each level has a value that can be added to a code with the same level in order to get its index in the alphabet. This works because the codes are arranged [https://en.wikipedia.org/wiki/Canonical_Huffman_code canonically]. As a code&#039;s bit width corresponds to the code&#039;s level in the Huffman tree, the width can be used to compare the current code with the level&#039;s total by getting &amp;lt;tt&amp;gt;total_codes[current_width]&amp;lt;/tt&amp;gt; for each extra bit read. If the code is smaller than the total number of codes encountered, it is a leaf node, and we get the symbol by adding the level&#039;s code offset to the code with &amp;lt;tt&amp;gt;alphabet[code + code_offsets[width]]&amp;lt;/tt&amp;gt;. This is more laborious than the use of prefix tables for direct lookup, but it only applies to codes that are occurring less frequently in the input file.&lt;br /&gt;
&lt;br /&gt;
==== Version differences ====&lt;br /&gt;
The Huffman decompression in the game code of Stunts 1.0 differs from the one in its LOAD.EXE and later versions of the game. The Huffman codes are written with the least significant bit first, as opposed to the other versions that has the codes written with the opposite orientation. The game code of Stunts 1.0 also does not use a prefix table, and the bit-stream orientation was likely changed with the introduction of this optimisation.&lt;br /&gt;
&lt;br /&gt;
== Amiga ==&lt;br /&gt;
The Amiga port uses two unrelated compression formats.&lt;br /&gt;
&lt;br /&gt;
=== Barchard ===&lt;br /&gt;
Non-3d shape resource files uses another Distinctive Software in-house format that is characterized by the identification byte &amp;lt;tt&amp;gt;0xFB&amp;lt;/tt&amp;gt;, assumed to be the initials of its author, [https://www.mobygames.com/person/7186/frank-barchard/ Frank Barchard]. This format supports a suite of different compression methods and it evolved through the 90&#039;s and early 2000&#039;s as a part of EA&#039;s internal engine libraries. Whereas later games tended to use the [https://en.wikipedia.org/wiki/Lempel%E2%80%93Ziv%E2%80%93Storer%E2%80%93Szymanski LZSS]-based [https://github.com/lingeringwillx/Refpack-QFS-Resources RefPack] algorithm, the Stunts ports uses other methods. We will therefore refer to these compressions as &#039;&#039;&amp;quot;Barchard&amp;quot;&#039;&#039; to distinguish them from the ubiquitous RefPack.&lt;br /&gt;
&lt;br /&gt;
This is the currently assumed header structure:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;struct&amp;lt;/span&amp;gt; Header &amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;{&amp;lt;/span&amp;gt;&lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt;  method_flags : 3&lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt;  method_type  : 4&lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt;  32bit_length : 1 &amp;lt;span class=&amp;quot;hlC&amp;quot;&amp;gt;// Not used by Stunts&amp;lt;/span&amp;gt;&lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt;  magic &amp;lt;span class=&amp;quot;hlC&amp;quot;&amp;gt;// Always 0xFB&amp;lt;/span&amp;gt;&lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint32&amp;lt;/span&amp;gt; uncompressed_size : 24&lt;br /&gt;
 &lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlC&amp;quot;&amp;gt;// Possibly more fields if indicated by method_flags&amp;lt;/span&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt;  data&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;[&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;hlC&amp;quot;&amp;gt;...&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;]&amp;lt;/span&amp;gt;&lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;}&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Below are the values of the first byte in the shipped files. Values from the DOS version of [https://www.mobygames.com/game/56474/mickeys-abcs-a-day-at-the-fair/ Mickey&#039;s ABC&#039;s: A Day at the Fair] are included, as this may be the first public incarnation of Barchard compression. The bitfield suspected to be the method is highlighted in red, the method flags in green.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Game                !! Hex  !! Bits&lt;br /&gt;
|-&lt;br /&gt;
| Mickey&#039;s ABC BPE      || &amp;lt;tt&amp;gt;0x44&amp;lt;/tt&amp;gt; || &amp;lt;tt&amp;gt;&amp;lt;span style=&amp;quot;color:lightgray&amp;quot;&amp;gt;0&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;1000&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt;100&amp;lt;/span&amp;gt;&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Stunts Amiga Huffman  || &amp;lt;tt&amp;gt;0x26&amp;lt;/tt&amp;gt; || &amp;lt;tt&amp;gt;&amp;lt;span style=&amp;quot;color:lightgray&amp;quot;&amp;gt;0&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;0100&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt;110&amp;lt;/span&amp;gt;&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Stunts Amiga Huffman  || &amp;lt;tt&amp;gt;0x27&amp;lt;/tt&amp;gt; || &amp;lt;tt&amp;gt;&amp;lt;span style=&amp;quot;color:lightgray&amp;quot;&amp;gt;0&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;0100&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt;111&amp;lt;/span&amp;gt;&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Stunts Amiga BPE      || &amp;lt;tt&amp;gt;0x42&amp;lt;/tt&amp;gt; || &amp;lt;tt&amp;gt;&amp;lt;span style=&amp;quot;color:lightgray&amp;quot;&amp;gt;0&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;1000&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt;010&amp;lt;/span&amp;gt;&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Stunts PC98 BPE       || &amp;lt;tt&amp;gt;0x46&amp;lt;/tt&amp;gt; || &amp;lt;tt&amp;gt;&amp;lt;span style=&amp;quot;color:lightgray&amp;quot;&amp;gt;0&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;1000&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt;110&amp;lt;/span&amp;gt;&amp;lt;/tt&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The game code appears to support several other methods that are not used by the shipped files.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Method !! Hex !! Bits !! Amiga !! PC98 !! Mickey&lt;br /&gt;
|-&lt;br /&gt;
| rowspan=2 | 0x4 Huffman coding&lt;br /&gt;
| &amp;lt;tt&amp;gt;0x26&amp;lt;/tt&amp;gt; || &amp;lt;tt&amp;gt;&amp;lt;span style=&amp;quot;color:lightgray&amp;quot;&amp;gt;0&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;0100&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt;110&amp;lt;/span&amp;gt;&amp;lt;/tt&amp;gt; || style=text-align:center | X || style=text-align:center |   || style=text-align:center | &lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;0x27&amp;lt;/tt&amp;gt; || &amp;lt;tt&amp;gt;&amp;lt;span style=&amp;quot;color:lightgray&amp;quot;&amp;gt;0&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;0100&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt;111&amp;lt;/span&amp;gt;&amp;lt;/tt&amp;gt; || style=text-align:center | X || style=text-align:center |   || style=text-align:center | &lt;br /&gt;
|-&lt;br /&gt;
| rowspan=7 | 0x8 Byte pair encoding&lt;br /&gt;
| &amp;lt;tt&amp;gt;0x40&amp;lt;/tt&amp;gt; || &amp;lt;tt&amp;gt;&amp;lt;span style=&amp;quot;color:lightgray&amp;quot;&amp;gt;0&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;1000&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt;000&amp;lt;/span&amp;gt;&amp;lt;/tt&amp;gt; || style=text-align:center | X || style=text-align:center |   || style=text-align:center | X&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;0x41&amp;lt;/tt&amp;gt; || &amp;lt;tt&amp;gt;&amp;lt;span style=&amp;quot;color:lightgray&amp;quot;&amp;gt;0&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;1000&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt;001&amp;lt;/span&amp;gt;&amp;lt;/tt&amp;gt; || style=text-align:center | X || style=text-align:center |   || style=text-align:center | X&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;0x42&amp;lt;/tt&amp;gt; || &amp;lt;tt&amp;gt;&amp;lt;span style=&amp;quot;color:lightgray&amp;quot;&amp;gt;0&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;1000&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt;010&amp;lt;/span&amp;gt;&amp;lt;/tt&amp;gt; || style=text-align:center | X || style=text-align:center |   || style=text-align:center | X&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;0x44&amp;lt;/tt&amp;gt; || &amp;lt;tt&amp;gt;&amp;lt;span style=&amp;quot;color:lightgray&amp;quot;&amp;gt;0&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;1000&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt;100&amp;lt;/span&amp;gt;&amp;lt;/tt&amp;gt; || style=text-align:center |   || style=text-align:center |   || style=text-align:center | X&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;0x45&amp;lt;/tt&amp;gt; || &amp;lt;tt&amp;gt;&amp;lt;span style=&amp;quot;color:lightgray&amp;quot;&amp;gt;0&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;1000&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt;101&amp;lt;/span&amp;gt;&amp;lt;/tt&amp;gt; || style=text-align:center |   || style=text-align:center |   || style=text-align:center | X&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;0x46&amp;lt;/tt&amp;gt; || &amp;lt;tt&amp;gt;&amp;lt;span style=&amp;quot;color:lightgray&amp;quot;&amp;gt;0&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;1000&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt;110&amp;lt;/span&amp;gt;&amp;lt;/tt&amp;gt; || style=text-align:center |   || style=text-align:center | X || style=text-align:center |&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;0x47&amp;lt;/tt&amp;gt; || &amp;lt;tt&amp;gt;&amp;lt;span style=&amp;quot;color:lightgray&amp;quot;&amp;gt;0&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;1000&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt;111&amp;lt;/span&amp;gt;&amp;lt;/tt&amp;gt; || style=text-align:center |   || style=text-align:center | X || style=text-align:center |&lt;br /&gt;
|-&lt;br /&gt;
| rowspan=3 | 0xC Obfuscation&lt;br /&gt;
| &amp;lt;tt&amp;gt;0x60&amp;lt;/tt&amp;gt; || &amp;lt;tt&amp;gt;&amp;lt;span style=&amp;quot;color:lightgray&amp;quot;&amp;gt;0&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;1100&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt;000&amp;lt;/span&amp;gt;&amp;lt;/tt&amp;gt; || style=text-align:center | X || style=text-align:center | X || style=text-align:center | X&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;0x62&amp;lt;/tt&amp;gt; || &amp;lt;tt&amp;gt;&amp;lt;span style=&amp;quot;color:lightgray&amp;quot;&amp;gt;0&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;1100&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt;010&amp;lt;/span&amp;gt;&amp;lt;/tt&amp;gt; || style=text-align:center | X || style=text-align:center | X || style=text-align:center | X&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;0x66&amp;lt;/tt&amp;gt; || &amp;lt;tt&amp;gt;&amp;lt;span style=&amp;quot;color:lightgray&amp;quot;&amp;gt;0&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;1100&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt;100&amp;lt;/span&amp;gt;&amp;lt;/tt&amp;gt; || style=text-align:center | X || style=text-align:center | X || style=text-align:center | X&lt;br /&gt;
|-&lt;br /&gt;
| 0xD Store&lt;br /&gt;
| &amp;lt;tt&amp;gt;0x6B || &amp;lt;tt&amp;gt;&amp;lt;span style=&amp;quot;color:lightgray&amp;quot;&amp;gt;0&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;1101&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt;011&amp;lt;/span&amp;gt;&amp;lt;/tt&amp;gt; || style=text-align:center |   || style=text-align:center | X || style=text-align:center | X&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== 0x4 Huffman coding ====&lt;br /&gt;
Similar to, but incompatible with the Huffman coding used in later EA games as method 0x6 and [https://problemkaputt.de/psxspx-cdrom-file-compression-ea-methods-huffman.htm documented by Martin Korth].&lt;br /&gt;
&lt;br /&gt;
==== 0x8 Byte pair encoding ====&lt;br /&gt;
[https://en.wikipedia.org/wiki/Byte_pair_encoding Byte pair encoding] replaces frequently occurring byte pairs with a single byte that is not used elsewhere in the data. The process is repeated recursively until there are no more repeated byte pairs or available code bytes. Appears to be the same format as [https://problemkaputt.de/psxspx-cdrom-file-compression-ea-methods-bpe.htm documented by Martin Korth].&lt;br /&gt;
&lt;br /&gt;
==== 0xC Obfuscation ====&lt;br /&gt;
Very simple data obfuscation scheme where each byte is subtracted from the previous. The process is reversed by adding running bytes as they are copied.&lt;br /&gt;
&lt;br /&gt;
==== 0xD Store ====&lt;br /&gt;
Data is embedded without any transformations.&lt;br /&gt;
&lt;br /&gt;
=== RPck ===&lt;br /&gt;
3-d shapes are compressed with RPck, a simple byte-oriented [https://en.wikipedia.org/wiki/Run-length_encoding RLE]-based format also found in earlier Amiga games from DSI. Compression ratio is inferior to Barchard&#039;s byte pair encoding. RPck may have been kept for performance reasons or deadline constraints.&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlC&amp;quot;&amp;gt;// Big endian byte ordering.&amp;lt;/span&amp;gt;&lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;struct&amp;lt;/span&amp;gt; Header &amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;{&amp;lt;/span&amp;gt;&lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;char&amp;lt;/span&amp;gt;   magic&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;[&amp;lt;/span&amp;gt;4&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;]&amp;lt;/span&amp;gt; &amp;lt;span class=&amp;quot;hlC&amp;quot;&amp;gt;// &amp;quot;RPck&amp;quot; or &amp;quot;Rpck&amp;quot;&amp;lt;/span&amp;gt;&lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint32&amp;lt;/span&amp;gt; uncompressed_size&lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint32&amp;lt;/span&amp;gt; bytes_saved&lt;br /&gt;
 &lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt;  data&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;[&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;hlC&amp;quot;&amp;gt;...&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;]&amp;lt;/span&amp;gt;&lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;}&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
After the header comes a one-byte control code treated as a signed integer. If the value is negative, it is negated and this number of bytes is read and copied directly to the output. Since the maximum length is 128, another control code is needed if there are more than 128 consecutive bytes without repetition. If the control byte value is positive, the following byte is copied to the output and then duplicated the number of times specified in the control byte. This is repeated until &amp;lt;tt&amp;gt;uncompressed_size&amp;lt;/tt&amp;gt; is reached or there is no more data in the source buffer.&lt;br /&gt;
&lt;br /&gt;
The game is also shipped with two files, &#039;&#039;stdapmin.psh&#039;&#039; and &#039;&#039;stdbaudi.psh&#039;&#039;, which appears to be wrapped in another variant of this format. The header is &amp;quot;&amp;lt;tt&amp;gt;PPkc&amp;lt;/tt&amp;gt;&amp;quot; [&#039;&#039;sic.&#039;&#039;] and the contents are stored without compression, but the length header is stripped from the wrapped resource files.&lt;br /&gt;
&lt;br /&gt;
== PC98 ==&lt;br /&gt;
The PC98 port of the game uses [[#Barchard|Barchard]] to compress some of the bitmap image resource files. See the Amiga section for more details.&lt;br /&gt;
&lt;br /&gt;
== FM Towns ==&lt;br /&gt;
The FM Towns and FM Towns Marty ports of the game were distributed on CD-ROM with ample storage and does not apply any compression to the game resource files.&lt;br /&gt;
&lt;br /&gt;
[[Category:Internals]]&lt;/div&gt;</summary>
		<author><name>Dstien</name></author>
	</entry>
	<entry>
		<id>https://wiki.stunts.hu/index.php?title=Compression&amp;diff=5783</id>
		<title>Compression</title>
		<link rel="alternate" type="text/html" href="https://wiki.stunts.hu/index.php?title=Compression&amp;diff=5783"/>
		<updated>2024-01-12T13:16:45Z</updated>

		<summary type="html">&lt;p&gt;Dstien: /* RPck */ Format description.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Stunts and its ports uses multiple compression formats for code and [[Resource_file_format|resource files]] to save disk space and, more importantly, the number of floppy disks used to distribute the game. &lt;br /&gt;
&lt;br /&gt;
== Formats by game version ==&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! rowspan=3 colspan=3 | Game version !! colspan=4 | Stunts packing !! rowspan=3 | Barchard !! rowspan=3 | RPck&lt;br /&gt;
|-&lt;br /&gt;
! rowspan=2 | RLE !! colspan=3 | Huffman&lt;br /&gt;
|-&lt;br /&gt;
! Supported !! Prefix table !! Code endianness&lt;br /&gt;
|-&lt;br /&gt;
! rowspan=4 style=text-align:left | MS DOS !! rowspan=2 | BB 1.0 !! style=text-align:left | Game&lt;br /&gt;
| style=text-align:center | X || style=text-align:center | X || || Big || ||&lt;br /&gt;
|-&lt;br /&gt;
! style=text-align:left | Loader&lt;br /&gt;
| || style=text-align:center | X || style=text-align:center | X || Little || ||&lt;br /&gt;
|-&lt;br /&gt;
! rowspan=2 | BB 1.1/MS 1.1 !! style=text-align:left | Game&lt;br /&gt;
| style=text-align:center | X || style=text-align:center | X || style=text-align:center | X || Little || ||&lt;br /&gt;
|-&lt;br /&gt;
! style=text-align:left | Loader&lt;br /&gt;
| || style=text-align:center | X || style=text-align:center | X || Little || ||&lt;br /&gt;
|-&lt;br /&gt;
! colspan=3 style=text-align:left | Amiga&lt;br /&gt;
| || || || || style=text-align:center | X || style=text-align:center | X&lt;br /&gt;
|-&lt;br /&gt;
! colspan=3 style=text-align:left | PC98&lt;br /&gt;
| || || || || style=text-align:center | X ||&lt;br /&gt;
|-&lt;br /&gt;
! colspan=3 style=text-align:left | FM Towns&lt;br /&gt;
| || || || || ||&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== MS DOS ==&lt;br /&gt;
The original release of Stunts uses a custom data compression format not found in the ports to other platforms. The code may have been hand-crafted for 16-bit x86 since other options were favoured in the later ports.&lt;br /&gt;
&lt;br /&gt;
The data format supports both [https://en.wikipedia.org/wiki/Run-length_encoding run-length encoding] (RLE) and [https://en.wikipedia.org/wiki/Huffman_coding Huffman coding]. They can be combined in multiple passes. The data format and the decompression code don&#039;t require any particular order or combination of algorithms. Every compressed file shipped with the game use Huffman coding, and when combined with RLE, the RLE pass is applied before Huffman.&lt;br /&gt;
&lt;br /&gt;
=== File header ===&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;enum&amp;lt;/span&amp;gt; CompressionType &amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;{&amp;lt;/span&amp;gt;&lt;br /&gt;
     RLE     = 1&lt;br /&gt;
     Huffman = 2&lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;}&amp;lt;/span&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;struct&amp;lt;/span&amp;gt; Header &amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;{&amp;lt;/span&amp;gt;&lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;union&amp;lt;/span&amp;gt; &amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;{&amp;lt;/span&amp;gt;&lt;br /&gt;
         &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt; passes : 7&lt;br /&gt;
         &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt; compression_type : 7&lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;}&amp;lt;/span&amp;gt;&lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt;  multi_pass : 1&lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint32&amp;lt;/span&amp;gt; uncompressed_size : 24&lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;}&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
If the most significant bit of the first byte of the file is set, this is a multi-pass file and the remaining 7 bits are the number of passes to be processed recursively. If the &amp;lt;tt&amp;gt;multi_pass&amp;lt;/tt&amp;gt; flag is not set, we are only doing a single pass and the first byte is the compression type. The next three bytes make up the uncompressed size. If the &amp;lt;tt&amp;gt;multi_pass&amp;lt;/tt&amp;gt; flag was set, this is the final uncompressed size. When the &amp;lt;tt&amp;gt;multi_pass&amp;lt;/tt&amp;gt; flag is not set, this is the uncompressed size of the current pass. The remaining data is processed recursively. The &amp;lt;tt&amp;gt;compression_type&amp;lt;/tt&amp;gt; field decides how it is decoded.&lt;br /&gt;
&lt;br /&gt;
=== Run-length encoding ===&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;struct&amp;lt;/span&amp;gt; RLE &amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;{&amp;lt;/span&amp;gt;&lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint32&amp;lt;/span&amp;gt; compressed_size : 24&lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt;  reserved &amp;lt;span class=&amp;quot;hlC&amp;quot;&amp;gt;// Always 0x00, value is ignored by the game&amp;lt;/span&amp;gt;&lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt;  escape_length : 7&lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt;  no_sequence : 1&lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt;  escape_codes&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;[&amp;lt;/span&amp;gt;escape_length&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;]&amp;lt;/span&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt;  data&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;[&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;hlC&amp;quot;&amp;gt;...&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;]&amp;lt;/span&amp;gt;&lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;}&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
RLE is used to reduce the length of consecutively repeated bytes by using an escape code followed by a counter to signify how many times the next byte should be repeated. It is particularly useful for compressing images, as large areas with a single colour would be represented by many consecutive identical bytes.&lt;br /&gt;
&lt;br /&gt;
The RLE stage can itself have two passes if &amp;lt;tt&amp;gt;no_sequence&amp;lt;/tt&amp;gt; is not set. The first pass will then expand sequences of bytes in the data. &amp;lt;tt&amp;gt;escape_codes[1]&amp;lt;/tt&amp;gt; will mark the beginning and the end of a byte sequence. When the escape code is encountered in the data, the following bytes are considered a sequence until the escape code is hit again. After the end-marking escape code, a one byte length counter tells how many times the preceding byte sequence should be repeated in the output buffer. Because the escape code cannot itself be escaped, sequential byte runs can only be applied in files that have unused byte values to use as the first escape code.&lt;br /&gt;
&lt;br /&gt;
The main RLE pass is a traditional expansion of single-byte runs, but with a twist that allows for multiple types of escape codes. The escape code&#039;s position in the header&#039;s escape code list affects its properties. When the first escape code is encountered in the source buffer, the following byte has the number of repetitions, and the next byte will be copied that many times to the output buffer. When the third escape code is encountered, the number of repetitions is stored in the following &#039;&#039;two&#039;&#039; bytes as a 16-bit integer. Then the following byte is copied that many times. All other escape codes use its position in the escape code list as the number of repetitions, and have no additional counter bytes before the data byte to be repeated. This allows the second escape code reserved for sequences to serve as a no-op without the two passes interfering. Escape codes can themselves be escaped in single-byte runs by having them expanded to only one copy.&lt;br /&gt;
&lt;br /&gt;
All repetition counters have an off-by-one surplus, as the data byte itself counts as the first copy. For optimal compression, escape codes should be chosen from byte values that occur least frequently, or not at all, in the source data.&lt;br /&gt;
&lt;br /&gt;
==== RLE decoding optimisation ====&lt;br /&gt;
Escape codes are put in an &amp;lt;tt&amp;gt;escape[256]&amp;lt;/tt&amp;gt; array, where the code&#039;s byte value is the index and the escape code&#039;s position is the entry&#039;s value. This array is used to test incoming bytes for escape codes. Raw bytes will have the value 0, while other values corresponds to the escape code&#039;s property. This optimisation makes the decoding run O(1), as opposed to O(&#039;&#039;n&#039;&#039;), where &#039;&#039;n&#039;&#039; is the number of escape codes.&lt;br /&gt;
&lt;br /&gt;
=== Huffman coding ===&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;struct&amp;lt;/span&amp;gt; Huffman &amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;{&amp;lt;/span&amp;gt;&lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt; tree_levels : 7&lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt; delta_coding : 1&lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt; symbols_per_level&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;[&amp;lt;/span&amp;gt;tree_levels&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;]&amp;lt;/span&amp;gt;&lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt; alphabet&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;[&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;SUM&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;(&amp;lt;/span&amp;gt;symbols_per_level&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;)&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;]&amp;lt;/span&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint16&amp;lt;/span&amp;gt; codes : var &amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;[&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;hlC&amp;quot;&amp;gt;...&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;]&amp;lt;/span&amp;gt;&lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;}&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Huffman coding uses a binary tree to store data. When Huffman codes are read, each bit tells which branch to take when traversing the tree. If a leaf node is hit, we have found the code&#039;s symbol and can proceed with the next code. Frequently used symbols have shorter paths and thus takes up fewer bits in the source file.&lt;br /&gt;
&lt;br /&gt;
The tree is stored by having two lists, one with symbols per level, and one with the alphabet. The alphabet is every possible symbol in the order they appear in the tree. The tree is built by going through each &amp;lt;tt&amp;gt;symbols_per_level&amp;lt;/tt&amp;gt;. If there are symbols at the current level, consume them from &amp;lt;tt&amp;gt;alphabet&amp;lt;/tt&amp;gt; and create leaf nodes. If there are no symbols, and there still are more levels to create, proceed to create left and right children nodes for the next level.&lt;br /&gt;
&lt;br /&gt;
The remaining data is the Huffman codes. Bit by bit is read to find leaf nodes in the Huffman tree whose symbols are appended to the output buffer. This is repeated until the output buffer has reached &amp;lt;tt&amp;gt;uncompressed_size&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
The maximum Huffman tree height is 16. While the data format allows for up to 127 levels, Stunts&#039; decompression function uses arrays with a fixed capacity of 16 for its level offset table.&lt;br /&gt;
&lt;br /&gt;
==== Delta coding ====&lt;br /&gt;
If the flag for [https://en.wikipedia.org/wiki/Delta_encoding delta coding] is set, each symbol is treated as the difference from the previous output byte instead of an independent final value. The last byte written to the output buffer is remembered and added to the next expanded symbol. While regular Huffman coding assigns shorter codes to frequently occurring values, this delta variant assigns shorter codes to differences that occurs frequently. This feature is not used by any shipped files, but the code is present in all versions that implements Huffman decoding. One can speculate that delta coding was outperformed by RLE combined with regular Huffman coding, making delta coding unnecessary.&lt;br /&gt;
&lt;br /&gt;
==== Huffman decoding optimisations ====&lt;br /&gt;
===== Prefix table =====&lt;br /&gt;
With Huffman codes being paths in a binary tree, they have the property of being prefix-free, meaning that one leaf node&#039;s code cannot be the prefix of another node&#039;s code. This allows for a decoding optimisation technique known as &#039;&#039;prefix tables&#039;&#039; or &#039;&#039;Huffman tables&#039;&#039;. By creating arrays of symbols and code widths where the indices are the Huffman codes, the codes can be looked up directly without traversing the tree. Every array index for non-leaf nodes between two leaf node entries are filled with data for the preceding leaf node. This way there&#039;s no need to filter out bits that belong to the next Huffman code, at the expense of common symbols taking up multiple entries in the lookup table during decompression.&lt;br /&gt;
&lt;br /&gt;
Stunts utilises this optimisation for Huffman codes that are up to 8 bits wide. The first byte of the code is checked in the &amp;lt;tt&amp;gt;widths[256]&amp;lt;/tt&amp;gt; array. If the code&#039;s width is 8 bits or less, the same code is looked up in the &amp;lt;tt&amp;gt;symbols[256]&amp;lt;/tt&amp;gt; array and written to the output buffer. To find the start of the next Huffman code, the source buffer is advanced by the code&#039;s bit width found in the &amp;lt;tt&amp;gt;widths&amp;lt;/tt&amp;gt; array.&lt;br /&gt;
&lt;br /&gt;
===== Offset table =====&lt;br /&gt;
As Stunts limits the prefix tables to 8 bit wide Huffman codes to save RAM, another novel optimisation is applied for codes that exceeds 8 bits. Prefixes for longer codes have the value &amp;lt;tt&amp;gt;0x40&amp;lt;/tt&amp;gt; in the &amp;lt;tt&amp;gt;widths&amp;lt;/tt&amp;gt; array, indicating that the current code is a prefix that needs further expansion. For this purpose Stunts uses two additional helper arrays: &amp;lt;tt&amp;gt;total_codes[tree_levels]&amp;lt;/tt&amp;gt;, which has the total number of leaf nodes that exists in the tree up to each level, and &amp;lt;tt&amp;gt;code_offsets[tree_levels]&amp;lt;/tt&amp;gt;, which for each level has a value that can be added to a code with the same level in order to get its index in the alphabet. This works because the codes are arranged [https://en.wikipedia.org/wiki/Canonical_Huffman_code canonically]. As a code&#039;s bit width corresponds to the code&#039;s level in the Huffman tree, the width can be used to compare the current code with the level&#039;s total by getting &amp;lt;tt&amp;gt;total_codes[current_width]&amp;lt;/tt&amp;gt; for each extra bit read. If the code is smaller than the total number of codes encountered, it is a leaf node, and we get the symbol by adding the level&#039;s code offset to the code with &amp;lt;tt&amp;gt;alphabet[code + code_offsets[width]]&amp;lt;/tt&amp;gt;. This is more laborious than the use of prefix tables for direct lookup, but it only applies to codes that are occurring less frequently in the input file.&lt;br /&gt;
&lt;br /&gt;
==== Version differences ====&lt;br /&gt;
The Huffman decompression in the game code of Stunts 1.0 differs from the one in its LOAD.EXE and later versions of the game. The Huffman codes are written with the least significant bit first, as opposed to the other versions that has the codes written with the opposite orientation. The game code of Stunts 1.0 also does not use a prefix table, and the bit-stream orientation was likely changed with the introduction of this optimisation.&lt;br /&gt;
&lt;br /&gt;
== Amiga ==&lt;br /&gt;
The Amiga port uses two unrelated compression formats.&lt;br /&gt;
&lt;br /&gt;
=== Barchard ===&lt;br /&gt;
Non-3d shape resource files uses another Distinctive Software in-house format that is characterized by the identification byte &amp;lt;tt&amp;gt;0xFB&amp;lt;/tt&amp;gt;, assumed to be the initials of its author, [https://www.mobygames.com/person/7186/frank-barchard/ Frank Barchard]. This format supports a suite of different compression methods and it evolved through the 90&#039;s and early 2000&#039;s as a part of EA&#039;s internal engine libraries. Whereas later games tended to use the [https://en.wikipedia.org/wiki/Lempel%E2%80%93Ziv%E2%80%93Storer%E2%80%93Szymanski LZSS]-based [https://github.com/lingeringwillx/Refpack-QFS-Resources RefPack] algorithm, the Stunts ports uses other methods. We will therefore refer to these compressions as &#039;&#039;&amp;quot;Barchard&amp;quot;&#039;&#039; to distinguish them from the ubiquitous RefPack.&lt;br /&gt;
&lt;br /&gt;
This is the currently assumed header structure:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;struct&amp;lt;/span&amp;gt; Header &amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;{&amp;lt;/span&amp;gt;&lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt;  method_flags : 3&lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt;  method_type  : 4&lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt;  32bit_length : 1 &amp;lt;span class=&amp;quot;hlC&amp;quot;&amp;gt;// Not used by Stunts&amp;lt;/span&amp;gt;&lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt;  magic &amp;lt;span class=&amp;quot;hlC&amp;quot;&amp;gt;// Always 0xFB&amp;lt;/span&amp;gt;&lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint32&amp;lt;/span&amp;gt; uncompressed_size : 24&lt;br /&gt;
 &lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlC&amp;quot;&amp;gt;// Possibly more fields if indicated by method_flags&amp;lt;/span&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt;  data&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;[&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;hlC&amp;quot;&amp;gt;...&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;]&amp;lt;/span&amp;gt;&lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;}&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Below are the values of the first byte in the shipped files. Values from the DOS version of [https://www.mobygames.com/game/56474/mickeys-abcs-a-day-at-the-fair/ Mickey&#039;s ABC&#039;s: A Day at the Fair] are included, as this may be the first public incarnation of Barchard compression. The bitfield suspected to be the method is highlighted in red, the method flags in green.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Game                !! Hex  !! Bits&lt;br /&gt;
|-&lt;br /&gt;
| Mickey&#039;s ABC BPE      || &amp;lt;tt&amp;gt;0x44&amp;lt;/tt&amp;gt; || &amp;lt;tt&amp;gt;&amp;lt;span style=&amp;quot;color:lightgray&amp;quot;&amp;gt;0&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;1000&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt;100&amp;lt;/span&amp;gt;&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Stunts Amiga Method 1 || &amp;lt;tt&amp;gt;0x26&amp;lt;/tt&amp;gt; || &amp;lt;tt&amp;gt;&amp;lt;span style=&amp;quot;color:lightgray&amp;quot;&amp;gt;0&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;0100&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt;110&amp;lt;/span&amp;gt;&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Stunts Amiga Method 1 || &amp;lt;tt&amp;gt;0x27&amp;lt;/tt&amp;gt; || &amp;lt;tt&amp;gt;&amp;lt;span style=&amp;quot;color:lightgray&amp;quot;&amp;gt;0&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;0100&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt;111&amp;lt;/span&amp;gt;&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Stunts Amiga BPE      || &amp;lt;tt&amp;gt;0x42&amp;lt;/tt&amp;gt; || &amp;lt;tt&amp;gt;&amp;lt;span style=&amp;quot;color:lightgray&amp;quot;&amp;gt;0&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;1000&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt;010&amp;lt;/span&amp;gt;&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Stunts PC98 BPE       || &amp;lt;tt&amp;gt;0x46&amp;lt;/tt&amp;gt; || &amp;lt;tt&amp;gt;&amp;lt;span style=&amp;quot;color:lightgray&amp;quot;&amp;gt;0&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;1000&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt;110&amp;lt;/span&amp;gt;&amp;lt;/tt&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The game code appears to support several other methods that are not used by the shipped files.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Method !! Hex !! Bits !! Amiga !! PC98 !! Mickey&lt;br /&gt;
|-&lt;br /&gt;
| rowspan=2 | 0x4&lt;br /&gt;
| &amp;lt;tt&amp;gt;0x26&amp;lt;/tt&amp;gt; || &amp;lt;tt&amp;gt;&amp;lt;span style=&amp;quot;color:lightgray&amp;quot;&amp;gt;0&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;0100&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt;110&amp;lt;/span&amp;gt;&amp;lt;/tt&amp;gt; || style=text-align:center | X || style=text-align:center |   || style=text-align:center | &lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;0x27&amp;lt;/tt&amp;gt; || &amp;lt;tt&amp;gt;&amp;lt;span style=&amp;quot;color:lightgray&amp;quot;&amp;gt;0&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;0100&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt;111&amp;lt;/span&amp;gt;&amp;lt;/tt&amp;gt; || style=text-align:center | X || style=text-align:center |   || style=text-align:center | &lt;br /&gt;
|-&lt;br /&gt;
| rowspan=7 | 0x8 Byte pair encoding&lt;br /&gt;
| &amp;lt;tt&amp;gt;0x40&amp;lt;/tt&amp;gt; || &amp;lt;tt&amp;gt;&amp;lt;span style=&amp;quot;color:lightgray&amp;quot;&amp;gt;0&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;1000&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt;000&amp;lt;/span&amp;gt;&amp;lt;/tt&amp;gt; || style=text-align:center | X || style=text-align:center |   || style=text-align:center | X&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;0x41&amp;lt;/tt&amp;gt; || &amp;lt;tt&amp;gt;&amp;lt;span style=&amp;quot;color:lightgray&amp;quot;&amp;gt;0&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;1000&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt;001&amp;lt;/span&amp;gt;&amp;lt;/tt&amp;gt; || style=text-align:center | X || style=text-align:center |   || style=text-align:center | X&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;0x42&amp;lt;/tt&amp;gt; || &amp;lt;tt&amp;gt;&amp;lt;span style=&amp;quot;color:lightgray&amp;quot;&amp;gt;0&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;1000&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt;010&amp;lt;/span&amp;gt;&amp;lt;/tt&amp;gt; || style=text-align:center | X || style=text-align:center |   || style=text-align:center | X&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;0x44&amp;lt;/tt&amp;gt; || &amp;lt;tt&amp;gt;&amp;lt;span style=&amp;quot;color:lightgray&amp;quot;&amp;gt;0&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;1000&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt;100&amp;lt;/span&amp;gt;&amp;lt;/tt&amp;gt; || style=text-align:center |   || style=text-align:center |   || style=text-align:center | X&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;0x45&amp;lt;/tt&amp;gt; || &amp;lt;tt&amp;gt;&amp;lt;span style=&amp;quot;color:lightgray&amp;quot;&amp;gt;0&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;1000&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt;101&amp;lt;/span&amp;gt;&amp;lt;/tt&amp;gt; || style=text-align:center |   || style=text-align:center |   || style=text-align:center | X&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;0x46&amp;lt;/tt&amp;gt; || &amp;lt;tt&amp;gt;&amp;lt;span style=&amp;quot;color:lightgray&amp;quot;&amp;gt;0&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;1000&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt;110&amp;lt;/span&amp;gt;&amp;lt;/tt&amp;gt; || style=text-align:center |   || style=text-align:center | X || style=text-align:center |&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;0x47&amp;lt;/tt&amp;gt; || &amp;lt;tt&amp;gt;&amp;lt;span style=&amp;quot;color:lightgray&amp;quot;&amp;gt;0&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;1000&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt;111&amp;lt;/span&amp;gt;&amp;lt;/tt&amp;gt; || style=text-align:center |   || style=text-align:center | X || style=text-align:center |&lt;br /&gt;
|-&lt;br /&gt;
| rowspan=3 | 0xC Obfuscation&lt;br /&gt;
| &amp;lt;tt&amp;gt;0x60&amp;lt;/tt&amp;gt; || &amp;lt;tt&amp;gt;&amp;lt;span style=&amp;quot;color:lightgray&amp;quot;&amp;gt;0&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;1100&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt;000&amp;lt;/span&amp;gt;&amp;lt;/tt&amp;gt; || style=text-align:center | X || style=text-align:center | X || style=text-align:center | X&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;0x62&amp;lt;/tt&amp;gt; || &amp;lt;tt&amp;gt;&amp;lt;span style=&amp;quot;color:lightgray&amp;quot;&amp;gt;0&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;1100&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt;010&amp;lt;/span&amp;gt;&amp;lt;/tt&amp;gt; || style=text-align:center | X || style=text-align:center | X || style=text-align:center | X&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;0x66&amp;lt;/tt&amp;gt; || &amp;lt;tt&amp;gt;&amp;lt;span style=&amp;quot;color:lightgray&amp;quot;&amp;gt;0&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;1100&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt;100&amp;lt;/span&amp;gt;&amp;lt;/tt&amp;gt; || style=text-align:center | X || style=text-align:center | X || style=text-align:center | X&lt;br /&gt;
|-&lt;br /&gt;
| 0xD Store&lt;br /&gt;
| &amp;lt;tt&amp;gt;0x6B || &amp;lt;tt&amp;gt;&amp;lt;span style=&amp;quot;color:lightgray&amp;quot;&amp;gt;0&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;1101&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt;011&amp;lt;/span&amp;gt;&amp;lt;/tt&amp;gt; || style=text-align:center |   || style=text-align:center | X || style=text-align:center | X&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== 0x8 - Byte pair encoding ====&lt;br /&gt;
[https://en.wikipedia.org/wiki/Byte_pair_encoding Byte pair encoding] replaces frequently occurring byte pairs with a single byte that is not used elsewhere in the data. The process is repeated recursively until there are no more repeated byte pairs or available code bytes. Appears to be the same format as [https://problemkaputt.de/psxspx-cdrom-file-compression-ea-methods-bpe.htm documented by Martin Korth].&lt;br /&gt;
&lt;br /&gt;
==== 0xC Obfuscation ====&lt;br /&gt;
Very simple data obfuscation scheme where each byte is subtracted from the previous. The process is reversed by adding running bytes as they are copied.&lt;br /&gt;
&lt;br /&gt;
==== 0xC Store ====&lt;br /&gt;
Data is embedded without any transformations.&lt;br /&gt;
&lt;br /&gt;
=== RPck ===&lt;br /&gt;
3-d shapes are compressed with RPck, a simple byte-oriented [https://en.wikipedia.org/wiki/Run-length_encoding RLE]-based format also found in earlier Amiga games from DSI. Compression ratio is inferior to Barchard&#039;s byte pair encoding. RPck may have been kept for performance reasons or deadline constraints.&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlC&amp;quot;&amp;gt;// Big endian byte ordering.&amp;lt;/span&amp;gt;&lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;struct&amp;lt;/span&amp;gt; Header &amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;{&amp;lt;/span&amp;gt;&lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;char&amp;lt;/span&amp;gt;   magic&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;[&amp;lt;/span&amp;gt;4&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;]&amp;lt;/span&amp;gt; &amp;lt;span class=&amp;quot;hlC&amp;quot;&amp;gt;// &amp;quot;RPck&amp;quot; or &amp;quot;Rpck&amp;quot;&amp;lt;/span&amp;gt;&lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint32&amp;lt;/span&amp;gt; uncompressed_size&lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint32&amp;lt;/span&amp;gt; bytes_saved&lt;br /&gt;
 &lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt;  data&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;[&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;hlC&amp;quot;&amp;gt;...&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;]&amp;lt;/span&amp;gt;&lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;}&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
After the header comes a one-byte control code treated as a signed integer. If the value is negative, it is negated and this number of bytes is read and copied directly to the output. Since the maximum length is 128, another control code is needed if there are more than 128 consecutive bytes without repetition. If the control byte value is positive, the following byte is copied to the output and then duplicated the number of times specified in the control byte. This is repeated until &amp;lt;tt&amp;gt;uncompressed_size&amp;lt;/tt&amp;gt; is reached or there is no more data in the source buffer.&lt;br /&gt;
&lt;br /&gt;
The game is also shipped with two files, &#039;&#039;stdapmin.psh&#039;&#039; and &#039;&#039;stdbaudi.psh&#039;&#039;, which appears to be wrapped in another variant of this format. The header is &amp;quot;&amp;lt;tt&amp;gt;PPkc&amp;lt;/tt&amp;gt;&amp;quot; and the contents are stored without compression, but the length header is stripped from the wrapped resource files.&lt;br /&gt;
&lt;br /&gt;
== PC98 ==&lt;br /&gt;
The PC98 port of the game uses [[#Barchard|Barchard]] to compress some of the bitmap image resource files. See the Amiga section for more details.&lt;br /&gt;
&lt;br /&gt;
== FM Towns ==&lt;br /&gt;
The FM Towns and FM Towns Marty ports of the game were distributed on CD-ROM with ample storage and does not apply any compression to the game resource files.&lt;br /&gt;
&lt;br /&gt;
[[Category:Internals]]&lt;/div&gt;</summary>
		<author><name>Dstien</name></author>
	</entry>
	<entry>
		<id>https://wiki.stunts.hu/index.php?title=Compression&amp;diff=5782</id>
		<title>Compression</title>
		<link rel="alternate" type="text/html" href="https://wiki.stunts.hu/index.php?title=Compression&amp;diff=5782"/>
		<updated>2024-01-11T17:40:58Z</updated>

		<summary type="html">&lt;p&gt;Dstien: /* Barchard */ Store&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Stunts and its ports uses multiple compression formats for code and [[Resource_file_format|resource files]] to save disk space and, more importantly, the number of floppy disks used to distribute the game. &lt;br /&gt;
&lt;br /&gt;
== Formats by game version ==&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! rowspan=3 colspan=3 | Game version !! colspan=4 | Stunts packing !! rowspan=3 | Barchard !! rowspan=3 | RPck&lt;br /&gt;
|-&lt;br /&gt;
! rowspan=2 | RLE !! colspan=3 | Huffman&lt;br /&gt;
|-&lt;br /&gt;
! Supported !! Prefix table !! Code endianness&lt;br /&gt;
|-&lt;br /&gt;
! rowspan=4 style=text-align:left | MS DOS !! rowspan=2 | BB 1.0 !! style=text-align:left | Game&lt;br /&gt;
| style=text-align:center | X || style=text-align:center | X || || Big || ||&lt;br /&gt;
|-&lt;br /&gt;
! style=text-align:left | Loader&lt;br /&gt;
| || style=text-align:center | X || style=text-align:center | X || Little || ||&lt;br /&gt;
|-&lt;br /&gt;
! rowspan=2 | BB 1.1/MS 1.1 !! style=text-align:left | Game&lt;br /&gt;
| style=text-align:center | X || style=text-align:center | X || style=text-align:center | X || Little || ||&lt;br /&gt;
|-&lt;br /&gt;
! style=text-align:left | Loader&lt;br /&gt;
| || style=text-align:center | X || style=text-align:center | X || Little || ||&lt;br /&gt;
|-&lt;br /&gt;
! colspan=3 style=text-align:left | Amiga&lt;br /&gt;
| || || || || style=text-align:center | X || style=text-align:center | X&lt;br /&gt;
|-&lt;br /&gt;
! colspan=3 style=text-align:left | PC98&lt;br /&gt;
| || || || || style=text-align:center | X ||&lt;br /&gt;
|-&lt;br /&gt;
! colspan=3 style=text-align:left | FM Towns&lt;br /&gt;
| || || || || ||&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== MS DOS ==&lt;br /&gt;
The original release of Stunts uses a custom data compression format not found in the ports to other platforms. The code may have been hand-crafted for 16-bit x86 since other options were favoured in the later ports.&lt;br /&gt;
&lt;br /&gt;
The data format supports both [https://en.wikipedia.org/wiki/Run-length_encoding run-length encoding] (RLE) and [https://en.wikipedia.org/wiki/Huffman_coding Huffman coding]. They can be combined in multiple passes. The data format and the decompression code don&#039;t require any particular order or combination of algorithms. Every compressed file shipped with the game use Huffman coding, and when combined with RLE, the RLE pass is applied before Huffman.&lt;br /&gt;
&lt;br /&gt;
=== File header ===&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;enum&amp;lt;/span&amp;gt; CompressionType &amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;{&amp;lt;/span&amp;gt;&lt;br /&gt;
     RLE     = 1&lt;br /&gt;
     Huffman = 2&lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;}&amp;lt;/span&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;struct&amp;lt;/span&amp;gt; Header &amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;{&amp;lt;/span&amp;gt;&lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;union&amp;lt;/span&amp;gt; &amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;{&amp;lt;/span&amp;gt;&lt;br /&gt;
         &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt; passes : 7&lt;br /&gt;
         &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt; compression_type : 7&lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;}&amp;lt;/span&amp;gt;&lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt;  multi_pass : 1&lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint32&amp;lt;/span&amp;gt; uncompressed_size : 24&lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;}&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
If the most significant bit of the first byte of the file is set, this is a multi-pass file and the remaining 7 bits are the number of passes to be processed recursively. If the &amp;lt;tt&amp;gt;multi_pass&amp;lt;/tt&amp;gt; flag is not set, we are only doing a single pass and the first byte is the compression type. The next three bytes make up the uncompressed size. If the &amp;lt;tt&amp;gt;multi_pass&amp;lt;/tt&amp;gt; flag was set, this is the final uncompressed size. When the &amp;lt;tt&amp;gt;multi_pass&amp;lt;/tt&amp;gt; flag is not set, this is the uncompressed size of the current pass. The remaining data is processed recursively. The &amp;lt;tt&amp;gt;compression_type&amp;lt;/tt&amp;gt; field decides how it is decoded.&lt;br /&gt;
&lt;br /&gt;
=== Run-length encoding ===&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;struct&amp;lt;/span&amp;gt; RLE &amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;{&amp;lt;/span&amp;gt;&lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint32&amp;lt;/span&amp;gt; compressed_size : 24&lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt;  reserved &amp;lt;span class=&amp;quot;hlC&amp;quot;&amp;gt;// Always 0x00, value is ignored by the game&amp;lt;/span&amp;gt;&lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt;  escape_length : 7&lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt;  no_sequence : 1&lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt;  escape_codes&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;[&amp;lt;/span&amp;gt;escape_length&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;]&amp;lt;/span&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt;  data&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;[&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;hlC&amp;quot;&amp;gt;...&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;]&amp;lt;/span&amp;gt;&lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;}&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
RLE is used to reduce the length of consecutively repeated bytes by using an escape code followed by a counter to signify how many times the next byte should be repeated. It is particularly useful for compressing images, as large areas with a single colour would be represented by many consecutive identical bytes.&lt;br /&gt;
&lt;br /&gt;
The RLE stage can itself have two passes if &amp;lt;tt&amp;gt;no_sequence&amp;lt;/tt&amp;gt; is not set. The first pass will then expand sequences of bytes in the data. &amp;lt;tt&amp;gt;escape_codes[1]&amp;lt;/tt&amp;gt; will mark the beginning and the end of a byte sequence. When the escape code is encountered in the data, the following bytes are considered a sequence until the escape code is hit again. After the end-marking escape code, a one byte length counter tells how many times the preceding byte sequence should be repeated in the output buffer. Because the escape code cannot itself be escaped, sequential byte runs can only be applied in files that have unused byte values to use as the first escape code.&lt;br /&gt;
&lt;br /&gt;
The main RLE pass is a traditional expansion of single-byte runs, but with a twist that allows for multiple types of escape codes. The escape code&#039;s position in the header&#039;s escape code list affects its properties. When the first escape code is encountered in the source buffer, the following byte has the number of repetitions, and the next byte will be copied that many times to the output buffer. When the third escape code is encountered, the number of repetitions is stored in the following &#039;&#039;two&#039;&#039; bytes as a 16-bit integer. Then the following byte is copied that many times. All other escape codes use its position in the escape code list as the number of repetitions, and have no additional counter bytes before the data byte to be repeated. This allows the second escape code reserved for sequences to serve as a no-op without the two passes interfering. Escape codes can themselves be escaped in single-byte runs by having them expanded to only one copy.&lt;br /&gt;
&lt;br /&gt;
All repetition counters have an off-by-one surplus, as the data byte itself counts as the first copy. For optimal compression, escape codes should be chosen from byte values that occur least frequently, or not at all, in the source data.&lt;br /&gt;
&lt;br /&gt;
==== RLE decoding optimisation ====&lt;br /&gt;
Escape codes are put in an &amp;lt;tt&amp;gt;escape[256]&amp;lt;/tt&amp;gt; array, where the code&#039;s byte value is the index and the escape code&#039;s position is the entry&#039;s value. This array is used to test incoming bytes for escape codes. Raw bytes will have the value 0, while other values corresponds to the escape code&#039;s property. This optimisation makes the decoding run O(1), as opposed to O(&#039;&#039;n&#039;&#039;), where &#039;&#039;n&#039;&#039; is the number of escape codes.&lt;br /&gt;
&lt;br /&gt;
=== Huffman coding ===&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;struct&amp;lt;/span&amp;gt; Huffman &amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;{&amp;lt;/span&amp;gt;&lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt; tree_levels : 7&lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt; delta_coding : 1&lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt; symbols_per_level&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;[&amp;lt;/span&amp;gt;tree_levels&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;]&amp;lt;/span&amp;gt;&lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt; alphabet&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;[&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;SUM&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;(&amp;lt;/span&amp;gt;symbols_per_level&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;)&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;]&amp;lt;/span&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint16&amp;lt;/span&amp;gt; codes : var &amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;[&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;hlC&amp;quot;&amp;gt;...&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;]&amp;lt;/span&amp;gt;&lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;}&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Huffman coding uses a binary tree to store data. When Huffman codes are read, each bit tells which branch to take when traversing the tree. If a leaf node is hit, we have found the code&#039;s symbol and can proceed with the next code. Frequently used symbols have shorter paths and thus takes up fewer bits in the source file.&lt;br /&gt;
&lt;br /&gt;
The tree is stored by having two lists, one with symbols per level, and one with the alphabet. The alphabet is every possible symbol in the order they appear in the tree. The tree is built by going through each &amp;lt;tt&amp;gt;symbols_per_level&amp;lt;/tt&amp;gt;. If there are symbols at the current level, consume them from &amp;lt;tt&amp;gt;alphabet&amp;lt;/tt&amp;gt; and create leaf nodes. If there are no symbols, and there still are more levels to create, proceed to create left and right children nodes for the next level.&lt;br /&gt;
&lt;br /&gt;
The remaining data is the Huffman codes. Bit by bit is read to find leaf nodes in the Huffman tree whose symbols are appended to the output buffer. This is repeated until the output buffer has reached &amp;lt;tt&amp;gt;uncompressed_size&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
The maximum Huffman tree height is 16. While the data format allows for up to 127 levels, Stunts&#039; decompression function uses arrays with a fixed capacity of 16 for its level offset table.&lt;br /&gt;
&lt;br /&gt;
==== Delta coding ====&lt;br /&gt;
If the flag for [https://en.wikipedia.org/wiki/Delta_encoding delta coding] is set, each symbol is treated as the difference from the previous output byte instead of an independent final value. The last byte written to the output buffer is remembered and added to the next expanded symbol. While regular Huffman coding assigns shorter codes to frequently occurring values, this delta variant assigns shorter codes to differences that occurs frequently. This feature is not used by any shipped files, but the code is present in all versions that implements Huffman decoding. One can speculate that delta coding was outperformed by RLE combined with regular Huffman coding, making delta coding unnecessary.&lt;br /&gt;
&lt;br /&gt;
==== Huffman decoding optimisations ====&lt;br /&gt;
===== Prefix table =====&lt;br /&gt;
With Huffman codes being paths in a binary tree, they have the property of being prefix-free, meaning that one leaf node&#039;s code cannot be the prefix of another node&#039;s code. This allows for a decoding optimisation technique known as &#039;&#039;prefix tables&#039;&#039; or &#039;&#039;Huffman tables&#039;&#039;. By creating arrays of symbols and code widths where the indices are the Huffman codes, the codes can be looked up directly without traversing the tree. Every array index for non-leaf nodes between two leaf node entries are filled with data for the preceding leaf node. This way there&#039;s no need to filter out bits that belong to the next Huffman code, at the expense of common symbols taking up multiple entries in the lookup table during decompression.&lt;br /&gt;
&lt;br /&gt;
Stunts utilises this optimisation for Huffman codes that are up to 8 bits wide. The first byte of the code is checked in the &amp;lt;tt&amp;gt;widths[256]&amp;lt;/tt&amp;gt; array. If the code&#039;s width is 8 bits or less, the same code is looked up in the &amp;lt;tt&amp;gt;symbols[256]&amp;lt;/tt&amp;gt; array and written to the output buffer. To find the start of the next Huffman code, the source buffer is advanced by the code&#039;s bit width found in the &amp;lt;tt&amp;gt;widths&amp;lt;/tt&amp;gt; array.&lt;br /&gt;
&lt;br /&gt;
===== Offset table =====&lt;br /&gt;
As Stunts limits the prefix tables to 8 bit wide Huffman codes to save RAM, another novel optimisation is applied for codes that exceeds 8 bits. Prefixes for longer codes have the value &amp;lt;tt&amp;gt;0x40&amp;lt;/tt&amp;gt; in the &amp;lt;tt&amp;gt;widths&amp;lt;/tt&amp;gt; array, indicating that the current code is a prefix that needs further expansion. For this purpose Stunts uses two additional helper arrays: &amp;lt;tt&amp;gt;total_codes[tree_levels]&amp;lt;/tt&amp;gt;, which has the total number of leaf nodes that exists in the tree up to each level, and &amp;lt;tt&amp;gt;code_offsets[tree_levels]&amp;lt;/tt&amp;gt;, which for each level has a value that can be added to a code with the same level in order to get its index in the alphabet. This works because the codes are arranged [https://en.wikipedia.org/wiki/Canonical_Huffman_code canonically]. As a code&#039;s bit width corresponds to the code&#039;s level in the Huffman tree, the width can be used to compare the current code with the level&#039;s total by getting &amp;lt;tt&amp;gt;total_codes[current_width]&amp;lt;/tt&amp;gt; for each extra bit read. If the code is smaller than the total number of codes encountered, it is a leaf node, and we get the symbol by adding the level&#039;s code offset to the code with &amp;lt;tt&amp;gt;alphabet[code + code_offsets[width]]&amp;lt;/tt&amp;gt;. This is more laborious than the use of prefix tables for direct lookup, but it only applies to codes that are occurring less frequently in the input file.&lt;br /&gt;
&lt;br /&gt;
==== Version differences ====&lt;br /&gt;
The Huffman decompression in the game code of Stunts 1.0 differs from the one in its LOAD.EXE and later versions of the game. The Huffman codes are written with the least significant bit first, as opposed to the other versions that has the codes written with the opposite orientation. The game code of Stunts 1.0 also does not use a prefix table, and the bit-stream orientation was likely changed with the introduction of this optimisation.&lt;br /&gt;
&lt;br /&gt;
== Amiga ==&lt;br /&gt;
The Amiga port uses two unrelated compression formats.&lt;br /&gt;
&lt;br /&gt;
=== Barchard ===&lt;br /&gt;
Non-3d shape resource files uses another Distinctive Software in-house format that is characterized by the identification byte &amp;lt;tt&amp;gt;0xFB&amp;lt;/tt&amp;gt;, assumed to be the initials of its author, [https://www.mobygames.com/person/7186/frank-barchard/ Frank Barchard]. This format supports a suite of different compression methods and it evolved through the 90&#039;s and early 2000&#039;s as a part of EA&#039;s internal engine libraries. Whereas later games tended to use the [https://en.wikipedia.org/wiki/Lempel%E2%80%93Ziv%E2%80%93Storer%E2%80%93Szymanski LZSS]-based [https://github.com/lingeringwillx/Refpack-QFS-Resources RefPack] algorithm, the Stunts ports uses other methods. We will therefore refer to these compressions as &#039;&#039;&amp;quot;Barchard&amp;quot;&#039;&#039; to distinguish them from the ubiquitous RefPack.&lt;br /&gt;
&lt;br /&gt;
This is the currently assumed header structure:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;struct&amp;lt;/span&amp;gt; Header &amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;{&amp;lt;/span&amp;gt;&lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt;  method_flags : 3&lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt;  method_type  : 4&lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt;  32bit_length : 1 &amp;lt;span class=&amp;quot;hlC&amp;quot;&amp;gt;// Not used by Stunts&amp;lt;/span&amp;gt;&lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt;  magic &amp;lt;span class=&amp;quot;hlC&amp;quot;&amp;gt;// Always 0xFB&amp;lt;/span&amp;gt;&lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint32&amp;lt;/span&amp;gt; uncompressed_size : 24&lt;br /&gt;
 &lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlC&amp;quot;&amp;gt;// Possibly more fields if indicated by method_flags&amp;lt;/span&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt;  data&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;[&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;hlC&amp;quot;&amp;gt;...&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;]&amp;lt;/span&amp;gt;&lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;}&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Below are the values of the first byte in the shipped files. Values from the DOS version of [https://www.mobygames.com/game/56474/mickeys-abcs-a-day-at-the-fair/ Mickey&#039;s ABC&#039;s: A Day at the Fair] are included, as this may be the first public incarnation of Barchard compression. The bitfield suspected to be the method is highlighted in red, the method flags in green.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Game                !! Hex  !! Bits&lt;br /&gt;
|-&lt;br /&gt;
| Mickey&#039;s ABC BPE      || &amp;lt;tt&amp;gt;0x44&amp;lt;/tt&amp;gt; || &amp;lt;tt&amp;gt;&amp;lt;span style=&amp;quot;color:lightgray&amp;quot;&amp;gt;0&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;1000&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt;100&amp;lt;/span&amp;gt;&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Stunts Amiga Method 1 || &amp;lt;tt&amp;gt;0x26&amp;lt;/tt&amp;gt; || &amp;lt;tt&amp;gt;&amp;lt;span style=&amp;quot;color:lightgray&amp;quot;&amp;gt;0&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;0100&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt;110&amp;lt;/span&amp;gt;&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Stunts Amiga Method 1 || &amp;lt;tt&amp;gt;0x27&amp;lt;/tt&amp;gt; || &amp;lt;tt&amp;gt;&amp;lt;span style=&amp;quot;color:lightgray&amp;quot;&amp;gt;0&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;0100&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt;111&amp;lt;/span&amp;gt;&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Stunts Amiga BPE      || &amp;lt;tt&amp;gt;0x42&amp;lt;/tt&amp;gt; || &amp;lt;tt&amp;gt;&amp;lt;span style=&amp;quot;color:lightgray&amp;quot;&amp;gt;0&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;1000&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt;010&amp;lt;/span&amp;gt;&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Stunts PC98 BPE       || &amp;lt;tt&amp;gt;0x46&amp;lt;/tt&amp;gt; || &amp;lt;tt&amp;gt;&amp;lt;span style=&amp;quot;color:lightgray&amp;quot;&amp;gt;0&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;1000&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt;110&amp;lt;/span&amp;gt;&amp;lt;/tt&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The game code appears to support several other methods that are not used by the shipped files.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Method !! Hex !! Bits !! Amiga !! PC98 !! Mickey&lt;br /&gt;
|-&lt;br /&gt;
| rowspan=2 | 0x4&lt;br /&gt;
| &amp;lt;tt&amp;gt;0x26&amp;lt;/tt&amp;gt; || &amp;lt;tt&amp;gt;&amp;lt;span style=&amp;quot;color:lightgray&amp;quot;&amp;gt;0&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;0100&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt;110&amp;lt;/span&amp;gt;&amp;lt;/tt&amp;gt; || style=text-align:center | X || style=text-align:center |   || style=text-align:center | &lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;0x27&amp;lt;/tt&amp;gt; || &amp;lt;tt&amp;gt;&amp;lt;span style=&amp;quot;color:lightgray&amp;quot;&amp;gt;0&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;0100&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt;111&amp;lt;/span&amp;gt;&amp;lt;/tt&amp;gt; || style=text-align:center | X || style=text-align:center |   || style=text-align:center | &lt;br /&gt;
|-&lt;br /&gt;
| rowspan=7 | 0x8 Byte pair encoding&lt;br /&gt;
| &amp;lt;tt&amp;gt;0x40&amp;lt;/tt&amp;gt; || &amp;lt;tt&amp;gt;&amp;lt;span style=&amp;quot;color:lightgray&amp;quot;&amp;gt;0&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;1000&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt;000&amp;lt;/span&amp;gt;&amp;lt;/tt&amp;gt; || style=text-align:center | X || style=text-align:center |   || style=text-align:center | X&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;0x41&amp;lt;/tt&amp;gt; || &amp;lt;tt&amp;gt;&amp;lt;span style=&amp;quot;color:lightgray&amp;quot;&amp;gt;0&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;1000&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt;001&amp;lt;/span&amp;gt;&amp;lt;/tt&amp;gt; || style=text-align:center | X || style=text-align:center |   || style=text-align:center | X&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;0x42&amp;lt;/tt&amp;gt; || &amp;lt;tt&amp;gt;&amp;lt;span style=&amp;quot;color:lightgray&amp;quot;&amp;gt;0&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;1000&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt;010&amp;lt;/span&amp;gt;&amp;lt;/tt&amp;gt; || style=text-align:center | X || style=text-align:center |   || style=text-align:center | X&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;0x44&amp;lt;/tt&amp;gt; || &amp;lt;tt&amp;gt;&amp;lt;span style=&amp;quot;color:lightgray&amp;quot;&amp;gt;0&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;1000&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt;100&amp;lt;/span&amp;gt;&amp;lt;/tt&amp;gt; || style=text-align:center |   || style=text-align:center |   || style=text-align:center | X&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;0x45&amp;lt;/tt&amp;gt; || &amp;lt;tt&amp;gt;&amp;lt;span style=&amp;quot;color:lightgray&amp;quot;&amp;gt;0&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;1000&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt;101&amp;lt;/span&amp;gt;&amp;lt;/tt&amp;gt; || style=text-align:center |   || style=text-align:center |   || style=text-align:center | X&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;0x46&amp;lt;/tt&amp;gt; || &amp;lt;tt&amp;gt;&amp;lt;span style=&amp;quot;color:lightgray&amp;quot;&amp;gt;0&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;1000&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt;110&amp;lt;/span&amp;gt;&amp;lt;/tt&amp;gt; || style=text-align:center |   || style=text-align:center | X || style=text-align:center |&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;0x47&amp;lt;/tt&amp;gt; || &amp;lt;tt&amp;gt;&amp;lt;span style=&amp;quot;color:lightgray&amp;quot;&amp;gt;0&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;1000&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt;111&amp;lt;/span&amp;gt;&amp;lt;/tt&amp;gt; || style=text-align:center |   || style=text-align:center | X || style=text-align:center |&lt;br /&gt;
|-&lt;br /&gt;
| rowspan=3 | 0xC Obfuscation&lt;br /&gt;
| &amp;lt;tt&amp;gt;0x60&amp;lt;/tt&amp;gt; || &amp;lt;tt&amp;gt;&amp;lt;span style=&amp;quot;color:lightgray&amp;quot;&amp;gt;0&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;1100&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt;000&amp;lt;/span&amp;gt;&amp;lt;/tt&amp;gt; || style=text-align:center | X || style=text-align:center | X || style=text-align:center | X&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;0x62&amp;lt;/tt&amp;gt; || &amp;lt;tt&amp;gt;&amp;lt;span style=&amp;quot;color:lightgray&amp;quot;&amp;gt;0&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;1100&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt;010&amp;lt;/span&amp;gt;&amp;lt;/tt&amp;gt; || style=text-align:center | X || style=text-align:center | X || style=text-align:center | X&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;0x66&amp;lt;/tt&amp;gt; || &amp;lt;tt&amp;gt;&amp;lt;span style=&amp;quot;color:lightgray&amp;quot;&amp;gt;0&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;1100&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt;100&amp;lt;/span&amp;gt;&amp;lt;/tt&amp;gt; || style=text-align:center | X || style=text-align:center | X || style=text-align:center | X&lt;br /&gt;
|-&lt;br /&gt;
| 0xD Store&lt;br /&gt;
| &amp;lt;tt&amp;gt;0x6B || &amp;lt;tt&amp;gt;&amp;lt;span style=&amp;quot;color:lightgray&amp;quot;&amp;gt;0&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;1101&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt;011&amp;lt;/span&amp;gt;&amp;lt;/tt&amp;gt; || style=text-align:center |   || style=text-align:center | X || style=text-align:center | X&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== 0x8 - Byte pair encoding ====&lt;br /&gt;
[https://en.wikipedia.org/wiki/Byte_pair_encoding Byte pair encoding] replaces frequently occurring byte pairs with a single byte that is not used elsewhere in the data. The process is repeated recursively until there are no more repeated byte pairs or available code bytes. Appears to be the same format as [https://problemkaputt.de/psxspx-cdrom-file-compression-ea-methods-bpe.htm documented by Martin Korth].&lt;br /&gt;
&lt;br /&gt;
==== 0xC Obfuscation ====&lt;br /&gt;
Very simple data obfuscation scheme where each byte is subtracted from the previous. The process is reversed by adding running bytes as they are copied.&lt;br /&gt;
&lt;br /&gt;
==== 0xC Store ====&lt;br /&gt;
Data is embedded without any transformations.&lt;br /&gt;
&lt;br /&gt;
=== RPck ===&lt;br /&gt;
3-d shapes are compressed with RPck, a simple [https://en.wikipedia.org/wiki/Run-length_encoding RLE]-based format found in some Amiga file archiving software. Compression ratio is inferior to RefPack, but the code is simpler and faster, which may explain why it was chosen for these files.&lt;br /&gt;
&lt;br /&gt;
== PC98 ==&lt;br /&gt;
The PC98 port of the game uses [[#Barchard|Barchard]] to compress some of the bitmap image resource files. See the Amiga section for more details.&lt;br /&gt;
&lt;br /&gt;
== FM Towns ==&lt;br /&gt;
The FM Towns and FM Towns Marty ports of the game were distributed on CD-ROM with ample storage and does not apply any compression to the game resource files.&lt;br /&gt;
&lt;br /&gt;
[[Category:Internals]]&lt;/div&gt;</summary>
		<author><name>Dstien</name></author>
	</entry>
	<entry>
		<id>https://wiki.stunts.hu/index.php?title=Compression&amp;diff=5781</id>
		<title>Compression</title>
		<link rel="alternate" type="text/html" href="https://wiki.stunts.hu/index.php?title=Compression&amp;diff=5781"/>
		<updated>2024-01-11T17:22:47Z</updated>

		<summary type="html">&lt;p&gt;Dstien: /* Barchard */ Identified obfuscation method.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Stunts and its ports uses multiple compression formats for code and [[Resource_file_format|resource files]] to save disk space and, more importantly, the number of floppy disks used to distribute the game. &lt;br /&gt;
&lt;br /&gt;
== Formats by game version ==&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! rowspan=3 colspan=3 | Game version !! colspan=4 | Stunts packing !! rowspan=3 | Barchard !! rowspan=3 | RPck&lt;br /&gt;
|-&lt;br /&gt;
! rowspan=2 | RLE !! colspan=3 | Huffman&lt;br /&gt;
|-&lt;br /&gt;
! Supported !! Prefix table !! Code endianness&lt;br /&gt;
|-&lt;br /&gt;
! rowspan=4 style=text-align:left | MS DOS !! rowspan=2 | BB 1.0 !! style=text-align:left | Game&lt;br /&gt;
| style=text-align:center | X || style=text-align:center | X || || Big || ||&lt;br /&gt;
|-&lt;br /&gt;
! style=text-align:left | Loader&lt;br /&gt;
| || style=text-align:center | X || style=text-align:center | X || Little || ||&lt;br /&gt;
|-&lt;br /&gt;
! rowspan=2 | BB 1.1/MS 1.1 !! style=text-align:left | Game&lt;br /&gt;
| style=text-align:center | X || style=text-align:center | X || style=text-align:center | X || Little || ||&lt;br /&gt;
|-&lt;br /&gt;
! style=text-align:left | Loader&lt;br /&gt;
| || style=text-align:center | X || style=text-align:center | X || Little || ||&lt;br /&gt;
|-&lt;br /&gt;
! colspan=3 style=text-align:left | Amiga&lt;br /&gt;
| || || || || style=text-align:center | X || style=text-align:center | X&lt;br /&gt;
|-&lt;br /&gt;
! colspan=3 style=text-align:left | PC98&lt;br /&gt;
| || || || || style=text-align:center | X ||&lt;br /&gt;
|-&lt;br /&gt;
! colspan=3 style=text-align:left | FM Towns&lt;br /&gt;
| || || || || ||&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== MS DOS ==&lt;br /&gt;
The original release of Stunts uses a custom data compression format not found in the ports to other platforms. The code may have been hand-crafted for 16-bit x86 since other options were favoured in the later ports.&lt;br /&gt;
&lt;br /&gt;
The data format supports both [https://en.wikipedia.org/wiki/Run-length_encoding run-length encoding] (RLE) and [https://en.wikipedia.org/wiki/Huffman_coding Huffman coding]. They can be combined in multiple passes. The data format and the decompression code don&#039;t require any particular order or combination of algorithms. Every compressed file shipped with the game use Huffman coding, and when combined with RLE, the RLE pass is applied before Huffman.&lt;br /&gt;
&lt;br /&gt;
=== File header ===&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;enum&amp;lt;/span&amp;gt; CompressionType &amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;{&amp;lt;/span&amp;gt;&lt;br /&gt;
     RLE     = 1&lt;br /&gt;
     Huffman = 2&lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;}&amp;lt;/span&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;struct&amp;lt;/span&amp;gt; Header &amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;{&amp;lt;/span&amp;gt;&lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;union&amp;lt;/span&amp;gt; &amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;{&amp;lt;/span&amp;gt;&lt;br /&gt;
         &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt; passes : 7&lt;br /&gt;
         &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt; compression_type : 7&lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;}&amp;lt;/span&amp;gt;&lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt;  multi_pass : 1&lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint32&amp;lt;/span&amp;gt; uncompressed_size : 24&lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;}&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
If the most significant bit of the first byte of the file is set, this is a multi-pass file and the remaining 7 bits are the number of passes to be processed recursively. If the &amp;lt;tt&amp;gt;multi_pass&amp;lt;/tt&amp;gt; flag is not set, we are only doing a single pass and the first byte is the compression type. The next three bytes make up the uncompressed size. If the &amp;lt;tt&amp;gt;multi_pass&amp;lt;/tt&amp;gt; flag was set, this is the final uncompressed size. When the &amp;lt;tt&amp;gt;multi_pass&amp;lt;/tt&amp;gt; flag is not set, this is the uncompressed size of the current pass. The remaining data is processed recursively. The &amp;lt;tt&amp;gt;compression_type&amp;lt;/tt&amp;gt; field decides how it is decoded.&lt;br /&gt;
&lt;br /&gt;
=== Run-length encoding ===&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;struct&amp;lt;/span&amp;gt; RLE &amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;{&amp;lt;/span&amp;gt;&lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint32&amp;lt;/span&amp;gt; compressed_size : 24&lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt;  reserved &amp;lt;span class=&amp;quot;hlC&amp;quot;&amp;gt;// Always 0x00, value is ignored by the game&amp;lt;/span&amp;gt;&lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt;  escape_length : 7&lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt;  no_sequence : 1&lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt;  escape_codes&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;[&amp;lt;/span&amp;gt;escape_length&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;]&amp;lt;/span&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt;  data&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;[&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;hlC&amp;quot;&amp;gt;...&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;]&amp;lt;/span&amp;gt;&lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;}&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
RLE is used to reduce the length of consecutively repeated bytes by using an escape code followed by a counter to signify how many times the next byte should be repeated. It is particularly useful for compressing images, as large areas with a single colour would be represented by many consecutive identical bytes.&lt;br /&gt;
&lt;br /&gt;
The RLE stage can itself have two passes if &amp;lt;tt&amp;gt;no_sequence&amp;lt;/tt&amp;gt; is not set. The first pass will then expand sequences of bytes in the data. &amp;lt;tt&amp;gt;escape_codes[1]&amp;lt;/tt&amp;gt; will mark the beginning and the end of a byte sequence. When the escape code is encountered in the data, the following bytes are considered a sequence until the escape code is hit again. After the end-marking escape code, a one byte length counter tells how many times the preceding byte sequence should be repeated in the output buffer. Because the escape code cannot itself be escaped, sequential byte runs can only be applied in files that have unused byte values to use as the first escape code.&lt;br /&gt;
&lt;br /&gt;
The main RLE pass is a traditional expansion of single-byte runs, but with a twist that allows for multiple types of escape codes. The escape code&#039;s position in the header&#039;s escape code list affects its properties. When the first escape code is encountered in the source buffer, the following byte has the number of repetitions, and the next byte will be copied that many times to the output buffer. When the third escape code is encountered, the number of repetitions is stored in the following &#039;&#039;two&#039;&#039; bytes as a 16-bit integer. Then the following byte is copied that many times. All other escape codes use its position in the escape code list as the number of repetitions, and have no additional counter bytes before the data byte to be repeated. This allows the second escape code reserved for sequences to serve as a no-op without the two passes interfering. Escape codes can themselves be escaped in single-byte runs by having them expanded to only one copy.&lt;br /&gt;
&lt;br /&gt;
All repetition counters have an off-by-one surplus, as the data byte itself counts as the first copy. For optimal compression, escape codes should be chosen from byte values that occur least frequently, or not at all, in the source data.&lt;br /&gt;
&lt;br /&gt;
==== RLE decoding optimisation ====&lt;br /&gt;
Escape codes are put in an &amp;lt;tt&amp;gt;escape[256]&amp;lt;/tt&amp;gt; array, where the code&#039;s byte value is the index and the escape code&#039;s position is the entry&#039;s value. This array is used to test incoming bytes for escape codes. Raw bytes will have the value 0, while other values corresponds to the escape code&#039;s property. This optimisation makes the decoding run O(1), as opposed to O(&#039;&#039;n&#039;&#039;), where &#039;&#039;n&#039;&#039; is the number of escape codes.&lt;br /&gt;
&lt;br /&gt;
=== Huffman coding ===&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;struct&amp;lt;/span&amp;gt; Huffman &amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;{&amp;lt;/span&amp;gt;&lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt; tree_levels : 7&lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt; delta_coding : 1&lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt; symbols_per_level&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;[&amp;lt;/span&amp;gt;tree_levels&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;]&amp;lt;/span&amp;gt;&lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt; alphabet&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;[&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;SUM&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;(&amp;lt;/span&amp;gt;symbols_per_level&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;)&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;]&amp;lt;/span&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint16&amp;lt;/span&amp;gt; codes : var &amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;[&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;hlC&amp;quot;&amp;gt;...&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;]&amp;lt;/span&amp;gt;&lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;}&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Huffman coding uses a binary tree to store data. When Huffman codes are read, each bit tells which branch to take when traversing the tree. If a leaf node is hit, we have found the code&#039;s symbol and can proceed with the next code. Frequently used symbols have shorter paths and thus takes up fewer bits in the source file.&lt;br /&gt;
&lt;br /&gt;
The tree is stored by having two lists, one with symbols per level, and one with the alphabet. The alphabet is every possible symbol in the order they appear in the tree. The tree is built by going through each &amp;lt;tt&amp;gt;symbols_per_level&amp;lt;/tt&amp;gt;. If there are symbols at the current level, consume them from &amp;lt;tt&amp;gt;alphabet&amp;lt;/tt&amp;gt; and create leaf nodes. If there are no symbols, and there still are more levels to create, proceed to create left and right children nodes for the next level.&lt;br /&gt;
&lt;br /&gt;
The remaining data is the Huffman codes. Bit by bit is read to find leaf nodes in the Huffman tree whose symbols are appended to the output buffer. This is repeated until the output buffer has reached &amp;lt;tt&amp;gt;uncompressed_size&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
The maximum Huffman tree height is 16. While the data format allows for up to 127 levels, Stunts&#039; decompression function uses arrays with a fixed capacity of 16 for its level offset table.&lt;br /&gt;
&lt;br /&gt;
==== Delta coding ====&lt;br /&gt;
If the flag for [https://en.wikipedia.org/wiki/Delta_encoding delta coding] is set, each symbol is treated as the difference from the previous output byte instead of an independent final value. The last byte written to the output buffer is remembered and added to the next expanded symbol. While regular Huffman coding assigns shorter codes to frequently occurring values, this delta variant assigns shorter codes to differences that occurs frequently. This feature is not used by any shipped files, but the code is present in all versions that implements Huffman decoding. One can speculate that delta coding was outperformed by RLE combined with regular Huffman coding, making delta coding unnecessary.&lt;br /&gt;
&lt;br /&gt;
==== Huffman decoding optimisations ====&lt;br /&gt;
===== Prefix table =====&lt;br /&gt;
With Huffman codes being paths in a binary tree, they have the property of being prefix-free, meaning that one leaf node&#039;s code cannot be the prefix of another node&#039;s code. This allows for a decoding optimisation technique known as &#039;&#039;prefix tables&#039;&#039; or &#039;&#039;Huffman tables&#039;&#039;. By creating arrays of symbols and code widths where the indices are the Huffman codes, the codes can be looked up directly without traversing the tree. Every array index for non-leaf nodes between two leaf node entries are filled with data for the preceding leaf node. This way there&#039;s no need to filter out bits that belong to the next Huffman code, at the expense of common symbols taking up multiple entries in the lookup table during decompression.&lt;br /&gt;
&lt;br /&gt;
Stunts utilises this optimisation for Huffman codes that are up to 8 bits wide. The first byte of the code is checked in the &amp;lt;tt&amp;gt;widths[256]&amp;lt;/tt&amp;gt; array. If the code&#039;s width is 8 bits or less, the same code is looked up in the &amp;lt;tt&amp;gt;symbols[256]&amp;lt;/tt&amp;gt; array and written to the output buffer. To find the start of the next Huffman code, the source buffer is advanced by the code&#039;s bit width found in the &amp;lt;tt&amp;gt;widths&amp;lt;/tt&amp;gt; array.&lt;br /&gt;
&lt;br /&gt;
===== Offset table =====&lt;br /&gt;
As Stunts limits the prefix tables to 8 bit wide Huffman codes to save RAM, another novel optimisation is applied for codes that exceeds 8 bits. Prefixes for longer codes have the value &amp;lt;tt&amp;gt;0x40&amp;lt;/tt&amp;gt; in the &amp;lt;tt&amp;gt;widths&amp;lt;/tt&amp;gt; array, indicating that the current code is a prefix that needs further expansion. For this purpose Stunts uses two additional helper arrays: &amp;lt;tt&amp;gt;total_codes[tree_levels]&amp;lt;/tt&amp;gt;, which has the total number of leaf nodes that exists in the tree up to each level, and &amp;lt;tt&amp;gt;code_offsets[tree_levels]&amp;lt;/tt&amp;gt;, which for each level has a value that can be added to a code with the same level in order to get its index in the alphabet. This works because the codes are arranged [https://en.wikipedia.org/wiki/Canonical_Huffman_code canonically]. As a code&#039;s bit width corresponds to the code&#039;s level in the Huffman tree, the width can be used to compare the current code with the level&#039;s total by getting &amp;lt;tt&amp;gt;total_codes[current_width]&amp;lt;/tt&amp;gt; for each extra bit read. If the code is smaller than the total number of codes encountered, it is a leaf node, and we get the symbol by adding the level&#039;s code offset to the code with &amp;lt;tt&amp;gt;alphabet[code + code_offsets[width]]&amp;lt;/tt&amp;gt;. This is more laborious than the use of prefix tables for direct lookup, but it only applies to codes that are occurring less frequently in the input file.&lt;br /&gt;
&lt;br /&gt;
==== Version differences ====&lt;br /&gt;
The Huffman decompression in the game code of Stunts 1.0 differs from the one in its LOAD.EXE and later versions of the game. The Huffman codes are written with the least significant bit first, as opposed to the other versions that has the codes written with the opposite orientation. The game code of Stunts 1.0 also does not use a prefix table, and the bit-stream orientation was likely changed with the introduction of this optimisation.&lt;br /&gt;
&lt;br /&gt;
== Amiga ==&lt;br /&gt;
The Amiga port uses two unrelated compression formats.&lt;br /&gt;
&lt;br /&gt;
=== Barchard ===&lt;br /&gt;
Non-3d shape resource files uses another Distinctive Software in-house format that is characterized by the identification byte &amp;lt;tt&amp;gt;0xFB&amp;lt;/tt&amp;gt;, assumed to be the initials of its author, [https://www.mobygames.com/person/7186/frank-barchard/ Frank Barchard]. This format supports a suite of different compression methods and it evolved through the 90&#039;s and early 2000&#039;s as a part of EA&#039;s internal engine libraries. Whereas later games tended to use the [https://en.wikipedia.org/wiki/Lempel%E2%80%93Ziv%E2%80%93Storer%E2%80%93Szymanski LZSS]-based [https://github.com/lingeringwillx/Refpack-QFS-Resources RefPack] algorithm, the Stunts ports uses other methods. We will therefore refer to these compressions as &#039;&#039;&amp;quot;Barchard&amp;quot;&#039;&#039; to distinguish them from the ubiquitous RefPack.&lt;br /&gt;
&lt;br /&gt;
This is the currently assumed header structure:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;struct&amp;lt;/span&amp;gt; Header &amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;{&amp;lt;/span&amp;gt;&lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt;  method_flags : 3&lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt;  method_type  : 4&lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt;  32bit_length : 1 &amp;lt;span class=&amp;quot;hlC&amp;quot;&amp;gt;// Not used by Stunts&amp;lt;/span&amp;gt;&lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt;  magic &amp;lt;span class=&amp;quot;hlC&amp;quot;&amp;gt;// Always 0xFB&amp;lt;/span&amp;gt;&lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint32&amp;lt;/span&amp;gt; uncompressed_size : 24&lt;br /&gt;
 &lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlC&amp;quot;&amp;gt;// Possibly more fields if indicated by method_flags&amp;lt;/span&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt;  data&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;[&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;hlC&amp;quot;&amp;gt;...&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;]&amp;lt;/span&amp;gt;&lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;}&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Below are the values of the first byte in the shipped files. Values from the DOS version of [https://www.mobygames.com/game/56474/mickeys-abcs-a-day-at-the-fair/ Mickey&#039;s ABC&#039;s: A Day at the Fair] are included, as this may be the first public incarnation of Barchard compression. The bitfield suspected to be the method is highlighted in red, the method flags in green.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Game                !! Hex  !! Bits&lt;br /&gt;
|-&lt;br /&gt;
| Mickey&#039;s ABC BPE      || &amp;lt;tt&amp;gt;0x44&amp;lt;/tt&amp;gt; || &amp;lt;tt&amp;gt;&amp;lt;span style=&amp;quot;color:lightgray&amp;quot;&amp;gt;0&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;1000&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt;100&amp;lt;/span&amp;gt;&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Stunts Amiga Method 1 || &amp;lt;tt&amp;gt;0x26&amp;lt;/tt&amp;gt; || &amp;lt;tt&amp;gt;&amp;lt;span style=&amp;quot;color:lightgray&amp;quot;&amp;gt;0&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;0100&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt;110&amp;lt;/span&amp;gt;&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Stunts Amiga Method 1 || &amp;lt;tt&amp;gt;0x27&amp;lt;/tt&amp;gt; || &amp;lt;tt&amp;gt;&amp;lt;span style=&amp;quot;color:lightgray&amp;quot;&amp;gt;0&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;0100&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt;111&amp;lt;/span&amp;gt;&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Stunts Amiga BPE      || &amp;lt;tt&amp;gt;0x42&amp;lt;/tt&amp;gt; || &amp;lt;tt&amp;gt;&amp;lt;span style=&amp;quot;color:lightgray&amp;quot;&amp;gt;0&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;1000&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt;010&amp;lt;/span&amp;gt;&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Stunts PC98 BPE       || &amp;lt;tt&amp;gt;0x46&amp;lt;/tt&amp;gt; || &amp;lt;tt&amp;gt;&amp;lt;span style=&amp;quot;color:lightgray&amp;quot;&amp;gt;0&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;1000&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt;110&amp;lt;/span&amp;gt;&amp;lt;/tt&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The game code appears to support several other methods that are not used by the shipped files.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Method !! Hex !! Bits !! Amiga !! PC98 !! Mickey&lt;br /&gt;
|-&lt;br /&gt;
| rowspan=2 | 0x4&lt;br /&gt;
| &amp;lt;tt&amp;gt;0x26&amp;lt;/tt&amp;gt; || &amp;lt;tt&amp;gt;&amp;lt;span style=&amp;quot;color:lightgray&amp;quot;&amp;gt;0&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;0100&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt;110&amp;lt;/span&amp;gt;&amp;lt;/tt&amp;gt; || style=text-align:center | X || style=text-align:center |   || style=text-align:center | &lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;0x27&amp;lt;/tt&amp;gt; || &amp;lt;tt&amp;gt;&amp;lt;span style=&amp;quot;color:lightgray&amp;quot;&amp;gt;0&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;0100&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt;111&amp;lt;/span&amp;gt;&amp;lt;/tt&amp;gt; || style=text-align:center | X || style=text-align:center |   || style=text-align:center | &lt;br /&gt;
|-&lt;br /&gt;
| rowspan=7 | 0x8 Byte pair encoding&lt;br /&gt;
| &amp;lt;tt&amp;gt;0x40&amp;lt;/tt&amp;gt; || &amp;lt;tt&amp;gt;&amp;lt;span style=&amp;quot;color:lightgray&amp;quot;&amp;gt;0&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;1000&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt;000&amp;lt;/span&amp;gt;&amp;lt;/tt&amp;gt; || style=text-align:center | X || style=text-align:center |   || style=text-align:center | X&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;0x41&amp;lt;/tt&amp;gt; || &amp;lt;tt&amp;gt;&amp;lt;span style=&amp;quot;color:lightgray&amp;quot;&amp;gt;0&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;1000&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt;001&amp;lt;/span&amp;gt;&amp;lt;/tt&amp;gt; || style=text-align:center | X || style=text-align:center |   || style=text-align:center | X&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;0x42&amp;lt;/tt&amp;gt; || &amp;lt;tt&amp;gt;&amp;lt;span style=&amp;quot;color:lightgray&amp;quot;&amp;gt;0&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;1000&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt;010&amp;lt;/span&amp;gt;&amp;lt;/tt&amp;gt; || style=text-align:center | X || style=text-align:center |   || style=text-align:center | X&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;0x44&amp;lt;/tt&amp;gt; || &amp;lt;tt&amp;gt;&amp;lt;span style=&amp;quot;color:lightgray&amp;quot;&amp;gt;0&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;1000&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt;100&amp;lt;/span&amp;gt;&amp;lt;/tt&amp;gt; || style=text-align:center |   || style=text-align:center |   || style=text-align:center | X&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;0x45&amp;lt;/tt&amp;gt; || &amp;lt;tt&amp;gt;&amp;lt;span style=&amp;quot;color:lightgray&amp;quot;&amp;gt;0&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;1000&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt;101&amp;lt;/span&amp;gt;&amp;lt;/tt&amp;gt; || style=text-align:center |   || style=text-align:center |   || style=text-align:center | X&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;0x46&amp;lt;/tt&amp;gt; || &amp;lt;tt&amp;gt;&amp;lt;span style=&amp;quot;color:lightgray&amp;quot;&amp;gt;0&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;1000&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt;110&amp;lt;/span&amp;gt;&amp;lt;/tt&amp;gt; || style=text-align:center |   || style=text-align:center | X || style=text-align:center |&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;0x47&amp;lt;/tt&amp;gt; || &amp;lt;tt&amp;gt;&amp;lt;span style=&amp;quot;color:lightgray&amp;quot;&amp;gt;0&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;1000&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt;111&amp;lt;/span&amp;gt;&amp;lt;/tt&amp;gt; || style=text-align:center |   || style=text-align:center | X || style=text-align:center |&lt;br /&gt;
|-&lt;br /&gt;
| rowspan=3 | 0xC Obfuscation&lt;br /&gt;
| &amp;lt;tt&amp;gt;0x60&amp;lt;/tt&amp;gt; || &amp;lt;tt&amp;gt;&amp;lt;span style=&amp;quot;color:lightgray&amp;quot;&amp;gt;0&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;1100&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt;000&amp;lt;/span&amp;gt;&amp;lt;/tt&amp;gt; || style=text-align:center | X || style=text-align:center | X || style=text-align:center | X&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;0x62&amp;lt;/tt&amp;gt; || &amp;lt;tt&amp;gt;&amp;lt;span style=&amp;quot;color:lightgray&amp;quot;&amp;gt;0&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;1100&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt;010&amp;lt;/span&amp;gt;&amp;lt;/tt&amp;gt; || style=text-align:center | X || style=text-align:center | X || style=text-align:center | X&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;0x66&amp;lt;/tt&amp;gt; || &amp;lt;tt&amp;gt;&amp;lt;span style=&amp;quot;color:lightgray&amp;quot;&amp;gt;0&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;1100&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt;100&amp;lt;/span&amp;gt;&amp;lt;/tt&amp;gt; || style=text-align:center | X || style=text-align:center | X || style=text-align:center | X&lt;br /&gt;
|-&lt;br /&gt;
| 0xD&lt;br /&gt;
| &amp;lt;tt&amp;gt;0x6B || &amp;lt;tt&amp;gt;&amp;lt;span style=&amp;quot;color:lightgray&amp;quot;&amp;gt;0&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;1101&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt;011&amp;lt;/span&amp;gt;&amp;lt;/tt&amp;gt; || style=text-align:center |   || style=text-align:center | X || style=text-align:center | X&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== 0x8 - Byte pair encoding ====&lt;br /&gt;
[https://en.wikipedia.org/wiki/Byte_pair_encoding Byte pair encoding] replaces frequently occurring byte pairs with a single byte that is not used elsewhere in the data. The process is repeated recursively until there are no more repeated byte pairs or available code bytes. Appears to be the same format as [https://problemkaputt.de/psxspx-cdrom-file-compression-ea-methods-bpe.htm documented by Martin Korth].&lt;br /&gt;
&lt;br /&gt;
==== 0xC Obfuscation ====&lt;br /&gt;
Very simple data obfuscation scheme where each byte is subtracted from the previous. The process is reversed by adding running bytes as they are copied.&lt;br /&gt;
&lt;br /&gt;
=== RPck ===&lt;br /&gt;
3-d shapes are compressed with RPck, a simple [https://en.wikipedia.org/wiki/Run-length_encoding RLE]-based format found in some Amiga file archiving software. Compression ratio is inferior to RefPack, but the code is simpler and faster, which may explain why it was chosen for these files.&lt;br /&gt;
&lt;br /&gt;
== PC98 ==&lt;br /&gt;
The PC98 port of the game uses [[#Barchard|Barchard]] to compress some of the bitmap image resource files. See the Amiga section for more details.&lt;br /&gt;
&lt;br /&gt;
== FM Towns ==&lt;br /&gt;
The FM Towns and FM Towns Marty ports of the game were distributed on CD-ROM with ample storage and does not apply any compression to the game resource files.&lt;br /&gt;
&lt;br /&gt;
[[Category:Internals]]&lt;/div&gt;</summary>
		<author><name>Dstien</name></author>
	</entry>
	<entry>
		<id>https://wiki.stunts.hu/index.php?title=Compression&amp;diff=5780</id>
		<title>Compression</title>
		<link rel="alternate" type="text/html" href="https://wiki.stunts.hu/index.php?title=Compression&amp;diff=5780"/>
		<updated>2024-01-11T16:39:03Z</updated>

		<summary type="html">&lt;p&gt;Dstien: /* Barchard */ Methods recognised by Amiga port&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Stunts and its ports uses multiple compression formats for code and [[Resource_file_format|resource files]] to save disk space and, more importantly, the number of floppy disks used to distribute the game. &lt;br /&gt;
&lt;br /&gt;
== Formats by game version ==&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! rowspan=3 colspan=3 | Game version !! colspan=4 | Stunts packing !! rowspan=3 | Barchard !! rowspan=3 | RPck&lt;br /&gt;
|-&lt;br /&gt;
! rowspan=2 | RLE !! colspan=3 | Huffman&lt;br /&gt;
|-&lt;br /&gt;
! Supported !! Prefix table !! Code endianness&lt;br /&gt;
|-&lt;br /&gt;
! rowspan=4 style=text-align:left | MS DOS !! rowspan=2 | BB 1.0 !! style=text-align:left | Game&lt;br /&gt;
| style=text-align:center | X || style=text-align:center | X || || Big || ||&lt;br /&gt;
|-&lt;br /&gt;
! style=text-align:left | Loader&lt;br /&gt;
| || style=text-align:center | X || style=text-align:center | X || Little || ||&lt;br /&gt;
|-&lt;br /&gt;
! rowspan=2 | BB 1.1/MS 1.1 !! style=text-align:left | Game&lt;br /&gt;
| style=text-align:center | X || style=text-align:center | X || style=text-align:center | X || Little || ||&lt;br /&gt;
|-&lt;br /&gt;
! style=text-align:left | Loader&lt;br /&gt;
| || style=text-align:center | X || style=text-align:center | X || Little || ||&lt;br /&gt;
|-&lt;br /&gt;
! colspan=3 style=text-align:left | Amiga&lt;br /&gt;
| || || || || style=text-align:center | X || style=text-align:center | X&lt;br /&gt;
|-&lt;br /&gt;
! colspan=3 style=text-align:left | PC98&lt;br /&gt;
| || || || || style=text-align:center | X ||&lt;br /&gt;
|-&lt;br /&gt;
! colspan=3 style=text-align:left | FM Towns&lt;br /&gt;
| || || || || ||&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== MS DOS ==&lt;br /&gt;
The original release of Stunts uses a custom data compression format not found in the ports to other platforms. The code may have been hand-crafted for 16-bit x86 since other options were favoured in the later ports.&lt;br /&gt;
&lt;br /&gt;
The data format supports both [https://en.wikipedia.org/wiki/Run-length_encoding run-length encoding] (RLE) and [https://en.wikipedia.org/wiki/Huffman_coding Huffman coding]. They can be combined in multiple passes. The data format and the decompression code don&#039;t require any particular order or combination of algorithms. Every compressed file shipped with the game use Huffman coding, and when combined with RLE, the RLE pass is applied before Huffman.&lt;br /&gt;
&lt;br /&gt;
=== File header ===&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;enum&amp;lt;/span&amp;gt; CompressionType &amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;{&amp;lt;/span&amp;gt;&lt;br /&gt;
     RLE     = 1&lt;br /&gt;
     Huffman = 2&lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;}&amp;lt;/span&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;struct&amp;lt;/span&amp;gt; Header &amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;{&amp;lt;/span&amp;gt;&lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;union&amp;lt;/span&amp;gt; &amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;{&amp;lt;/span&amp;gt;&lt;br /&gt;
         &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt; passes : 7&lt;br /&gt;
         &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt; compression_type : 7&lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;}&amp;lt;/span&amp;gt;&lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt;  multi_pass : 1&lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint32&amp;lt;/span&amp;gt; uncompressed_size : 24&lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;}&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
If the most significant bit of the first byte of the file is set, this is a multi-pass file and the remaining 7 bits are the number of passes to be processed recursively. If the &amp;lt;tt&amp;gt;multi_pass&amp;lt;/tt&amp;gt; flag is not set, we are only doing a single pass and the first byte is the compression type. The next three bytes make up the uncompressed size. If the &amp;lt;tt&amp;gt;multi_pass&amp;lt;/tt&amp;gt; flag was set, this is the final uncompressed size. When the &amp;lt;tt&amp;gt;multi_pass&amp;lt;/tt&amp;gt; flag is not set, this is the uncompressed size of the current pass. The remaining data is processed recursively. The &amp;lt;tt&amp;gt;compression_type&amp;lt;/tt&amp;gt; field decides how it is decoded.&lt;br /&gt;
&lt;br /&gt;
=== Run-length encoding ===&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;struct&amp;lt;/span&amp;gt; RLE &amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;{&amp;lt;/span&amp;gt;&lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint32&amp;lt;/span&amp;gt; compressed_size : 24&lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt;  reserved &amp;lt;span class=&amp;quot;hlC&amp;quot;&amp;gt;// Always 0x00, value is ignored by the game&amp;lt;/span&amp;gt;&lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt;  escape_length : 7&lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt;  no_sequence : 1&lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt;  escape_codes&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;[&amp;lt;/span&amp;gt;escape_length&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;]&amp;lt;/span&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt;  data&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;[&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;hlC&amp;quot;&amp;gt;...&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;]&amp;lt;/span&amp;gt;&lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;}&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
RLE is used to reduce the length of consecutively repeated bytes by using an escape code followed by a counter to signify how many times the next byte should be repeated. It is particularly useful for compressing images, as large areas with a single colour would be represented by many consecutive identical bytes.&lt;br /&gt;
&lt;br /&gt;
The RLE stage can itself have two passes if &amp;lt;tt&amp;gt;no_sequence&amp;lt;/tt&amp;gt; is not set. The first pass will then expand sequences of bytes in the data. &amp;lt;tt&amp;gt;escape_codes[1]&amp;lt;/tt&amp;gt; will mark the beginning and the end of a byte sequence. When the escape code is encountered in the data, the following bytes are considered a sequence until the escape code is hit again. After the end-marking escape code, a one byte length counter tells how many times the preceding byte sequence should be repeated in the output buffer. Because the escape code cannot itself be escaped, sequential byte runs can only be applied in files that have unused byte values to use as the first escape code.&lt;br /&gt;
&lt;br /&gt;
The main RLE pass is a traditional expansion of single-byte runs, but with a twist that allows for multiple types of escape codes. The escape code&#039;s position in the header&#039;s escape code list affects its properties. When the first escape code is encountered in the source buffer, the following byte has the number of repetitions, and the next byte will be copied that many times to the output buffer. When the third escape code is encountered, the number of repetitions is stored in the following &#039;&#039;two&#039;&#039; bytes as a 16-bit integer. Then the following byte is copied that many times. All other escape codes use its position in the escape code list as the number of repetitions, and have no additional counter bytes before the data byte to be repeated. This allows the second escape code reserved for sequences to serve as a no-op without the two passes interfering. Escape codes can themselves be escaped in single-byte runs by having them expanded to only one copy.&lt;br /&gt;
&lt;br /&gt;
All repetition counters have an off-by-one surplus, as the data byte itself counts as the first copy. For optimal compression, escape codes should be chosen from byte values that occur least frequently, or not at all, in the source data.&lt;br /&gt;
&lt;br /&gt;
==== RLE decoding optimisation ====&lt;br /&gt;
Escape codes are put in an &amp;lt;tt&amp;gt;escape[256]&amp;lt;/tt&amp;gt; array, where the code&#039;s byte value is the index and the escape code&#039;s position is the entry&#039;s value. This array is used to test incoming bytes for escape codes. Raw bytes will have the value 0, while other values corresponds to the escape code&#039;s property. This optimisation makes the decoding run O(1), as opposed to O(&#039;&#039;n&#039;&#039;), where &#039;&#039;n&#039;&#039; is the number of escape codes.&lt;br /&gt;
&lt;br /&gt;
=== Huffman coding ===&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;struct&amp;lt;/span&amp;gt; Huffman &amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;{&amp;lt;/span&amp;gt;&lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt; tree_levels : 7&lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt; delta_coding : 1&lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt; symbols_per_level&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;[&amp;lt;/span&amp;gt;tree_levels&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;]&amp;lt;/span&amp;gt;&lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt; alphabet&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;[&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;SUM&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;(&amp;lt;/span&amp;gt;symbols_per_level&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;)&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;]&amp;lt;/span&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint16&amp;lt;/span&amp;gt; codes : var &amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;[&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;hlC&amp;quot;&amp;gt;...&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;]&amp;lt;/span&amp;gt;&lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;}&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Huffman coding uses a binary tree to store data. When Huffman codes are read, each bit tells which branch to take when traversing the tree. If a leaf node is hit, we have found the code&#039;s symbol and can proceed with the next code. Frequently used symbols have shorter paths and thus takes up fewer bits in the source file.&lt;br /&gt;
&lt;br /&gt;
The tree is stored by having two lists, one with symbols per level, and one with the alphabet. The alphabet is every possible symbol in the order they appear in the tree. The tree is built by going through each &amp;lt;tt&amp;gt;symbols_per_level&amp;lt;/tt&amp;gt;. If there are symbols at the current level, consume them from &amp;lt;tt&amp;gt;alphabet&amp;lt;/tt&amp;gt; and create leaf nodes. If there are no symbols, and there still are more levels to create, proceed to create left and right children nodes for the next level.&lt;br /&gt;
&lt;br /&gt;
The remaining data is the Huffman codes. Bit by bit is read to find leaf nodes in the Huffman tree whose symbols are appended to the output buffer. This is repeated until the output buffer has reached &amp;lt;tt&amp;gt;uncompressed_size&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
The maximum Huffman tree height is 16. While the data format allows for up to 127 levels, Stunts&#039; decompression function uses arrays with a fixed capacity of 16 for its level offset table.&lt;br /&gt;
&lt;br /&gt;
==== Delta coding ====&lt;br /&gt;
If the flag for [https://en.wikipedia.org/wiki/Delta_encoding delta coding] is set, each symbol is treated as the difference from the previous output byte instead of an independent final value. The last byte written to the output buffer is remembered and added to the next expanded symbol. While regular Huffman coding assigns shorter codes to frequently occurring values, this delta variant assigns shorter codes to differences that occurs frequently. This feature is not used by any shipped files, but the code is present in all versions that implements Huffman decoding. One can speculate that delta coding was outperformed by RLE combined with regular Huffman coding, making delta coding unnecessary.&lt;br /&gt;
&lt;br /&gt;
==== Huffman decoding optimisations ====&lt;br /&gt;
===== Prefix table =====&lt;br /&gt;
With Huffman codes being paths in a binary tree, they have the property of being prefix-free, meaning that one leaf node&#039;s code cannot be the prefix of another node&#039;s code. This allows for a decoding optimisation technique known as &#039;&#039;prefix tables&#039;&#039; or &#039;&#039;Huffman tables&#039;&#039;. By creating arrays of symbols and code widths where the indices are the Huffman codes, the codes can be looked up directly without traversing the tree. Every array index for non-leaf nodes between two leaf node entries are filled with data for the preceding leaf node. This way there&#039;s no need to filter out bits that belong to the next Huffman code, at the expense of common symbols taking up multiple entries in the lookup table during decompression.&lt;br /&gt;
&lt;br /&gt;
Stunts utilises this optimisation for Huffman codes that are up to 8 bits wide. The first byte of the code is checked in the &amp;lt;tt&amp;gt;widths[256]&amp;lt;/tt&amp;gt; array. If the code&#039;s width is 8 bits or less, the same code is looked up in the &amp;lt;tt&amp;gt;symbols[256]&amp;lt;/tt&amp;gt; array and written to the output buffer. To find the start of the next Huffman code, the source buffer is advanced by the code&#039;s bit width found in the &amp;lt;tt&amp;gt;widths&amp;lt;/tt&amp;gt; array.&lt;br /&gt;
&lt;br /&gt;
===== Offset table =====&lt;br /&gt;
As Stunts limits the prefix tables to 8 bit wide Huffman codes to save RAM, another novel optimisation is applied for codes that exceeds 8 bits. Prefixes for longer codes have the value &amp;lt;tt&amp;gt;0x40&amp;lt;/tt&amp;gt; in the &amp;lt;tt&amp;gt;widths&amp;lt;/tt&amp;gt; array, indicating that the current code is a prefix that needs further expansion. For this purpose Stunts uses two additional helper arrays: &amp;lt;tt&amp;gt;total_codes[tree_levels]&amp;lt;/tt&amp;gt;, which has the total number of leaf nodes that exists in the tree up to each level, and &amp;lt;tt&amp;gt;code_offsets[tree_levels]&amp;lt;/tt&amp;gt;, which for each level has a value that can be added to a code with the same level in order to get its index in the alphabet. This works because the codes are arranged [https://en.wikipedia.org/wiki/Canonical_Huffman_code canonically]. As a code&#039;s bit width corresponds to the code&#039;s level in the Huffman tree, the width can be used to compare the current code with the level&#039;s total by getting &amp;lt;tt&amp;gt;total_codes[current_width]&amp;lt;/tt&amp;gt; for each extra bit read. If the code is smaller than the total number of codes encountered, it is a leaf node, and we get the symbol by adding the level&#039;s code offset to the code with &amp;lt;tt&amp;gt;alphabet[code + code_offsets[width]]&amp;lt;/tt&amp;gt;. This is more laborious than the use of prefix tables for direct lookup, but it only applies to codes that are occurring less frequently in the input file.&lt;br /&gt;
&lt;br /&gt;
==== Version differences ====&lt;br /&gt;
The Huffman decompression in the game code of Stunts 1.0 differs from the one in its LOAD.EXE and later versions of the game. The Huffman codes are written with the least significant bit first, as opposed to the other versions that has the codes written with the opposite orientation. The game code of Stunts 1.0 also does not use a prefix table, and the bit-stream orientation was likely changed with the introduction of this optimisation.&lt;br /&gt;
&lt;br /&gt;
== Amiga ==&lt;br /&gt;
The Amiga port uses two unrelated compression formats.&lt;br /&gt;
&lt;br /&gt;
=== Barchard ===&lt;br /&gt;
Non-3d shape resource files uses another Distinctive Software in-house format that is characterized by the identification byte &amp;lt;tt&amp;gt;0xFB&amp;lt;/tt&amp;gt;, assumed to be the initials of its author, [https://www.mobygames.com/person/7186/frank-barchard/ Frank Barchard]. This format supports a suite of different compression methods and it evolved through the 90&#039;s and early 2000&#039;s as a part of EA&#039;s internal engine libraries. Whereas later games tended to use the [https://en.wikipedia.org/wiki/Lempel%E2%80%93Ziv%E2%80%93Storer%E2%80%93Szymanski LZSS]-based [https://github.com/lingeringwillx/Refpack-QFS-Resources RefPack] algorithm, the Stunts ports uses other methods. We will therefore refer to these compressions as &#039;&#039;&amp;quot;Barchard&amp;quot;&#039;&#039; to distinguish them from the ubiquitous RefPack.&lt;br /&gt;
&lt;br /&gt;
This is the currently assumed header structure:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;struct&amp;lt;/span&amp;gt; Header &amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;{&amp;lt;/span&amp;gt;&lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt;  method_flags : 3&lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt;  method_type  : 4&lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt;  32bit_length : 1 &amp;lt;span class=&amp;quot;hlC&amp;quot;&amp;gt;// Not used by Stunts&amp;lt;/span&amp;gt;&lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt;  magic &amp;lt;span class=&amp;quot;hlC&amp;quot;&amp;gt;// Always 0xFB&amp;lt;/span&amp;gt;&lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint32&amp;lt;/span&amp;gt; uncompressed_size : 24&lt;br /&gt;
 &lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlC&amp;quot;&amp;gt;// Possibly more fields if indicated by method_flags&amp;lt;/span&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt;  data&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;[&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;hlC&amp;quot;&amp;gt;...&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;]&amp;lt;/span&amp;gt;&lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;}&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Below are the values of the first byte in the shipped files. Values from the DOS version of [https://www.mobygames.com/game/56474/mickeys-abcs-a-day-at-the-fair/ Mickey&#039;s ABC&#039;s: A Day at the Fair] are included, as this may be the first public incarnation of Barchard compression. The bitfield suspected to be the method is highlighted in red, the method flags in green.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Game                !! Hex  !! Bits&lt;br /&gt;
|-&lt;br /&gt;
| Mickey&#039;s ABC BPE      || &amp;lt;tt&amp;gt;0x44&amp;lt;/tt&amp;gt; || &amp;lt;tt&amp;gt;&amp;lt;span style=&amp;quot;color:lightgray&amp;quot;&amp;gt;0&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;1000&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt;100&amp;lt;/span&amp;gt;&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Stunts Amiga Method 1 || &amp;lt;tt&amp;gt;0x26&amp;lt;/tt&amp;gt; || &amp;lt;tt&amp;gt;&amp;lt;span style=&amp;quot;color:lightgray&amp;quot;&amp;gt;0&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;0100&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt;110&amp;lt;/span&amp;gt;&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Stunts Amiga BPE      || &amp;lt;tt&amp;gt;0x42&amp;lt;/tt&amp;gt; || &amp;lt;tt&amp;gt;&amp;lt;span style=&amp;quot;color:lightgray&amp;quot;&amp;gt;0&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;1000&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt;010&amp;lt;/span&amp;gt;&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Stunts PC98 BPE       || &amp;lt;tt&amp;gt;0x46&amp;lt;/tt&amp;gt; || &amp;lt;tt&amp;gt;&amp;lt;span style=&amp;quot;color:lightgray&amp;quot;&amp;gt;0&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;1000&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt;110&amp;lt;/span&amp;gt;&amp;lt;/tt&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The game code appears to support several other methods that are not used by the shipped files.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Method !! Hex !! Bits !! Amiga !! PC98 !! Mickey&lt;br /&gt;
|-&lt;br /&gt;
| rowspan=2 | Method 1&lt;br /&gt;
| &amp;lt;tt&amp;gt;0x26&amp;lt;/tt&amp;gt; || &amp;lt;tt&amp;gt;&amp;lt;span style=&amp;quot;color:lightgray&amp;quot;&amp;gt;0&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;0100&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt;110&amp;lt;/span&amp;gt;&amp;lt;/tt&amp;gt; || style=text-align:center | X || style=text-align:center |   || style=text-align:center | &lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;0x27&amp;lt;/tt&amp;gt; || &amp;lt;tt&amp;gt;&amp;lt;span style=&amp;quot;color:lightgray&amp;quot;&amp;gt;0&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;0100&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt;111&amp;lt;/span&amp;gt;&amp;lt;/tt&amp;gt; || style=text-align:center | X || style=text-align:center |   || style=text-align:center | &lt;br /&gt;
|-&lt;br /&gt;
| rowspan=7 | [https://en.wikipedia.org/wiki/Byte_pair_encoding Byte pair encoding]&lt;br /&gt;
| &amp;lt;tt&amp;gt;0x40&amp;lt;/tt&amp;gt; || &amp;lt;tt&amp;gt;&amp;lt;span style=&amp;quot;color:lightgray&amp;quot;&amp;gt;0&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;1000&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt;000&amp;lt;/span&amp;gt;&amp;lt;/tt&amp;gt; || style=text-align:center | X || style=text-align:center |   || style=text-align:center | X&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;0x41&amp;lt;/tt&amp;gt; || &amp;lt;tt&amp;gt;&amp;lt;span style=&amp;quot;color:lightgray&amp;quot;&amp;gt;0&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;1000&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt;001&amp;lt;/span&amp;gt;&amp;lt;/tt&amp;gt; || style=text-align:center | X || style=text-align:center |   || style=text-align:center | X&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;0x42&amp;lt;/tt&amp;gt; || &amp;lt;tt&amp;gt;&amp;lt;span style=&amp;quot;color:lightgray&amp;quot;&amp;gt;0&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;1000&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt;010&amp;lt;/span&amp;gt;&amp;lt;/tt&amp;gt; || style=text-align:center | X || style=text-align:center |   || style=text-align:center | X&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;0x44&amp;lt;/tt&amp;gt; || &amp;lt;tt&amp;gt;&amp;lt;span style=&amp;quot;color:lightgray&amp;quot;&amp;gt;0&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;1000&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt;100&amp;lt;/span&amp;gt;&amp;lt;/tt&amp;gt; || style=text-align:center |   || style=text-align:center |   || style=text-align:center | X&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;0x45&amp;lt;/tt&amp;gt; || &amp;lt;tt&amp;gt;&amp;lt;span style=&amp;quot;color:lightgray&amp;quot;&amp;gt;0&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;1000&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt;101&amp;lt;/span&amp;gt;&amp;lt;/tt&amp;gt; || style=text-align:center |   || style=text-align:center |   || style=text-align:center | X&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;0x46&amp;lt;/tt&amp;gt; || &amp;lt;tt&amp;gt;&amp;lt;span style=&amp;quot;color:lightgray&amp;quot;&amp;gt;0&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;1000&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt;110&amp;lt;/span&amp;gt;&amp;lt;/tt&amp;gt; || style=text-align:center |   || style=text-align:center | X || style=text-align:center |&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;0x47&amp;lt;/tt&amp;gt; || &amp;lt;tt&amp;gt;&amp;lt;span style=&amp;quot;color:lightgray&amp;quot;&amp;gt;0&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;1000&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt;111&amp;lt;/span&amp;gt;&amp;lt;/tt&amp;gt; || style=text-align:center |   || style=text-align:center | X || style=text-align:center |&lt;br /&gt;
|-&lt;br /&gt;
| rowspan=3 | Method 3&lt;br /&gt;
| &amp;lt;tt&amp;gt;0x60&amp;lt;/tt&amp;gt; || &amp;lt;tt&amp;gt;&amp;lt;span style=&amp;quot;color:lightgray&amp;quot;&amp;gt;0&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;1100&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt;000&amp;lt;/span&amp;gt;&amp;lt;/tt&amp;gt; || style=text-align:center | X || style=text-align:center | X || style=text-align:center | X&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;0x62&amp;lt;/tt&amp;gt; || &amp;lt;tt&amp;gt;&amp;lt;span style=&amp;quot;color:lightgray&amp;quot;&amp;gt;0&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;1100&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt;010&amp;lt;/span&amp;gt;&amp;lt;/tt&amp;gt; || style=text-align:center | X || style=text-align:center | X || style=text-align:center | X&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;0x66&amp;lt;/tt&amp;gt; || &amp;lt;tt&amp;gt;&amp;lt;span style=&amp;quot;color:lightgray&amp;quot;&amp;gt;0&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;1100&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt;100&amp;lt;/span&amp;gt;&amp;lt;/tt&amp;gt; || style=text-align:center | X || style=text-align:center | X || style=text-align:center | X&lt;br /&gt;
|-&lt;br /&gt;
| Method 4&lt;br /&gt;
| &amp;lt;tt&amp;gt;0x6B || &amp;lt;tt&amp;gt;&amp;lt;span style=&amp;quot;color:lightgray&amp;quot;&amp;gt;0&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;1101&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt;011&amp;lt;/span&amp;gt;&amp;lt;/tt&amp;gt; || style=text-align:center | X || style=text-align:center | X || style=text-align:center | X&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
A strong hypothesis suggests that the compression methods found here are related to the EA formats from PSX games [https://problemkaputt.de/psxspx-cdrom-file-compression-ea-methods.htm documented by Martin Korth]. Further analysis is required to verify this.&lt;br /&gt;
&lt;br /&gt;
=== RPck ===&lt;br /&gt;
3-d shapes are compressed with RPck, a simple [https://en.wikipedia.org/wiki/Run-length_encoding RLE]-based format found in some Amiga file archiving software. Compression ratio is inferior to RefPack, but the code is simpler and faster, which may explain why it was chosen for these files.&lt;br /&gt;
&lt;br /&gt;
== PC98 ==&lt;br /&gt;
The PC98 port of the game uses [[#Barchard|Barchard]] to compress some of the bitmap image resource files. See the Amiga section for more details.&lt;br /&gt;
&lt;br /&gt;
== FM Towns ==&lt;br /&gt;
The FM Towns and FM Towns Marty ports of the game were distributed on CD-ROM with ample storage and does not apply any compression to the game resource files.&lt;br /&gt;
&lt;br /&gt;
[[Category:Internals]]&lt;/div&gt;</summary>
		<author><name>Dstien</name></author>
	</entry>
	<entry>
		<id>https://wiki.stunts.hu/index.php?title=Compression&amp;diff=5769</id>
		<title>Compression</title>
		<link rel="alternate" type="text/html" href="https://wiki.stunts.hu/index.php?title=Compression&amp;diff=5769"/>
		<updated>2024-01-09T17:11:32Z</updated>

		<summary type="html">&lt;p&gt;Dstien: /* PC98 */ s/RefPack/Barchard/&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Stunts and its ports uses multiple compression formats for code and [[Resource_file_format|resource files]] to save disk space and, more importantly, the number of floppy disks used to distribute the game. &lt;br /&gt;
&lt;br /&gt;
== Formats by game version ==&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! rowspan=3 colspan=3 | Game version !! colspan=4 | Stunts packing !! rowspan=3 | Barchard !! rowspan=3 | RPck&lt;br /&gt;
|-&lt;br /&gt;
! rowspan=2 | RLE !! colspan=3 | Huffman&lt;br /&gt;
|-&lt;br /&gt;
! Supported !! Prefix table !! Code endianness&lt;br /&gt;
|-&lt;br /&gt;
! rowspan=4 style=text-align:left | MS DOS !! rowspan=2 | BB 1.0 !! style=text-align:left | Game&lt;br /&gt;
| style=text-align:center | X || style=text-align:center | X || || Big || ||&lt;br /&gt;
|-&lt;br /&gt;
! style=text-align:left | Loader&lt;br /&gt;
| || style=text-align:center | X || style=text-align:center | X || Little || ||&lt;br /&gt;
|-&lt;br /&gt;
! rowspan=2 | BB 1.1/MS 1.1 !! style=text-align:left | Game&lt;br /&gt;
| style=text-align:center | X || style=text-align:center | X || style=text-align:center | X || Little || ||&lt;br /&gt;
|-&lt;br /&gt;
! style=text-align:left | Loader&lt;br /&gt;
| || style=text-align:center | X || style=text-align:center | X || Little || ||&lt;br /&gt;
|-&lt;br /&gt;
! colspan=3 style=text-align:left | Amiga&lt;br /&gt;
| || || || || style=text-align:center | X || style=text-align:center | X&lt;br /&gt;
|-&lt;br /&gt;
! colspan=3 style=text-align:left | PC98&lt;br /&gt;
| || || || || style=text-align:center | X ||&lt;br /&gt;
|-&lt;br /&gt;
! colspan=3 style=text-align:left | FM Towns&lt;br /&gt;
| || || || || ||&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== MS DOS ==&lt;br /&gt;
The original release of Stunts uses a custom data compression format not found in the ports to other platforms. The code may have been hand-crafted for 16-bit x86 since other options were favoured in the later ports.&lt;br /&gt;
&lt;br /&gt;
The data format supports both [https://en.wikipedia.org/wiki/Run-length_encoding run-length encoding] (RLE) and [https://en.wikipedia.org/wiki/Huffman_coding Huffman coding]. They can be combined in multiple passes. The data format and the decompression code don&#039;t require any particular order or combination of algorithms. Every compressed file shipped with the game use Huffman coding, and when combined with RLE, the RLE pass is applied before Huffman.&lt;br /&gt;
&lt;br /&gt;
=== File header ===&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;enum&amp;lt;/span&amp;gt; CompressionType &amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;{&amp;lt;/span&amp;gt;&lt;br /&gt;
     RLE     = 1&lt;br /&gt;
     Huffman = 2&lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;}&amp;lt;/span&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;struct&amp;lt;/span&amp;gt; Header &amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;{&amp;lt;/span&amp;gt;&lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;union&amp;lt;/span&amp;gt; &amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;{&amp;lt;/span&amp;gt;&lt;br /&gt;
         &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt; passes : 7&lt;br /&gt;
         &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt; compression_type : 7&lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;}&amp;lt;/span&amp;gt;&lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt;  multi_pass : 1&lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint32&amp;lt;/span&amp;gt; uncompressed_size : 24&lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;}&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
If the most significant bit of the first byte of the file is set, this is a multi-pass file and the remaining 7 bits are the number of passes to be processed recursively. If the &amp;lt;tt&amp;gt;multi_pass&amp;lt;/tt&amp;gt; flag is not set, we are only doing a single pass and the first byte is the compression type. The next three bytes make up the uncompressed size. If the &amp;lt;tt&amp;gt;multi_pass&amp;lt;/tt&amp;gt; flag was set, this is the final uncompressed size. When the &amp;lt;tt&amp;gt;multi_pass&amp;lt;/tt&amp;gt; flag is not set, this is the uncompressed size of the current pass. The remaining data is processed recursively. The &amp;lt;tt&amp;gt;compression_type&amp;lt;/tt&amp;gt; field decides how it is decoded.&lt;br /&gt;
&lt;br /&gt;
=== Run-length encoding ===&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;struct&amp;lt;/span&amp;gt; RLE &amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;{&amp;lt;/span&amp;gt;&lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint32&amp;lt;/span&amp;gt; compressed_size : 24&lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt;  reserved &amp;lt;span class=&amp;quot;hlC&amp;quot;&amp;gt;// Always 0x00, value is ignored by the game&amp;lt;/span&amp;gt;&lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt;  escape_length : 7&lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt;  no_sequence : 1&lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt;  escape_codes&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;[&amp;lt;/span&amp;gt;escape_length&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;]&amp;lt;/span&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt;  data&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;[&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;hlC&amp;quot;&amp;gt;...&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;]&amp;lt;/span&amp;gt;&lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;}&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
RLE is used to reduce the length of consecutively repeated bytes by using an escape code followed by a counter to signify how many times the next byte should be repeated. It is particularly useful for compressing images, as large areas with a single colour would be represented by many consecutive identical bytes.&lt;br /&gt;
&lt;br /&gt;
The RLE stage can itself have two passes if &amp;lt;tt&amp;gt;no_sequence&amp;lt;/tt&amp;gt; is not set. The first pass will then expand sequences of bytes in the data. &amp;lt;tt&amp;gt;escape_codes[1]&amp;lt;/tt&amp;gt; will mark the beginning and the end of a byte sequence. When the escape code is encountered in the data, the following bytes are considered a sequence until the escape code is hit again. After the end-marking escape code, a one byte length counter tells how many times the preceding byte sequence should be repeated in the output buffer. Because the escape code cannot itself be escaped, sequential byte runs can only be applied in files that have unused byte values to use as the first escape code.&lt;br /&gt;
&lt;br /&gt;
The main RLE pass is a traditional expansion of single-byte runs, but with a twist that allows for multiple types of escape codes. The escape code&#039;s position in the header&#039;s escape code list affects its properties. When the first escape code is encountered in the source buffer, the following byte has the number of repetitions, and the next byte will be copied that many times to the output buffer. When the third escape code is encountered, the number of repetitions is stored in the following &#039;&#039;two&#039;&#039; bytes as a 16-bit integer. Then the following byte is copied that many times. All other escape codes use its position in the escape code list as the number of repetitions, and have no additional counter bytes before the data byte to be repeated. This allows the second escape code reserved for sequences to serve as a no-op without the two passes interfering. Escape codes can themselves be escaped in single-byte runs by having them expanded to only one copy.&lt;br /&gt;
&lt;br /&gt;
All repetition counters have an off-by-one surplus, as the data byte itself counts as the first copy. For optimal compression, escape codes should be chosen from byte values that occur least frequently, or not at all, in the source data.&lt;br /&gt;
&lt;br /&gt;
==== RLE decoding optimisation ====&lt;br /&gt;
Escape codes are put in an &amp;lt;tt&amp;gt;escape[256]&amp;lt;/tt&amp;gt; array, where the code&#039;s byte value is the index and the escape code&#039;s position is the entry&#039;s value. This array is used to test incoming bytes for escape codes. Raw bytes will have the value 0, while other values corresponds to the escape code&#039;s property. This optimisation makes the decoding run O(1), as opposed to O(&#039;&#039;n&#039;&#039;), where &#039;&#039;n&#039;&#039; is the number of escape codes.&lt;br /&gt;
&lt;br /&gt;
=== Huffman coding ===&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;struct&amp;lt;/span&amp;gt; Huffman &amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;{&amp;lt;/span&amp;gt;&lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt; tree_levels : 7&lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt; delta_coding : 1&lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt; symbols_per_level&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;[&amp;lt;/span&amp;gt;tree_levels&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;]&amp;lt;/span&amp;gt;&lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt; alphabet&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;[&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;SUM&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;(&amp;lt;/span&amp;gt;symbols_per_level&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;)&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;]&amp;lt;/span&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint16&amp;lt;/span&amp;gt; codes : var &amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;[&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;hlC&amp;quot;&amp;gt;...&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;]&amp;lt;/span&amp;gt;&lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;}&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Huffman coding uses a binary tree to store data. When Huffman codes are read, each bit tells which branch to take when traversing the tree. If a leaf node is hit, we have found the code&#039;s symbol and can proceed with the next code. Frequently used symbols have shorter paths and thus takes up fewer bits in the source file.&lt;br /&gt;
&lt;br /&gt;
The tree is stored by having two lists, one with symbols per level, and one with the alphabet. The alphabet is every possible symbol in the order they appear in the tree. The tree is built by going through each &amp;lt;tt&amp;gt;symbols_per_level&amp;lt;/tt&amp;gt;. If there are symbols at the current level, consume them from &amp;lt;tt&amp;gt;alphabet&amp;lt;/tt&amp;gt; and create leaf nodes. If there are no symbols, and there still are more levels to create, proceed to create left and right children nodes for the next level.&lt;br /&gt;
&lt;br /&gt;
The remaining data is the Huffman codes. Bit by bit is read to find leaf nodes in the Huffman tree whose symbols are appended to the output buffer. This is repeated until the output buffer has reached &amp;lt;tt&amp;gt;uncompressed_size&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
The maximum Huffman tree height is 16. While the data format allows for up to 127 levels, Stunts&#039; decompression function uses arrays with a fixed capacity of 16 for its level offset table.&lt;br /&gt;
&lt;br /&gt;
==== Delta coding ====&lt;br /&gt;
If the flag for [https://en.wikipedia.org/wiki/Delta_encoding delta coding] is set, each symbol is treated as the difference from the previous output byte instead of an independent final value. The last byte written to the output buffer is remembered and added to the next expanded symbol. While regular Huffman coding assigns shorter codes to frequently occurring values, this delta variant assigns shorter codes to differences that occurs frequently. This feature is not used by any shipped files, but the code is present in all versions that implements Huffman decoding. One can speculate that delta coding was outperformed by RLE combined with regular Huffman coding, making delta coding unnecessary.&lt;br /&gt;
&lt;br /&gt;
==== Huffman decoding optimisations ====&lt;br /&gt;
===== Prefix table =====&lt;br /&gt;
With Huffman codes being paths in a binary tree, they have the property of being prefix-free, meaning that one leaf node&#039;s code cannot be the prefix of another node&#039;s code. This allows for a decoding optimisation technique known as &#039;&#039;prefix tables&#039;&#039; or &#039;&#039;Huffman tables&#039;&#039;. By creating arrays of symbols and code widths where the indices are the Huffman codes, the codes can be looked up directly without traversing the tree. Every array index for non-leaf nodes between two leaf node entries are filled with data for the preceding leaf node. This way there&#039;s no need to filter out bits that belong to the next Huffman code, at the expense of common symbols taking up multiple entries in the lookup table during decompression.&lt;br /&gt;
&lt;br /&gt;
Stunts utilises this optimisation for Huffman codes that are up to 8 bits wide. The first byte of the code is checked in the &amp;lt;tt&amp;gt;widths[256]&amp;lt;/tt&amp;gt; array. If the code&#039;s width is 8 bits or less, the same code is looked up in the &amp;lt;tt&amp;gt;symbols[256]&amp;lt;/tt&amp;gt; array and written to the output buffer. To find the start of the next Huffman code, the source buffer is advanced by the code&#039;s bit width found in the &amp;lt;tt&amp;gt;widths&amp;lt;/tt&amp;gt; array.&lt;br /&gt;
&lt;br /&gt;
===== Offset table =====&lt;br /&gt;
As Stunts limits the prefix tables to 8 bit wide Huffman codes to save RAM, another novel optimisation is applied for codes that exceeds 8 bits. Prefixes for longer codes have the value &amp;lt;tt&amp;gt;0x40&amp;lt;/tt&amp;gt; in the &amp;lt;tt&amp;gt;widths&amp;lt;/tt&amp;gt; array, indicating that the current code is a prefix that needs further expansion. For this purpose Stunts uses two additional helper arrays: &amp;lt;tt&amp;gt;total_codes[tree_levels]&amp;lt;/tt&amp;gt;, which has the total number of leaf nodes that exists in the tree up to each level, and &amp;lt;tt&amp;gt;code_offsets[tree_levels]&amp;lt;/tt&amp;gt;, which for each level has a value that can be added to a code with the same level in order to get its index in the alphabet. This works because the codes are arranged [https://en.wikipedia.org/wiki/Canonical_Huffman_code canonically]. As a code&#039;s bit width corresponds to the code&#039;s level in the Huffman tree, the width can be used to compare the current code with the level&#039;s total by getting &amp;lt;tt&amp;gt;total_codes[current_width]&amp;lt;/tt&amp;gt; for each extra bit read. If the code is smaller than the total number of codes encountered, it is a leaf node, and we get the symbol by adding the level&#039;s code offset to the code with &amp;lt;tt&amp;gt;alphabet[code + code_offsets[width]]&amp;lt;/tt&amp;gt;. This is more laborious than the use of prefix tables for direct lookup, but it only applies to codes that are occurring less frequently in the input file.&lt;br /&gt;
&lt;br /&gt;
==== Version differences ====&lt;br /&gt;
The Huffman decompression in the game code of Stunts 1.0 differs from the one in its LOAD.EXE and later versions of the game. The Huffman codes are written with the least significant bit first, as opposed to the other versions that has the codes written with the opposite orientation. The game code of Stunts 1.0 also does not use a prefix table, and the bit-stream orientation was likely changed with the introduction of this optimisation.&lt;br /&gt;
&lt;br /&gt;
== Amiga ==&lt;br /&gt;
The Amiga port uses two unrelated compression formats.&lt;br /&gt;
&lt;br /&gt;
=== Barchard ===&lt;br /&gt;
Non-3d shape resource files uses another Distinctive Software in-house format that is characterized by the identification byte &amp;lt;tt&amp;gt;0xFB&amp;lt;/tt&amp;gt;, assumed to be the initials of its author, [https://www.mobygames.com/person/7186/frank-barchard/ Frank Barchard]. This format supports a suite of different compression methods and it evolved through the 90&#039;s and early 2000&#039;s as a part of EA&#039;s internal engine libraries. Whereas later games tended to use the [https://en.wikipedia.org/wiki/Lempel%E2%80%93Ziv%E2%80%93Storer%E2%80%93Szymanski LZSS]-based [https://github.com/lingeringwillx/Refpack-QFS-Resources RefPack] algorithm, the Stunts ports uses other methods. We will therefore refer to these compressions as &#039;&#039;&amp;quot;Barchard&amp;quot;&#039;&#039; to distinguish them from the ubiquitous RefPack.&lt;br /&gt;
&lt;br /&gt;
This is the currently assumed header structure:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;struct&amp;lt;/span&amp;gt; Header &amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;{&amp;lt;/span&amp;gt;&lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt;  method_flags : 3&lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt;  method_type  : 4&lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt;  32bit_length : 1 &amp;lt;span class=&amp;quot;hlC&amp;quot;&amp;gt;// Not used by Stunts&amp;lt;/span&amp;gt;&lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt;  magic &amp;lt;span class=&amp;quot;hlC&amp;quot;&amp;gt;// Always 0xFB&amp;lt;/span&amp;gt;&lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint32&amp;lt;/span&amp;gt; uncompressed_size : 24&lt;br /&gt;
 &lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlC&amp;quot;&amp;gt;// Possibly more fields if indicated by method_flags&amp;lt;/span&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt;  data&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;[&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;hlC&amp;quot;&amp;gt;...&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;]&amp;lt;/span&amp;gt;&lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;}&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Below are the values of the first byte in the shipped files. Values from the DOS version of [https://www.mobygames.com/game/56474/mickeys-abcs-a-day-at-the-fair/ Mickey&#039;s ABC&#039;s: A Day at the Fair] are included, as this may be the first public incarnation of Barchard compression. The bitfield suspected to be the method is highlighted in red, the method flags in green.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Game                !! Hex  !! Bits&lt;br /&gt;
|-&lt;br /&gt;
| Mickey&#039;s ABC        || &amp;lt;tt&amp;gt;0x44&amp;lt;/tt&amp;gt; || &amp;lt;tt&amp;gt;&amp;lt;span style=&amp;quot;color:lightgray&amp;quot;&amp;gt;0&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;1000&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt;100&amp;lt;/span&amp;gt;&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Stunts Amiga type 1 || &amp;lt;tt&amp;gt;0x26&amp;lt;/tt&amp;gt; || &amp;lt;tt&amp;gt;&amp;lt;span style=&amp;quot;color:lightgray&amp;quot;&amp;gt;0&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;0100&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt;110&amp;lt;/span&amp;gt;&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Stunts Amiga type 2 || &amp;lt;tt&amp;gt;0x42&amp;lt;/tt&amp;gt; || &amp;lt;tt&amp;gt;&amp;lt;span style=&amp;quot;color:lightgray&amp;quot;&amp;gt;0&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;1000&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt;010&amp;lt;/span&amp;gt;&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Stunts PC98         || &amp;lt;tt&amp;gt;0x46&amp;lt;/tt&amp;gt; || &amp;lt;tt&amp;gt;&amp;lt;span style=&amp;quot;color:lightgray&amp;quot;&amp;gt;0&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;1000&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt;110&amp;lt;/span&amp;gt;&amp;lt;/tt&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The game code appears to support several other methods that are not used by the shipped files. This analysis does not include the Amiga port, as this code has not been dissected yet.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Method !! Hex !! Bits&lt;br /&gt;
|-&lt;br /&gt;
| rowspan=4 | Mickey type 1&lt;br /&gt;
| &amp;lt;tt&amp;gt;0x40&amp;lt;/tt&amp;gt; || &amp;lt;tt&amp;gt;&amp;lt;span style=&amp;quot;color:lightgray&amp;quot;&amp;gt;0&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;1000&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt;000&amp;lt;/span&amp;gt;&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;0x41&amp;lt;/tt&amp;gt; || &amp;lt;tt&amp;gt;&amp;lt;span style=&amp;quot;color:lightgray&amp;quot;&amp;gt;0&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;1000&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt;001&amp;lt;/span&amp;gt;&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;0x42&amp;lt;/tt&amp;gt; || &amp;lt;tt&amp;gt;&amp;lt;span style=&amp;quot;color:lightgray&amp;quot;&amp;gt;0&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;1000&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt;010&amp;lt;/span&amp;gt;&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;0x44&amp;lt;/tt&amp;gt; || &amp;lt;tt&amp;gt;&amp;lt;span style=&amp;quot;color:lightgray&amp;quot;&amp;gt;0&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;1000&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt;100&amp;lt;/span&amp;gt;&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| rowspan=2 | Stunts type 1&lt;br /&gt;
| &amp;lt;tt&amp;gt;0x46&amp;lt;/tt&amp;gt; || &amp;lt;tt&amp;gt;&amp;lt;span style=&amp;quot;color:lightgray&amp;quot;&amp;gt;0&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;1000&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt;110&amp;lt;/span&amp;gt;&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;0x47&amp;lt;/tt&amp;gt; || &amp;lt;tt&amp;gt;&amp;lt;span style=&amp;quot;color:lightgray&amp;quot;&amp;gt;0&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;1000&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt;111&amp;lt;/span&amp;gt;&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| rowspan=3 | Stunts PC98 and Mickey type 2&lt;br /&gt;
| &amp;lt;tt&amp;gt;0x60&amp;lt;/tt&amp;gt; || &amp;lt;tt&amp;gt;&amp;lt;span style=&amp;quot;color:lightgray&amp;quot;&amp;gt;0&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;1100&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt;000&amp;lt;/span&amp;gt;&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;0x62&amp;lt;/tt&amp;gt; || &amp;lt;tt&amp;gt;&amp;lt;span style=&amp;quot;color:lightgray&amp;quot;&amp;gt;0&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;1100&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt;010&amp;lt;/span&amp;gt;&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;0x66&amp;lt;/tt&amp;gt; || &amp;lt;tt&amp;gt;&amp;lt;span style=&amp;quot;color:lightgray&amp;quot;&amp;gt;0&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;1100&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt;100&amp;lt;/span&amp;gt;&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Stunts PC98 and Mickey type 3&lt;br /&gt;
| &amp;lt;tt&amp;gt;0x6B || &amp;lt;tt&amp;gt;&amp;lt;span style=&amp;quot;color:lightgray&amp;quot;&amp;gt;0&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;1101&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt;011&amp;lt;/span&amp;gt;&amp;lt;/tt&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
A strong hypothesis suggests that the compression methods found here are related to the EA formats from PSX games [https://problemkaputt.de/psxspx-cdrom-file-compression-ea-methods.htm documented by Martin Korth]. Further analysis is required to verify this.&lt;br /&gt;
&lt;br /&gt;
=== RPck ===&lt;br /&gt;
3-d shapes are compressed with RPck, a simple [https://en.wikipedia.org/wiki/Run-length_encoding RLE]-based format found in some Amiga file archiving software. Compression ratio is inferior to RefPack, but the code is simpler and faster, which may explain why it was chosen for these files.&lt;br /&gt;
&lt;br /&gt;
== PC98 ==&lt;br /&gt;
The PC98 port of the game uses [[#Barchard|Barchard]] to compress some of the bitmap image resource files. See the Amiga section for more details.&lt;br /&gt;
&lt;br /&gt;
== FM Towns ==&lt;br /&gt;
The FM Towns and FM Towns Marty ports of the game were distributed on CD-ROM with ample storage and does not apply any compression to the game resource files.&lt;br /&gt;
&lt;br /&gt;
[[Category:Internals]]&lt;/div&gt;</summary>
		<author><name>Dstien</name></author>
	</entry>
	<entry>
		<id>https://wiki.stunts.hu/index.php?title=Compression&amp;diff=5768</id>
		<title>Compression</title>
		<link rel="alternate" type="text/html" href="https://wiki.stunts.hu/index.php?title=Compression&amp;diff=5768"/>
		<updated>2024-01-09T17:00:19Z</updated>

		<summary type="html">&lt;p&gt;Dstien: Replaced disproved RefPack speculation with updated research.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Stunts and its ports uses multiple compression formats for code and [[Resource_file_format|resource files]] to save disk space and, more importantly, the number of floppy disks used to distribute the game. &lt;br /&gt;
&lt;br /&gt;
== Formats by game version ==&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! rowspan=3 colspan=3 | Game version !! colspan=4 | Stunts packing !! rowspan=3 | Barchard !! rowspan=3 | RPck&lt;br /&gt;
|-&lt;br /&gt;
! rowspan=2 | RLE !! colspan=3 | Huffman&lt;br /&gt;
|-&lt;br /&gt;
! Supported !! Prefix table !! Code endianness&lt;br /&gt;
|-&lt;br /&gt;
! rowspan=4 style=text-align:left | MS DOS !! rowspan=2 | BB 1.0 !! style=text-align:left | Game&lt;br /&gt;
| style=text-align:center | X || style=text-align:center | X || || Big || ||&lt;br /&gt;
|-&lt;br /&gt;
! style=text-align:left | Loader&lt;br /&gt;
| || style=text-align:center | X || style=text-align:center | X || Little || ||&lt;br /&gt;
|-&lt;br /&gt;
! rowspan=2 | BB 1.1/MS 1.1 !! style=text-align:left | Game&lt;br /&gt;
| style=text-align:center | X || style=text-align:center | X || style=text-align:center | X || Little || ||&lt;br /&gt;
|-&lt;br /&gt;
! style=text-align:left | Loader&lt;br /&gt;
| || style=text-align:center | X || style=text-align:center | X || Little || ||&lt;br /&gt;
|-&lt;br /&gt;
! colspan=3 style=text-align:left | Amiga&lt;br /&gt;
| || || || || style=text-align:center | X || style=text-align:center | X&lt;br /&gt;
|-&lt;br /&gt;
! colspan=3 style=text-align:left | PC98&lt;br /&gt;
| || || || || style=text-align:center | X ||&lt;br /&gt;
|-&lt;br /&gt;
! colspan=3 style=text-align:left | FM Towns&lt;br /&gt;
| || || || || ||&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== MS DOS ==&lt;br /&gt;
The original release of Stunts uses a custom data compression format not found in the ports to other platforms. The code may have been hand-crafted for 16-bit x86 since other options were favoured in the later ports.&lt;br /&gt;
&lt;br /&gt;
The data format supports both [https://en.wikipedia.org/wiki/Run-length_encoding run-length encoding] (RLE) and [https://en.wikipedia.org/wiki/Huffman_coding Huffman coding]. They can be combined in multiple passes. The data format and the decompression code don&#039;t require any particular order or combination of algorithms. Every compressed file shipped with the game use Huffman coding, and when combined with RLE, the RLE pass is applied before Huffman.&lt;br /&gt;
&lt;br /&gt;
=== File header ===&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;enum&amp;lt;/span&amp;gt; CompressionType &amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;{&amp;lt;/span&amp;gt;&lt;br /&gt;
     RLE     = 1&lt;br /&gt;
     Huffman = 2&lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;}&amp;lt;/span&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;struct&amp;lt;/span&amp;gt; Header &amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;{&amp;lt;/span&amp;gt;&lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;union&amp;lt;/span&amp;gt; &amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;{&amp;lt;/span&amp;gt;&lt;br /&gt;
         &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt; passes : 7&lt;br /&gt;
         &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt; compression_type : 7&lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;}&amp;lt;/span&amp;gt;&lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt;  multi_pass : 1&lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint32&amp;lt;/span&amp;gt; uncompressed_size : 24&lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;}&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
If the most significant bit of the first byte of the file is set, this is a multi-pass file and the remaining 7 bits are the number of passes to be processed recursively. If the &amp;lt;tt&amp;gt;multi_pass&amp;lt;/tt&amp;gt; flag is not set, we are only doing a single pass and the first byte is the compression type. The next three bytes make up the uncompressed size. If the &amp;lt;tt&amp;gt;multi_pass&amp;lt;/tt&amp;gt; flag was set, this is the final uncompressed size. When the &amp;lt;tt&amp;gt;multi_pass&amp;lt;/tt&amp;gt; flag is not set, this is the uncompressed size of the current pass. The remaining data is processed recursively. The &amp;lt;tt&amp;gt;compression_type&amp;lt;/tt&amp;gt; field decides how it is decoded.&lt;br /&gt;
&lt;br /&gt;
=== Run-length encoding ===&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;struct&amp;lt;/span&amp;gt; RLE &amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;{&amp;lt;/span&amp;gt;&lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint32&amp;lt;/span&amp;gt; compressed_size : 24&lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt;  reserved &amp;lt;span class=&amp;quot;hlC&amp;quot;&amp;gt;// Always 0x00, value is ignored by the game&amp;lt;/span&amp;gt;&lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt;  escape_length : 7&lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt;  no_sequence : 1&lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt;  escape_codes&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;[&amp;lt;/span&amp;gt;escape_length&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;]&amp;lt;/span&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt;  data&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;[&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;hlC&amp;quot;&amp;gt;...&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;]&amp;lt;/span&amp;gt;&lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;}&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
RLE is used to reduce the length of consecutively repeated bytes by using an escape code followed by a counter to signify how many times the next byte should be repeated. It is particularly useful for compressing images, as large areas with a single colour would be represented by many consecutive identical bytes.&lt;br /&gt;
&lt;br /&gt;
The RLE stage can itself have two passes if &amp;lt;tt&amp;gt;no_sequence&amp;lt;/tt&amp;gt; is not set. The first pass will then expand sequences of bytes in the data. &amp;lt;tt&amp;gt;escape_codes[1]&amp;lt;/tt&amp;gt; will mark the beginning and the end of a byte sequence. When the escape code is encountered in the data, the following bytes are considered a sequence until the escape code is hit again. After the end-marking escape code, a one byte length counter tells how many times the preceding byte sequence should be repeated in the output buffer. Because the escape code cannot itself be escaped, sequential byte runs can only be applied in files that have unused byte values to use as the first escape code.&lt;br /&gt;
&lt;br /&gt;
The main RLE pass is a traditional expansion of single-byte runs, but with a twist that allows for multiple types of escape codes. The escape code&#039;s position in the header&#039;s escape code list affects its properties. When the first escape code is encountered in the source buffer, the following byte has the number of repetitions, and the next byte will be copied that many times to the output buffer. When the third escape code is encountered, the number of repetitions is stored in the following &#039;&#039;two&#039;&#039; bytes as a 16-bit integer. Then the following byte is copied that many times. All other escape codes use its position in the escape code list as the number of repetitions, and have no additional counter bytes before the data byte to be repeated. This allows the second escape code reserved for sequences to serve as a no-op without the two passes interfering. Escape codes can themselves be escaped in single-byte runs by having them expanded to only one copy.&lt;br /&gt;
&lt;br /&gt;
All repetition counters have an off-by-one surplus, as the data byte itself counts as the first copy. For optimal compression, escape codes should be chosen from byte values that occur least frequently, or not at all, in the source data.&lt;br /&gt;
&lt;br /&gt;
==== RLE decoding optimisation ====&lt;br /&gt;
Escape codes are put in an &amp;lt;tt&amp;gt;escape[256]&amp;lt;/tt&amp;gt; array, where the code&#039;s byte value is the index and the escape code&#039;s position is the entry&#039;s value. This array is used to test incoming bytes for escape codes. Raw bytes will have the value 0, while other values corresponds to the escape code&#039;s property. This optimisation makes the decoding run O(1), as opposed to O(&#039;&#039;n&#039;&#039;), where &#039;&#039;n&#039;&#039; is the number of escape codes.&lt;br /&gt;
&lt;br /&gt;
=== Huffman coding ===&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;struct&amp;lt;/span&amp;gt; Huffman &amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;{&amp;lt;/span&amp;gt;&lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt; tree_levels : 7&lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt; delta_coding : 1&lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt; symbols_per_level&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;[&amp;lt;/span&amp;gt;tree_levels&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;]&amp;lt;/span&amp;gt;&lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt; alphabet&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;[&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;SUM&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;(&amp;lt;/span&amp;gt;symbols_per_level&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;)&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;]&amp;lt;/span&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint16&amp;lt;/span&amp;gt; codes : var &amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;[&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;hlC&amp;quot;&amp;gt;...&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;]&amp;lt;/span&amp;gt;&lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;}&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Huffman coding uses a binary tree to store data. When Huffman codes are read, each bit tells which branch to take when traversing the tree. If a leaf node is hit, we have found the code&#039;s symbol and can proceed with the next code. Frequently used symbols have shorter paths and thus takes up fewer bits in the source file.&lt;br /&gt;
&lt;br /&gt;
The tree is stored by having two lists, one with symbols per level, and one with the alphabet. The alphabet is every possible symbol in the order they appear in the tree. The tree is built by going through each &amp;lt;tt&amp;gt;symbols_per_level&amp;lt;/tt&amp;gt;. If there are symbols at the current level, consume them from &amp;lt;tt&amp;gt;alphabet&amp;lt;/tt&amp;gt; and create leaf nodes. If there are no symbols, and there still are more levels to create, proceed to create left and right children nodes for the next level.&lt;br /&gt;
&lt;br /&gt;
The remaining data is the Huffman codes. Bit by bit is read to find leaf nodes in the Huffman tree whose symbols are appended to the output buffer. This is repeated until the output buffer has reached &amp;lt;tt&amp;gt;uncompressed_size&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
The maximum Huffman tree height is 16. While the data format allows for up to 127 levels, Stunts&#039; decompression function uses arrays with a fixed capacity of 16 for its level offset table.&lt;br /&gt;
&lt;br /&gt;
==== Delta coding ====&lt;br /&gt;
If the flag for [https://en.wikipedia.org/wiki/Delta_encoding delta coding] is set, each symbol is treated as the difference from the previous output byte instead of an independent final value. The last byte written to the output buffer is remembered and added to the next expanded symbol. While regular Huffman coding assigns shorter codes to frequently occurring values, this delta variant assigns shorter codes to differences that occurs frequently. This feature is not used by any shipped files, but the code is present in all versions that implements Huffman decoding. One can speculate that delta coding was outperformed by RLE combined with regular Huffman coding, making delta coding unnecessary.&lt;br /&gt;
&lt;br /&gt;
==== Huffman decoding optimisations ====&lt;br /&gt;
===== Prefix table =====&lt;br /&gt;
With Huffman codes being paths in a binary tree, they have the property of being prefix-free, meaning that one leaf node&#039;s code cannot be the prefix of another node&#039;s code. This allows for a decoding optimisation technique known as &#039;&#039;prefix tables&#039;&#039; or &#039;&#039;Huffman tables&#039;&#039;. By creating arrays of symbols and code widths where the indices are the Huffman codes, the codes can be looked up directly without traversing the tree. Every array index for non-leaf nodes between two leaf node entries are filled with data for the preceding leaf node. This way there&#039;s no need to filter out bits that belong to the next Huffman code, at the expense of common symbols taking up multiple entries in the lookup table during decompression.&lt;br /&gt;
&lt;br /&gt;
Stunts utilises this optimisation for Huffman codes that are up to 8 bits wide. The first byte of the code is checked in the &amp;lt;tt&amp;gt;widths[256]&amp;lt;/tt&amp;gt; array. If the code&#039;s width is 8 bits or less, the same code is looked up in the &amp;lt;tt&amp;gt;symbols[256]&amp;lt;/tt&amp;gt; array and written to the output buffer. To find the start of the next Huffman code, the source buffer is advanced by the code&#039;s bit width found in the &amp;lt;tt&amp;gt;widths&amp;lt;/tt&amp;gt; array.&lt;br /&gt;
&lt;br /&gt;
===== Offset table =====&lt;br /&gt;
As Stunts limits the prefix tables to 8 bit wide Huffman codes to save RAM, another novel optimisation is applied for codes that exceeds 8 bits. Prefixes for longer codes have the value &amp;lt;tt&amp;gt;0x40&amp;lt;/tt&amp;gt; in the &amp;lt;tt&amp;gt;widths&amp;lt;/tt&amp;gt; array, indicating that the current code is a prefix that needs further expansion. For this purpose Stunts uses two additional helper arrays: &amp;lt;tt&amp;gt;total_codes[tree_levels]&amp;lt;/tt&amp;gt;, which has the total number of leaf nodes that exists in the tree up to each level, and &amp;lt;tt&amp;gt;code_offsets[tree_levels]&amp;lt;/tt&amp;gt;, which for each level has a value that can be added to a code with the same level in order to get its index in the alphabet. This works because the codes are arranged [https://en.wikipedia.org/wiki/Canonical_Huffman_code canonically]. As a code&#039;s bit width corresponds to the code&#039;s level in the Huffman tree, the width can be used to compare the current code with the level&#039;s total by getting &amp;lt;tt&amp;gt;total_codes[current_width]&amp;lt;/tt&amp;gt; for each extra bit read. If the code is smaller than the total number of codes encountered, it is a leaf node, and we get the symbol by adding the level&#039;s code offset to the code with &amp;lt;tt&amp;gt;alphabet[code + code_offsets[width]]&amp;lt;/tt&amp;gt;. This is more laborious than the use of prefix tables for direct lookup, but it only applies to codes that are occurring less frequently in the input file.&lt;br /&gt;
&lt;br /&gt;
==== Version differences ====&lt;br /&gt;
The Huffman decompression in the game code of Stunts 1.0 differs from the one in its LOAD.EXE and later versions of the game. The Huffman codes are written with the least significant bit first, as opposed to the other versions that has the codes written with the opposite orientation. The game code of Stunts 1.0 also does not use a prefix table, and the bit-stream orientation was likely changed with the introduction of this optimisation.&lt;br /&gt;
&lt;br /&gt;
== Amiga ==&lt;br /&gt;
The Amiga port uses two unrelated compression formats.&lt;br /&gt;
&lt;br /&gt;
=== Barchard ===&lt;br /&gt;
Non-3d shape resource files uses another Distinctive Software in-house format that is characterized by the identification byte &amp;lt;tt&amp;gt;0xFB&amp;lt;/tt&amp;gt;, assumed to be the initials of its author, [https://www.mobygames.com/person/7186/frank-barchard/ Frank Barchard]. This format supports a suite of different compression methods and it evolved through the 90&#039;s and early 2000&#039;s as a part of EA&#039;s internal engine libraries. Whereas later games tended to use the [https://en.wikipedia.org/wiki/Lempel%E2%80%93Ziv%E2%80%93Storer%E2%80%93Szymanski LZSS]-based [https://github.com/lingeringwillx/Refpack-QFS-Resources RefPack] algorithm, the Stunts ports uses other methods. We will therefore refer to these compressions as &#039;&#039;&amp;quot;Barchard&amp;quot;&#039;&#039; to distinguish them from the ubiquitous RefPack.&lt;br /&gt;
&lt;br /&gt;
This is the currently assumed header structure:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;struct&amp;lt;/span&amp;gt; Header &amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;{&amp;lt;/span&amp;gt;&lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt;  method_flags : 3&lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt;  method_type  : 4&lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt;  32bit_length : 1 &amp;lt;span class=&amp;quot;hlC&amp;quot;&amp;gt;// Not used by Stunts&amp;lt;/span&amp;gt;&lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt;  magic &amp;lt;span class=&amp;quot;hlC&amp;quot;&amp;gt;// Always 0xFB&amp;lt;/span&amp;gt;&lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint32&amp;lt;/span&amp;gt; uncompressed_size : 24&lt;br /&gt;
 &lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlC&amp;quot;&amp;gt;// Possibly more fields if indicated by method_flags&amp;lt;/span&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt;  data&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;[&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;hlC&amp;quot;&amp;gt;...&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;]&amp;lt;/span&amp;gt;&lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;}&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Below are the values of the first byte in the shipped files. Values from the DOS version of [https://www.mobygames.com/game/56474/mickeys-abcs-a-day-at-the-fair/ Mickey&#039;s ABC&#039;s: A Day at the Fair] are included, as this may be the first public incarnation of Barchard compression. The bitfield suspected to be the method is highlighted in red, the method flags in green.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Game                !! Hex  !! Bits&lt;br /&gt;
|-&lt;br /&gt;
| Mickey&#039;s ABC        || &amp;lt;tt&amp;gt;0x44&amp;lt;/tt&amp;gt; || &amp;lt;tt&amp;gt;&amp;lt;span style=&amp;quot;color:lightgray&amp;quot;&amp;gt;0&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;1000&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt;100&amp;lt;/span&amp;gt;&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Stunts Amiga type 1 || &amp;lt;tt&amp;gt;0x26&amp;lt;/tt&amp;gt; || &amp;lt;tt&amp;gt;&amp;lt;span style=&amp;quot;color:lightgray&amp;quot;&amp;gt;0&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;0100&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt;110&amp;lt;/span&amp;gt;&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Stunts Amiga type 2 || &amp;lt;tt&amp;gt;0x42&amp;lt;/tt&amp;gt; || &amp;lt;tt&amp;gt;&amp;lt;span style=&amp;quot;color:lightgray&amp;quot;&amp;gt;0&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;1000&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt;010&amp;lt;/span&amp;gt;&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Stunts PC98         || &amp;lt;tt&amp;gt;0x46&amp;lt;/tt&amp;gt; || &amp;lt;tt&amp;gt;&amp;lt;span style=&amp;quot;color:lightgray&amp;quot;&amp;gt;0&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;1000&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt;110&amp;lt;/span&amp;gt;&amp;lt;/tt&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The game code appears to support several other methods that are not used by the shipped files. This analysis does not include the Amiga port, as this code has not been dissected yet.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Method !! Hex !! Bits&lt;br /&gt;
|-&lt;br /&gt;
| rowspan=4 | Mickey type 1&lt;br /&gt;
| &amp;lt;tt&amp;gt;0x40&amp;lt;/tt&amp;gt; || &amp;lt;tt&amp;gt;&amp;lt;span style=&amp;quot;color:lightgray&amp;quot;&amp;gt;0&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;1000&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt;000&amp;lt;/span&amp;gt;&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;0x41&amp;lt;/tt&amp;gt; || &amp;lt;tt&amp;gt;&amp;lt;span style=&amp;quot;color:lightgray&amp;quot;&amp;gt;0&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;1000&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt;001&amp;lt;/span&amp;gt;&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;0x42&amp;lt;/tt&amp;gt; || &amp;lt;tt&amp;gt;&amp;lt;span style=&amp;quot;color:lightgray&amp;quot;&amp;gt;0&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;1000&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt;010&amp;lt;/span&amp;gt;&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;0x44&amp;lt;/tt&amp;gt; || &amp;lt;tt&amp;gt;&amp;lt;span style=&amp;quot;color:lightgray&amp;quot;&amp;gt;0&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;1000&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt;100&amp;lt;/span&amp;gt;&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| rowspan=2 | Stunts type 1&lt;br /&gt;
| &amp;lt;tt&amp;gt;0x46&amp;lt;/tt&amp;gt; || &amp;lt;tt&amp;gt;&amp;lt;span style=&amp;quot;color:lightgray&amp;quot;&amp;gt;0&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;1000&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt;110&amp;lt;/span&amp;gt;&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;0x47&amp;lt;/tt&amp;gt; || &amp;lt;tt&amp;gt;&amp;lt;span style=&amp;quot;color:lightgray&amp;quot;&amp;gt;0&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;1000&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt;111&amp;lt;/span&amp;gt;&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| rowspan=3 | Stunts PC98 and Mickey type 2&lt;br /&gt;
| &amp;lt;tt&amp;gt;0x60&amp;lt;/tt&amp;gt; || &amp;lt;tt&amp;gt;&amp;lt;span style=&amp;quot;color:lightgray&amp;quot;&amp;gt;0&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;1100&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt;000&amp;lt;/span&amp;gt;&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;0x62&amp;lt;/tt&amp;gt; || &amp;lt;tt&amp;gt;&amp;lt;span style=&amp;quot;color:lightgray&amp;quot;&amp;gt;0&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;1100&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt;010&amp;lt;/span&amp;gt;&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;0x66&amp;lt;/tt&amp;gt; || &amp;lt;tt&amp;gt;&amp;lt;span style=&amp;quot;color:lightgray&amp;quot;&amp;gt;0&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;1100&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt;100&amp;lt;/span&amp;gt;&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Stunts PC98 and Mickey type 3&lt;br /&gt;
| &amp;lt;tt&amp;gt;0x6B || &amp;lt;tt&amp;gt;&amp;lt;span style=&amp;quot;color:lightgray&amp;quot;&amp;gt;0&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;1101&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt;011&amp;lt;/span&amp;gt;&amp;lt;/tt&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
A strong hypothesis suggests that the compression methods found here are related to the EA formats from PSX games [https://problemkaputt.de/psxspx-cdrom-file-compression-ea-methods.htm documented by Martin Korth]. Further analysis is required to verify this.&lt;br /&gt;
&lt;br /&gt;
=== RPck ===&lt;br /&gt;
3-d shapes are compressed with RPck, a simple [https://en.wikipedia.org/wiki/Run-length_encoding RLE]-based format found in some Amiga file archiving software. Compression ratio is inferior to RefPack, but the code is simpler and faster, which may explain why it was chosen for these files.&lt;br /&gt;
&lt;br /&gt;
== PC98 ==&lt;br /&gt;
The PC98 port of the game uses [http://wiki.niotso.org/RefPack RefPack] to compress some of the bitmap image resource files. See the Amiga section for more details.&lt;br /&gt;
&lt;br /&gt;
== FM Towns ==&lt;br /&gt;
The FM Towns and FM Towns Marty ports of the game were distributed on CD-ROM with ample storage and does not apply any compression to the game resource files.&lt;br /&gt;
&lt;br /&gt;
[[Category:Internals]]&lt;/div&gt;</summary>
		<author><name>Dstien</name></author>
	</entry>
	<entry>
		<id>https://wiki.stunts.hu/index.php?title=Compression&amp;diff=5633</id>
		<title>Compression</title>
		<link rel="alternate" type="text/html" href="https://wiki.stunts.hu/index.php?title=Compression&amp;diff=5633"/>
		<updated>2023-06-29T10:29:36Z</updated>

		<summary type="html">&lt;p&gt;Dstien: /* Run-length encoding */ Typos.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Stunts and its ports uses multiple compression formats for code and [[Resource_file_format|resource files]] to save disk space and, more importantly, the number of floppy disks used to distribute the game. &lt;br /&gt;
&lt;br /&gt;
== Formats by game version ==&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! rowspan=3 colspan=3 | Game version !! colspan=4 | Stunts packing !! rowspan=3 | RefPack !! rowspan=3 | RPck&lt;br /&gt;
|-&lt;br /&gt;
! rowspan=2 | RLE !! colspan=3 | Huffman&lt;br /&gt;
|-&lt;br /&gt;
! Supported !! Prefix table !! Code endianness&lt;br /&gt;
|-&lt;br /&gt;
! rowspan=4 style=text-align:left | MS DOS !! rowspan=2 | BB 1.0 !! style=text-align:left | Game&lt;br /&gt;
| style=text-align:center | X || style=text-align:center | X || || Big || ||&lt;br /&gt;
|-&lt;br /&gt;
! style=text-align:left | Loader&lt;br /&gt;
| || style=text-align:center | X || style=text-align:center | X || Little || ||&lt;br /&gt;
|-&lt;br /&gt;
! rowspan=2 | BB 1.1/MS 1.1 !! style=text-align:left | Game&lt;br /&gt;
| style=text-align:center | X || style=text-align:center | X || style=text-align:center | X || Little || ||&lt;br /&gt;
|-&lt;br /&gt;
! style=text-align:left | Loader&lt;br /&gt;
| || style=text-align:center | X || style=text-align:center | X || Little || ||&lt;br /&gt;
|-&lt;br /&gt;
! colspan=3 style=text-align:left | Amiga&lt;br /&gt;
| || || || || style=text-align:center | X || style=text-align:center | X&lt;br /&gt;
|-&lt;br /&gt;
! colspan=3 style=text-align:left | PC98&lt;br /&gt;
| || || || || style=text-align:center | X ||&lt;br /&gt;
|-&lt;br /&gt;
! colspan=3 style=text-align:left | FM Towns&lt;br /&gt;
| || || || || ||&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== MS DOS ==&lt;br /&gt;
The original release of Stunts uses a custom data compression format not found in the ports to other platforms. The code may have been hand-crafted for 16-bit x86 since other options were favoured in the later ports.&lt;br /&gt;
&lt;br /&gt;
The data format supports both [https://en.wikipedia.org/wiki/Run-length_encoding run-length encoding] (RLE) and [https://en.wikipedia.org/wiki/Huffman_coding Huffman coding]. They can be combined in multiple passes. The data format and the decompression code don&#039;t require any particular order or combination of algorithms. Every compressed file shipped with the game use Huffman coding, and when combined with RLE, the RLE pass is applied before Huffman.&lt;br /&gt;
&lt;br /&gt;
=== File header ===&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;enum&amp;lt;/span&amp;gt; CompressionType &amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;{&amp;lt;/span&amp;gt;&lt;br /&gt;
     RLE     = 1&lt;br /&gt;
     Huffman = 2&lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;}&amp;lt;/span&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;struct&amp;lt;/span&amp;gt; Header &amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;{&amp;lt;/span&amp;gt;&lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;union&amp;lt;/span&amp;gt; &amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;{&amp;lt;/span&amp;gt;&lt;br /&gt;
         &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt; passes : 7&lt;br /&gt;
         &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt; compression_type : 7&lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;}&amp;lt;/span&amp;gt;&lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt;  multi_pass : 1&lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint32&amp;lt;/span&amp;gt; uncompressed_size : 24&lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;}&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
If the most significant bit of the first byte of the file is set, this is a multi-pass file and the remaining 7 bits are the number of passes to be processed recursively. If the &amp;lt;tt&amp;gt;multi_pass&amp;lt;/tt&amp;gt; flag is not set, we are only doing a single pass and the first byte is the compression type. The next three bytes make up the uncompressed size. If the &amp;lt;tt&amp;gt;multi_pass&amp;lt;/tt&amp;gt; flag was set, this is the final uncompressed size. When the &amp;lt;tt&amp;gt;multi_pass&amp;lt;/tt&amp;gt; flag is not set, this is the uncompressed size of the current pass. The remaining data is processed recursively. The &amp;lt;tt&amp;gt;compression_type&amp;lt;/tt&amp;gt; field decides how it is decoded.&lt;br /&gt;
&lt;br /&gt;
=== Run-length encoding ===&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;struct&amp;lt;/span&amp;gt; RLE &amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;{&amp;lt;/span&amp;gt;&lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint32&amp;lt;/span&amp;gt; compressed_size : 24&lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt;  reserved &amp;lt;span class=&amp;quot;hlC&amp;quot;&amp;gt;// Always 0x00, value is ignored by the game&amp;lt;/span&amp;gt;&lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt;  escape_length : 7&lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt;  no_sequence : 1&lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt;  escape_codes&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;[&amp;lt;/span&amp;gt;escape_length&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;]&amp;lt;/span&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt;  data&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;[&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;hlC&amp;quot;&amp;gt;...&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;]&amp;lt;/span&amp;gt;&lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;}&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
RLE is used to reduce the length of consecutively repeated bytes by using an escape code followed by a counter to signify how many times the next byte should be repeated. It is particularly useful for compressing images, as large areas with a single colour would be represented by many consecutive identical bytes.&lt;br /&gt;
&lt;br /&gt;
The RLE stage can itself have two passes if &amp;lt;tt&amp;gt;no_sequence&amp;lt;/tt&amp;gt; is not set. The first pass will then expand sequences of bytes in the data. &amp;lt;tt&amp;gt;escape_codes[1]&amp;lt;/tt&amp;gt; will mark the beginning and the end of a byte sequence. When the escape code is encountered in the data, the following bytes are considered a sequence until the escape code is hit again. After the end-marking escape code, a one byte length counter tells how many times the preceding byte sequence should be repeated in the output buffer. Because the escape code cannot itself be escaped, sequential byte runs can only be applied in files that have unused byte values to use as the first escape code.&lt;br /&gt;
&lt;br /&gt;
The main RLE pass is a traditional expansion of single-byte runs, but with a twist that allows for multiple types of escape codes. The escape code&#039;s position in the header&#039;s escape code list affects its properties. When the first escape code is encountered in the source buffer, the following byte has the number of repetitions, and the next byte will be copied that many times to the output buffer. When the third escape code is encountered, the number of repetitions is stored in the following &#039;&#039;two&#039;&#039; bytes as a 16-bit integer. Then the following byte is copied that many times. All other escape codes use its position in the escape code list as the number of repetitions, and have no additional counter bytes before the data byte to be repeated. This allows the second escape code reserved for sequences to serve as a no-op without the two passes interfering. Escape codes can themselves be escaped in single-byte runs by having them expanded to only one copy.&lt;br /&gt;
&lt;br /&gt;
All repetition counters have an off-by-one surplus, as the data byte itself counts as the first copy. For optimal compression, escape codes should be chosen from byte values that occur least frequently, or not at all, in the source data.&lt;br /&gt;
&lt;br /&gt;
==== RLE decoding optimisation ====&lt;br /&gt;
Escape codes are put in an &amp;lt;tt&amp;gt;escape[256]&amp;lt;/tt&amp;gt; array, where the code&#039;s byte value is the index and the escape code&#039;s position is the entry&#039;s value. This array is used to test incoming bytes for escape codes. Raw bytes will have the value 0, while other values corresponds to the escape code&#039;s property. This optimisation makes the decoding run O(1), as opposed to O(&#039;&#039;n&#039;&#039;), where &#039;&#039;n&#039;&#039; is the number of escape codes.&lt;br /&gt;
&lt;br /&gt;
=== Huffman coding ===&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;struct&amp;lt;/span&amp;gt; Huffman &amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;{&amp;lt;/span&amp;gt;&lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt; tree_levels : 7&lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt; delta_coding : 1&lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt; symbols_per_level&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;[&amp;lt;/span&amp;gt;tree_levels&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;]&amp;lt;/span&amp;gt;&lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt; alphabet&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;[&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;SUM&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;(&amp;lt;/span&amp;gt;symbols_per_level&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;)&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;]&amp;lt;/span&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint16&amp;lt;/span&amp;gt; codes : var &amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;[&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;hlC&amp;quot;&amp;gt;...&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;]&amp;lt;/span&amp;gt;&lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;}&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Huffman coding uses a binary tree to store data. When Huffman codes are read, each bit tells which branch to take when traversing the tree. If a leaf node is hit, we have found the code&#039;s symbol and can proceed with the next code. Frequently used symbols have shorter paths and thus takes up fewer bits in the source file.&lt;br /&gt;
&lt;br /&gt;
The tree is stored by having two lists, one with symbols per level, and one with the alphabet. The alphabet is every possible symbol in the order they appear in the tree. The tree is built by going through each &amp;lt;tt&amp;gt;symbols_per_level&amp;lt;/tt&amp;gt;. If there are symbols at the current level, consume them from &amp;lt;tt&amp;gt;alphabet&amp;lt;/tt&amp;gt; and create leaf nodes. If there are no symbols, and there still are more levels to create, proceed to create left and right children nodes for the next level.&lt;br /&gt;
&lt;br /&gt;
The remaining data is the Huffman codes. Bit by bit is read to find leaf nodes in the Huffman tree whose symbols are appended to the output buffer. This is repeated until the output buffer has reached &amp;lt;tt&amp;gt;uncompressed_size&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
The maximum Huffman tree height is 16. While the data format allows for up to 127 levels, Stunts&#039; decompression function uses arrays with a fixed capacity of 16 for its level offset table.&lt;br /&gt;
&lt;br /&gt;
==== Delta coding ====&lt;br /&gt;
If the flag for [https://en.wikipedia.org/wiki/Delta_encoding delta coding] is set, each symbol is treated as the difference from the previous output byte instead of an independent final value. The last byte written to the output buffer is remembered and added to the next expanded symbol. While regular Huffman coding assigns shorter codes to frequently occurring values, this delta variant assigns shorter codes to differences that occurs frequently. This feature is not used by any shipped files, but the code is present in all versions that implements Huffman decoding. One can speculate that delta coding was outperformed by RLE combined with regular Huffman coding, making delta coding unnecessary.&lt;br /&gt;
&lt;br /&gt;
==== Huffman decoding optimisations ====&lt;br /&gt;
===== Prefix table =====&lt;br /&gt;
With Huffman codes being paths in a binary tree, they have the property of being prefix-free, meaning that one leaf node&#039;s code cannot be the prefix of another node&#039;s code. This allows for a decoding optimisation technique known as &#039;&#039;prefix tables&#039;&#039; or &#039;&#039;Huffman tables&#039;&#039;. By creating arrays of symbols and code widths where the indices are the Huffman codes, the codes can be looked up directly without traversing the tree. Every array index for non-leaf nodes between two leaf node entries are filled with data for the preceding leaf node. This way there&#039;s no need to filter out bits that belong to the next Huffman code, at the expense of common symbols taking up multiple entries in the lookup table during decompression.&lt;br /&gt;
&lt;br /&gt;
Stunts utilises this optimisation for Huffman codes that are up to 8 bits wide. The first byte of the code is checked in the &amp;lt;tt&amp;gt;widths[256]&amp;lt;/tt&amp;gt; array. If the code&#039;s width is 8 bits or less, the same code is looked up in the &amp;lt;tt&amp;gt;symbols[256]&amp;lt;/tt&amp;gt; array and written to the output buffer. To find the start of the next Huffman code, the source buffer is advanced by the code&#039;s bit width found in the &amp;lt;tt&amp;gt;widths&amp;lt;/tt&amp;gt; array.&lt;br /&gt;
&lt;br /&gt;
===== Offset table =====&lt;br /&gt;
As Stunts limits the prefix tables to 8 bit wide Huffman codes to save RAM, another novel optimisation is applied for codes that exceeds 8 bits. Prefixes for longer codes have the value &amp;lt;tt&amp;gt;0x40&amp;lt;/tt&amp;gt; in the &amp;lt;tt&amp;gt;widths&amp;lt;/tt&amp;gt; array, indicating that the current code is a prefix that needs further expansion. For this purpose Stunts uses two additional helper arrays: &amp;lt;tt&amp;gt;total_codes[tree_levels]&amp;lt;/tt&amp;gt;, which has the total number of leaf nodes that exists in the tree up to each level, and &amp;lt;tt&amp;gt;code_offsets[tree_levels]&amp;lt;/tt&amp;gt;, which for each level has a value that can be added to a code with the same level in order to get its index in the alphabet. This works because the codes are arranged [https://en.wikipedia.org/wiki/Canonical_Huffman_code canonically]. As a code&#039;s bit width corresponds to the code&#039;s level in the Huffman tree, the width can be used to compare the current code with the level&#039;s total by getting &amp;lt;tt&amp;gt;total_codes[current_width]&amp;lt;/tt&amp;gt; for each extra bit read. If the code is smaller than the total number of codes encountered, it is a leaf node, and we get the symbol by adding the level&#039;s code offset to the code with &amp;lt;tt&amp;gt;alphabet[code + code_offsets[width]]&amp;lt;/tt&amp;gt;. This is more laborious than the use of prefix tables for direct lookup, but it only applies to codes that are occurring less frequently in the input file.&lt;br /&gt;
&lt;br /&gt;
==== Version differences ====&lt;br /&gt;
The Huffman decompression in the game code of Stunts 1.0 differs from the one in its LOAD.EXE and later versions of the game. The Huffman codes are written with the least significant bit first, as opposed to the other versions that has the codes written with the opposite orientation. The game code of Stunts 1.0 also does not use a prefix table, and the bit-stream orientation was likely changed with the introduction of this optimisation.&lt;br /&gt;
&lt;br /&gt;
== Amiga ==&lt;br /&gt;
The Amiga port uses two unrelated compression formats.&lt;br /&gt;
&lt;br /&gt;
=== RefPack ===&lt;br /&gt;
Non-3d shape resource files uses the Electronic Arts in-house [https://en.wikipedia.org/wiki/Lempel%E2%80%93Ziv%E2%80%93Storer%E2%80%93Szymanski LZSS]-based compression format [http://wiki.niotso.org/RefPack RefPack]. This may be one of the first known uses of RefPack which since became part of EA&#039;s internal engine libraries and has been used in many games through the 90&#039;s and early 2000&#039;s. The bit stream format is fully documented and has multiple implementations available, but the header flags have either changed, or the unofficial implementations make incorrect assumptions about them, causing the decompressors to wrongfully assume that the 4D Sports Driving files are not compressed due to not having the &amp;lt;tt&amp;gt;0x01&amp;lt;/tt&amp;gt; flag set.&lt;br /&gt;
&lt;br /&gt;
=== RPck ===&lt;br /&gt;
3-d shapes are compressed with RPck, a simple [https://en.wikipedia.org/wiki/Run-length_encoding RLE]-based format found in some Amiga file archiving software. Compression ratio is inferior to RefPack, but the code is simpler and faster, which may explain why it was chosen for these files.&lt;br /&gt;
&lt;br /&gt;
== PC98 ==&lt;br /&gt;
The PC98 port of the game uses [http://wiki.niotso.org/RefPack RefPack] to compress some of the bitmap image resource files. See the Amiga section for more details.&lt;br /&gt;
&lt;br /&gt;
== FM Towns ==&lt;br /&gt;
The FM Towns and FM Towns Marty ports of the game were distributed on CD-ROM with ample storage and does not apply any compression to the game resource files.&lt;br /&gt;
&lt;br /&gt;
[[Category:Internals]]&lt;/div&gt;</summary>
		<author><name>Dstien</name></author>
	</entry>
	<entry>
		<id>https://wiki.stunts.hu/index.php?title=Compression&amp;diff=5613</id>
		<title>Compression</title>
		<link rel="alternate" type="text/html" href="https://wiki.stunts.hu/index.php?title=Compression&amp;diff=5613"/>
		<updated>2023-06-25T13:45:09Z</updated>

		<summary type="html">&lt;p&gt;Dstien: Cover all platforms.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Stunts and its ports uses multiple compression formats for code and [[Resource_file_format|resource files]] to save disk space and, more importantly, the number of floppy disks used to distribute the game. &lt;br /&gt;
&lt;br /&gt;
== Formats by game version ==&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! rowspan=3 colspan=3 | Game version !! colspan=4 | Stunts packing !! rowspan=3 | RefPack !! rowspan=3 | RPck&lt;br /&gt;
|-&lt;br /&gt;
! rowspan=2 | RLE !! colspan=3 | Huffman&lt;br /&gt;
|-&lt;br /&gt;
! Supported !! Prefix table !! Code endianness&lt;br /&gt;
|-&lt;br /&gt;
! rowspan=4 style=text-align:left | MS DOS !! rowspan=2 | BB 1.0 !! style=text-align:left | Game&lt;br /&gt;
| style=text-align:center | X || style=text-align:center | X || || Big || ||&lt;br /&gt;
|-&lt;br /&gt;
! style=text-align:left | Loader&lt;br /&gt;
| || style=text-align:center | X || style=text-align:center | X || Little || ||&lt;br /&gt;
|-&lt;br /&gt;
! rowspan=2 | BB 1.1/MS 1.1 !! style=text-align:left | Game&lt;br /&gt;
| style=text-align:center | X || style=text-align:center | X || style=text-align:center | X || Little || ||&lt;br /&gt;
|-&lt;br /&gt;
! style=text-align:left | Loader&lt;br /&gt;
| || style=text-align:center | X || style=text-align:center | X || Little || ||&lt;br /&gt;
|-&lt;br /&gt;
! colspan=3 style=text-align:left | Amiga&lt;br /&gt;
| || || || || style=text-align:center | X || style=text-align:center | X&lt;br /&gt;
|-&lt;br /&gt;
! colspan=3 style=text-align:left | PC98&lt;br /&gt;
| || || || || style=text-align:center | X ||&lt;br /&gt;
|-&lt;br /&gt;
! colspan=3 style=text-align:left | FM Towns&lt;br /&gt;
| || || || || ||&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== MS DOS ==&lt;br /&gt;
The original release of Stunts uses a custom data compression format not found in the ports to other platforms. The code may have been hand-crafted for 16-bit x86 since other options were favoured in the later ports.&lt;br /&gt;
&lt;br /&gt;
The data format supports both [https://en.wikipedia.org/wiki/Run-length_encoding run-length encoding] (RLE) and [https://en.wikipedia.org/wiki/Huffman_coding Huffman coding]. They can be combined in multiple passes. The data format and the decompression code don&#039;t require any particular order or combination of algorithms. Every compressed file shipped with the game use Huffman coding, and when combined with RLE, the RLE pass is applied before Huffman.&lt;br /&gt;
&lt;br /&gt;
=== File header ===&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;enum&amp;lt;/span&amp;gt; CompressionType &amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;{&amp;lt;/span&amp;gt;&lt;br /&gt;
     RLE     = 1&lt;br /&gt;
     Huffman = 2&lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;}&amp;lt;/span&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;struct&amp;lt;/span&amp;gt; Header &amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;{&amp;lt;/span&amp;gt;&lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;union&amp;lt;/span&amp;gt; &amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;{&amp;lt;/span&amp;gt;&lt;br /&gt;
         &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt; passes : 7&lt;br /&gt;
         &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt; compression_type : 7&lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;}&amp;lt;/span&amp;gt;&lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt;  multi_pass : 1&lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint32&amp;lt;/span&amp;gt; uncompressed_size : 24&lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;}&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
If the most significant bit of the first byte of the file is set, this is a multi-pass file and the remaining 7 bits are the number of passes to be processed recursively. If the &amp;lt;tt&amp;gt;multi_pass&amp;lt;/tt&amp;gt; flag is not set, we are only doing a single pass and the first byte is the compression type. The next three bytes make up the uncompressed size. If the &amp;lt;tt&amp;gt;multi_pass&amp;lt;/tt&amp;gt; flag was set, this is the final uncompressed size. When the &amp;lt;tt&amp;gt;multi_pass&amp;lt;/tt&amp;gt; flag is not set, this is the uncompressed size of the current pass. The remaining data is processed recursively. The &amp;lt;tt&amp;gt;compression_type&amp;lt;/tt&amp;gt; field decides how it is decoded.&lt;br /&gt;
&lt;br /&gt;
=== Run length coding ===&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;struct&amp;lt;/span&amp;gt; RLE &amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;{&amp;lt;/span&amp;gt;&lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt;  unknown &amp;lt;span class=&amp;quot;hlC&amp;quot;&amp;gt;// Always 0x00, value is ignored by the game&amp;lt;/span&amp;gt;&lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint32&amp;lt;/span&amp;gt; compressed_size : 24&lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt;  escape_length : 7&lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt;  no_sequence : 1&lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt;  escape_codes&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;[&amp;lt;/span&amp;gt;escape_length&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;]&amp;lt;/span&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt;  data&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;[&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;hlC&amp;quot;&amp;gt;...&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;]&amp;lt;/span&amp;gt;&lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;}&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
RLE is used to reduce the length of consecutively repeated bytes by using an escape code followed by a counter to signify how many times the next byte should be repeated. It is particularly useful for compressing images, as large areas with a single colour would be represented by many consecutive identical bytes.&lt;br /&gt;
&lt;br /&gt;
The RLE stage can itself have two passes if &amp;lt;tt&amp;gt;no_sequence&amp;lt;/tt&amp;gt; is not set. The first pass will then expand sequences of bytes in the data. &amp;lt;tt&amp;gt;escape_codes[1]&amp;lt;/tt&amp;gt; will mark the beginning and the end of a byte sequence. When the escape code is encountered in the data, the following bytes are considered a sequence until the escape code is hit again. After the end-marking escape code, a one byte length counter tells how many times the preceding byte sequence should be repeated in the output buffer. Because the escape code cannot itself be escaped, sequential byte runs can only be applied in files that have unused byte values to use as the first escape code.&lt;br /&gt;
&lt;br /&gt;
The main RLE pass is a traditional expansion of single-byte runs, but with a twist that allows for multiple types of escape codes. The escape code&#039;s position in the header&#039;s escape code list affects its properties. When the first escape code is encountered in the source buffer, the following byte has the number of repetitions, and the next byte will be copied that many times to the output buffer. When the third escape code is encountered, the number of repetitions is stored in the following &#039;&#039;two&#039;&#039; bytes as a 16-bit integer. Then the following byte is copied that many times. All other escape codes use its position in the escape code list as the number of repetitions, and have no additional counter bytes before the data byte to be repeated. This allows the second escape code reserved for sequences to serve as a no-op without the two passes interfering. Escape codes can themselves be escaped in single-byte runs by having them expanded to only one copy.&lt;br /&gt;
&lt;br /&gt;
All repetition counters have an off-by-one surplus, as the data byte itself counts as the first copy. For optimal compression, escape codes should be chosen from byte values that occur least frequently, or not at all, in the source data.&lt;br /&gt;
&lt;br /&gt;
==== RLE decoding optimisation ====&lt;br /&gt;
Escape codes are put in an &amp;lt;tt&amp;gt;escape[256]&amp;lt;/tt&amp;gt; array, where the code&#039;s byte value is the index and the escape code&#039;s position is the entry&#039;s value. This array is used to test incoming bytes for escape codes. Raw bytes will have the value 0, while other values corresponds to the escape code&#039;s property. This optimisation makes the decoding run O(1), as opposed to O(&#039;&#039;n&#039;&#039;), where &#039;&#039;n&#039;&#039; is the number of escape codes.&lt;br /&gt;
&lt;br /&gt;
=== Huffman coding ===&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;struct&amp;lt;/span&amp;gt; Huffman &amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;{&amp;lt;/span&amp;gt;&lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt; tree_levels : 7&lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt; delta_coding : 1&lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt; symbols_per_level&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;[&amp;lt;/span&amp;gt;tree_levels&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;]&amp;lt;/span&amp;gt;&lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt; alphabet&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;[&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;SUM&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;(&amp;lt;/span&amp;gt;symbols_per_level&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;)&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;]&amp;lt;/span&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint16&amp;lt;/span&amp;gt; codes : var &amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;[&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;hlC&amp;quot;&amp;gt;...&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;]&amp;lt;/span&amp;gt;&lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;}&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Huffman coding uses a binary tree to store data. When Huffman codes are read, each bit tells which branch to take when traversing the tree. If a leaf node is hit, we have found the code&#039;s symbol and can proceed with the next code. Frequently used symbols have shorter paths and thus takes up fewer bits in the source file.&lt;br /&gt;
&lt;br /&gt;
The tree is stored by having two lists, one with symbols per level, and one with the alphabet. The alphabet is every possible symbol in the order they appear in the tree. The tree is built by going through each &amp;lt;tt&amp;gt;symbols_per_level&amp;lt;/tt&amp;gt;. If there are symbols at the current level, consume them from &amp;lt;tt&amp;gt;alphabet&amp;lt;/tt&amp;gt; and create leaf nodes. If there are no symbols, and there still are more levels to create, proceed to create left and right children nodes for the next level.&lt;br /&gt;
&lt;br /&gt;
The remaining data is the Huffman codes. Bit by bit is read to find leaf nodes in the Huffman tree whose symbols are appended to the output buffer. This is repeated until the output buffer has reached &amp;lt;tt&amp;gt;uncompressed_size&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
The maximum Huffman tree height is 16. While the data format allows for up to 127 levels, Stunts&#039; decompression function uses arrays with a fixed capacity of 16 for its level offset table.&lt;br /&gt;
&lt;br /&gt;
==== Delta coding ====&lt;br /&gt;
If the flag for [https://en.wikipedia.org/wiki/Delta_encoding delta coding] is set, each symbol is treated as the difference from the previous output byte instead of an independent final value. The last byte written to the output buffer is remembered and added to the next expanded symbol. While regular Huffman coding assigns shorter codes to frequently occurring values, this delta variant assigns shorter codes to differences that occurs frequently. This feature is not used by any shipped files, but the code is present in all versions that implements Huffman decoding. One can speculate that delta coding was outperformed by RLE combined with regular Huffman coding, making delta coding unnecessary.&lt;br /&gt;
&lt;br /&gt;
==== Huffman decoding optimisations ====&lt;br /&gt;
===== Prefix table =====&lt;br /&gt;
With Huffman codes being paths in a binary tree, they have the property of being prefix-free, meaning that one leaf node&#039;s code cannot be the prefix of another node&#039;s code. This allows for a decoding optimisation technique known as &#039;&#039;prefix tables&#039;&#039; or &#039;&#039;Huffman tables&#039;&#039;. By creating arrays of symbols and code widths where the indices are the Huffman codes, the codes can be looked up directly without traversing the tree. Every array index for non-leaf nodes between two leaf node entries are filled with data for the preceding leaf node. This way there&#039;s no need to filter out bits that belong to the next Huffman code, at the expense of common symbols taking up multiple entries in the lookup table during decompression.&lt;br /&gt;
&lt;br /&gt;
Stunts utilises this optimisation for Huffman codes that are up to 8 bits wide. The first byte of the code is checked in the &amp;lt;tt&amp;gt;widths[256]&amp;lt;/tt&amp;gt; array. If the code&#039;s width is 8 bits or less, the same code is looked up in the &amp;lt;tt&amp;gt;symbols[256]&amp;lt;/tt&amp;gt; array and written to the output buffer. To find the start of the next Huffman code, the source buffer is advanced by the code&#039;s bit width found in the &amp;lt;tt&amp;gt;widths&amp;lt;/tt&amp;gt; array.&lt;br /&gt;
&lt;br /&gt;
===== Offset table =====&lt;br /&gt;
As Stunts limits the prefix tables to 8 bit wide Huffman codes to save RAM, another novel optimisation is applied for codes that exceeds 8 bits. Prefixes for longer codes have the value &amp;lt;tt&amp;gt;0x40&amp;lt;/tt&amp;gt; in the &amp;lt;tt&amp;gt;widths&amp;lt;/tt&amp;gt; array, indicating that the current code is a prefix that needs further expansion. For this purpose Stunts uses two additional helper arrays: &amp;lt;tt&amp;gt;total_codes[tree_levels]&amp;lt;/tt&amp;gt;, which has the total number of leaf nodes that exists in the tree up to each level, and &amp;lt;tt&amp;gt;code_offsets[tree_levels]&amp;lt;/tt&amp;gt;, which for each level has a value that can be added to a code with the same level in order to get its index in the alphabet. This works because the codes are arranged [https://en.wikipedia.org/wiki/Canonical_Huffman_code canonically]. As a code&#039;s bit width corresponds to the code&#039;s level in the Huffman tree, the width can be used to compare the current code with the level&#039;s total by getting &amp;lt;tt&amp;gt;total_codes[current_width]&amp;lt;/tt&amp;gt; for each extra bit read. If the code is smaller than the total number of codes encountered, it is a leaf node, and we get the symbol by adding the level&#039;s code offset to the code with &amp;lt;tt&amp;gt;alphabet[code + code_offsets[width]]&amp;lt;/tt&amp;gt;. This is more laborious than the use of prefix tables for direct lookup, but it only applies to codes that are occurring less frequently in the input file.&lt;br /&gt;
&lt;br /&gt;
==== Version differences ====&lt;br /&gt;
The Huffman decompression in the game code of Stunts 1.0 differs from the one in its LOAD.EXE and later versions of the game. The Huffman codes are written with the least significant bit first, as opposed to the other versions that has the codes written with the opposite orientation. The game code of Stunts 1.0 also does not use a prefix table, and the bit-stream orientation was likely changed with the introduction of this optimisation.&lt;br /&gt;
&lt;br /&gt;
== Amiga ==&lt;br /&gt;
The Amiga port uses two unrelated compression formats.&lt;br /&gt;
&lt;br /&gt;
=== RefPack ===&lt;br /&gt;
Non-3d shape resource files uses the Electronic Arts in-house [https://en.wikipedia.org/wiki/Lempel%E2%80%93Ziv%E2%80%93Storer%E2%80%93Szymanski LZSS]-based compression format [http://wiki.niotso.org/RefPack RefPack]. This may be one of the first known uses of RefPack which since became part of EA&#039;s internal engine libraries and has been used in many games through the 90&#039;s and early 2000&#039;s. The bit stream format is fully documented and has multiple implementations available, but the header flags have either changed, or the unofficial implementations make incorrect assumptions about them, causing the decompressors to wrongfully assume that the 4D Sports Driving files are not compressed due to not having the &amp;lt;tt&amp;gt;0x01&amp;lt;/tt&amp;gt; flag set.&lt;br /&gt;
&lt;br /&gt;
=== RPck ===&lt;br /&gt;
3-d shapes are compressed with RPck, a simple [https://en.wikipedia.org/wiki/Run-length_encoding RLE]-based format found in some Amiga file archiving software. Compression ratio is inferior to RefPack, but the code is simpler and faster, which may explain why it was chosen for these files.&lt;br /&gt;
&lt;br /&gt;
== PC98 ==&lt;br /&gt;
The PC98 port of the game uses [http://wiki.niotso.org/RefPack RefPack] to compress some of the bitmap image resource files. See the Amiga section for more details.&lt;br /&gt;
&lt;br /&gt;
== FM Towns ==&lt;br /&gt;
The FM Towns and FM Towns Marty ports of the game were distributed on CD-ROM with ample storage and does not apply any compression to the game resource files.&lt;br /&gt;
&lt;br /&gt;
[[Category:Internals]]&lt;/div&gt;</summary>
		<author><name>Dstien</name></author>
	</entry>
	<entry>
		<id>https://wiki.stunts.hu/index.php?title=Compression&amp;diff=5611</id>
		<title>Compression</title>
		<link rel="alternate" type="text/html" href="https://wiki.stunts.hu/index.php?title=Compression&amp;diff=5611"/>
		<updated>2023-06-22T07:49:13Z</updated>

		<summary type="html">&lt;p&gt;Dstien: Typos.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Stunts uses a custom data compression format for code and [[Resource_file_format|resource files]] to save disk space and, more importantly, the number of floppy disks used to distribute the game. The data format supports both [https://en.wikipedia.org/wiki/Run-length_encoding run-length encoding] (RLE) and [https://en.wikipedia.org/wiki/Huffman_coding Huffman coding]. They can be combined in multiple passes. The data format and the decompression code don&#039;t require any particular order or combination of algorithms. Every compressed file shipped with the game use Huffman coding, and when combined with RLE, the RLE pass is applied before Huffman.&lt;br /&gt;
&lt;br /&gt;
== File header ==&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;enum&amp;lt;/span&amp;gt; CompressionType &amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;{&amp;lt;/span&amp;gt;&lt;br /&gt;
     RLE     = 1&lt;br /&gt;
     Huffman = 2&lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;}&amp;lt;/span&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;struct&amp;lt;/span&amp;gt; Header &amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;{&amp;lt;/span&amp;gt;&lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;union&amp;lt;/span&amp;gt; &amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;{&amp;lt;/span&amp;gt;&lt;br /&gt;
         &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt; passes : 7&lt;br /&gt;
         &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt; compression_type : 7&lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;}&amp;lt;/span&amp;gt;&lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt;  multi_pass : 1&lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint32&amp;lt;/span&amp;gt; uncompressed_size : 24&lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;}&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
If the most significant bit of the first byte of the file is set, this is a multi-pass file and the remaining 7 bits are the number of passes to be processed recursively. If the &amp;lt;tt&amp;gt;multi_pass&amp;lt;/tt&amp;gt; flag is not set, we are only doing a single pass and the first byte is the compression type. The next three bytes make up the uncompressed size. If the &amp;lt;tt&amp;gt;multi_pass&amp;lt;/tt&amp;gt; flag was set, this is the final uncompressed size. When the &amp;lt;tt&amp;gt;multi_pass&amp;lt;/tt&amp;gt; flag is not set, this is the uncompressed size of the current pass. The remaining data is processed recursively. The &amp;lt;tt&amp;gt;compression_type&amp;lt;/tt&amp;gt; field decides how it is decoded.&lt;br /&gt;
&lt;br /&gt;
== Run length coding ==&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;struct&amp;lt;/span&amp;gt; RLE &amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;{&amp;lt;/span&amp;gt;&lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt;  unknown &amp;lt;span class=&amp;quot;hlC&amp;quot;&amp;gt;// Always 0x00, value is ignored by the game&amp;lt;/span&amp;gt;&lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint32&amp;lt;/span&amp;gt; compressed_size : 24&lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt;  escape_length : 7&lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt;  no_sequence : 1&lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt;  escape_codes&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;[&amp;lt;/span&amp;gt;escape_length&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;]&amp;lt;/span&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt;  data&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;[&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;hlC&amp;quot;&amp;gt;...&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;]&amp;lt;/span&amp;gt;&lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;}&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
RLE is used to reduce the length of consecutively repeated bytes by using an escape code followed by a counter to signify how many times the next byte should be repeated. It is particularly useful for compressing images, as large areas with a single colour would be represented by many consecutive identical bytes.&lt;br /&gt;
&lt;br /&gt;
The RLE stage can itself have two passes if &amp;lt;tt&amp;gt;no_sequence&amp;lt;/tt&amp;gt; is not set. The first pass will then expand sequences of bytes in the data. &amp;lt;tt&amp;gt;escape_codes[1]&amp;lt;/tt&amp;gt; will mark the beginning and the end of a byte sequence. When the escape code is encountered in the data, the following bytes are considered a sequence until the escape code is hit again. After the end-marking escape code, a one byte length counter tells how many times the preceding byte sequence should be repeated in the output buffer. Because the escape code cannot itself be escaped, sequential byte runs can only be applied in files that have unused byte values to use as the first escape code.&lt;br /&gt;
&lt;br /&gt;
The main RLE pass is a traditional expansion of single-byte runs, but with a twist that allows for multiple types of escape codes. The escape code&#039;s position in the header&#039;s escape code list affects its properties. When the first escape code is encountered in the source buffer, the following byte has the number of repetitions, and the next byte will be copied that many times to the output buffer. When the third escape code is encountered, the number of repetitions is stored in the following &#039;&#039;two&#039;&#039; bytes as a 16-bit integer. Then the following byte is copied that many times. All other escape codes use its position in the escape code list as the number of repetitions, and have no additional counter bytes before the data byte to be repeated. This allows the second escape code reserved for sequences to serve as a no-op without the two passes interfering. Escape codes can themselves be escaped in single-byte runs by having them expanded to only one copy.&lt;br /&gt;
&lt;br /&gt;
All repetition counters have an off-by-one surplus, as the data byte itself counts as the first copy. For optimal compression, escape codes should be chosen from byte values that occur least frequently, or not at all, in the source data.&lt;br /&gt;
&lt;br /&gt;
=== RLE decoding optimisation ===&lt;br /&gt;
Escape codes are put in an &amp;lt;tt&amp;gt;escape[256]&amp;lt;/tt&amp;gt; array, where the code&#039;s byte value is the index and the escape code&#039;s position is the entry&#039;s value. This array is used to test incoming bytes for escape codes. Raw bytes will have the value 0, while other values corresponds to the escape code&#039;s property. This optimisation makes the decoding run O(1), as opposed to O(&#039;&#039;n&#039;&#039;), where &#039;&#039;n&#039;&#039; is the number of escape codes.&lt;br /&gt;
&lt;br /&gt;
== Huffman coding ==&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;struct&amp;lt;/span&amp;gt; Huffman &amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;{&amp;lt;/span&amp;gt;&lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt; tree_levels : 7&lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt; delta_coding : 1&lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt; symbols_per_level&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;[&amp;lt;/span&amp;gt;tree_levels&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;]&amp;lt;/span&amp;gt;&lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt; alphabet&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;[&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;SUM&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;(&amp;lt;/span&amp;gt;symbols_per_level&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;)&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;]&amp;lt;/span&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint16&amp;lt;/span&amp;gt; codes : var &amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;[&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;hlC&amp;quot;&amp;gt;...&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;]&amp;lt;/span&amp;gt;&lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;}&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Huffman coding uses a binary tree to store data. When Huffman codes are read, each bit tells which branch to take when traversing the tree. If a leaf node is hit, we have found the code&#039;s symbol and can proceed with the next code. Frequently used symbols have shorter paths and thus takes up fewer bits in the source file.&lt;br /&gt;
&lt;br /&gt;
The tree is stored by having two lists, one with symbols per level, and one with the alphabet. The alphabet is every possible symbol in the order they appear in the tree. The tree is built by going through each &amp;lt;tt&amp;gt;symbols_per_level&amp;lt;/tt&amp;gt;. If there are symbols at the current level, consume them from &amp;lt;tt&amp;gt;alphabet&amp;lt;/tt&amp;gt; and create leaf nodes. If there are no symbols, and there still are more levels to create, proceed to create left and right children nodes for the next level.&lt;br /&gt;
&lt;br /&gt;
The remaining data is the Huffman codes. Bit by bit is read to find leaf nodes in the Huffman tree whose symbols are appended to the output buffer. This is repeated until the output buffer has reached &amp;lt;tt&amp;gt;uncompressed_size&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
The maximum Huffman tree height is 16. While the data format allows for up to 127 levels, Stunts&#039; decompression function uses arrays with a fixed capacity of 16 for its level offset table.&lt;br /&gt;
&lt;br /&gt;
=== Delta coding ===&lt;br /&gt;
If the flag for [https://en.wikipedia.org/wiki/Delta_encoding delta coding] is set, each symbol is treated as the difference from the previous output byte instead of an independent final value. The last byte written to the output buffer is remembered and added to the next expanded symbol. While regular Huffman coding assigns shorter codes to frequently occurring values, this delta variant assigns shorter codes to differences that occurs frequently. This feature is not used by any shipped files, but the code is present in all versions that implements Huffman decoding. One can speculate that delta coding was outperformed by RLE combined with regular Huffman coding, making delta coding unnecessary.&lt;br /&gt;
&lt;br /&gt;
=== Huffman decoding optimisations ===&lt;br /&gt;
==== Prefix table ====&lt;br /&gt;
With Huffman codes being paths in a binary tree, they have the property of being prefix-free, meaning that one leaf node&#039;s code cannot be the prefix of another node&#039;s code. This allows for a decoding optimisation technique known as &#039;&#039;prefix tables&#039;&#039; or &#039;&#039;Huffman tables&#039;&#039;. By creating arrays of symbols and code widths where the indices are the Huffman codes, the codes can be looked up directly without traversing the tree. Every array index for non-leaf nodes between two leaf node entries are filled with data for the preceding leaf node. This way there&#039;s no need to filter out bits that belong to the next Huffman code, at the expense of common symbols taking up multiple entries in the lookup table during decompression.&lt;br /&gt;
&lt;br /&gt;
Stunts utilises this optimisation for Huffman codes that are up to 8 bits wide. The first byte of the code is checked in the &amp;lt;tt&amp;gt;widths[256]&amp;lt;/tt&amp;gt; array. If the code&#039;s width is 8 bits or less, the same code is looked up in the &amp;lt;tt&amp;gt;symbols[256]&amp;lt;/tt&amp;gt; array and written to the output buffer. To find the start of the next Huffman code, the source buffer is advanced by the code&#039;s bit width found in the &amp;lt;tt&amp;gt;widths&amp;lt;/tt&amp;gt; array.&lt;br /&gt;
&lt;br /&gt;
==== Offset table ====&lt;br /&gt;
As Stunts limits the prefix tables to 8 bit wide Huffman codes to save RAM, another novel optimisation is applied for codes that exceeds 8 bits. Prefixes for longer codes have the value &amp;lt;tt&amp;gt;0x40&amp;lt;/tt&amp;gt; in the &amp;lt;tt&amp;gt;widths&amp;lt;/tt&amp;gt; array, indicating that the current code is a prefix that needs further expansion. For this purpose Stunts uses two additional helper arrays: &amp;lt;tt&amp;gt;total_codes[tree_levels]&amp;lt;/tt&amp;gt;, which has the total number of leaf nodes that exists in the tree up to each level, and &amp;lt;tt&amp;gt;code_offsets[tree_levels]&amp;lt;/tt&amp;gt;, which for each level has a value that can be added to a code with the same level in order to get its index in the alphabet. This works because the codes are arranged [https://en.wikipedia.org/wiki/Canonical_Huffman_code canonically]. As a code&#039;s bit width corresponds to the code&#039;s level in the Huffman tree, the width can be used to compare the current code with the level&#039;s total by getting &amp;lt;tt&amp;gt;total_codes[current_width]&amp;lt;/tt&amp;gt; for each extra bit read. If the code is smaller than the total number of codes encountered, it is a leaf node, and we get the symbol by adding the level&#039;s code offset to the code with &amp;lt;tt&amp;gt;alphabet[code + code_offsets[width]]&amp;lt;/tt&amp;gt;. This is more laborious than the use of prefix tables for direct lookup, but it only applies to codes that are occurring less frequently in the input file.&lt;br /&gt;
&lt;br /&gt;
=== Version differences ===&lt;br /&gt;
The Huffman decompression in the game code of Stunts 1.0 differs from the one in its LOAD.EXE and later versions of the game. The Huffman codes are written with the least significant bit first, as opposed to the other versions that has the codes written with the opposite orientation. The game code of Stunts 1.0 also does not use a prefix table, and the bit-stream orientation was likely changed with the introduction of this optimisation.&lt;br /&gt;
&lt;br /&gt;
[[Category:Internals]]&lt;/div&gt;</summary>
		<author><name>Dstien</name></author>
	</entry>
	<entry>
		<id>https://wiki.stunts.hu/index.php?title=Compression&amp;diff=5590</id>
		<title>Compression</title>
		<link rel="alternate" type="text/html" href="https://wiki.stunts.hu/index.php?title=Compression&amp;diff=5590"/>
		<updated>2023-06-16T08:45:36Z</updated>

		<summary type="html">&lt;p&gt;Dstien: /* Run length coding */ Sequence escape code.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Stunts uses a custom data compression format for code and [[Resource_file_format|resource files]] to save disk space and, more importantly, the number of floppy disks used to distribute the game. The data format supports both [https://en.wikipedia.org/wiki/Run-length_encoding run-length encoding] (RLE) and [https://en.wikipedia.org/wiki/Huffman_coding Huffman coding]. They can be combined in multiple passes. The data format and the decompression code don&#039;t require any particular order or combination of algorithms. Every compressed file shipped with the game use Huffman coding, and when combined with RLE, the RLE pass is applied before Huffman.&lt;br /&gt;
&lt;br /&gt;
== File header ==&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;enum&amp;lt;/span&amp;gt; CompressionType &amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;{&amp;lt;/span&amp;gt;&lt;br /&gt;
     RLE     = 1&lt;br /&gt;
     Huffman = 2&lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;}&amp;lt;/span&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;struct&amp;lt;/span&amp;gt; Header &amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;{&amp;lt;/span&amp;gt;&lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;union&amp;lt;/span&amp;gt; &amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;{&amp;lt;/span&amp;gt;&lt;br /&gt;
         &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt; passes : 7&lt;br /&gt;
         &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt; compression_type : 7&lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;}&amp;lt;/span&amp;gt;&lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt;  multi_pass : 1&lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint32&amp;lt;/span&amp;gt; uncompressed_size : 24&lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;}&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
If the most significant bit of the first byte of the file is set, this is a multi-pass file and the remaining 7 bits are the number of passes to be processed recursively. If the &amp;lt;tt&amp;gt;multi_pass&amp;lt;/tt&amp;gt; flag is not set, we are only doing a single pass and the first byte is the compression type. The next three bytes make up the uncompressed size. If the &amp;lt;tt&amp;gt;multi_pass&amp;lt;/tt&amp;gt; flag was set, this is the final uncompressed size. When the &amp;lt;tt&amp;gt;multi_pass&amp;lt;/tt&amp;gt; flag is not set, this is the uncompressed size of the current pass. The remaining data is processed recursively. The &amp;lt;tt&amp;gt;compression_type&amp;lt;/tt&amp;gt; field decides how it is decoded.&lt;br /&gt;
&lt;br /&gt;
== Run length coding ==&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;struct&amp;lt;/span&amp;gt; RLE &amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;{&amp;lt;/span&amp;gt;&lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt; unknown &amp;lt;span class=&amp;quot;hlC&amp;quot;&amp;gt;// Always 0x00, value is ignored by the game&amp;lt;/span&amp;gt;&lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt; escape_length : 7&lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt; no_sequence : 1&lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt; escape_codes&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;[&amp;lt;/span&amp;gt;escape_length&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;]&amp;lt;/span&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt; data&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;[&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;hlC&amp;quot;&amp;gt;...&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;]&amp;lt;/span&amp;gt;&lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;}&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
RLE is used to reduce the length of consecutively repeated bytes by using an escape code followed by a counter to signify how many times the next byte should be repeated. It is particularly useful for compressing images, as large areas with a single colour would be represented by many consecutive identical bytes.&lt;br /&gt;
&lt;br /&gt;
The RLE stage can itself have two passes if &amp;lt;tt&amp;gt;no_sequence&amp;lt;/tt&amp;gt; is not set. The first pass will then expand sequences of bytes in the data. &amp;lt;tt&amp;gt;escape_codes[1]&amp;lt;/tt&amp;gt; will mark the beginning and the end of a byte sequence. When the escape code is encountered in the data, the following bytes are considered a sequence until the escape code is hit again. After the end-marking escape code, a one byte length counter tells how many times the preceding byte sequence should be repeated in the output buffer. Because the escape code cannot itself be escaped, sequential byte runs can only be applied in files that have unused byte values to use as the first escape code.&lt;br /&gt;
&lt;br /&gt;
The main RLE pass is a traditional expansion of single-byte runs, but with a twist that allows for multiple types of escape codes. The escape code&#039;s position in the header&#039;s escape code list affects its properties. When the first escape code is encountered in the source buffer, the following byte has the number of repetitions, and the next byte will be copied that many times to the output buffer. When the third escape code is encountered, the number of repetitions is stored in the following &#039;&#039;two&#039;&#039; bytes as a 16-bit integer. Then the following byte is copied that many times. All other escape codes use its position in the escape code list as the number of repetitions, and have no additional counter bytes before the data byte to be repeated. This allows the second escape code reserved for sequences to serve as a no-op without the two passes interfering. Escape codes can themselves be escaped in single-byte runs by having them expanded to only one copy.&lt;br /&gt;
&lt;br /&gt;
All repetition counters have an off-by-one surplus, as the data byte itself counts as the first copy. For optimal compression, escape codes should be chosen from byte values that occur least frequently, or not at all, in the source data.&lt;br /&gt;
&lt;br /&gt;
=== RLE decoding optimisation ===&lt;br /&gt;
Escape codes are put in an &amp;lt;tt&amp;gt;escape[256]&amp;lt;/tt&amp;gt; array, where the code&#039;s byte value is the index and the escape code&#039;s position is the entry&#039;s value. This array is used to test incoming bytes for escape codes. Raw bytes will have the value 0, while other values corresponds to the escape code&#039;s property. This optimisation makes the decoding run O(1), as opposed to O(&#039;&#039;n&#039;&#039;), where &#039;&#039;n&#039;&#039; is the number of escape codes.&lt;br /&gt;
&lt;br /&gt;
== Huffman coding ==&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;struct&amp;lt;/span&amp;gt; Huffman &amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;{&amp;lt;/span&amp;gt;&lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt; tree_levels : 7&lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt; delta_coding : 1&lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt; symbols_per_level&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;[&amp;lt;/span&amp;gt;tree_levels&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;]&amp;lt;/span&amp;gt;&lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt; alphabet&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;[&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;SUM&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;(&amp;lt;/span&amp;gt;symbols_per_level&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;)&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;]&amp;lt;/span&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint16&amp;lt;/span&amp;gt; codes : var &amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;[&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;hlC&amp;quot;&amp;gt;...&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;]&amp;lt;/span&amp;gt;&lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;}&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Huffman coding uses a binary tree to store data. When Huffman codes are read, each bit tells which branch to take when traversing the tree. If a leaf node is hit, we have found the code&#039;s symbol and can proceed with the next code. Frequently used symbols have shorter paths and thus takes up fewer bits in the source file.&lt;br /&gt;
&lt;br /&gt;
The tree is stored by having two lists, one with symbols per level, and one with the alphabet. The alphabet is every possible symbol in the order they appear in the tree. The tree is built by going through each &amp;lt;tt&amp;gt;symbols_per_level&amp;lt;/tt&amp;gt;. If there are symbols at the current level, consume them from &amp;lt;tt&amp;gt;alphabet&amp;lt;/tt&amp;gt; and create a leaf nodes. If there are no symbols, and there still are more levels to create, proceed to create left and right children nodes for the next level.&lt;br /&gt;
&lt;br /&gt;
The remaining data is the Huffman codes. Bit by bit is read to find leaf nodes in the Huffman tree whose symbols are appended to the output buffer. This is repeated until the output buffer has reached &amp;lt;tt&amp;gt;uncompressed_size&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
The maximum Huffman tree height is 16. While the data format allows for up to 127 levels, Stunts&#039; decompression function uses arrays with a fixed capacity of 16 for its level offset table.&lt;br /&gt;
&lt;br /&gt;
=== Delta coding ===&lt;br /&gt;
If the flag for [https://en.wikipedia.org/wiki/Delta_encoding delta coding] is set, each symbol is treated as the difference from the previous output byte instead of an independent final value. The last byte written to the output buffer is remembered and added to the next expanded symbol. While regular Huffman coding assigns shorter codes to frequently occurring values, this delta variant assigns shorter codes to differences that occurs frequently. This feature is not used by any shipped files, but the code is present in all versions that implements Huffman decoding. One can speculate that delta coding was outperformed by RLE combined with regular Huffman coding, making delta coding unnecessary.&lt;br /&gt;
&lt;br /&gt;
=== Huffman decoding optimisations ===&lt;br /&gt;
==== Prefix table ====&lt;br /&gt;
With Huffman codes being paths in a binary tree, they have the property of being prefix-free, meaning that one leaf node&#039;s code cannot be the prefix of another node&#039;s code. This allows for a decoding optimisation technique known as &#039;&#039;prefix tables&#039;&#039; or &#039;&#039;Huffman tables&#039;&#039;. By creating arrays of symbols and code widths where the indices are the Huffman codes, the codes can be looked up directly without traversing the tree. Every array index for non-leaf nodes between two leaf node entries are filled with data for the preceding leaf node. This way there&#039;s no need to filter out bits that belong to the next Huffman code, at the expense of common symbols taking up multiple entries in the lookup table during decompression.&lt;br /&gt;
&lt;br /&gt;
Stunts utilises this optimisation for Huffman codes that are up to 8 bits wide. The first byte of the code is checked in the &amp;lt;tt&amp;gt;widths[256]&amp;lt;/tt&amp;gt; array. If the code&#039;s width is 8 bits or less, the same code is looked up in the &amp;lt;tt&amp;gt;symbols[256]&amp;lt;/tt&amp;gt; array and written to the output buffer. To find the start of the next Huffman code, the source buffer is advanced by the code&#039;s bit width found in the &amp;lt;tt&amp;gt;widths&amp;lt;/tt&amp;gt; array.&lt;br /&gt;
&lt;br /&gt;
==== Offset table ====&lt;br /&gt;
As Stunts limits the prefix tables to 8 bit wide Huffman codes to save RAM, another novel optimisation is applied for codes that exceeds 8 bits. Prefixes for longer codes have the value &amp;lt;tt&amp;gt;0x40&amp;lt;/tt&amp;gt; in the &amp;lt;tt&amp;gt;widths&amp;lt;/tt&amp;gt; array, indicating that the current code is a prefix that needs further expansion. For this purpose Stunts uses two additional helper arrays: &amp;lt;tt&amp;gt;total_codes[tree_levels]&amp;lt;/tt&amp;gt;, which has the total number of leaf nodes that exists in the tree up to each level, and &amp;lt;tt&amp;gt;code_offsets[tree_levels]&amp;lt;/tt&amp;gt;, which for each level has a value that can be added to a code with the same level in order to get its index in the alphabet. This works because the codes are arranged [https://en.wikipedia.org/wiki/Canonical_Huffman_code canonically]. As a code&#039;s bit width corresponds to the code&#039;s level in the Huffman tree, the width can be used to compare the current code with the level&#039;s total by getting &amp;lt;tt&amp;gt;total_codes[current_width]&amp;lt;/tt&amp;gt; for each extra bit read. If the code is smaller than the total number of codes encountered, it is a leaf node, and we get the symbol by adding the level&#039;s code offset to the code with &amp;lt;tt&amp;gt;alphabet[code + code_offsets[width]]&amp;lt;/tt&amp;gt;. This is more laborious than the use of prefix tables for direct lookup, but it only applies to codes that are occurring less frequently in the input file.&lt;br /&gt;
&lt;br /&gt;
=== Version differences ===&lt;br /&gt;
The Huffman decompression in the game code of Stunts 1.0 differs from the one in its LOAD.EXE and later versions of the game. The Huffman codes are written with the least significant bit first, as opposed to the other versions that has the codes written with the opposite orientation. The game code of Stunts 1.0 also does not use a prefix table, and the bit-stream orientation was likely changed with the introduction of this optimisation.&lt;br /&gt;
&lt;br /&gt;
[[Category:Internals]]&lt;/div&gt;</summary>
		<author><name>Dstien</name></author>
	</entry>
	<entry>
		<id>https://wiki.stunts.hu/index.php?title=Compression&amp;diff=5589</id>
		<title>Compression</title>
		<link rel="alternate" type="text/html" href="https://wiki.stunts.hu/index.php?title=Compression&amp;diff=5589"/>
		<updated>2023-06-16T04:56:11Z</updated>

		<summary type="html">&lt;p&gt;Dstien: RLE intro, article category, typo fixes.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Stunts uses a custom data compression format for code and [[Resource_file_format|resource files]] to save disk space and, more importantly, the number of floppy disks used to distribute the game. The data format supports both [https://en.wikipedia.org/wiki/Run-length_encoding run-length encoding] (RLE) and [https://en.wikipedia.org/wiki/Huffman_coding Huffman coding]. They can be combined in multiple passes. The data format and the decompression code don&#039;t require any particular order or combination of algorithms. Every compressed file shipped with the game use Huffman coding, and when combined with RLE, the RLE pass is applied before Huffman.&lt;br /&gt;
&lt;br /&gt;
== File header ==&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;enum&amp;lt;/span&amp;gt; CompressionType &amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;{&amp;lt;/span&amp;gt;&lt;br /&gt;
     RLE     = 1&lt;br /&gt;
     Huffman = 2&lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;}&amp;lt;/span&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;struct&amp;lt;/span&amp;gt; Header &amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;{&amp;lt;/span&amp;gt;&lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;union&amp;lt;/span&amp;gt; &amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;{&amp;lt;/span&amp;gt;&lt;br /&gt;
         &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt; passes : 7&lt;br /&gt;
         &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt; compression_type : 7&lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;}&amp;lt;/span&amp;gt;&lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt;  multi_pass : 1&lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint32&amp;lt;/span&amp;gt; uncompressed_size : 24&lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;}&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
If the most significant bit of the first byte of the file is set, this is a multi-pass file and the remaining 7 bits are the number of passes to be processed recursively. If the &amp;lt;tt&amp;gt;multi_pass&amp;lt;/tt&amp;gt; flag is not set, we are only doing a single pass and the first byte is the compression type. The next three bytes make up the uncompressed size. If the &amp;lt;tt&amp;gt;multi_pass&amp;lt;/tt&amp;gt; flag was set, this is the final uncompressed size. When the &amp;lt;tt&amp;gt;multi_pass&amp;lt;/tt&amp;gt; flag is not set, this is the uncompressed size of the current pass. The remaining data is processed recursively. The &amp;lt;tt&amp;gt;compression_type&amp;lt;/tt&amp;gt; field decides how it is decoded.&lt;br /&gt;
&lt;br /&gt;
== Run length coding ==&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;struct&amp;lt;/span&amp;gt; RLE &amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;{&amp;lt;/span&amp;gt;&lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt; unknown &amp;lt;span class=&amp;quot;hlC&amp;quot;&amp;gt;// Always 0x00, value is ignored by the game&amp;lt;/span&amp;gt;&lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt; escape_length : 7&lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt; no_sequence : 1&lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt; escape_codes&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;[&amp;lt;/span&amp;gt;escape_length&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;]&amp;lt;/span&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt; data&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;[&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;hlC&amp;quot;&amp;gt;...&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;]&amp;lt;/span&amp;gt;&lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;}&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
RLE is used to reduce the length of consecutively repeated bytes by using an escape code followed by a counter to signify how many times the next byte should be repeated. It is particularly useful for compressing images, as large areas with a single colour would be represented by many consecutive identical bytes.&lt;br /&gt;
&lt;br /&gt;
The RLE stage can itself have two passes if &amp;lt;tt&amp;gt;no_sequence&amp;lt;/tt&amp;gt; is not set. The first pass will then expand sequences of bytes in the data. &amp;lt;tt&amp;gt;escape_codes[0]&amp;lt;/tt&amp;gt; will mark the beginning and the end of a byte sequence. When the escape code is encountered in the data, the following bytes are considered a sequence until the escape code is hit again. After the end-marking escape code, a one byte length counter tells how many times the preceding byte sequence should be repeated in the output buffer. Because the escape code cannot itself be escaped, sequential byte runs can only be applied in files that have unused byte values to use as the first escape code.&lt;br /&gt;
&lt;br /&gt;
The main RLE pass is a traditional expansion of single-byte runs, but with a twist that allows for multiple types of escape codes. The escape code&#039;s position in the header&#039;s escape code list affects its properties. When the first escape code is encountered in the source buffer, the following byte has the number of repetitions, and the next byte will be copied that many times to the output buffer. When the third escape code is encountered, the number of repetitions is stored in the following &#039;&#039;two&#039;&#039; bytes as a 16-bit integer. Then the following byte is copied that many times. All other escape codes use its position in the escape code list as the number of repetitions, and have no additional counter bytes before the data byte to be repeated. Escape codes can themselves be escaped in single-byte runs by having them expanded to only one copy.&lt;br /&gt;
&lt;br /&gt;
All repetition counters have an off-by-one surplus, as the data byte itself counts as the first copy. For optimal compression, escape codes should be chosen from byte values that occur least frequently, or not at all, in the source data.&lt;br /&gt;
&lt;br /&gt;
=== RLE decoding optimisation ===&lt;br /&gt;
Escape codes are put in an &amp;lt;tt&amp;gt;escape[256]&amp;lt;/tt&amp;gt; array, where the code&#039;s byte value is the index and the escape code&#039;s position is the entry&#039;s value. This array is used to test incoming bytes for escape codes. Raw bytes will have the value 0, while other values corresponds to the escape code&#039;s property. This optimisation makes the decoding run O(1), as opposed to O(&#039;&#039;n&#039;&#039;), where &#039;&#039;n&#039;&#039; is the number of escape codes.&lt;br /&gt;
&lt;br /&gt;
== Huffman coding ==&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;struct&amp;lt;/span&amp;gt; Huffman &amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;{&amp;lt;/span&amp;gt;&lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt; tree_levels : 7&lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt; delta_coding : 1&lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt; symbols_per_level&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;[&amp;lt;/span&amp;gt;tree_levels&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;]&amp;lt;/span&amp;gt;&lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt; alphabet&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;[&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;SUM&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;(&amp;lt;/span&amp;gt;symbols_per_level&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;)&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;]&amp;lt;/span&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint16&amp;lt;/span&amp;gt; codes : var &amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;[&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;hlC&amp;quot;&amp;gt;...&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;]&amp;lt;/span&amp;gt;&lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;}&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Huffman coding uses a binary tree to store data. When Huffman codes are read, each bit tells which branch to take when traversing the tree. If a leaf node is hit, we have found the code&#039;s symbol and can proceed with the next code. Frequently used symbols have shorter paths and thus takes up fewer bits in the source file.&lt;br /&gt;
&lt;br /&gt;
The tree is stored by having two lists, one with symbols per level, and one with the alphabet. The alphabet is every possible symbol in the order they appear in the tree. The tree is built by going through each &amp;lt;tt&amp;gt;symbols_per_level&amp;lt;/tt&amp;gt;. If there are symbols at the current level, consume them from &amp;lt;tt&amp;gt;alphabet&amp;lt;/tt&amp;gt; and create a leaf nodes. If there are no symbols, and there still are more levels to create, proceed to create left and right children nodes for the next level.&lt;br /&gt;
&lt;br /&gt;
The remaining data is the Huffman codes. Bit by bit is read to find leaf nodes in the Huffman tree whose symbols are appended to the output buffer. This is repeated until the output buffer has reached &amp;lt;tt&amp;gt;uncompressed_size&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
The maximum Huffman tree height is 16. While the data format allows for up to 127 levels, Stunts&#039; decompression function uses arrays with a fixed capacity of 16 for its level offset table.&lt;br /&gt;
&lt;br /&gt;
=== Delta coding ===&lt;br /&gt;
If the flag for [https://en.wikipedia.org/wiki/Delta_encoding delta coding] is set, each symbol is treated as the difference from the previous output byte instead of an independent final value. The last byte written to the output buffer is remembered and added to the next expanded symbol. While regular Huffman coding assigns shorter codes to frequently occurring values, this delta variant assigns shorter codes to differences that occurs frequently. This feature is not used by any shipped files, but the code is present in all versions that implements Huffman decoding. One can speculate that delta coding was outperformed by RLE combined with regular Huffman coding, making delta coding unnecessary.&lt;br /&gt;
&lt;br /&gt;
=== Huffman decoding optimisations ===&lt;br /&gt;
==== Prefix table ====&lt;br /&gt;
With Huffman codes being paths in a binary tree, they have the property of being prefix-free, meaning that one leaf node&#039;s code cannot be the prefix of another node&#039;s code. This allows for a decoding optimisation technique known as &#039;&#039;prefix tables&#039;&#039; or &#039;&#039;Huffman tables&#039;&#039;. By creating arrays of symbols and code widths where the indices are the Huffman codes, the codes can be looked up directly without traversing the tree. Every array index for non-leaf nodes between two leaf node entries are filled with data for the preceding leaf node. This way there&#039;s no need to filter out bits that belong to the next Huffman code, at the expense of common symbols taking up multiple entries in the lookup table during decompression.&lt;br /&gt;
&lt;br /&gt;
Stunts utilises this optimisation for Huffman codes that are up to 8 bits wide. The first byte of the code is checked in the &amp;lt;tt&amp;gt;widths[256]&amp;lt;/tt&amp;gt; array. If the code&#039;s width is 8 bits or less, the same code is looked up in the &amp;lt;tt&amp;gt;symbols[256]&amp;lt;/tt&amp;gt; array and written to the output buffer. To find the start of the next Huffman code, the source buffer is advanced by the code&#039;s bit width found in the &amp;lt;tt&amp;gt;widths&amp;lt;/tt&amp;gt; array.&lt;br /&gt;
&lt;br /&gt;
==== Offset table ====&lt;br /&gt;
As Stunts limits the prefix tables to 8 bit wide Huffman codes to save RAM, another novel optimisation is applied for codes that exceeds 8 bits. Prefixes for longer codes have the value &amp;lt;tt&amp;gt;0x40&amp;lt;/tt&amp;gt; in the &amp;lt;tt&amp;gt;widths&amp;lt;/tt&amp;gt; array, indicating that the current code is a prefix that needs further expansion. For this purpose Stunts uses two additional helper arrays: &amp;lt;tt&amp;gt;total_codes[tree_levels]&amp;lt;/tt&amp;gt;, which has the total number of leaf nodes that exists in the tree up to each level, and &amp;lt;tt&amp;gt;code_offsets[tree_levels]&amp;lt;/tt&amp;gt;, which for each level has a value that can be added to a code with the same level in order to get its index in the alphabet. This works because the codes are arranged [https://en.wikipedia.org/wiki/Canonical_Huffman_code canonically]. As a code&#039;s bit width corresponds to the code&#039;s level in the Huffman tree, the width can be used to compare the current code with the level&#039;s total by getting &amp;lt;tt&amp;gt;total_codes[current_width]&amp;lt;/tt&amp;gt; for each extra bit read. If the code is smaller than the total number of codes encountered, it is a leaf node, and we get the symbol by adding the level&#039;s code offset to the code with &amp;lt;tt&amp;gt;alphabet[code + code_offsets[width]]&amp;lt;/tt&amp;gt;. This is more laborious than the use of prefix tables for direct lookup, but it only applies to codes that are occurring less frequently in the input file.&lt;br /&gt;
&lt;br /&gt;
=== Version differences ===&lt;br /&gt;
The Huffman decompression in the game code of Stunts 1.0 differs from the one in its LOAD.EXE and later versions of the game. The Huffman codes are written with the least significant bit first, as opposed to the other versions that has the codes written with the opposite orientation. The game code of Stunts 1.0 also does not use a prefix table, and the bit-stream orientation was likely changed with the introduction of this optimisation.&lt;br /&gt;
&lt;br /&gt;
[[Category:Internals]]&lt;/div&gt;</summary>
		<author><name>Dstien</name></author>
	</entry>
	<entry>
		<id>https://wiki.stunts.hu/index.php?title=Compression&amp;diff=5588</id>
		<title>Compression</title>
		<link rel="alternate" type="text/html" href="https://wiki.stunts.hu/index.php?title=Compression&amp;diff=5588"/>
		<updated>2023-06-14T13:16:18Z</updated>

		<summary type="html">&lt;p&gt;Dstien: Created page with &amp;quot;Stunts uses a custom data compression format for code and resource files to save disk space and, more importantly, the number of floppy disks used to...&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Stunts uses a custom data compression format for code and [[Resource_file_format|resource files]] to save disk space and, more importantly, the number of floppy disks used to distribute the game. The data format supports both [https://en.wikipedia.org/wiki/Run-length_encoding run-length encoding] (RLE) and [https://en.wikipedia.org/wiki/Huffman_coding Huffman coding]. They can be combined in multiple passes. The data format and the decompression code don&#039;t require any particular order or combination of algorithms. Every compressed file shipped with the game use Huffman coding, and when combined with RLE, the RLE pass is applied before Huffman.&lt;br /&gt;
&lt;br /&gt;
== File header ==&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;enum&amp;lt;/span&amp;gt; CompressionType &amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;{&amp;lt;/span&amp;gt;&lt;br /&gt;
     RLE     = 1&lt;br /&gt;
     Huffman = 2&lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;}&amp;lt;/span&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;struct&amp;lt;/span&amp;gt; Header &amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;{&amp;lt;/span&amp;gt;&lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;union&amp;lt;/span&amp;gt; &amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;{&amp;lt;/span&amp;gt;&lt;br /&gt;
         &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt; passes : 7&lt;br /&gt;
         &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt; compression_type : 7&lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;}&amp;lt;/span&amp;gt;&lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt;  multi_pass : 1&lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint32&amp;lt;/span&amp;gt; uncompressed_size : 24&lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;}&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
If the most significant bit of the first byte of the file is set, this is a multi-pass file and the remaining 7 bits are the number of passes to be processed recursively. If the &amp;lt;tt&amp;gt;multi_pass&amp;lt;/tt&amp;gt; flag is not set, we are only doing a single pass and the first byte is the compression type. The next three bytes make up the uncompressed size. If the &amp;lt;tt&amp;gt;multi_pass&amp;lt;/tt&amp;gt; flag was set, this is the final uncompressed size. When the &amp;lt;tt&amp;gt;multi_pass&amp;lt;/tt&amp;gt; flag is not set, this is the uncompressed size of the current pass. The remaining data is processed recursively. The &amp;lt;tt&amp;gt;compression_type&amp;lt;/tt&amp;gt; field decides how it is decoded.&lt;br /&gt;
&lt;br /&gt;
== Run length coding ==&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;struct&amp;lt;/span&amp;gt; RLE &amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;{&amp;lt;/span&amp;gt;&lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt; unknown&lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt; escape_length : 7&lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt; no_sequence : 1&lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt; escape_codes&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;[&amp;lt;/span&amp;gt;escape_length&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;]&amp;lt;/span&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt; data&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;[&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;hlC&amp;quot;&amp;gt;...&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;]&amp;lt;/span&amp;gt;&lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;}&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The RLE stage can itself have two passes if &amp;lt;tt&amp;gt;no_sequence&amp;lt;/tt&amp;gt; is not set. The first pass will then expand sequences of bytes in the data. &amp;lt;tt&amp;gt;escape_codes[0]&amp;lt;/tt&amp;gt; will mark the beginning and the end of a byte sequence. When the escape code is encountered in the data, the following bytes are considered a sequence until the escape code is hit again. After the end-marking escape code, a one byte length counter tells how many times the preceding byte sequence should be repeated in the output buffer. Because the escape code cannot itself be escaped, sequential byte runs can only be applied in files that have unused byte values to use as the first escape code.&lt;br /&gt;
&lt;br /&gt;
The main RLE pass is a traditional expansion of single-byte runs, but with a twist that allows for multiple types of escape codes. The escape code&#039;s position in the header&#039;s escape code list affects its properties. When the first escape code is encountered in the source buffer, the following byte has the number of repetitions, and the next byte will be copied that many times to the output buffer. When the third escape code is encountered, the number of repetitions is stored in the following &#039;&#039;two&#039;&#039; bytes as a 16-bit integer. Then the following byte is copied that many times. All other escape codes use its position in the escape code list as the number of repetitions, and have no additional counter bytes before the data byte to be repeated. Escape codes can themselves be escaped in single-byte runs by having them expanded to only one copy.&lt;br /&gt;
&lt;br /&gt;
All repetition counters have an off-by-one surplus, as the data byte itself counts as the first copy. For optimal compression, escape codes should be chosen from byte values that occur least frequently, or not at all, in the source data.&lt;br /&gt;
&lt;br /&gt;
=== RLE decoding optimisation ===&lt;br /&gt;
Escape codes are put in an &amp;lt;tt&amp;gt;escape[256]&amp;lt;/tt&amp;gt; array, where the code&#039;s byte value is the index and the escape code&#039;s position is the entry&#039;s value. This array is used to test incoming bytes for escape codes. Raw bytes will have the value 0, while other values corresponds to the escape code&#039;s property. This optimisation makes the decoding run O(1), as opposed to O(&#039;&#039;n&#039;&#039;), where &#039;&#039;n&#039;&#039; is the number of escape codes.&lt;br /&gt;
&lt;br /&gt;
== Huffman coding ==&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;struct&amp;lt;/span&amp;gt; Huffman &amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;{&amp;lt;/span&amp;gt;&lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt; tree_levels : 7&lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt; delta_coding : 1&lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt; symbols_per_level&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;[&amp;lt;/span&amp;gt;tree_levels&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;]&amp;lt;/span&amp;gt;&lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt; alphabet&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;[&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;SUM&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;(&amp;lt;/span&amp;gt;symbols_per_level&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;)&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;]&amp;lt;/span&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
     &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint16&amp;lt;/span&amp;gt; codes : var &amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;[&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;hlC&amp;quot;&amp;gt;...&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;]&amp;lt;/span&amp;gt;&lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;}&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Huffman coding uses a binary tree to store data. When Huffman codes are read, each bit tells which branch to take when traversing the tree. If a leaf node is hit, we have found the code&#039;s symbol and can proceed with the next code. Frequently used symbols have shorter paths and thus takes up fewer bits in the source file.&lt;br /&gt;
&lt;br /&gt;
The tree is stored by having two lists, one with symbols per level, and one with the alphabet. The alphabet is every possible symbol in the order they appear in the tree. The tree is built by going through each &amp;lt;tt&amp;gt;symbols_per_level&amp;lt;/tt&amp;gt;. If there are symbols at the current level, consume them from &amp;lt;tt&amp;gt;alphabet&amp;lt;/tt&amp;gt; and create a leaf nodes. If there are no symbols, and there still are more levels to create, proceed to create left and right children nodes for the next level.&lt;br /&gt;
&lt;br /&gt;
The remaining data is the Huffman codes. Bit by bit is read to find leaf nodes in the Huffman tree whose symbols are appended to the output buffer. This is repeated until the output buffer has reached &amp;lt;tt&amp;gt;uncompressed_size&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
The maximum Huffman tree height is 16. While the data format allows for up to 127 levels, Stunts&#039; decompression function uses arrays with a fixed capacity of 16 for its level offset table.&lt;br /&gt;
&lt;br /&gt;
=== Delta coding ===&lt;br /&gt;
If the flag for [https://en.wikipedia.org/wiki/Delta_encoding delta coding] is set, each symbol is treated as the difference from the previous output byte instead of an independent final value. The last byte written to the output buffer is remembered and added to the next expanded symbol. While regular Huffman coding assigns shorter codes to frequently occurring values, this delta variant assigns shorter codes to differences that occurs frequently. This feature is not used by any shipped files, but the code is present in all versions that implements Huffman decoding. One can speculate that delta coding was outperformed by RLE combined with regular Huffman coding, making delta coding unnecessary.&lt;br /&gt;
&lt;br /&gt;
=== Huffman decoding optimisations ===&lt;br /&gt;
==== Prefix table ====&lt;br /&gt;
With Huffman codes being paths in a binary tree, they have the property of being prefix-free, meaning that one leaf node&#039;s code cannot be the prefix of another node&#039;s code. This allows for a decoding optimisation technique known as &#039;&#039;prefix tables&#039;&#039; or &#039;&#039;Huffman tables&#039;&#039;. By creating arrays of symbols and code widths where the indices are the Huffman codes, the codes can be looked up directly without traversing the tree. Every array index for non-leaf nodes between two leaf node entries are filled with data for the preceding leaf node. This way there&#039;s no need to filter out bits that belong to the next Huffman code, at the expense of common symbols taking up multiple entries in the lookup table during decompression.&lt;br /&gt;
&lt;br /&gt;
Stunts utilises this optimisation for Huffman codes that are up to 8 bits long. The first byte of the code is checked in the &amp;lt;tt&amp;gt;widths[256]&amp;lt;/tt&amp;gt; array. If the code&#039;s width is 8 bits or less, the same code is looked up in the &amp;lt;tt&amp;gt;symbols[256]&amp;lt;/tt&amp;gt; array and written to the output buffer. To find the start of the next Huffman code, the source buffer is advanced by the code&#039;s bit width found in the &amp;lt;tt&amp;gt;widths&amp;lt;/tt&amp;gt; array.&lt;br /&gt;
&lt;br /&gt;
==== Offset table ====&lt;br /&gt;
As Stunts limits the prefix tables to 8 bit wide Huffman codes to save RAM, another novel optimisation is applied for codes that exceeds 8 bits. Prefixes for longer codes have the value &amp;lt;tt&amp;gt;0x40&amp;lt;/tt&amp;gt; in the &amp;lt;tt&amp;gt;widths&amp;lt;/tt&amp;gt; array, indicating that the current code is a prefix that needs further expansion. For this purpose Stunts uses two additional helper arrays: &amp;lt;tt&amp;gt;total_codes[tree_levels]&amp;lt;/tt&amp;gt;, which has the total number of leaf nodes that exists in the tree up to each level, and &amp;lt;tt&amp;gt;code_offsets[tree_levels]&amp;lt;/tt&amp;gt;, which for each level has a value that can be added to a code with the same level in order to get its index in the alphabet. This works because the codes are arranged [https://en.wikipedia.org/wiki/Canonical_Huffman_code canonically]. As a code&#039;s bit width corresponds to the code&#039;s level in the Huffman tree, the width can be used to compare the current code with the level&#039;s total by getting &amp;lt;tt&amp;gt;total_codes[current_width]&amp;lt;/tt&amp;gt; for each extra bit read. If the code is smaller than the total number of codes encountered, it is a leaf node, and we get the symbol by adding the level&#039;s code offset to the code with &amp;lt;tt&amp;gt;alphabet[code + code_offsets[width]]&amp;lt;/tt&amp;gt;. This is more laborious than the use of prefix tables for direct lookup, but it only applies to codes that are occurring less frequently in the input file.&lt;br /&gt;
&lt;br /&gt;
=== Version differences ===&lt;br /&gt;
The Huffman decompression in the game code of Stunts 1.0 differs from the one in its LOAD.EXE and later versions of the game. The Huffman codes are written with the least significant bit first, as opposed to the other versions that has the codes written with the opposite orientation. The game code of Stunts 1.0 also does not use the prefix tables, and the bit-stream orientation was likely changed with the introduction of this optimisation.&lt;/div&gt;</summary>
		<author><name>Dstien</name></author>
	</entry>
	<entry>
		<id>https://wiki.stunts.hu/index.php?title=Opponent_files&amp;diff=1771</id>
		<title>Opponent files</title>
		<link rel="alternate" type="text/html" href="https://wiki.stunts.hu/index.php?title=Opponent_files&amp;diff=1771"/>
		<updated>2010-02-20T23:55:04Z</updated>

		<summary type="html">&lt;p&gt;Dstien: /* Opponent animations */ Frame index list is NULL-terminated.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Data corresponding to the Stunts [[opponents]] is stored by a number of [[Resource file format|resource files]], namely sdosel.pvs and the multiple opp?win.pvs, opp?lose.pvs and opp?.pre. As denoted by their extensions, the opp?.pre files store control parameters and text data, while the .pvs files contain bitmaps. A vanilla installation of Stunts 1.1 uses compressed opp?.pre files, while Stunts 1.0 has them uncompressed, as opp?.res. The contents of each file will be described below, organized by function of the resources.&lt;br /&gt;
&lt;br /&gt;
==Opponent selection==&lt;br /&gt;
&lt;br /&gt;
All the images used for composing the opponent selection menu are within &#039;&#039;sdosel.pvs&#039;&#039;. Bitmap resources &#039;&#039;&#039;opp0&#039;&#039;&#039; to &#039;&#039;&#039;opp6&#039;&#039;&#039; are opponent portraits (opp0 is actually the chronometer for the time trial option); &#039;&#039;&#039;scrn&#039;&#039;&#039; and the auxiliary overlay &#039;&#039;&#039;clip&#039;&#039;&#039; form the background. Text for the opponent profiles is sourced from text resources in the &#039;&#039;opp?.pre&#039;&#039; (there are six of these, one for each opponent).&lt;br /&gt;
&lt;br /&gt;
==Opponent animations==&lt;br /&gt;
&lt;br /&gt;
{{sectstub}}&lt;br /&gt;
&lt;br /&gt;
Win/lose animations are made from individual bitmaps in &#039;&#039;opp?win.pvs&#039;&#039; or &#039;&#039;opp?lose.pvs&#039;&#039;. The bitmap resources are named &#039;&#039;&#039;op01&#039;&#039;&#039; to &#039;&#039;&#039;op08&#039;&#039;&#039; - the actual number of frames within a file varies from 3 to 8. The animations are controlled through simple, unstructured resources in &#039;&#039;&#039;opp?.pre&#039;&#039;&#039; named &#039;&#039;&#039;winn&#039;&#039;&#039; and &#039;&#039;&#039;lose&#039;&#039;&#039;. Each byte in these NULL-terminated resources is a numerical index to the op01 ... op08 bitmaps, and the overall sequence is the succession of frames.&lt;br /&gt;
&lt;br /&gt;
==Opponent performance==&lt;br /&gt;
&lt;br /&gt;
{{sectstub}}&lt;br /&gt;
&lt;br /&gt;
The primary adjustable parameters which determine opponent skills are maximum speeds for different track elements. These parameters are in an unstructured resource within &#039;&#039;opp?.pre&#039;&#039; called &#039;&#039;&#039;sped&#039;&#039;&#039;. sped is 15 bytes long for Stunts 1.0 and 16 bytes long for 1.1 . Each byte corresponds to the speed in mph for a track element, as described below:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Byte (in 1.1) !! Track element !! Observations&lt;br /&gt;
|-&lt;br /&gt;
| 1 - 3 || paved, dirt and icy road         || respectively&lt;br /&gt;
|-&lt;br /&gt;
| 4 - 6 || paved, dirt and icy small corner || respectively&lt;br /&gt;
|-&lt;br /&gt;
| 7 - 9 || paved, dirt and icy large corner || respectively&lt;br /&gt;
|-&lt;br /&gt;
| 10    || banked corner                                   || &#039;&#039;absent in 1.0&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
| 11    || bridge                                          ||&lt;br /&gt;
|-&lt;br /&gt;
| 12    || slalom                                          ||&lt;br /&gt;
|-&lt;br /&gt;
| 13    || cork u/d                                        ||&lt;br /&gt;
|-&lt;br /&gt;
| 14    || chicane                                         ||&lt;br /&gt;
|-&lt;br /&gt;
| 15    || loop                                            ||&lt;br /&gt;
|-&lt;br /&gt;
| 16    || cork l/r                                        ||&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
[[Opponent Blaster]], a [[Mark Nailwood]] program, allows for edition of sped parameter from Stunts 1.0 opp?.res files. The program can&#039;t open compressed opp?.pre files from 1.1 without prior unpacking with [[stunpack]]. Even after unpacking, the addition of the banked corner parameter and the reordering of the resource list in the 1.1 files means Opponent Blaster is unable to parse them correctly. In fact, it turns out that 1.0 and 1.1 opponent data files are not interchangeable at all.&lt;br /&gt;
&lt;br /&gt;
In addition to sped, opp?.pre also contains &#039;&#039;&#039;path&#039;&#039;&#039;, a much larger (186 bytes) numerical data resource which function is not yet understood. &lt;br /&gt;
&lt;br /&gt;
[[Category:Modding]]&lt;/div&gt;</summary>
		<author><name>Dstien</name></author>
	</entry>
	<entry>
		<id>https://wiki.stunts.hu/index.php?title=Category:Driving&amp;diff=1027</id>
		<title>Category:Driving</title>
		<link rel="alternate" type="text/html" href="https://wiki.stunts.hu/index.php?title=Category:Driving&amp;diff=1027"/>
		<updated>2008-11-11T12:59:33Z</updated>

		<summary type="html">&lt;p&gt;Dstien: Reverted edits by 78.46.197.81 (Talk); changed back to last version by Zaqrack&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Everything related to driving&lt;/div&gt;</summary>
		<author><name>Dstien</name></author>
	</entry>
	<entry>
		<id>https://wiki.stunts.hu/index.php?title=Resource_file_format&amp;diff=1007</id>
		<title>Resource file format</title>
		<link rel="alternate" type="text/html" href="https://wiki.stunts.hu/index.php?title=Resource_file_format&amp;diff=1007"/>
		<updated>2008-10-18T22:33:27Z</updated>

		<summary type="html">&lt;p&gt;Dstien: /* 3d shapes */ Corrections according to latest discoveries.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Stunts game data are stored in a common container format. Files of this format can hold multiple &#039;&#039;resources&#039;&#039;, blocks of data that may be of various types - text, bitmaps, sounds, etc. Resources are uniquely identified within each file solely by a 4-byte name. A resource container file can be encapsulated by [[Compression|compression]].&lt;br /&gt;
&lt;br /&gt;
This document focuses on [[Game versions#PC versions|BB Stunts 1.1]], but details described here may still—partly or wholly—cover other versions, or even other games developed by DSI at the time.&lt;br /&gt;
&lt;br /&gt;
==File names==&lt;br /&gt;
Different file name extensions are used to indicate the content of the files. Compressed files has &#039;&#039;&amp;quot;P&amp;quot;&#039;&#039; (packed) as the first letter of their extensions. Whether the game prefers raw or compressed files varies based on file type.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! File contents           !! Raw !! Compressed !! Preferred&lt;br /&gt;
|-&lt;br /&gt;
| Text and misc. settings || RES || PRE        || Raw&lt;br /&gt;
|-&lt;br /&gt;
| Bitmap images           || VSH || PVS        || Compressed&lt;br /&gt;
|-&lt;br /&gt;
| Icons                   || ESH || PES        || Compressed&lt;br /&gt;
|-&lt;br /&gt;
| 3d shapes               || 3SH || P3S        || Compressed&lt;br /&gt;
|-&lt;br /&gt;
| Music tracks            || KMS || PKM        || Raw&lt;br /&gt;
|-&lt;br /&gt;
| Instrument samples      || VCE || PVC        || Raw&lt;br /&gt;
|-&lt;br /&gt;
| Sound effects           || SFX || PSF        || Raw&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==Structure==&lt;br /&gt;
&lt;br /&gt;
The resource file header consists of two integer fields denoting the total length of the file and the number of resources contained. The following table of contents has a list of ids and a corresponding list of offsets into the remaining data section.&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlC&amp;quot;&amp;gt;// Header&amp;lt;/span&amp;gt;&lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint32&amp;lt;/span&amp;gt; fileLength&lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint16&amp;lt;/span&amp;gt; numResources&lt;br /&gt;
 &lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlC&amp;quot;&amp;gt;// Table of contents&amp;lt;/span&amp;gt;&lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;char&amp;lt;/span&amp;gt;   ids&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;[&amp;lt;/span&amp;gt;numResources&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;][&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;hlN&amp;quot;&amp;gt;4&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;]&amp;lt;/span&amp;gt;&lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint32&amp;lt;/span&amp;gt; offsets&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;[&amp;lt;/span&amp;gt;numResources&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;]&amp;lt;/span&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlC&amp;quot;&amp;gt;// Resource data&amp;lt;/span&amp;gt;&lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;char&amp;lt;/span&amp;gt;   data&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;[]&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Types==&lt;br /&gt;
Resource type can be determined by looking at the resource&#039;s id string and/or the source file name.&lt;br /&gt;
&lt;br /&gt;
===Plain text===&lt;br /&gt;
Text resources are null-terminated [http://en.wikipedia.org/wiki/C_string C strings] found in &amp;lt;tt&amp;gt;RES&amp;lt;/tt&amp;gt;/&amp;lt;tt&amp;gt;PRE&amp;lt;/tt&amp;gt; files. Strings can contain non-alphanumeric codes used by the game to achieve certain effects. Most prominent is the &#039;&#039;&amp;quot;]&amp;quot;&#039;&#039; (right square bracket) used to represent [http://en.wikipedia.org/wiki/Newline newline] in multi-line text.&lt;br /&gt;
&lt;br /&gt;
===Bitmap images===&lt;br /&gt;
[[Image:Stunts-pal-vga.png|128px|right|thumb|VGA palette used by bitmap images. Value 255 is transparency.]]&lt;br /&gt;
Bitmaps are images with 8-bit color depth using a [[:Image:Stunts-pal-vga.png|fixed palette]] in VGA mode. Special bitmaps using the naming scheme &amp;lt;tt&amp;gt;!cg_&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;!eg_&amp;lt;/tt&amp;gt; provides color mapping for graphics modes with fewer available colors.&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint16&amp;lt;/span&amp;gt; width&lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint16&amp;lt;/span&amp;gt; height&lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint16&amp;lt;/span&amp;gt; unknown1&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;[&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;hlN&amp;quot;&amp;gt;4&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;]&amp;lt;/span&amp;gt;&lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt;  unknown2&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;[&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;hlN&amp;quot;&amp;gt;4&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;]&amp;lt;/span&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt;  image&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;[&amp;lt;/span&amp;gt;width &amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;*&amp;lt;/span&amp;gt; height&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;]&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Parts of this structure are not fully understood. &amp;lt;tt&amp;gt;unknown1&amp;lt;/tt&amp;gt; appears to be related to Stunts&#039; internal memory management. &amp;lt;tt&amp;gt;unknown2&amp;lt;/tt&amp;gt; seems to affect how image pixels are organized in compressed resource files, likely to gain more effective [http://en.wikipedia.org/wiki/Run-length_encoding run-length compression]. Images with pixel data stored as continuous horizontal lines has &amp;lt;tt&amp;gt;unknown2&amp;lt;/tt&amp;gt; set to &amp;lt;code&amp;gt;{ 0x1, 0x2, 0x4, 0x8 }&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
{{sectstub}}&lt;br /&gt;
&lt;br /&gt;
===Icons===&lt;br /&gt;
{{sectstub}}&lt;br /&gt;
&lt;br /&gt;
===3d shapes===&lt;br /&gt;
Shapes are composed of a vertex list and a list of primitives. Primitives are basic shapes that can have different types, such as polygons or wheels. Depending on the type it contains a number of indices into the vertex list needed to draw the shape, color variations and some rendering hints. Stunts&#039; coordinate system use 16-bit signed integers, making the resolution relative to the scale of the model. Shapes presented in the car selection screen are more detailed than in-game shapes, thus requiring larger scaling. By comparing the car shapes to their real-life originals 1 meter in-game corresponds to 20 units, making each track tile roughly 50 meters wide.&lt;br /&gt;
&lt;br /&gt;
Due to the counter header fields being stored in single bytes, the total amount of vertices and primitives are limited to 255 per shape.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Main strcture&#039;&#039;&#039;&lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt;     numVertices&lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt;     numPrimitives&lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt;     numPaintJobs&lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt;     reserved &amp;lt;span class=&amp;quot;hlC&amp;quot;&amp;gt;// Always == 0&amp;lt;/span&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
 VERTEX    vertices&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;[&amp;lt;/span&amp;gt;numVertices&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;]&amp;lt;/span&amp;gt;&lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint32&amp;lt;/span&amp;gt;    cullHorizontal&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;[&amp;lt;/span&amp;gt;numPrimitives&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;]&amp;lt;/span&amp;gt;&lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint32&amp;lt;/span&amp;gt;    cullVertical&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;[&amp;lt;/span&amp;gt;numPrimitives&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;]&amp;lt;/span&amp;gt;&lt;br /&gt;
 PRIMITIVE primitives&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;[&amp;lt;/span&amp;gt;numPrimitives&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;]&amp;lt;/span&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt;     terminate&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;[&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;hlC&amp;quot;&amp;gt;...&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;]&amp;lt;/span&amp;gt; &amp;lt;span class=&amp;quot;hlC&amp;quot;&amp;gt;// 1-3 NULL-bytes for data alignment&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Additional structures&#039;&#039;&#039;&lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;struct&amp;lt;/span&amp;gt; VERTEX &amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;{&amp;lt;/span&amp;gt;&lt;br /&gt;
   &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;int16&amp;lt;/span&amp;gt; x&lt;br /&gt;
   &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;int16&amp;lt;/span&amp;gt; y&lt;br /&gt;
   &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;int16&amp;lt;/span&amp;gt; z&lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;}&amp;lt;/span&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;struct&amp;lt;/span&amp;gt; PRIMITIVE &amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;{&amp;lt;/span&amp;gt;&lt;br /&gt;
   &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt; type&lt;br /&gt;
   &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt; flags&lt;br /&gt;
   &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt; materials&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;[&amp;lt;/span&amp;gt;numPaintJobs&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;]&amp;lt;/span&amp;gt;&lt;br /&gt;
   &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt; indices&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;[&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;hlC&amp;quot;&amp;gt;...&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;]&amp;lt;/span&amp;gt; &amp;lt;span class=&amp;quot;hlC&amp;quot;&amp;gt;// Size depends on type.&amp;lt;/span&amp;gt;&lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;}&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Primitive types&#039;&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Primitive type !! Vertex indices needed !! Description&lt;br /&gt;
|-&lt;br /&gt;
| 1              || 1              || Particle, 1 pixel&lt;br /&gt;
|-&lt;br /&gt;
| 2              || 2              || Line segment, 1 pixel width&lt;br /&gt;
|-&lt;br /&gt;
| 3–10           || 3–10           || Polygon, &#039;&#039;n&#039;&#039; sides&lt;br /&gt;
|-&lt;br /&gt;
| 11             || 2              || Sphere (center + ~(radius / 2)&lt;br /&gt;
|-&lt;br /&gt;
| 12             || 6              || Wheel&lt;br /&gt;
|-&lt;br /&gt;
| *              || 0              || Ignored&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Primitive flags&#039;&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Flag          !! Name&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;0x01&amp;lt;/tt&amp;gt; || Two-sided&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;0x02&amp;lt;/tt&amp;gt; || Z-Bias&lt;br /&gt;
|-&lt;br /&gt;
| *    || Ignored&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Culling data masks&#039;&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Flag                !! Description&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;0xFFFE0000&amp;lt;/tt&amp;gt; || Angle ranges, positive direction&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;0x0001FFFC&amp;lt;/tt&amp;gt; || Angle ranges, negative direction&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;0x00000001&amp;lt;/tt&amp;gt; || Unknown flag 1&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;0x00000002&amp;lt;/tt&amp;gt; || Unknown flag 2&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
For car body and track element shapes the first eight vertices are reserved for the corner vertices of the shape&#039;s bound box, used to cull entire shapes located outside the view frustum.&lt;br /&gt;
&lt;br /&gt;
[[Image:Wheel_Primitive_Anatomy.png|200px|right|thumb|Anatomy of a wheel shape primitive.]]&lt;br /&gt;
The first three vertices in a wheel primitive marks the center, tire radius and rim radius for the inner wheel-half facing the vehicle. The last three vertices does the same, in the same order, for the outer half of the wheel. Directions may not matter, the vertex locations are used to measure distances. This rule applies to the sphere primitive as well.&lt;br /&gt;
&lt;br /&gt;
Wheel transformations are performed on fixed vertex positions. Since the first eight vertices of &amp;lt;tt&amp;gt;car[0-2]&amp;lt;/tt&amp;gt; shapes are occupied by the bound box, vertices 9-14 and 15-20 are front wheels. Misplaced wheel vertices will lead to corrupted shape rendering.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;tt&amp;gt;flags&amp;lt;/tt&amp;gt; in the &amp;lt;tt&amp;gt;PRIMITIVE&amp;lt;/tt&amp;gt; structure are used for two-sided polygons (disable [http://en.wikipedia.org/wiki/Back-face_culling back-face culling]) and to enable Z-bias in order to resolve [http://en.wikipedia.org/wiki/Z-fighting Z-fighting].&lt;br /&gt;
&lt;br /&gt;
[[Shape materials|Materials]] are indices into a permanent, internal game structure and are assigned per-primitive. Cars can have multiple paint jobs, every primitive in the shape must set a material for each color scheme.&lt;br /&gt;
&lt;br /&gt;
Each primitive has two 32-bit culling data fields to determine visibility. A culling data field holds angular visibility in positive and negative direction using 15 bits each. One bit corresponds to 1/15th of a full circle and the bits can be set in any combination. The two least significant bits are reserved for two currently unknown flags.&lt;br /&gt;
&lt;br /&gt;
A shape resource must be terminated with NULL-bytes. The number of bytes needed is not known, but padding three NULL-bytes has proven to work regardless of resource size or byte alignment. Failing to meet this requirement will lead to obscure rendering artifacts.&lt;br /&gt;
&lt;br /&gt;
{{sectstub}}&lt;br /&gt;
&lt;br /&gt;
===Car parameters===&lt;br /&gt;
{{main|Car parameters}}&lt;br /&gt;
Numerical car*.res parameters are stored in a 776 bytes sized resource identified as &#039;&#039;simd&#039;&#039;. Most data in simd is stored as signed 16-bit integers. Noteworthy exceptions include number of gears, gear ratios, torque curve data and bitmap coordinates for dashboard instruments - which are unsigned 8-bit integers. Organization and function of the parameters are outside the scope of this article; the reader should consult the main article on the topic for further information. &lt;br /&gt;
{{sectstub}}&lt;br /&gt;
&lt;br /&gt;
===Opponent parameters===&lt;br /&gt;
{{sectstub}}&lt;br /&gt;
&lt;br /&gt;
===Music tracks===&lt;br /&gt;
{{sectstub}}&lt;br /&gt;
&lt;br /&gt;
===Instrument samples===&lt;br /&gt;
{{sectstub}}&lt;br /&gt;
&lt;br /&gt;
===Sound effects===&lt;br /&gt;
{{sectstub}}&lt;br /&gt;
&lt;br /&gt;
==Tools==&lt;br /&gt;
* [[stressed]] - Stunts/4D [Sports] Driving resource editor [http://stuntstools.googlecode.com/].&lt;br /&gt;
&lt;br /&gt;
[[Category:Game]]&lt;/div&gt;</summary>
		<author><name>Dstien</name></author>
	</entry>
	<entry>
		<id>https://wiki.stunts.hu/index.php?title=Resource_file_format&amp;diff=843</id>
		<title>Resource file format</title>
		<link rel="alternate" type="text/html" href="https://wiki.stunts.hu/index.php?title=Resource_file_format&amp;diff=843"/>
		<updated>2008-06-28T17:23:30Z</updated>

		<summary type="html">&lt;p&gt;Dstien: /* 3d shapes */ Unit scale&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Stunts game data are stored in a common container format. Files of this format can hold multiple &#039;&#039;resources&#039;&#039;, blocks of data that may be of various types - text, bitmaps, sounds, etc. Resources are uniquely identified within each file solely by a 4-byte name. A resource container file can be encapsulated by [[Compression|compression]].&lt;br /&gt;
&lt;br /&gt;
This document focuses on [[Game versions#PC versions|BB Stunts 1.1]], but details described here may still—partly or wholly—cover other versions, or even other games developed by DSI at the time.&lt;br /&gt;
&lt;br /&gt;
==File names==&lt;br /&gt;
Different file name extensions are used to indicate the content of the files. Compressed files has &#039;&#039;&amp;quot;P&amp;quot;&#039;&#039; (packed) as the first letter of their extensions. Whether the game prefers raw or compressed files varies based on file type.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! File contents           !! Raw !! Compressed !! Preferred&lt;br /&gt;
|-&lt;br /&gt;
| Text and misc. settings || RES || PRE        || Raw&lt;br /&gt;
|-&lt;br /&gt;
| Bitmap images           || VSH || PVS        || Compressed&lt;br /&gt;
|-&lt;br /&gt;
| Icons                   || ESH || PES        || Compressed&lt;br /&gt;
|-&lt;br /&gt;
| 3d shapes               || 3SH || P3S        || Compressed&lt;br /&gt;
|-&lt;br /&gt;
| Music tracks            || KMS || PKM        || Raw&lt;br /&gt;
|-&lt;br /&gt;
| Instrument samples      || VCE || PVC        || Raw&lt;br /&gt;
|-&lt;br /&gt;
| Sound effects           || SFX || PSF        || Raw&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==Structure==&lt;br /&gt;
&lt;br /&gt;
The resource file header consists of two integer fields denoting the total length of the file and the number of resources contained. The following table of contents has a list of ids and a corresponding list of offsets into the remaining data section.&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlC&amp;quot;&amp;gt;// Header&amp;lt;/span&amp;gt;&lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint32&amp;lt;/span&amp;gt; fileLength&lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint16&amp;lt;/span&amp;gt; numResources&lt;br /&gt;
 &lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlC&amp;quot;&amp;gt;// Table of contents&amp;lt;/span&amp;gt;&lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;char&amp;lt;/span&amp;gt;   ids&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;[&amp;lt;/span&amp;gt;numResources&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;][&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;hlN&amp;quot;&amp;gt;4&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;]&amp;lt;/span&amp;gt;&lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint32&amp;lt;/span&amp;gt; offsets&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;[&amp;lt;/span&amp;gt;numResources&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;]&amp;lt;/span&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlC&amp;quot;&amp;gt;// Resource data&amp;lt;/span&amp;gt;&lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;char&amp;lt;/span&amp;gt;   data&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;[]&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Types==&lt;br /&gt;
Resource type can be determined by looking at the resource&#039;s id string and/or the source file name.&lt;br /&gt;
&lt;br /&gt;
===Plain text===&lt;br /&gt;
Text resources are null-terminated [http://en.wikipedia.org/wiki/C_string C strings] found in &amp;lt;tt&amp;gt;RES&amp;lt;/tt&amp;gt;/&amp;lt;tt&amp;gt;PRE&amp;lt;/tt&amp;gt; files. Strings can contain non-alphanumeric codes used by the game to achieve certain effects. Most prominent is the &#039;&#039;&amp;quot;]&amp;quot;&#039;&#039; (right square bracket) used to represent [http://en.wikipedia.org/wiki/Newline newline] in multi-line text.&lt;br /&gt;
&lt;br /&gt;
===Bitmap images===&lt;br /&gt;
[[Image:Stunts-pal-vga.png|128px|right|thumb|VGA palette used by bitmap images. Value 255 is transparency.]]&lt;br /&gt;
Bitmaps are images with 8-bit color depth using a [[:Image:Stunts-pal-vga.png|fixed palette]] in VGA mode. Special bitmaps using the naming scheme &amp;lt;tt&amp;gt;!cg_&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;!eg_&amp;lt;/tt&amp;gt; provides color mapping for graphics modes with fewer available colors.&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint16&amp;lt;/span&amp;gt; width&lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint16&amp;lt;/span&amp;gt; height&lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint16&amp;lt;/span&amp;gt; unknown1&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;[&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;hlN&amp;quot;&amp;gt;4&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;]&amp;lt;/span&amp;gt;&lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt;  unknown2&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;[&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;hlN&amp;quot;&amp;gt;4&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;]&amp;lt;/span&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt;  image&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;[&amp;lt;/span&amp;gt;width &amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;*&amp;lt;/span&amp;gt; height&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;]&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Parts of this structure are not fully understood. &amp;lt;tt&amp;gt;unknown1&amp;lt;/tt&amp;gt; appears to be related to Stunts&#039; internal memory management. &amp;lt;tt&amp;gt;unknown2&amp;lt;/tt&amp;gt; seems to affect how image pixels are organized in compressed resource files, likely to gain more effective [http://en.wikipedia.org/wiki/Run-length_encoding run-length compression]. Images with pixel data stored as continuous horizontal lines has &amp;lt;tt&amp;gt;unknown2&amp;lt;/tt&amp;gt; set to &amp;lt;code&amp;gt;{ 0x1, 0x2, 0x4, 0x8 }&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
{{sectstub}}&lt;br /&gt;
&lt;br /&gt;
===Icons===&lt;br /&gt;
{{sectstub}}&lt;br /&gt;
&lt;br /&gt;
===3d shapes===&lt;br /&gt;
Shapes are composed of a vertex list and a list of primitives. Primitives are basic shapes that can have different types, such as polygons or wheels. Depending on the type it contains a number of indices into the vertex list needed to draw the shape, color variations and some rendering hints. Stunts&#039; coordinate system use 16-bit signed integers, making the resolution relative to the scale of the model. Shapes presented in the car selection screen are more detailed than in-game shapes, thus requiring larger scaling. By comparing the car shapes to their real-life originals 1 meter in-game corresponds to 20 units, making each track tile roughly 50 meters wide.&lt;br /&gt;
&lt;br /&gt;
Due to the counter header fields being stored in single bytes, the total amount of vertices and primitives are limited to 255 per shape.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Main strcture&#039;&#039;&#039;&lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt;     numVertices&lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt;     numPrimitives&lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt;     numPaintJobs&lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt;     reserved &amp;lt;span class=&amp;quot;hlC&amp;quot;&amp;gt;// Always == 0&amp;lt;/span&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
 VERTEX    vertices&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;[&amp;lt;/span&amp;gt;numVertices&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;]&amp;lt;/span&amp;gt;&lt;br /&gt;
 UNKNOWN   unknowns&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;[&amp;lt;/span&amp;gt;numPrimitives&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;]&amp;lt;/span&amp;gt;&lt;br /&gt;
 PRIMITIVE primitives&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;[&amp;lt;/span&amp;gt;numPrimitives&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;]&amp;lt;/span&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt;     terminate&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;[&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;hlC&amp;quot;&amp;gt;...&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;]&amp;lt;/span&amp;gt; &amp;lt;span class=&amp;quot;hlC&amp;quot;&amp;gt;// One or two NULL-bytes to make resource size divisible by 2.&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Additional structures&#039;&#039;&#039;&lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;struct&amp;lt;/span&amp;gt; VERTEX &amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;{&amp;lt;/span&amp;gt;&lt;br /&gt;
   &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;int16&amp;lt;/span&amp;gt; x&lt;br /&gt;
   &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;int16&amp;lt;/span&amp;gt; y&lt;br /&gt;
   &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;int16&amp;lt;/span&amp;gt; z&lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;}&amp;lt;/span&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;struct&amp;lt;/span&amp;gt; UNKNOWN &amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;{&amp;lt;/span&amp;gt;&lt;br /&gt;
   &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;int8&amp;lt;/span&amp;gt; data&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;[&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;hlN&amp;quot;&amp;gt;8&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;]&amp;lt;/span&amp;gt;&lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;}&amp;lt;/span&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;struct&amp;lt;/span&amp;gt; PRIMITIVE &amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;{&amp;lt;/span&amp;gt;&lt;br /&gt;
   &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt; type&lt;br /&gt;
   &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt; depthIndex&lt;br /&gt;
   &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt; materials&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;[&amp;lt;/span&amp;gt;numPaintJobs&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;]&amp;lt;/span&amp;gt;&lt;br /&gt;
   &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt; indices&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;[&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;hlC&amp;quot;&amp;gt;...&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;]&amp;lt;/span&amp;gt; &amp;lt;span class=&amp;quot;hlC&amp;quot;&amp;gt;// Size depends on type.&amp;lt;/span&amp;gt;&lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;}&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Primitive types&#039;&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Primitive type !! Vertex indices needed !! Description&lt;br /&gt;
|-&lt;br /&gt;
| 1              || 1              || Particle, 1 pixel&lt;br /&gt;
|-&lt;br /&gt;
| 2              || 2              || Line segment, 1 pixel width&lt;br /&gt;
|-&lt;br /&gt;
| 3–10           || 3–10           || Polygon, &#039;&#039;n&#039;&#039; sides&lt;br /&gt;
|-&lt;br /&gt;
| 11             || 2              || Sphere (center + ~(radius / 2)&lt;br /&gt;
|-&lt;br /&gt;
| 12             || 6              || Wheel&lt;br /&gt;
|-&lt;br /&gt;
| *              || 0              || Ignored&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
For car body and track element shapes the first eight vertices are reserved for the corner vertices of the shape&#039;s bound box, used to cull entire shapes located outside the view frustum.&lt;br /&gt;
&lt;br /&gt;
[[Image:Wheel_Primitive_Anatomy.png|200px|right|thumb|Anatomy of a wheel shape primitive.]]&lt;br /&gt;
The first three vertices in a wheel primitive marks the center, tire radius and rim radius for the inner wheel-half facing the vehicle. The last three vertices does the same, in the same order, for the outer half of the wheel. Directions does not matter, the vertex locations are only used to measure distances. This rule applies to the sphere primitive as well.&lt;br /&gt;
&lt;br /&gt;
Wheel transformations are performed on fixed vertex positions. Since the first eight vertices of &amp;lt;tt&amp;gt;car[0-2]&amp;lt;/tt&amp;gt; shapes are occupied by the bound box, vertices 9-14 and 15-20 are front wheels. Misplaced wheel vertices will lead to corrupted shape rendering.&lt;br /&gt;
&lt;br /&gt;
The value &amp;lt;tt&amp;gt;depthIndex&amp;lt;/tt&amp;gt; in the &amp;lt;tt&amp;gt;PRIMITIVE&amp;lt;/tt&amp;gt; structure is used to override the game&#039;s depth clipping in order to avoid flickering when several primitives are being drawn at the exact same depth. Higher value gives the primitive higher precedence.&lt;br /&gt;
&lt;br /&gt;
[[Shape materials|Materials]] are indices into a permanent, internal game structure and are assigned per-primitive. Cars can have multiple paint jobs, every primitive in the shape must set a material for each color scheme.&lt;br /&gt;
&lt;br /&gt;
Experimentation has revealed that &amp;lt;tt&amp;gt;UNKNOWN&amp;lt;/tt&amp;gt; data at least partially controls occlusion culling on primitive level. How, and exactly which parts of this structure does what has yet to be understood.&lt;br /&gt;
&lt;br /&gt;
A shape resource must be terminated with a NULL-byte and the size must be divisible by two, hence two NULL-bytes are needed to terminate and pad resources with an even number of bytes. Failing to meet this requirement will lead to obscure rendering artifacts.&lt;br /&gt;
&lt;br /&gt;
{{sectstub}}&lt;br /&gt;
&lt;br /&gt;
===Car parameters===&lt;br /&gt;
{{main|Car parameters}}&lt;br /&gt;
Numerical car*.res parameters are stored in a 776 bytes sized resource identified as &#039;&#039;simd&#039;&#039;. Most data in simd is stored as signed 16-bit integers. Noteworthy exceptions include number of gears, gear ratios, torque curve data and bitmap coordinates for dashboard instruments - which are unsigned 8-bit integers. Organization and function of the parameters are outside the scope of this article; the reader should consult the main article on the topic for further information. &lt;br /&gt;
{{sectstub}}&lt;br /&gt;
&lt;br /&gt;
===Opponent parameters===&lt;br /&gt;
{{sectstub}}&lt;br /&gt;
&lt;br /&gt;
===Music tracks===&lt;br /&gt;
{{sectstub}}&lt;br /&gt;
&lt;br /&gt;
===Instrument samples===&lt;br /&gt;
{{sectstub}}&lt;br /&gt;
&lt;br /&gt;
===Sound effects===&lt;br /&gt;
{{sectstub}}&lt;br /&gt;
&lt;br /&gt;
==Tools==&lt;br /&gt;
* [[stressed]] - Stunts/4D [Sports] Driving resource editor [http://stuntstools.googlecode.com/].&lt;br /&gt;
&lt;br /&gt;
[[Category:Game]]&lt;/div&gt;</summary>
		<author><name>Dstien</name></author>
	</entry>
	<entry>
		<id>https://wiki.stunts.hu/index.php?title=User:Dstien&amp;diff=838</id>
		<title>User:Dstien</title>
		<link rel="alternate" type="text/html" href="https://wiki.stunts.hu/index.php?title=User:Dstien&amp;diff=838"/>
		<updated>2008-06-22T15:04:21Z</updated>

		<summary type="html">&lt;p&gt;Dstien: Wiping user page&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;tt&amp;gt;Hello, world!&amp;lt;/tt&amp;gt;&lt;/div&gt;</summary>
		<author><name>Dstien</name></author>
	</entry>
	<entry>
		<id>https://wiki.stunts.hu/index.php?title=Replay_Handling&amp;diff=837</id>
		<title>Replay Handling</title>
		<link rel="alternate" type="text/html" href="https://wiki.stunts.hu/index.php?title=Replay_Handling&amp;diff=837"/>
		<updated>2008-06-22T15:00:59Z</updated>

		<summary type="html">&lt;p&gt;Dstien: Pipsqueak wikilink&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;A greatly helpful rule in online tournaments, which allows [[Pipsqueak|pipsqueaks]] to simply rewind the replay after a crash, or running off the road, and continue driving from some seconds earlier. This way you can not enter your name in Stunts&#039; internal highscore table, but your final saved replay will be valid for online competitions. RH allows pipsqueaks to save a lot of time, achieve better results, and do insane stunts.   &lt;br /&gt;
There is an endless debate on RH in the community, whether it&#039;s a good thing, or not, but as there is no way to proof (without the usage of extrenal tools) whether a pipsqueak used RH or not, it&#039;s allowed by default.&lt;br /&gt;
&lt;br /&gt;
== See Also ==&lt;br /&gt;
&lt;br /&gt;
[[NoRH]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Driving]]&lt;/div&gt;</summary>
		<author><name>Dstien</name></author>
	</entry>
	<entry>
		<id>https://wiki.stunts.hu/index.php?title=Time_hiding&amp;diff=836</id>
		<title>Time hiding</title>
		<link rel="alternate" type="text/html" href="https://wiki.stunts.hu/index.php?title=Time_hiding&amp;diff=836"/>
		<updated>2008-06-22T15:00:02Z</updated>

		<summary type="html">&lt;p&gt;Dstien: Pipsqueak wikilink&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;A [[Pipsqueak|pipsqueak]] having a really fast, winning replay, but not sending it, only replays where he slows down at the end, reaching the pole position only with some milliseconds is called a time hider. Altough time hiding is slightly unethical, it&#039;s a key method for winning a track of hard battles.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Competition]]&lt;/div&gt;</summary>
		<author><name>Dstien</name></author>
	</entry>
	<entry>
		<id>https://wiki.stunts.hu/index.php?title=Talk:Game_versions&amp;diff=832</id>
		<title>Talk:Game versions</title>
		<link rel="alternate" type="text/html" href="https://wiki.stunts.hu/index.php?title=Talk:Game_versions&amp;diff=832"/>
		<updated>2008-06-19T19:24:39Z</updated>

		<summary type="html">&lt;p&gt;Dstien: Reply&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;If somebody knows how to avoid the PC9801 box pictures to be next to FM Towns box pictures, please correct it. ;-)&lt;br /&gt;
I tried to put images in the middle of the text, but it&#039;s not enough. I also couldn&#039;t put the 3 images in one line. {{unsigned|Krys Toff|16:59, 19 June 2008 (CEST)}}&lt;br /&gt;
:Added an example of the &amp;lt;tt&amp;gt;&amp;lt;nowiki&amp;gt;&amp;lt;gallery&amp;gt;&amp;lt;/nowiki&amp;gt;&amp;lt;/tt&amp;gt; tag. Forgot to log in. —[[User:Dstien|dstien]] 21:24, 19 June 2008 (CEST)&lt;/div&gt;</summary>
		<author><name>Dstien</name></author>
	</entry>
	<entry>
		<id>https://wiki.stunts.hu/index.php?title=Stunts_Wiki_talk:Cascading_protected_pages&amp;diff=750</id>
		<title>Stunts Wiki talk:Cascading protected pages</title>
		<link rel="alternate" type="text/html" href="https://wiki.stunts.hu/index.php?title=Stunts_Wiki_talk:Cascading_protected_pages&amp;diff=750"/>
		<updated>2008-05-13T23:50:00Z</updated>

		<summary type="html">&lt;p&gt;Dstien: Reply&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;How do you protect pages to be used by spam bots ? And how do you delete spam posts ? I saw these spam posts but didn&#039;t know how to delete them... &amp;lt;small&amp;gt;—Preceding [[Wikipedia:Wikipedia:Signatures|unsigned]] comment added by [[User:Krys Toff|Krys Toff]] ([[User talk:Krys Toff|talk]] • [[Special:Contributions/Krys Toff|contribs]]) 23:57, 13 May 2008 (CEST)&amp;lt;/small&amp;gt;&lt;br /&gt;
:Users with sysop privileges[http://wiki.stunts.hu/index.php/Special:Listusers?group=sysop] get extra options in the wiki interface to delete and protect pages, and block users. The bots weren&#039;t able to defeat the CAPTCHA, but kept creating [[Index.php]] anyway without including external links, so I protected it. Let&#039;s see if it ends here... —[[User:Dstien|dstien]] 01:50, 14 May 2008 (CEST)&lt;/div&gt;</summary>
		<author><name>Dstien</name></author>
	</entry>
	<entry>
		<id>https://wiki.stunts.hu/index.php?title=Stunts_Wiki:Cascading_protected_pages&amp;diff=748</id>
		<title>Stunts Wiki:Cascading protected pages</title>
		<link rel="alternate" type="text/html" href="https://wiki.stunts.hu/index.php?title=Stunts_Wiki:Cascading_protected_pages&amp;diff=748"/>
		<updated>2008-05-13T19:26:52Z</updated>

		<summary type="html">&lt;p&gt;Dstien: Protected &amp;quot;Stunts Wiki:Cascading protected pages&amp;quot;: Protect all included pages. [edit=sysop:move=sysop] [cascading]&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;* {{:Index.php}}&lt;/div&gt;</summary>
		<author><name>Dstien</name></author>
	</entry>
	<entry>
		<id>https://wiki.stunts.hu/index.php?title=Stunts_Wiki:Cascading_protected_pages&amp;diff=747</id>
		<title>Stunts Wiki:Cascading protected pages</title>
		<link rel="alternate" type="text/html" href="https://wiki.stunts.hu/index.php?title=Stunts_Wiki:Cascading_protected_pages&amp;diff=747"/>
		<updated>2008-05-13T19:25:01Z</updated>

		<summary type="html">&lt;p&gt;Dstien: Protect non-existing pages.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;* {{:Index.php}}&lt;/div&gt;</summary>
		<author><name>Dstien</name></author>
	</entry>
	<entry>
		<id>https://wiki.stunts.hu/index.php?title=Shape_materials&amp;diff=743</id>
		<title>Shape materials</title>
		<link rel="alternate" type="text/html" href="https://wiki.stunts.hu/index.php?title=Shape_materials&amp;diff=743"/>
		<updated>2008-05-05T23:17:13Z</updated>

		<summary type="html">&lt;p&gt;Dstien: Added VGA palette indices for nifty sorting.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;3d shapes refers to a predefined set of materials. A material defines the appearance of a polygon with a color and a pattern. Most materials are opaque colors, while some have see-through patterns. Multiple polygons with different material patterns can be layered to achieve certain effects, such as multi-colored grilles and lights.&lt;br /&gt;
&lt;br /&gt;
==Materials==&lt;br /&gt;
{| class=&amp;quot;wikitable sortable&amp;quot;&lt;br /&gt;
! # !! Hex # !! Pattern        !! Color                                                    !! Pal # !! Name !! Comment&lt;br /&gt;
|-&lt;br /&gt;
|   0 ||   0 || Opaque         || &amp;lt;span style=&amp;quot;color:#000000&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;000000&amp;lt;/tt&amp;gt; ||   0 || Black&lt;br /&gt;
|-&lt;br /&gt;
|   1 ||   1 || Opaque         || &amp;lt;span style=&amp;quot;color:#0000A8&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;0000A8&amp;lt;/tt&amp;gt; ||   1 || Blue&lt;br /&gt;
|-&lt;br /&gt;
|   2 ||   2 || Opaque         || &amp;lt;span style=&amp;quot;color:#00A800&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;00A800&amp;lt;/tt&amp;gt; ||   2 || Green&lt;br /&gt;
|-&lt;br /&gt;
|   3 ||   3 || Opaque         || &amp;lt;span style=&amp;quot;color:#00A8A8&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;00A8A8&amp;lt;/tt&amp;gt; ||   3&lt;br /&gt;
|-&lt;br /&gt;
|   4 ||   4 || Opaque         || &amp;lt;span style=&amp;quot;color:#A80000&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;A80000&amp;lt;/tt&amp;gt; ||   4 || || Highway light / cork l/r wall&lt;br /&gt;
|-&lt;br /&gt;
|   5 ||   5 || Opaque         || &amp;lt;span style=&amp;quot;color:#A800A8&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;A800A8&amp;lt;/tt&amp;gt; ||   5&lt;br /&gt;
|-&lt;br /&gt;
|   6 ||   6 || Opaque         || &amp;lt;span style=&amp;quot;color:#A85400&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;A85400&amp;lt;/tt&amp;gt; ||   6 || || Barn roof&lt;br /&gt;
|-&lt;br /&gt;
|   7 ||   7 || Opaque         || &amp;lt;span style=&amp;quot;color:#A8A8A8&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;A8A8A8&amp;lt;/tt&amp;gt; ||   7 || || Gas station doors&lt;br /&gt;
|-&lt;br /&gt;
|   8 ||   8 || Opaque         || &amp;lt;span style=&amp;quot;color:#545454&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;545454&amp;lt;/tt&amp;gt; ||   8&lt;br /&gt;
|-&lt;br /&gt;
|   9 ||   9 || Opaque         || &amp;lt;span style=&amp;quot;color:#5454FC&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;5454FC&amp;lt;/tt&amp;gt; ||   9&lt;br /&gt;
|-&lt;br /&gt;
|  10 ||   A || Opaque         || &amp;lt;span style=&amp;quot;color:#54FC54&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;54FC54&amp;lt;/tt&amp;gt; ||  10 || || Tree (pine)&lt;br /&gt;
|-&lt;br /&gt;
|  11 ||   B || Opaque         || &amp;lt;span style=&amp;quot;color:#54FCFC&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;54FCFC&amp;lt;/tt&amp;gt; ||  11&lt;br /&gt;
|-&lt;br /&gt;
|  12 ||   C || Opaque         || &amp;lt;span style=&amp;quot;color:#FC5454&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;FC5454&amp;lt;/tt&amp;gt; ||  12 || || Highway split light&lt;br /&gt;
|-&lt;br /&gt;
|  13 ||   D || Opaque         || &amp;lt;span style=&amp;quot;color:#FC54FC&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;FC54FC&amp;lt;/tt&amp;gt; ||  13&lt;br /&gt;
|-&lt;br /&gt;
|  14 ||   E || Opaque         || &amp;lt;span style=&amp;quot;color:#FCFC54&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;FCFC54&amp;lt;/tt&amp;gt; ||  14 || || Sharp turn sign&lt;br /&gt;
|-&lt;br /&gt;
|  15 ||   F || Opaque         || &amp;lt;span style=&amp;quot;color:#FCFCFC&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;FCFCFC&amp;lt;/tt&amp;gt; ||  15 || || Tennis court lines&lt;br /&gt;
|-&lt;br /&gt;
|  16 ||  10 || Opaque         || &amp;lt;span style=&amp;quot;color:#246820&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;246820&amp;lt;/tt&amp;gt; || 108 || || Grass&lt;br /&gt;
|-&lt;br /&gt;
|  17 ||  11 || Opaque         || &amp;lt;span style=&amp;quot;color:#5CFCFC&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;5CFCFC&amp;lt;/tt&amp;gt; || 116 || || Sky&lt;br /&gt;
|-&lt;br /&gt;
|  18 ||  12 || Opaque         || &amp;lt;span style=&amp;quot;color:#FCFCFC&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;FCFCFC&amp;lt;/tt&amp;gt; ||  15 || || Highway centerline&lt;br /&gt;
|-&lt;br /&gt;
|  19 ||  13 || Opaque         || &amp;lt;span style=&amp;quot;color:#484848&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;484848&amp;lt;/tt&amp;gt; ||  28 || || Asphalt pavement&lt;br /&gt;
|-&lt;br /&gt;
|  20 ||  14 || Opaque         || &amp;lt;span style=&amp;quot;color:#383838&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;383838&amp;lt;/tt&amp;gt; ||  29 || || Tunnel centerline&lt;br /&gt;
|-&lt;br /&gt;
|  21 ||  15 || Opaque         || &amp;lt;span style=&amp;quot;color:#FCFC54&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;FCFC54&amp;lt;/tt&amp;gt; ||  14 || || Asphalt centerline&lt;br /&gt;
|-&lt;br /&gt;
|  22 ||  16 || Grate          || &amp;lt;span style=&amp;quot;color:#484848&amp;quot;&amp;gt;▒▒▒▒&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;484848&amp;lt;/tt&amp;gt; ||  28 || || Loop / Elev. road surface &lt;br /&gt;
|-&lt;br /&gt;
|  23 ||  17 || Grate          || &amp;lt;span style=&amp;quot;color:#202020&amp;quot;&amp;gt;▒▒▒▒&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;202020&amp;lt;/tt&amp;gt; ||  31 || || Pipe surface&lt;br /&gt;
|-&lt;br /&gt;
|  24 ||  18 || Grate          || &amp;lt;span style=&amp;quot;color:#FCFC54&amp;quot;&amp;gt;▒▒▒▒&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;FCFC54&amp;lt;/tt&amp;gt; ||  14&lt;br /&gt;
|-&lt;br /&gt;
|  25 ||  19 || Opaque         || &amp;lt;span style=&amp;quot;color:#9C6438&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;9C6438&amp;lt;/tt&amp;gt; || 200 || || Dirt pavement&lt;br /&gt;
|-&lt;br /&gt;
|  26 ||  1A || Opaque         || &amp;lt;span style=&amp;quot;color:#B48054&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;B48054&amp;lt;/tt&amp;gt; || 198&lt;br /&gt;
|-&lt;br /&gt;
|  27 ||  1B || Opaque         || &amp;lt;span style=&amp;quot;color:#CCA080&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;CCA080&amp;lt;/tt&amp;gt; || 196 || || Dirt centerline&lt;br /&gt;
|-&lt;br /&gt;
|  28 ||  1C || Opaque         || &amp;lt;span style=&amp;quot;color:#D8FCFC&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;D8FCFC&amp;lt;/tt&amp;gt; || 112 || || Ice pavement&lt;br /&gt;
|-&lt;br /&gt;
|  29 ||  1D || Opaque         || &amp;lt;span style=&amp;quot;color:#9CFCFC&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;9CFCFC&amp;lt;/tt&amp;gt; || 114&lt;br /&gt;
|-&lt;br /&gt;
|  30 ||  1E || Opaque         || &amp;lt;span style=&amp;quot;color:#5CFCFC&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;5CFCFC&amp;lt;/tt&amp;gt; || 116 || || Ice centerline&lt;br /&gt;
|-&lt;br /&gt;
|  31 ||  1F || Opaque         || &amp;lt;span style=&amp;quot;color:#E4C4AC&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;E4C4AC&amp;lt;/tt&amp;gt; || 194 || || Bridges, buildings, etc.&lt;br /&gt;
|-&lt;br /&gt;
|  32 ||  20 || Opaque         || &amp;lt;span style=&amp;quot;color:#C0906C&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;C0906C&amp;lt;/tt&amp;gt; || 197 || || Bridges, buildings, etc.&lt;br /&gt;
|-&lt;br /&gt;
|  33 ||  21 || Opaque         || &amp;lt;span style=&amp;quot;color:#9C6438&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;9C6438&amp;lt;/tt&amp;gt; || 200 || || Bridges, buildings, etc.&lt;br /&gt;
|-&lt;br /&gt;
|  34 ||  22 || Grate          || &amp;lt;span style=&amp;quot;color:#9C9CFC&amp;quot;&amp;gt;▒▒▒▒&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;9C9CFC&amp;lt;/tt&amp;gt; || 146&lt;br /&gt;
|-&lt;br /&gt;
|  35 ||  23 || Opaque         || &amp;lt;span style=&amp;quot;color:#FC4040&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;FC4040&amp;lt;/tt&amp;gt; ||  37 || || Banked road outer side&lt;br /&gt;
|-&lt;br /&gt;
|  36 ||  24 || Opaque         || &amp;lt;span style=&amp;quot;color:#FC7C7C&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;FC7C7C&amp;lt;/tt&amp;gt; ||  35 || || Tunnel walls / Bankings&lt;br /&gt;
|-&lt;br /&gt;
|  37 ||  25 || Opaque         || &amp;lt;span style=&amp;quot;color:#FC40FC&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;FC40FC&amp;lt;/tt&amp;gt; || 181 || || Bridge cables&lt;br /&gt;
|-&lt;br /&gt;
|  38 ||  26 || Opaque         || &amp;lt;span style=&amp;quot;color:#383838&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;383838&amp;lt;/tt&amp;gt; ||  29 || || Wheel (tyre tread)&lt;br /&gt;
|-&lt;br /&gt;
|  39 ||  27 || Opaque         || &amp;lt;span style=&amp;quot;color:#202020&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;202020&amp;lt;/tt&amp;gt; ||  31 || || Wheel (tyre sidewall)&lt;br /&gt;
|-&lt;br /&gt;
|  40 ||  28 || Opaque         || &amp;lt;span style=&amp;quot;color:#C0C0C0&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;C0C0C0&amp;lt;/tt&amp;gt; ||  19 || || Wheel (&amp;quot;rim&amp;quot;)&lt;br /&gt;
|-&lt;br /&gt;
|  41 ||  29 || Opaque         || &amp;lt;span style=&amp;quot;color:#00A8A8&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;00A8A8&amp;lt;/tt&amp;gt; ||   3 || || Windows (LM002 car1)&lt;br /&gt;
|-&lt;br /&gt;
|  42 ||  2A || Opaque         || &amp;lt;span style=&amp;quot;color:#54FCFC&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;54FCFC&amp;lt;/tt&amp;gt; ||  11 || || Gas station windows&lt;br /&gt;
|-&lt;br /&gt;
|  43 ||  2B || Opaque         || &amp;lt;span style=&amp;quot;color:#545454&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;545454&amp;lt;/tt&amp;gt; ||   8 || || Windows and windshields&lt;br /&gt;
|-&lt;br /&gt;
|  44 ||  2C || Opaque         || &amp;lt;span style=&amp;quot;color:#000000&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;000000&amp;lt;/tt&amp;gt; ||   0 || || Windows and windshields&lt;br /&gt;
|-&lt;br /&gt;
|  45 ||  2D || Opaque         || &amp;lt;span style=&amp;quot;color:#A80000&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;A80000&amp;lt;/tt&amp;gt; ||   4&lt;br /&gt;
|-&lt;br /&gt;
|  46 ||  2E || Opaque         || &amp;lt;span style=&amp;quot;color:#A80000&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;A80000&amp;lt;/tt&amp;gt; ||   4&lt;br /&gt;
|-&lt;br /&gt;
|  47 ||  2F || Opaque         || &amp;lt;span style=&amp;quot;color:#FC5454&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;FC5454&amp;lt;/tt&amp;gt; ||  12&lt;br /&gt;
|-&lt;br /&gt;
|  48 ||  30 || Opaque         || &amp;lt;span style=&amp;quot;color:#00007C&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;00007C&amp;lt;/tt&amp;gt; || 156 || Blue 1     || Car body&lt;br /&gt;
|-&lt;br /&gt;
|  49 ||  31 || Opaque         || &amp;lt;span style=&amp;quot;color:#0000A8&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;0000A8&amp;lt;/tt&amp;gt; ||   1 || Blue 2     || Car body&lt;br /&gt;
|-&lt;br /&gt;
|  50 ||  32 || Opaque         || &amp;lt;span style=&amp;quot;color:#0000D0&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;0000D0&amp;lt;/tt&amp;gt; || 152 || Blue 3     || Car body&lt;br /&gt;
|-&lt;br /&gt;
|  51 ||  33 || Opaque         || &amp;lt;span style=&amp;quot;color:#0004FC&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;0004FC&amp;lt;/tt&amp;gt; || 150 || Blue 4     || Car body&lt;br /&gt;
|-&lt;br /&gt;
|  52 ||  34 || Opaque         || &amp;lt;span style=&amp;quot;color:#B40000&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;B40000&amp;lt;/tt&amp;gt; ||  42 || Red 1      || Car body&lt;br /&gt;
|-&lt;br /&gt;
|  53 ||  35 || Opaque         || &amp;lt;span style=&amp;quot;color:#E40000&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;E40000&amp;lt;/tt&amp;gt; ||  40 || Red 2      || Car body&lt;br /&gt;
|-&lt;br /&gt;
|  54 ||  36 || Opaque         || &amp;lt;span style=&amp;quot;color:#FC2020&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;FC2020&amp;lt;/tt&amp;gt; ||  38 || Red 3      || Car body&lt;br /&gt;
|-&lt;br /&gt;
|  55 ||  37 || Opaque         || &amp;lt;span style=&amp;quot;color:#FC4040&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;FC4040&amp;lt;/tt&amp;gt; ||  37 || Red 4      || Car body&lt;br /&gt;
|-&lt;br /&gt;
|  56 ||  38 || Opaque         || &amp;lt;span style=&amp;quot;color:#545454&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;545454&amp;lt;/tt&amp;gt; ||   8 || Graphite 1 || Car body&lt;br /&gt;
|-&lt;br /&gt;
|  57 ||  39 || Opaque         || &amp;lt;span style=&amp;quot;color:#606060&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;606060&amp;lt;/tt&amp;gt; ||  26 || Graphite 2 || Car body&lt;br /&gt;
|-&lt;br /&gt;
|  58 ||  3A || Opaque         || &amp;lt;span style=&amp;quot;color:#707070&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;707070&amp;lt;/tt&amp;gt; ||  25 || Graphite 3 || Car body&lt;br /&gt;
|-&lt;br /&gt;
|  59 ||  3B || Opaque         || &amp;lt;span style=&amp;quot;color:#7C7C7C&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;7C7C7C&amp;lt;/tt&amp;gt; ||  24 || Graphite 4 || Car body&lt;br /&gt;
|-&lt;br /&gt;
|  60 ||  3C || Opaque         || &amp;lt;span style=&amp;quot;color:#E4D800&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;E4D800&amp;lt;/tt&amp;gt; ||  72 || Yellow 1   || Car body&lt;br /&gt;
|-&lt;br /&gt;
|  61 ||  3D || Opaque         || &amp;lt;span style=&amp;quot;color:#FCF420&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;FCF420&amp;lt;/tt&amp;gt; ||  70 || Yellow 2   || Car body&lt;br /&gt;
|-&lt;br /&gt;
|  62 ||  3E || Opaque         || &amp;lt;span style=&amp;quot;color:#FCF85C&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;FCF85C&amp;lt;/tt&amp;gt; ||  68 || Yellow 3   || Car body&lt;br /&gt;
|-&lt;br /&gt;
|  63 ||  3F || Opaque         || &amp;lt;span style=&amp;quot;color:#FCFC9C&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;FCFC9C&amp;lt;/tt&amp;gt; ||  66 || Yellow 4   || Car body&lt;br /&gt;
|-&lt;br /&gt;
|  64 ||  40 || Opaque         || &amp;lt;span style=&amp;quot;color:#009C9C&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;009C9C&amp;lt;/tt&amp;gt; || 123 || Cyan 1     || Car body&lt;br /&gt;
|-&lt;br /&gt;
|  65 ||  41 || Opaque         || &amp;lt;span style=&amp;quot;color:#00CCCC&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;00CCCC&amp;lt;/tt&amp;gt; || 121 || Cyan 2     || Car body&lt;br /&gt;
|-&lt;br /&gt;
|  66 ||  42 || Opaque         || &amp;lt;span style=&amp;quot;color:#00E4E4&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;00E4E4&amp;lt;/tt&amp;gt; || 120 || Cyan 3     || Car body&lt;br /&gt;
|-&lt;br /&gt;
|  67 ||  43 || Opaque         || &amp;lt;span style=&amp;quot;color:#40FCFC&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;40FCFC&amp;lt;/tt&amp;gt; || 117 || Cyan 4     || Car body&lt;br /&gt;
|-&lt;br /&gt;
|  68 ||  44 || Opaque         || &amp;lt;span style=&amp;quot;color:#508400&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;508400&amp;lt;/tt&amp;gt; ||  92 || Green 1    || Car body / Tree (palm)&lt;br /&gt;
|-&lt;br /&gt;
|  69 ||  45 || Opaque         || &amp;lt;span style=&amp;quot;color:#74B400&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;74B400&amp;lt;/tt&amp;gt; ||  90 || Green 2    || Car body / Tree (palm)&lt;br /&gt;
|-&lt;br /&gt;
|  70 ||  46 || Opaque         || &amp;lt;span style=&amp;quot;color:#90E400&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;90E400&amp;lt;/tt&amp;gt; ||  88 || Green 3    || Car body / Tree (palm)&lt;br /&gt;
|-&lt;br /&gt;
|  71 ||  47 || Opaque         || &amp;lt;span style=&amp;quot;color:#A0FC00&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;A0FC00&amp;lt;/tt&amp;gt; ||  87 || Green 4    || Car body&lt;br /&gt;
|-&lt;br /&gt;
|  72 ||  48 || Opaque         || &amp;lt;span style=&amp;quot;color:#440070&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;440070&amp;lt;/tt&amp;gt; || 173 || Purple 1   || Car body&lt;br /&gt;
|-&lt;br /&gt;
|  73 ||  49 || Opaque         || &amp;lt;span style=&amp;quot;color:#60009C&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;60009C&amp;lt;/tt&amp;gt; || 171 || Purple 2   || Car body&lt;br /&gt;
|-&lt;br /&gt;
|  74 ||  4A || Opaque         || &amp;lt;span style=&amp;quot;color:#8000CC&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;8000CC&amp;lt;/tt&amp;gt; || 169 || Purple 3   || Car body&lt;br /&gt;
|-&lt;br /&gt;
|  75 ||  4B || Opaque         || &amp;lt;span style=&amp;quot;color:#A800FC&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;A800FC&amp;lt;/tt&amp;gt; || 167 || Purple 4   || Car body&lt;br /&gt;
|-&lt;br /&gt;
|  76 ||  4C || Opaque         || &amp;lt;span style=&amp;quot;color:#B0B0B0&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;B0B0B0&amp;lt;/tt&amp;gt; ||  20 || Silver 1   || Car body&lt;br /&gt;
|-&lt;br /&gt;
|  77 ||  4D || Opaque         || &amp;lt;span style=&amp;quot;color:#C0C0C0&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;C0C0C0&amp;lt;/tt&amp;gt; ||  19 || Silver 2   || Car body&lt;br /&gt;
|-&lt;br /&gt;
|  78 ||  4E || Opaque         || &amp;lt;span style=&amp;quot;color:#CCCCCC&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;CCCCCC&amp;lt;/tt&amp;gt; ||  18 || Silver 3   || Car body&lt;br /&gt;
|-&lt;br /&gt;
|  79 ||  4F || Opaque         || &amp;lt;span style=&amp;quot;color:#DCDCDC&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;DCDCDC&amp;lt;/tt&amp;gt; ||  17 || Silver 4   || Car body&lt;br /&gt;
|-&lt;br /&gt;
|  80 ||  50 || Opaque         || &amp;lt;span style=&amp;quot;color:#6C5800&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;6C5800&amp;lt;/tt&amp;gt; ||  77 || Golden 1   || Car body&lt;br /&gt;
|-&lt;br /&gt;
|  81 ||  51 || Opaque         || &amp;lt;span style=&amp;quot;color:#847400&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;847400&amp;lt;/tt&amp;gt; ||  76 || Golden 2   || Car body&lt;br /&gt;
|-&lt;br /&gt;
|  82 ||  52 || Opaque         || &amp;lt;span style=&amp;quot;color:#B4A400&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;B4A400&amp;lt;/tt&amp;gt; ||  74 || Golden 3   || Car body&lt;br /&gt;
|-&lt;br /&gt;
|  83 ||  53 || Opaque         || &amp;lt;span style=&amp;quot;color:#CCC000&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;CCC000&amp;lt;/tt&amp;gt; ||  73 || Golden 4   || Car body&lt;br /&gt;
|-&lt;br /&gt;
|  84 ||  54 || Opaque         || &amp;lt;span style=&amp;quot;color:#700000&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;700000&amp;lt;/tt&amp;gt; ||  45 || Burgundy 1 || Car body&lt;br /&gt;
|-&lt;br /&gt;
|  85 ||  55 || Opaque         || &amp;lt;span style=&amp;quot;color:#840000&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;840000&amp;lt;/tt&amp;gt; ||  44 || Burgundy 2 || Car body&lt;br /&gt;
|-&lt;br /&gt;
|  86 ||  56 || Opaque         || &amp;lt;span style=&amp;quot;color:#B40000&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;B40000&amp;lt;/tt&amp;gt; ||  42 || Burgundy 3 || Car body&lt;br /&gt;
|-&lt;br /&gt;
|  87 ||  57 || Opaque         || &amp;lt;span style=&amp;quot;color:#CC0000&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;CC0000&amp;lt;/tt&amp;gt; ||  41 || Burgundy 4 || Car body&lt;br /&gt;
|-&lt;br /&gt;
|  88 ||  58 || Opaque         || &amp;lt;span style=&amp;quot;color:#000040&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;000040&amp;lt;/tt&amp;gt; || 159 || Violet 1   || Car body&lt;br /&gt;
|-&lt;br /&gt;
|  89 ||  59 || Opaque         || &amp;lt;span style=&amp;quot;color:#280040&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;280040&amp;lt;/tt&amp;gt; || 175 || Violet 2   || Car body&lt;br /&gt;
|-&lt;br /&gt;
|  90 ||  5A || Opaque         || &amp;lt;span style=&amp;quot;color:#340058&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;340058&amp;lt;/tt&amp;gt; || 174 || Violet 3   || Car body&lt;br /&gt;
|-&lt;br /&gt;
|  91 ||  5B || Opaque         || &amp;lt;span style=&amp;quot;color:#500084&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;500084&amp;lt;/tt&amp;gt; || 172 || Violet 4   || Car body&lt;br /&gt;
|-&lt;br /&gt;
|  92 ||  5C || Opaque         || &amp;lt;span style=&amp;quot;color:#383838&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;383838&amp;lt;/tt&amp;gt; ||  29&lt;br /&gt;
|-&lt;br /&gt;
|  93 ||  5D || Opaque         || &amp;lt;span style=&amp;quot;color:#484848&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;484848&amp;lt;/tt&amp;gt; ||  28&lt;br /&gt;
|-&lt;br /&gt;
|  94 ||  5E || Grate          || &amp;lt;span style=&amp;quot;color:#CCCCCC&amp;quot;&amp;gt;▒▒▒▒&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;CCCCCC&amp;lt;/tt&amp;gt; ||  18 || || Tennis net&lt;br /&gt;
|-&lt;br /&gt;
|  95 ||  5F || Opaque         || &amp;lt;span style=&amp;quot;color:#74B400&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;74B400&amp;lt;/tt&amp;gt; ||  90 || || Tennis grass&lt;br /&gt;
|-&lt;br /&gt;
|  96 ||  60 || Opaque         || &amp;lt;span style=&amp;quot;color:#FCFCFC&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;FCFCFC&amp;lt;/tt&amp;gt; ||  15 || || Clouds&lt;br /&gt;
|-&lt;br /&gt;
|  97 ||  61 || Opaque         || &amp;lt;span style=&amp;quot;color:#A8A8A8&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;A8A8A8&amp;lt;/tt&amp;gt; ||   7 || || Clouds&lt;br /&gt;
|-&lt;br /&gt;
|  98 ||  62 || Opaque         || &amp;lt;span style=&amp;quot;color:#9C6438&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;9C6438&amp;lt;/tt&amp;gt; || 200 || || Pinetree trunk&lt;br /&gt;
|-&lt;br /&gt;
|  99 ||  63 || Opaque         || &amp;lt;span style=&amp;quot;color:#C0602C&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;C0602C&amp;lt;/tt&amp;gt; || 219 || || Pinetree trunk&lt;br /&gt;
|-&lt;br /&gt;
| 100 ||  64 || Opaque         || &amp;lt;span style=&amp;quot;color:#0080D0&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;0080D0&amp;lt;/tt&amp;gt; || 136 || || Water&lt;br /&gt;
|-&lt;br /&gt;
| 101 ||  65 || Opaque         || &amp;lt;span style=&amp;quot;color:#84E084&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;84E084&amp;lt;/tt&amp;gt; ||  99 || || Grass (hilltop)&lt;br /&gt;
|-&lt;br /&gt;
| 102 ||  66 || Opaque         || &amp;lt;span style=&amp;quot;color:#70C46C&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;70C46C&amp;lt;/tt&amp;gt; || 101 || || Grass (hill slope)&lt;br /&gt;
|-&lt;br /&gt;
| 103 ||  67 || Opaque         || &amp;lt;span style=&amp;quot;color:#58A858&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;58A858&amp;lt;/tt&amp;gt; || 103 || || Grass (angled slope)&lt;br /&gt;
|-&lt;br /&gt;
| 104 ||  68 || Opaque         || &amp;lt;span style=&amp;quot;color:#509C4C&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;509C4C&amp;lt;/tt&amp;gt; || 104 || || Grass (angled slope)&lt;br /&gt;
|-&lt;br /&gt;
| 105 ||  69 || Opaque         || &amp;lt;span style=&amp;quot;color:#388034&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;388034&amp;lt;/tt&amp;gt; || 106 || || Grass (angled slope)&lt;br /&gt;
|-&lt;br /&gt;
| 106 ||  6A || Opaque         || &amp;lt;span style=&amp;quot;color:#DCDCDC&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;DCDCDC&amp;lt;/tt&amp;gt; ||  17 || || Gas station / Joe&#039;s&lt;br /&gt;
|-&lt;br /&gt;
| 107 ||  6B || Opaque         || &amp;lt;span style=&amp;quot;color:#B0B0B0&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;B0B0B0&amp;lt;/tt&amp;gt; ||  20 || || Gas station / Joe&#039;s&lt;br /&gt;
|-&lt;br /&gt;
| 108 ||  6C || Opaque         || &amp;lt;span style=&amp;quot;color:#905410&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;905410&amp;lt;/tt&amp;gt; ||  60 || || Trunk (palmtree)&lt;br /&gt;
|-&lt;br /&gt;
| 109 ||  6D || Opaque         || &amp;lt;span style=&amp;quot;color:#6C5800&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;6C5800&amp;lt;/tt&amp;gt; ||  77 || || Trunk (palmtree)&lt;br /&gt;
|-&lt;br /&gt;
| 110 ||  6E || Opaque         || &amp;lt;span style=&amp;quot;color:#580000&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;580000&amp;lt;/tt&amp;gt; ||  46 || || Joe&#039;s roof&lt;br /&gt;
|-&lt;br /&gt;
| 111 ||  6F || Opaque         || &amp;lt;span style=&amp;quot;color:#744008&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;744008&amp;lt;/tt&amp;gt; ||  61 || || Windmill (base)&lt;br /&gt;
|-&lt;br /&gt;
| 112 ||  70 || Opaque         || &amp;lt;span style=&amp;quot;color:#700000&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;700000&amp;lt;/tt&amp;gt; ||  45 || || Windmill (base)&lt;br /&gt;
|-&lt;br /&gt;
| 113 ||  71 || Opaque         || &amp;lt;span style=&amp;quot;color:#80542C&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;80542C&amp;lt;/tt&amp;gt; || 202 || || Windmill (blades)&lt;br /&gt;
|-&lt;br /&gt;
| 114 ||  72 || Opaque         || &amp;lt;span style=&amp;quot;color:#540054&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;540054&amp;lt;/tt&amp;gt; || 190 || || Joe&#039;s flashing sign&lt;br /&gt;
|-&lt;br /&gt;
| 115 ||  73 || Opaque         || &amp;lt;span style=&amp;quot;color:#A400A4&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;A400A4&amp;lt;/tt&amp;gt; || 186 || || Joe&#039;s flashing sign&lt;br /&gt;
|-&lt;br /&gt;
| 116 ||  74 || Opaque         || &amp;lt;span style=&amp;quot;color:#E000E4&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;E000E4&amp;lt;/tt&amp;gt; || 183 || || Joe&#039;s flashing sign&lt;br /&gt;
|-&lt;br /&gt;
| 117 ||  75 || Opaque         || &amp;lt;span style=&amp;quot;color:#FC5CFC&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;FC5CFC&amp;lt;/tt&amp;gt; || 180 || || Joe&#039;s flashing sign&lt;br /&gt;
|-&lt;br /&gt;
| 118 ||  76 || Transparent    || &amp;lt;span style=&amp;quot;color:#FFFFFF&amp;quot;&amp;gt;​​​​​&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;N/A&amp;lt;/tt&amp;gt; || 255  || || Windmill animation mask&lt;br /&gt;
|-&lt;br /&gt;
| 119 ||  77 || Grille         || &amp;lt;span style=&amp;quot;color:#484848&amp;quot;&amp;gt;▒▒▒▒&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;484848&amp;lt;/tt&amp;gt; ||  28&lt;br /&gt;
|-&lt;br /&gt;
| 120 ||  78 || Inverse grille || &amp;lt;span style=&amp;quot;color:#2C2C2C&amp;quot;&amp;gt;▒▒▒▒&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;2C2C2C&amp;lt;/tt&amp;gt; ||  30&lt;br /&gt;
|-&lt;br /&gt;
| 121 ||  79 || Glass          || &amp;lt;span style=&amp;quot;color:#FCFCFC&amp;quot;&amp;gt;▓▓▓▓&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;FCFCFC&amp;lt;/tt&amp;gt; ||  15&lt;br /&gt;
|-&lt;br /&gt;
| 122 ||  7A || Inverse glass  || &amp;lt;span style=&amp;quot;color:#B0B0B0&amp;quot;&amp;gt;░░░░&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;B0B0B0&amp;lt;/tt&amp;gt; ||  20&lt;br /&gt;
|-&lt;br /&gt;
| 123 ||  7B || Glass          || &amp;lt;span style=&amp;quot;color:#FCF85C&amp;quot;&amp;gt;▓▓▓▓&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;FCF85C&amp;lt;/tt&amp;gt; ||  68&lt;br /&gt;
|-&lt;br /&gt;
| 124 ||  7C || Inverse glass  || &amp;lt;span style=&amp;quot;color:#FCAC54&amp;quot;&amp;gt;░░░░&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;FCAC54&amp;lt;/tt&amp;gt; ||  54&lt;br /&gt;
|-&lt;br /&gt;
| 125 ||  7D || Glass          || &amp;lt;span style=&amp;quot;color:#FC0000&amp;quot;&amp;gt;▓▓▓▓&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;FC0000&amp;lt;/tt&amp;gt; ||  39&lt;br /&gt;
|-&lt;br /&gt;
| 126 ||  7E || Inverse glass  || &amp;lt;span style=&amp;quot;color:#9C0000&amp;quot;&amp;gt;░░░░&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;9C0000&amp;lt;/tt&amp;gt; ||  43&lt;br /&gt;
|-&lt;br /&gt;
| 127 ||  7F || Opaque         || &amp;lt;span style=&amp;quot;color:#FC5454&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;FC5454&amp;lt;/tt&amp;gt; ||  12 || || Corner kerbs&lt;br /&gt;
|-&lt;br /&gt;
| 128 ||  80 || Opaque         || &amp;lt;span style=&amp;quot;color:#DCDCDC&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;DCDCDC&amp;lt;/tt&amp;gt; ||  17 || || Corner kerbs&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==Patterns==&lt;br /&gt;
Patterns are used as a mask when drawing the polygon akin to polygon stippling in OpenGL.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;gallery widths=&amp;quot;128px&amp;quot; heights=&amp;quot;128px&amp;quot; perrow=&amp;quot;3&amp;quot;&amp;gt;&lt;br /&gt;
Image:Pattern_Grille.png|Grille&lt;br /&gt;
Image:Pattern_Glass.png|Glass (lights)&lt;br /&gt;
Image:Pattern_Grate.png|Grate (ramps, bridges)&lt;br /&gt;
Image:Pattern_Grille_Inverse.png|Inverse grille&lt;br /&gt;
Image:Pattern_Glass_Inverse.png|Inverse glass&lt;br /&gt;
&amp;lt;/gallery&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Category:Game]]&lt;/div&gt;</summary>
		<author><name>Dstien</name></author>
	</entry>
	<entry>
		<id>https://wiki.stunts.hu/index.php?title=Resource_file_format&amp;diff=708</id>
		<title>Resource file format</title>
		<link rel="alternate" type="text/html" href="https://wiki.stunts.hu/index.php?title=Resource_file_format&amp;diff=708"/>
		<updated>2008-04-28T18:36:07Z</updated>

		<summary type="html">&lt;p&gt;Dstien: /* 3d shapes */ Added some details I encountered while implementing a shape file writer.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Stunts game data are stored in a common container format. Files of this format can hold multiple &#039;&#039;resources&#039;&#039;, blocks of data that may be of various types - text, bitmaps, sounds, etc. Resources are uniquely identified within each file solely by a 4-byte name. A resource container file can be encapsulated by [[Compression|compression]].&lt;br /&gt;
&lt;br /&gt;
This document focuses on [[Game versions#PC versions|BB Stunts 1.1]], but details described here may still—partly or wholly—cover other versions, or even other games developed by DSI at the time.&lt;br /&gt;
&lt;br /&gt;
==File names==&lt;br /&gt;
Different file name extensions are used to indicate the content of the files. Compressed files has &#039;&#039;&amp;quot;P&amp;quot;&#039;&#039; (packed) as the first letter of their extensions. Whether the game prefers raw or compressed files varies based on file type.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! File contents           !! Raw !! Compressed !! Preferred&lt;br /&gt;
|-&lt;br /&gt;
| Text and misc. settings || RES || PRE        || Raw&lt;br /&gt;
|-&lt;br /&gt;
| Bitmap images           || VSH || PVS        || Compressed&lt;br /&gt;
|-&lt;br /&gt;
| Icons                   || ESH || PES        || Compressed&lt;br /&gt;
|-&lt;br /&gt;
| 3d shapes               || 3SH || P3S        || Compressed&lt;br /&gt;
|-&lt;br /&gt;
| Music tracks            || KMS || PKM        || Raw&lt;br /&gt;
|-&lt;br /&gt;
| Instrument samples      || VCE || PVC        || Raw&lt;br /&gt;
|-&lt;br /&gt;
| Sound effects           || SFX || PSF        || Raw&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==Structure==&lt;br /&gt;
&lt;br /&gt;
The resource file header consists of two integer fields denoting the total length of the file and the number of resources contained. The following table of contents has a list of ids and a corresponding list of offsets into the remaining data section.&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlC&amp;quot;&amp;gt;// Header&amp;lt;/span&amp;gt;&lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint32&amp;lt;/span&amp;gt; fileLength&lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint16&amp;lt;/span&amp;gt; numResources&lt;br /&gt;
 &lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlC&amp;quot;&amp;gt;// Table of contents&amp;lt;/span&amp;gt;&lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;char&amp;lt;/span&amp;gt;   ids&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;[&amp;lt;/span&amp;gt;numResources&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;][&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;hlN&amp;quot;&amp;gt;4&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;]&amp;lt;/span&amp;gt;&lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint32&amp;lt;/span&amp;gt; offsets&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;[&amp;lt;/span&amp;gt;numResources&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;]&amp;lt;/span&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlC&amp;quot;&amp;gt;// Resource data&amp;lt;/span&amp;gt;&lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;char&amp;lt;/span&amp;gt;   data&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;[]&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Types==&lt;br /&gt;
Resource type can be determined by looking at the resource&#039;s id string and/or the source file name.&lt;br /&gt;
&lt;br /&gt;
===Plain text===&lt;br /&gt;
Text resources are null-terminated [http://en.wikipedia.org/wiki/C_string C strings] found in &amp;lt;tt&amp;gt;RES&amp;lt;/tt&amp;gt;/&amp;lt;tt&amp;gt;PRE&amp;lt;/tt&amp;gt; files. Strings can contain non-alphanumeric codes used by the game to achieve certain effects. Most prominent is the &#039;&#039;&amp;quot;]&amp;quot;&#039;&#039; (right square bracket) used to represent [http://en.wikipedia.org/wiki/Newline newline] in multi-line text.&lt;br /&gt;
&lt;br /&gt;
===Bitmap images===&lt;br /&gt;
[[Image:Stunts-pal-vga.png|128px|right|thumb|VGA palette used by bitmap images. Value 255 is transparency.]]&lt;br /&gt;
Bitmaps are images with 8-bit color depth using a [[:Image:Stunts-pal-vga.png|fixed palette]] in VGA mode. Special bitmaps using the naming scheme &amp;lt;tt&amp;gt;!cg_&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;!eg_&amp;lt;/tt&amp;gt; provides color mapping for graphics modes with fewer available colors.&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint16&amp;lt;/span&amp;gt; width&lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint16&amp;lt;/span&amp;gt; height&lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint16&amp;lt;/span&amp;gt; unknown1&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;[&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;hlN&amp;quot;&amp;gt;4&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;]&amp;lt;/span&amp;gt;&lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt;  unknown2&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;[&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;hlN&amp;quot;&amp;gt;4&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;]&amp;lt;/span&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt;  image&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;[&amp;lt;/span&amp;gt;width &amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;*&amp;lt;/span&amp;gt; height&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;]&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Parts of this structure are not fully understood. &amp;lt;tt&amp;gt;unknown1&amp;lt;/tt&amp;gt; appears to be related to Stunts&#039; internal memory management. &amp;lt;tt&amp;gt;unknown2&amp;lt;/tt&amp;gt; seems to affect how image pixels are organized in compressed resource files, likely to gain more effective [http://en.wikipedia.org/wiki/Run-length_encoding run-length compression]. Images with pixel data stored as continuos horizontal lines has &amp;lt;tt&amp;gt;unknown2&amp;lt;/tt&amp;gt; set to &amp;lt;code&amp;gt;{ 0x1, 0x2, 0x4, 0x8 }&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
{{sectstub}}&lt;br /&gt;
&lt;br /&gt;
===Icons===&lt;br /&gt;
{{sectstub}}&lt;br /&gt;
&lt;br /&gt;
===3d shapes===&lt;br /&gt;
Shapes are composed of a vertex list and a list of primitives. Primitives are basic shapes that can have different types, such as polygons or wheels. Depending on the type it contains a number of indices into the vertex list needed to draw the shape, color variations and some rendering hints. Stunts&#039; coordinate system use 16-bit signed integers, making the resolution relative to the scale of the model. Shapes presented in the car selection screen are more detailed than in-game shapes, thus requiring larger scaling.&lt;br /&gt;
&lt;br /&gt;
Due to the counter header fields being stored in single bytes, the total amount of vertices and primitives are limited to 255 per shape.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Main strcture&#039;&#039;&#039;&lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt;     numVertices&lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt;     numPrimitives&lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt;     numPaintJobs&lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt;     reserved &amp;lt;span class=&amp;quot;hlC&amp;quot;&amp;gt;// Always == 0&amp;lt;/span&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
 VERTEX    vertices&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;[&amp;lt;/span&amp;gt;numVertices&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;]&amp;lt;/span&amp;gt;&lt;br /&gt;
 UNKNOWN   unknowns&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;[&amp;lt;/span&amp;gt;numPrimitives&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;]&amp;lt;/span&amp;gt;&lt;br /&gt;
 PRIMITIVE primitives&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;[&amp;lt;/span&amp;gt;numPrimitives&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;]&amp;lt;/span&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt;     terminate&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;[&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;hlC&amp;quot;&amp;gt;...&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;]&amp;lt;/span&amp;gt; &amp;lt;span class=&amp;quot;hlC&amp;quot;&amp;gt;// One or two NULL-bytes to make resource size divisible by 2.&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Additional structures&#039;&#039;&#039;&lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;struct&amp;lt;/span&amp;gt; VERTEX &amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;{&amp;lt;/span&amp;gt;&lt;br /&gt;
   &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;int16&amp;lt;/span&amp;gt; x&lt;br /&gt;
   &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;int16&amp;lt;/span&amp;gt; y&lt;br /&gt;
   &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;int16&amp;lt;/span&amp;gt; z&lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;}&amp;lt;/span&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;struct&amp;lt;/span&amp;gt; UNKNOWN &amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;{&amp;lt;/span&amp;gt;&lt;br /&gt;
   &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;int8&amp;lt;/span&amp;gt; data&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;[&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;hlN&amp;quot;&amp;gt;8&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;]&amp;lt;/span&amp;gt;&lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;}&amp;lt;/span&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;struct&amp;lt;/span&amp;gt; PRIMITIVE &amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;{&amp;lt;/span&amp;gt;&lt;br /&gt;
   &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt; type&lt;br /&gt;
   &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt; depthIndex&lt;br /&gt;
   &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt; materials&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;[&amp;lt;/span&amp;gt;numPaintJobs&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;]&amp;lt;/span&amp;gt;&lt;br /&gt;
   &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt; indices&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;[&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;hlC&amp;quot;&amp;gt;...&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;]&amp;lt;/span&amp;gt; &amp;lt;span class=&amp;quot;hlC&amp;quot;&amp;gt;// Size depends on type.&amp;lt;/span&amp;gt;&lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;}&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Primitive types&#039;&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Primitive type !! Vertex indices needed !! Description&lt;br /&gt;
|-&lt;br /&gt;
| 1              || 1              || Particle, 1 pixel&lt;br /&gt;
|-&lt;br /&gt;
| 2              || 2              || Line segment, 1 pixel width&lt;br /&gt;
|-&lt;br /&gt;
| 3–10           || 3–10           || Polygon, &#039;&#039;n&#039;&#039; sides&lt;br /&gt;
|-&lt;br /&gt;
| 11             || 2              || Sphere (center + ~(radius / 2)&lt;br /&gt;
|-&lt;br /&gt;
| 12             || 6              || Wheel&lt;br /&gt;
|-&lt;br /&gt;
| *              || 0              || Ignored&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
For car body and track element shapes the first eight vertices are reserved for the corner vertices of the shape&#039;s bound box, used to cull entire shapes located outside the view frustum.&lt;br /&gt;
&lt;br /&gt;
[[Image:Wheel_Primitive_Anatomy.png|200px|right|thumb|Anatomy of a wheel shape primitive.]]&lt;br /&gt;
The first three vertices in a wheel primitive marks the center, tire radius and rim radius for the inner wheel-half facing the vehicle. The last three vertices does the same, in the same order, for the outer half of the wheel. Directions does not matter, the vertex locations are only used to measure distances. This rule applies to the sphere primitive as well.&lt;br /&gt;
&lt;br /&gt;
Wheel transformations are performed on fixed vertex positions. Since the first eight vertices of &amp;lt;tt&amp;gt;car[0-2]&amp;lt;/tt&amp;gt; shapes are occupied by the bound box, vertices 9-14 and 15-20 are front wheels. Misplaced wheel vertices will lead to corrupted shape rendering.&lt;br /&gt;
&lt;br /&gt;
The value &amp;lt;tt&amp;gt;depthIndex&amp;lt;/tt&amp;gt; in the &amp;lt;tt&amp;gt;PRIMITIVE&amp;lt;/tt&amp;gt; structure is used to override the game&#039;s depth clipping in order to avoid flickering when several primitives are being drawn at the exact same depth. Higher value gives the primitive higher precedence.&lt;br /&gt;
&lt;br /&gt;
[[Shape materials|Materials]] are indices into a permanent, internal game structure and are assigned per-primitive. Cars can have multiple paint jobs, every primitive in the shape must set a material for each color scheme.&lt;br /&gt;
&lt;br /&gt;
Experimentation has revealed that &amp;lt;tt&amp;gt;UNKNOWN&amp;lt;/tt&amp;gt; data at least partially controls occlusion culling on primitive level. How, and exactly which parts of this structure does what has yet to be understood.&lt;br /&gt;
&lt;br /&gt;
A shape resource must be terminated with a NULL-byte and the size must be divisible by two, hence two NULL-bytes are needed to terminate and pad resources with an even number of bytes. Failing to meet this requirement will lead to obscure rendering artifacts.&lt;br /&gt;
&lt;br /&gt;
{{sectstub}}&lt;br /&gt;
&lt;br /&gt;
===Car parameters===&lt;br /&gt;
{{main|Car parameters}}&lt;br /&gt;
{{sectstub}}&lt;br /&gt;
&lt;br /&gt;
===Opponent parameters===&lt;br /&gt;
{{sectstub}}&lt;br /&gt;
&lt;br /&gt;
===Music tracks===&lt;br /&gt;
{{sectstub}}&lt;br /&gt;
&lt;br /&gt;
===Instrument samples===&lt;br /&gt;
{{sectstub}}&lt;br /&gt;
&lt;br /&gt;
===Sound effects===&lt;br /&gt;
{{sectstub}}&lt;br /&gt;
&lt;br /&gt;
==Tools==&lt;br /&gt;
* [[stressed]] - Stunts/4D [Sports] Driving resource editor [http://stuntstools.googlecode.com/].&lt;br /&gt;
&lt;br /&gt;
[[Category:Game]]&lt;/div&gt;</summary>
		<author><name>Dstien</name></author>
	</entry>
	<entry>
		<id>https://wiki.stunts.hu/index.php?title=Shape_materials&amp;diff=701</id>
		<title>Shape materials</title>
		<link rel="alternate" type="text/html" href="https://wiki.stunts.hu/index.php?title=Shape_materials&amp;diff=701"/>
		<updated>2008-04-28T00:32:28Z</updated>

		<summary type="html">&lt;p&gt;Dstien: Category.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;3d shapes refers to a predefined set of materials. A material defines the appearance of a polygon with a color and a pattern. Most materials are opaque colors, while some have see-through patterns. Multiple polygons with different material patterns can be layered to achieve certain effects, such as multi-colored grilles and lights.&lt;br /&gt;
&lt;br /&gt;
==Materials==&lt;br /&gt;
{| class=&amp;quot;wikitable sortable&amp;quot;&lt;br /&gt;
! #  !! Pattern         !! Color                                                    !! Name !! Comment&lt;br /&gt;
|-&lt;br /&gt;
|   0 || Opaque         || &amp;lt;span style=&amp;quot;color:#000000&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;000000&amp;lt;/tt&amp;gt; || Black&lt;br /&gt;
|-&lt;br /&gt;
|   1 || Opaque         || &amp;lt;span style=&amp;quot;color:#0000A8&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;0000A8&amp;lt;/tt&amp;gt; || Blue&lt;br /&gt;
|-&lt;br /&gt;
|   2 || Opaque         || &amp;lt;span style=&amp;quot;color:#00A800&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;00A800&amp;lt;/tt&amp;gt; || Green&lt;br /&gt;
|-&lt;br /&gt;
|   3 || Opaque         || &amp;lt;span style=&amp;quot;color:#00A8A8&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;00A8A8&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|   4 || Opaque         || &amp;lt;span style=&amp;quot;color:#A80000&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;A80000&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|   5 || Opaque         || &amp;lt;span style=&amp;quot;color:#A800A8&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;A800A8&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|   6 || Opaque         || &amp;lt;span style=&amp;quot;color:#A85400&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;A85400&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|   7 || Opaque         || &amp;lt;span style=&amp;quot;color:#A8A8A8&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;A8A8A8&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|   8 || Opaque         || &amp;lt;span style=&amp;quot;color:#545454&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;545454&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|   9 || Opaque         || &amp;lt;span style=&amp;quot;color:#5454FC&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;5454FC&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|  10 || Opaque         || &amp;lt;span style=&amp;quot;color:#54FC54&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;54FC54&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|  11 || Opaque         || &amp;lt;span style=&amp;quot;color:#54FCFC&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;54FCFC&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|  12 || Opaque         || &amp;lt;span style=&amp;quot;color:#FC5454&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;FC5454&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|  13 || Opaque         || &amp;lt;span style=&amp;quot;color:#FC54FC&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;FC54FC&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|  14 || Opaque         || &amp;lt;span style=&amp;quot;color:#FCFC54&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;FCFC54&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|  15 || Opaque         || &amp;lt;span style=&amp;quot;color:#FCFCFC&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;FCFCFC&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|  16 || Opaque         || &amp;lt;span style=&amp;quot;color:#246820&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;246820&amp;lt;/tt&amp;gt; || Green || Grass&lt;br /&gt;
|-&lt;br /&gt;
|  17 || Opaque         || &amp;lt;span style=&amp;quot;color:#5CFCFC&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;5CFCFC&amp;lt;/tt&amp;gt; || Cyan  || Sky&lt;br /&gt;
|-&lt;br /&gt;
|  18 || Opaque         || &amp;lt;span style=&amp;quot;color:#FCFCFC&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;FCFCFC&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|  19 || Opaque         || &amp;lt;span style=&amp;quot;color:#484848&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;484848&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|  20 || Opaque         || &amp;lt;span style=&amp;quot;color:#383838&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;383838&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|  21 || Opaque         || &amp;lt;span style=&amp;quot;color:#FCFC54&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;FCFC54&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|  22 || Grate          || &amp;lt;span style=&amp;quot;color:#484848&amp;quot;&amp;gt;▒▒▒▒&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;484848&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|  23 || Grate          || &amp;lt;span style=&amp;quot;color:#202020&amp;quot;&amp;gt;▒▒▒▒&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;202020&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|  24 || Grate          || &amp;lt;span style=&amp;quot;color:#FCFC54&amp;quot;&amp;gt;▒▒▒▒&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;FCFC54&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|  25 || Opaque         || &amp;lt;span style=&amp;quot;color:#9C6438&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;9C6438&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|  26 || Opaque         || &amp;lt;span style=&amp;quot;color:#B48054&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;B48054&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|  27 || Opaque         || &amp;lt;span style=&amp;quot;color:#CCA080&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;CCA080&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|  28 || Opaque         || &amp;lt;span style=&amp;quot;color:#D8FCFC&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;D8FCFC&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|  29 || Opaque         || &amp;lt;span style=&amp;quot;color:#9CFCFC&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;9CFCFC&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|  30 || Opaque         || &amp;lt;span style=&amp;quot;color:#5CFCFC&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;5CFCFC&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|  31 || Opaque         || &amp;lt;span style=&amp;quot;color:#E4C4AC&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;E4C4AC&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|  32 || Opaque         || &amp;lt;span style=&amp;quot;color:#C0906C&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;C0906C&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|  33 || Opaque         || &amp;lt;span style=&amp;quot;color:#9C6438&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;9C6438&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|  34 || Grate          || &amp;lt;span style=&amp;quot;color:#9C9CFC&amp;quot;&amp;gt;▒▒▒▒&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;9C9CFC&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|  35 || Opaque         || &amp;lt;span style=&amp;quot;color:#FC4040&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;FC4040&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|  36 || Opaque         || &amp;lt;span style=&amp;quot;color:#FC7C7C&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;FC7C7C&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|  37 || Opaque         || &amp;lt;span style=&amp;quot;color:#FC40FC&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;FC40FC&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|  38 || Opaque         || &amp;lt;span style=&amp;quot;color:#383838&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;383838&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|  39 || Opaque         || &amp;lt;span style=&amp;quot;color:#202020&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;202020&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|  40 || Opaque         || &amp;lt;span style=&amp;quot;color:#C0C0C0&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;C0C0C0&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|  41 || Opaque         || &amp;lt;span style=&amp;quot;color:#00A8A8&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;00A8A8&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|  42 || Opaque         || &amp;lt;span style=&amp;quot;color:#54FCFC&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;54FCFC&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|  43 || Opaque         || &amp;lt;span style=&amp;quot;color:#545454&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;545454&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|  44 || Opaque         || &amp;lt;span style=&amp;quot;color:#000000&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;000000&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|  45 || Opaque         || &amp;lt;span style=&amp;quot;color:#A80000&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;A80000&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|  46 || Opaque         || &amp;lt;span style=&amp;quot;color:#A80000&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;A80000&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|  47 || Opaque         || &amp;lt;span style=&amp;quot;color:#FC5454&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;FC5454&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|  48 || Opaque         || &amp;lt;span style=&amp;quot;color:#00007C&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;00007C&amp;lt;/tt&amp;gt; || Blue 1     || Car body&lt;br /&gt;
|-&lt;br /&gt;
|  49 || Opaque         || &amp;lt;span style=&amp;quot;color:#0000A8&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;0000A8&amp;lt;/tt&amp;gt; || Blue 2     || Car body&lt;br /&gt;
|-&lt;br /&gt;
|  50 || Opaque         || &amp;lt;span style=&amp;quot;color:#0000D0&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;0000D0&amp;lt;/tt&amp;gt; || Blue 3     || Car body&lt;br /&gt;
|-&lt;br /&gt;
|  51 || Opaque         || &amp;lt;span style=&amp;quot;color:#0004FC&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;0004FC&amp;lt;/tt&amp;gt; || Blue 4     || Car body&lt;br /&gt;
|-&lt;br /&gt;
|  52 || Opaque         || &amp;lt;span style=&amp;quot;color:#B40000&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;B40000&amp;lt;/tt&amp;gt; || Red 1      || Car body&lt;br /&gt;
|-&lt;br /&gt;
|  53 || Opaque         || &amp;lt;span style=&amp;quot;color:#E40000&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;E40000&amp;lt;/tt&amp;gt; || Red 2      || Car body&lt;br /&gt;
|-&lt;br /&gt;
|  54 || Opaque         || &amp;lt;span style=&amp;quot;color:#FC2020&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;FC2020&amp;lt;/tt&amp;gt; || Red 3      || Car body&lt;br /&gt;
|-&lt;br /&gt;
|  55 || Opaque         || &amp;lt;span style=&amp;quot;color:#FC4040&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;FC4040&amp;lt;/tt&amp;gt; || Red 4      || Car body&lt;br /&gt;
|-&lt;br /&gt;
|  56 || Opaque         || &amp;lt;span style=&amp;quot;color:#545454&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;545454&amp;lt;/tt&amp;gt; || Graphite 1 || Car body&lt;br /&gt;
|-&lt;br /&gt;
|  57 || Opaque         || &amp;lt;span style=&amp;quot;color:#606060&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;606060&amp;lt;/tt&amp;gt; || Graphite 2 || Car body&lt;br /&gt;
|-&lt;br /&gt;
|  58 || Opaque         || &amp;lt;span style=&amp;quot;color:#707070&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;707070&amp;lt;/tt&amp;gt; || Graphite 3 || Car body&lt;br /&gt;
|-&lt;br /&gt;
|  59 || Opaque         || &amp;lt;span style=&amp;quot;color:#7C7C7C&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;7C7C7C&amp;lt;/tt&amp;gt; || Graphite 4 || Car body&lt;br /&gt;
|-&lt;br /&gt;
|  60 || Opaque         || &amp;lt;span style=&amp;quot;color:#E4D800&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;E4D800&amp;lt;/tt&amp;gt; || Yellow 1   || Car body&lt;br /&gt;
|-&lt;br /&gt;
|  61 || Opaque         || &amp;lt;span style=&amp;quot;color:#FCF420&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;FCF420&amp;lt;/tt&amp;gt; || Yellow 2   || Car body&lt;br /&gt;
|-&lt;br /&gt;
|  62 || Opaque         || &amp;lt;span style=&amp;quot;color:#FCF85C&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;FCF85C&amp;lt;/tt&amp;gt; || Yellow 3   || Car body&lt;br /&gt;
|-&lt;br /&gt;
|  63 || Opaque         || &amp;lt;span style=&amp;quot;color:#FCFC9C&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;FCFC9C&amp;lt;/tt&amp;gt; || Yellow 4   || Car body&lt;br /&gt;
|-&lt;br /&gt;
|  64 || Opaque         || &amp;lt;span style=&amp;quot;color:#009C9C&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;009C9C&amp;lt;/tt&amp;gt; || Cyan 1     || Car body&lt;br /&gt;
|-&lt;br /&gt;
|  65 || Opaque         || &amp;lt;span style=&amp;quot;color:#00CCCC&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;00CCCC&amp;lt;/tt&amp;gt; || Cyan 2     || Car body&lt;br /&gt;
|-&lt;br /&gt;
|  66 || Opaque         || &amp;lt;span style=&amp;quot;color:#00E4E4&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;00E4E4&amp;lt;/tt&amp;gt; || Cyan 3     || Car body&lt;br /&gt;
|-&lt;br /&gt;
|  67 || Opaque         || &amp;lt;span style=&amp;quot;color:#40FCFC&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;40FCFC&amp;lt;/tt&amp;gt; || Cyan 4     || Car body&lt;br /&gt;
|-&lt;br /&gt;
|  68 || Opaque         || &amp;lt;span style=&amp;quot;color:#508400&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;508400&amp;lt;/tt&amp;gt; || Green 1    || Car body&lt;br /&gt;
|-&lt;br /&gt;
|  69 || Opaque         || &amp;lt;span style=&amp;quot;color:#74B400&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;74B400&amp;lt;/tt&amp;gt; || Green 2    || Car body&lt;br /&gt;
|-&lt;br /&gt;
|  70 || Opaque         || &amp;lt;span style=&amp;quot;color:#90E400&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;90E400&amp;lt;/tt&amp;gt; || Green 3    || Car body&lt;br /&gt;
|-&lt;br /&gt;
|  71 || Opaque         || &amp;lt;span style=&amp;quot;color:#A0FC00&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;A0FC00&amp;lt;/tt&amp;gt; || Green 4    || Car body&lt;br /&gt;
|-&lt;br /&gt;
|  72 || Opaque         || &amp;lt;span style=&amp;quot;color:#440070&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;440070&amp;lt;/tt&amp;gt; || Purple 1   || Car body&lt;br /&gt;
|-&lt;br /&gt;
|  73 || Opaque         || &amp;lt;span style=&amp;quot;color:#60009C&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;60009C&amp;lt;/tt&amp;gt; || Purple 2   || Car body&lt;br /&gt;
|-&lt;br /&gt;
|  74 || Opaque         || &amp;lt;span style=&amp;quot;color:#8000CC&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;8000CC&amp;lt;/tt&amp;gt; || Purple 3   || Car body&lt;br /&gt;
|-&lt;br /&gt;
|  75 || Opaque         || &amp;lt;span style=&amp;quot;color:#A800FC&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;A800FC&amp;lt;/tt&amp;gt; || Purple 4   || Car body&lt;br /&gt;
|-&lt;br /&gt;
|  76 || Opaque         || &amp;lt;span style=&amp;quot;color:#B0B0B0&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;B0B0B0&amp;lt;/tt&amp;gt; || Silver 1   || Car body&lt;br /&gt;
|-&lt;br /&gt;
|  77 || Opaque         || &amp;lt;span style=&amp;quot;color:#C0C0C0&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;C0C0C0&amp;lt;/tt&amp;gt; || Silver 2   || Car body&lt;br /&gt;
|-&lt;br /&gt;
|  78 || Opaque         || &amp;lt;span style=&amp;quot;color:#CCCCCC&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;CCCCCC&amp;lt;/tt&amp;gt; || Silver 3   || Car body&lt;br /&gt;
|-&lt;br /&gt;
|  79 || Opaque         || &amp;lt;span style=&amp;quot;color:#DCDCDC&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;DCDCDC&amp;lt;/tt&amp;gt; || Silver 4   || Car body&lt;br /&gt;
|-&lt;br /&gt;
|  80 || Opaque         || &amp;lt;span style=&amp;quot;color:#6C5800&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;6C5800&amp;lt;/tt&amp;gt; || Golden 1   || Car body&lt;br /&gt;
|-&lt;br /&gt;
|  81 || Opaque         || &amp;lt;span style=&amp;quot;color:#847400&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;847400&amp;lt;/tt&amp;gt; || Golden 2   || Car body&lt;br /&gt;
|-&lt;br /&gt;
|  82 || Opaque         || &amp;lt;span style=&amp;quot;color:#B4A400&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;B4A400&amp;lt;/tt&amp;gt; || Golden 3   || Car body&lt;br /&gt;
|-&lt;br /&gt;
|  83 || Opaque         || &amp;lt;span style=&amp;quot;color:#CCC000&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;CCC000&amp;lt;/tt&amp;gt; || Golden 4   || Car body&lt;br /&gt;
|-&lt;br /&gt;
|  84 || Opaque         || &amp;lt;span style=&amp;quot;color:#700000&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;700000&amp;lt;/tt&amp;gt; || Burgundy 1 || Car body&lt;br /&gt;
|-&lt;br /&gt;
|  85 || Opaque         || &amp;lt;span style=&amp;quot;color:#840000&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;840000&amp;lt;/tt&amp;gt; || Burgundy 2 || Car body&lt;br /&gt;
|-&lt;br /&gt;
|  86 || Opaque         || &amp;lt;span style=&amp;quot;color:#B40000&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;B40000&amp;lt;/tt&amp;gt; || Burgundy 3 || Car body&lt;br /&gt;
|-&lt;br /&gt;
|  87 || Opaque         || &amp;lt;span style=&amp;quot;color:#CC0000&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;CC0000&amp;lt;/tt&amp;gt; || Burgundy 4 || Car body&lt;br /&gt;
|-&lt;br /&gt;
|  88 || Opaque         || &amp;lt;span style=&amp;quot;color:#000040&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;000040&amp;lt;/tt&amp;gt; || Violet 1   || Car body&lt;br /&gt;
|-&lt;br /&gt;
|  89 || Opaque         || &amp;lt;span style=&amp;quot;color:#280040&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;280040&amp;lt;/tt&amp;gt; || Violet 2   || Car body&lt;br /&gt;
|-&lt;br /&gt;
|  90 || Opaque         || &amp;lt;span style=&amp;quot;color:#340058&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;340058&amp;lt;/tt&amp;gt; || Violet 3   || Car body&lt;br /&gt;
|-&lt;br /&gt;
|  91 || Opaque         || &amp;lt;span style=&amp;quot;color:#500084&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;500084&amp;lt;/tt&amp;gt; || Violet 4   || Car body&lt;br /&gt;
|-&lt;br /&gt;
|  92 || Opaque         || &amp;lt;span style=&amp;quot;color:#383838&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;383838&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|  93 || Opaque         || &amp;lt;span style=&amp;quot;color:#484848&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;484848&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|  94 || Grate          || &amp;lt;span style=&amp;quot;color:#CCCCCC&amp;quot;&amp;gt;▒▒▒▒&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;CCCCCC&amp;lt;/tt&amp;gt; || || Tennis net&lt;br /&gt;
|-&lt;br /&gt;
|  95 || Opaque         || &amp;lt;span style=&amp;quot;color:#74B400&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;74B400&amp;lt;/tt&amp;gt; || || Tennis grass&lt;br /&gt;
|-&lt;br /&gt;
|  96 || Opaque         || &amp;lt;span style=&amp;quot;color:#FCFCFC&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;FCFCFC&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|  97 || Opaque         || &amp;lt;span style=&amp;quot;color:#A8A8A8&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;A8A8A8&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|  98 || Opaque         || &amp;lt;span style=&amp;quot;color:#9C6438&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;9C6438&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|  99 || Opaque         || &amp;lt;span style=&amp;quot;color:#C0602C&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;C0602C&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| 100 || Opaque         || &amp;lt;span style=&amp;quot;color:#0080D0&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;0080D0&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| 101 || Opaque         || &amp;lt;span style=&amp;quot;color:#84E084&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;84E084&amp;lt;/tt&amp;gt; || || Grass&lt;br /&gt;
|-&lt;br /&gt;
| 102 || Opaque         || &amp;lt;span style=&amp;quot;color:#70C46C&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;70C46C&amp;lt;/tt&amp;gt; || || Grass&lt;br /&gt;
|-&lt;br /&gt;
| 103 || Opaque         || &amp;lt;span style=&amp;quot;color:#58A858&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;58A858&amp;lt;/tt&amp;gt; || || Grass&lt;br /&gt;
|-&lt;br /&gt;
| 104 || Opaque         || &amp;lt;span style=&amp;quot;color:#509C4C&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;509C4C&amp;lt;/tt&amp;gt; || || Grass&lt;br /&gt;
|-&lt;br /&gt;
| 105 || Opaque         || &amp;lt;span style=&amp;quot;color:#388034&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;388034&amp;lt;/tt&amp;gt; || || Grass&lt;br /&gt;
|-&lt;br /&gt;
| 106 || Opaque         || &amp;lt;span style=&amp;quot;color:#DCDCDC&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;DCDCDC&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| 107 || Opaque         || &amp;lt;span style=&amp;quot;color:#B0B0B0&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;B0B0B0&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| 108 || Opaque         || &amp;lt;span style=&amp;quot;color:#905410&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;905410&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| 109 || Opaque         || &amp;lt;span style=&amp;quot;color:#6C5800&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;6C5800&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| 110 || Opaque         || &amp;lt;span style=&amp;quot;color:#580000&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;580000&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| 111 || Opaque         || &amp;lt;span style=&amp;quot;color:#744008&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;744008&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| 112 || Opaque         || &amp;lt;span style=&amp;quot;color:#700000&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;700000&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| 113 || Opaque         || &amp;lt;span style=&amp;quot;color:#80542C&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;80542C&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| 114 || Opaque         || &amp;lt;span style=&amp;quot;color:#540054&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;540054&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| 115 || Opaque         || &amp;lt;span style=&amp;quot;color:#A400A4&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;A400A4&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| 116 || Opaque         || &amp;lt;span style=&amp;quot;color:#E000E4&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;E000E4&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| 117 || Opaque         || &amp;lt;span style=&amp;quot;color:#FC5CFC&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;FC5CFC&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| 118 || Transparent    || &amp;lt;span style=&amp;quot;color:#FFFFFF&amp;quot;&amp;gt;​​​​​&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;N/A&amp;lt;/tt&amp;gt; || || Windmill animation mask&lt;br /&gt;
|-&lt;br /&gt;
| 119 || Grille         || &amp;lt;span style=&amp;quot;color:#484848&amp;quot;&amp;gt;▒▒▒▒&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;484848&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| 120 || Inverse grille || &amp;lt;span style=&amp;quot;color:#2C2C2C&amp;quot;&amp;gt;▒▒▒▒&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;2C2C2C&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| 121 || Glass          || &amp;lt;span style=&amp;quot;color:#FCFCFC&amp;quot;&amp;gt;▓▓▓▓&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;FCFCFC&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| 122 || Inverse glass  || &amp;lt;span style=&amp;quot;color:#B0B0B0&amp;quot;&amp;gt;░░░░&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;B0B0B0&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| 123 || Glass          || &amp;lt;span style=&amp;quot;color:#FCF85C&amp;quot;&amp;gt;▓▓▓▓&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;FCF85C&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| 124 || Inverse glass  || &amp;lt;span style=&amp;quot;color:#FCAC54&amp;quot;&amp;gt;░░░░&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;FCAC54&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| 125 || Glass          || &amp;lt;span style=&amp;quot;color:#FC0000&amp;quot;&amp;gt;▓▓▓▓&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;FC0000&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| 126 || Inverse glass  || &amp;lt;span style=&amp;quot;color:#9C0000&amp;quot;&amp;gt;░░░░&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;9C0000&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| 127 || Opaque         || &amp;lt;span style=&amp;quot;color:#FC5454&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;FC5454&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| 128 || Opaque         || &amp;lt;span style=&amp;quot;color:#DCDCDC&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;DCDCDC&amp;lt;/tt&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==Patterns==&lt;br /&gt;
Patterns are used as a mask when drawing the polygon akin to polygon stippling in OpenGL.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;gallery widths=&amp;quot;128px&amp;quot; heights=&amp;quot;128px&amp;quot; perrow=&amp;quot;3&amp;quot;&amp;gt;&lt;br /&gt;
Image:Pattern_Grille.png|Grille&lt;br /&gt;
Image:Pattern_Glass.png|Glass (lights)&lt;br /&gt;
Image:Pattern_Grate.png|Grate (ramps, bridges)&lt;br /&gt;
Image:Pattern_Grille_Inverse.png|Inverse grille&lt;br /&gt;
Image:Pattern_Glass_Inverse.png|Inverse glass&lt;br /&gt;
&amp;lt;/gallery&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Category:Game]]&lt;/div&gt;</summary>
		<author><name>Dstien</name></author>
	</entry>
	<entry>
		<id>https://wiki.stunts.hu/index.php?title=Car_files&amp;diff=700</id>
		<title>Car files</title>
		<link rel="alternate" type="text/html" href="https://wiki.stunts.hu/index.php?title=Car_files&amp;diff=700"/>
		<updated>2008-04-28T00:04:13Z</updated>

		<summary type="html">&lt;p&gt;Dstien: /* Editing and combining car graphics */ dstein → dstien&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Stunts cars are made of four different [[Resource file format|resource files]]: st*.p3s, stda*.pvs, stdb*.pvs and car*.res ; where the * stands for an arbitrary 4-letter abbreviation shared by files of the same car. All of the car graphics are stored in the [[Compression|compressed]] .p3s and .pvs files. The car*.res contains numerical and text parameters, including data about car performance essential to the creation of [[Cheated Cars|tuned cars]]. &lt;br /&gt;
&lt;br /&gt;
==Graphics files (.p3s/.pvs)==&lt;br /&gt;
&lt;br /&gt;
Different aspects of a car&#039;s appearance are stored in each of the graphic files:&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;st*.p3s&#039;&#039;&#039; - [[Resource file format#3d shapes|3d shape resource]] file that stores the graphical 3D models of the car, including their colour data.&lt;br /&gt;
*&#039;&#039;&#039;stda*.pvs&#039;&#039;&#039; - [[Resource file format#Bitmap images|Bitmap resource]] file that contains the dashboard image, including the shifting stick&#039;s base. &lt;br /&gt;
*&#039;&#039;&#039;stdb*.pvs&#039;&#039;&#039; - [[Resource file format#Bitmap images|Bitmap resource]] file that contains the shifting knob. For the [[Corvette ZR1|Corvette]], it also stores the digital speedometer graphics.&lt;br /&gt;
&lt;br /&gt;
Each of the files contain a number of independent resources, used on different places or in-game situations. Here a rundown of those resources contained within each file will be presented. For an explanation of internal structure of the resources, applicable to all files here discussed, check the [[Resource file format]] article. It is important to emphasize all graphics files are [[Compression|compressed]], and thus any visualization or edition of structure calls for prior decompression. &lt;br /&gt;
&lt;br /&gt;
===3D shapes (st*.p3s)===&lt;br /&gt;
[[image:Resdifcar0car1.png|240px|right|thumb|An illustration of the resolution differences between car0 and car1 shapes. On this image, car0 was used instead of the usual car1 to render the Indycar on-track. The screenshot was taken with the car on the ground, and under F3 camera fully zoomed out.]]&lt;br /&gt;
Standard st*.p3s files contain seven 3D shape resources, each being used in different circumstances: &lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;car0&#039;&#039;&#039; shape is the one used in the car selection screen. It is richly detailed for Stunts usual standards, and has pretty high internal resolution. &lt;br /&gt;
*&#039;&#039;&#039;car1&#039;&#039;&#039; shape corresponds to the car actually rendered on-track. Its resolution is much smaller than the car0 shape, the scaling down factor being in the order of 1:20, thus explaining why many fine details seen on the &amp;quot;showroom&amp;quot; car are not seen on-track. &lt;br /&gt;
*&#039;&#039;&#039;car2&#039;&#039;&#039; shape is the very long distance model, used only for the initial zoom-in animation that precedes the &amp;quot;Fasten your seatbelt!&amp;quot; message at the start of a race. It has very low resolution, to the point of being barely recognizable.&lt;br /&gt;
*&#039;&#039;&#039;exp0&#039;&#039;&#039;, &#039;&#039;&#039;exp1&#039;&#039;&#039;, &#039;&#039;&#039;exp2&#039;&#039;&#039; and &#039;&#039;&#039;exp3&#039;&#039;&#039; aren&#039;t really proper 3D shapes, but rather individual lines and polygons that make up the bits of debris seen after a crash.&lt;br /&gt;
&lt;br /&gt;
===Dashboard static parts (stda*.pvs)===&lt;br /&gt;
&lt;br /&gt;
A car dashboard is composed by a number of separate bitmaps, not of them being used by all cars:&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;!cg0&#039;&#039;&#039; and &#039;&#039;&#039;!eg0&#039;&#039;&#039; are alternative palettes for non-VGA graphic modes.&lt;br /&gt;
*&#039;&#039;&#039;dash&#039;&#039;&#039; is the base panel of the dashboard, covering most of its drawn area.&lt;br /&gt;
*&#039;&#039;&#039;dast&#039;&#039;&#039; complements the top of the dash bitmap with curved areas, as seen on the [[Porsche March Indy|Indy]] for instance. Since all bitmap resources   correspond, naturally, to rectangular areas, there&#039;s an additional bitmap, &#039;&#039;&#039;dasm&#039;&#039;&#039;, which acts as an alpha mask in order to have the proper looks of a curved surface instead of a rectangular block.&lt;br /&gt;
*&#039;&#039;&#039;roof&#039;&#039;&#039; is the strip seen atop above the windshield for a number of cars - for instance, the ones containing &amp;quot;PORSCHE&amp;quot; or &amp;quot;JAGUAR&amp;quot; inscriptions on the [[IMSA]] cars.&lt;br /&gt;
*&#039;&#039;&#039;whl2&#039;&#039;&#039; is the centered steering wheel bitmap. The internal pixel coordinates of it are used to define steering wheel dot positions in the car*.res.&lt;br /&gt;
*&#039;&#039;&#039;whl1&#039;&#039;&#039; and &#039;&#039;&#039;whl3&#039;&#039;&#039; are graphics for the wheel steered left and right respectively.&lt;br /&gt;
*&#039;&#039;&#039;ins2&#039;&#039;&#039; corresponds to the meters - tachometer and/or analog speedometer. Although the bitmap itself is redundant for all default cars, since the meter graphics are included in dash as well, ins2 has an actual purpose: define the internal coordinates for speedometer/tachometer needle render, controlled by car*.res.&lt;br /&gt;
*&#039;&#039;&#039;ins1&#039;&#039;&#039; and &#039;&#039;&#039;ins3&#039;&#039;&#039; are complementary graphics corresponding to small sections of the dashboard uncovered when the wheel is steered left or right (and so they are complementary to whl1 and whl3, in that order). Since the images are not rectangular, alpha masks &#039;&#039;&#039;inm1&#039;&#039;&#039; and &#039;&#039;&#039;inm3&#039;&#039;&#039; are needed, just like dasm was for dast.&lt;br /&gt;
*&#039;&#039;&#039;gbox&#039;&#039;&#039; is the shifting stick base. Coordinates for shifting knob positions are defined within the reference frame of this bitmap.&lt;br /&gt;
&lt;br /&gt;
===Dashboard moving parts (stdb*.pvs)=== &lt;br /&gt;
&lt;br /&gt;
The stdb*.pvs file contains a few auxiliary bitmaps that are not rendered all the time or change position within the screen often: &lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;!cg0&#039;&#039;&#039; and &#039;&#039;&#039;!eg0&#039;&#039;&#039; are alternative palettes for non-VGA graphic modes.&lt;br /&gt;
*&#039;&#039;&#039;dot &#039;&#039;&#039; is the blue steering wheel dot. As every non-rectangular bitmap, it calls for an alpha mask, in this case called &#039;&#039;&#039;dota&#039;&#039;&#039;.&lt;br /&gt;
*&#039;&#039;&#039;dot1&#039;&#039;&#039; and &#039;&#039;&#039;dot2&#039;&#039;&#039; are strange versions of dot  with a tiny palette-like strip inserted into its top. Their purpose is currently unknown.&lt;br /&gt;
*&#039;&#039;&#039;gnob&#039;&#039;&#039; is the shifting gear knob, and &#039;&#039;&#039;gnab&#039;&#039;&#039;, its alpha mask.&lt;br /&gt;
*From &#039;&#039;&#039;dig0&#039;&#039;&#039; to &#039;&#039;&#039;dig9&#039;&#039;&#039; there are individually-stored digits for Corvette-style digital speedometers. Their rendering is not completely straightforward, as those digits do not are not placed over the dashboard as a rectangular block and yet there are no alpha masks. &lt;br /&gt;
&lt;br /&gt;
All the dashboard moving parts are positioned according to various car*.res parameters, as described in the [[Car parameters#Dashboard controls|Car parameters]] article. The vector-drawn speedometer and tachometer needles are controlled by car*.res as well.&lt;br /&gt;
&lt;br /&gt;
===Editing and combining car graphics===&lt;br /&gt;
&lt;br /&gt;
Graphic files of different cars are independent, and thus can be mixed freely when constructing a new car. The main point of concern when doing so usually is adjusting car*.res so that moving parts of the dashboard behave properly. The classical example of this mix-and-match approach is [[Alan Rotoi]]&#039;s famous [[Melange]].&lt;br /&gt;
The actual edition of the graphics was a long-standing goal of the community that for many years was deemed impossible due the lack of information about the format employed by the developers to compress the files. In March 2008, this riddle was finally solved by [[dstien]], and since then perspectives for modding became extremely interesting (see [[Car files#Tools|Tools]] section further down the article).&lt;br /&gt;
&lt;br /&gt;
==Car behaviour (car*.res)==&lt;br /&gt;
&lt;br /&gt;
All adjustable aspects of a car behaviour are stored in car*.res, a miscellaneous data resource file. It contains both physics data, such as power curves, and visual parameters, like car height in cockpit view or speedometer behaviour. Also, the file also contains the text data displayed at the car selection screen. Data in car*.res may be read and modified by any hex editor, or more conveniently by a specially-designed graphical editor (see the Tools section ahead). &lt;br /&gt;
&lt;br /&gt;
The function of a large fraction of car*.res hex addresses was elucidated over the years, allowing modifications of many car aspects. Here is a quick reference for those addresses, adapted from the chart available at [http://www.kalpen.de/luke/4dinfo.html#cs Lukas Loehrer&#039;s site]. A more throughout discussion on the effects and quirks of the parameters is available at [[Car parameters]]; clicking on a parameter description will lead to the corresponding entry there.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Byte offset !! Function&lt;br /&gt;
|-&lt;br /&gt;
| 26h         || [[Car_parameters#Number_of_gears|Number of gears]]&lt;br /&gt;
|-&lt;br /&gt;
| 28h-29h     || [[Car_parameters#Car_mass|Car mass]]&lt;br /&gt;
|-&lt;br /&gt;
| 2Ah-2Bh     || [[Car parameters#Braking effectiveness|Braking effectiveness]]&lt;br /&gt;
|-&lt;br /&gt;
| 2Ch-2Dh     || [[Car parameters#Idle rpm|Idle rpm]]&lt;br /&gt;
|-&lt;br /&gt;
| 2Eh-2Fh     || [[Car parameters#Downshift rpm|Downshift rpm (auto transm.)]]&lt;br /&gt;
|-&lt;br /&gt;
| 30h-31h     || [[Car parameters#Upshift rpm|Upshift rpm (auto transm.)]]&lt;br /&gt;
|-&lt;br /&gt;
| 32h-33h     || [[Car parameters#Maximum rpm|Maximum rpm]]&lt;br /&gt;
|-&lt;br /&gt;
| 37h-41h     || [[Car parameters#Gear ratios|Gear ratios (odd offsets)]]&lt;br /&gt;
|-&lt;br /&gt;
| 46h-5Ch     || [[Car parameters#Shifting knob positions|Shifting knob positions (even offsets)]]&lt;br /&gt;
|-&lt;br /&gt;
| 5Dh-5Eh     || [[Car parameters#Aerodynamic resistance|Aerodynamic resistance]]&lt;br /&gt;
|-&lt;br /&gt;
| 60h-C7h     || [[Car parameters#Torque curve|Torque curve]]&lt;br /&gt;
|-&lt;br /&gt;
| CAh-CBh     || [[Car parameters#Grip|Grip]]&lt;br /&gt;
|-&lt;br /&gt;
| F6h-F7h     || [[Car parameters#Car height|Car height on cockpit view]]&lt;br /&gt;
|-&lt;br /&gt;
| 110h-14Dh   || [[Car parameters#Steering wheel dot movement|Steering wheel dot movement]]&lt;br /&gt;
|-&lt;br /&gt;
| 14Eh-223h   || [[Car parameters#Speedometer needle movement|Speedometer needle movement]]&lt;br /&gt;
|-&lt;br /&gt;
| 150h-159h   || [[Car parameters#Digital speedometer|Digital speedometer]]&lt;br /&gt;
|-&lt;br /&gt;
| 224h-32Dh   || [[Car parameters#Rev meter needle movement|Rev meter needle movement]]&lt;br /&gt;
|-&lt;br /&gt;
| 32Eh-EOF    || [[Car parameters#Text data|Text data (car selection screen and high score table)]]&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The actual structure of car*.res consists of four resources:&lt;br /&gt;
*&#039;&#039;&#039;simd&#039;&#039;&#039;, which contains all the numerical parameters;&lt;br /&gt;
*&#039;&#039;&#039;edes&#039;&#039;&#039;, a [[Resource file format#Plain text|text resource]] containing the description displayed in the car selection screen;&lt;br /&gt;
*&#039;&#039;&#039;gsna&#039;&#039;&#039;, the 4-letter scoreboard abbreviation stored as a text resource; and&lt;br /&gt;
*&#039;&#039;&#039;gnam&#039;&#039;&#039;, the scoreboard car name.&lt;br /&gt;
&lt;br /&gt;
==Version compatibility==&lt;br /&gt;
&lt;br /&gt;
Cars that use graphic files from Stunts 1.0 do not work properly on 1.1 versions, and vice-versa. Attempting to exchange cars between versions will cause crashes in the car selection screen due to file format incompatibilities. The simpler and naturally uncompressed car*.res files may be exchanged between versions, although car performance won&#039;t be the same due to the known differences between [[Game versions|game versions]] in that respect.&lt;br /&gt;
&lt;br /&gt;
==Tools==&lt;br /&gt;
&lt;br /&gt;
The car*.res files can be read and edited by any hex-editor or text editor able to display files in hexadecimal mode - [http://hte.sourceforge.net HT] and [http://www.vim.org Vim] are examples of each case). A more convenient alternative are graphical hex-editors designed especially for Stunts car hacking. [[Mark_Nailwood|Mark Nailwood]]&#039;s [[Car_Blaster|Car Blaster]], by far the most used of those, has resources such as tags on useful bytes and comparison between cars. Other editors include [[Caredit]] and [[Winedit]].&lt;br /&gt;
&lt;br /&gt;
Modified cars are not recognized in the [[RPL_Info|RPL Info]] tool, also created by [[Mark_Nailwood|Mark Nailwood]].&lt;br /&gt;
&lt;br /&gt;
In 2008, [[dstien]] started development of [[stuntstools]], a set of programs that allow decompression of packed resource files and manipulation of contained resources, already including ,as of now, some import and export capabilities. This landmark event had immediate impact on the possibilities for car modification - the day when we will be able to change car shapes is approaching, and at breathtaking speed...&lt;br /&gt;
&lt;br /&gt;
==See also==&lt;br /&gt;
&lt;br /&gt;
* [[Car_parameters|Car parameters]]&amp;lt;br&amp;gt;&lt;br /&gt;
* [[Car model physics]]&amp;lt;br&amp;gt;&lt;br /&gt;
* [[Cheated_cars|Cheated cars]]&lt;br /&gt;
&lt;br /&gt;
==External Links==&lt;br /&gt;
&lt;br /&gt;
*[http://code.google.com/p/stuntstools/ dstein&#039;s stuntstools Google Code project]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Driving]]&lt;br /&gt;
[[Category:Game]]&lt;/div&gt;</summary>
		<author><name>Dstien</name></author>
	</entry>
	<entry>
		<id>https://wiki.stunts.hu/index.php?title=Resource_file_format&amp;diff=699</id>
		<title>Resource file format</title>
		<link rel="alternate" type="text/html" href="https://wiki.stunts.hu/index.php?title=Resource_file_format&amp;diff=699"/>
		<updated>2008-04-28T00:01:09Z</updated>

		<summary type="html">&lt;p&gt;Dstien: /* 3d shapes */ Materials link.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Stunts game data are stored in a common container format. Files of this format can hold multiple &#039;&#039;resources&#039;&#039;, blocks of data that may be of various types - text, bitmaps, sounds, etc. Resources are uniquely identified within each file solely by a 4-byte name. A resource container file can be encapsulated by [[Compression|compression]].&lt;br /&gt;
&lt;br /&gt;
This document focuses on [[Game versions#PC versions|BB Stunts 1.1]], but details described here may still—partly or wholly—cover other versions, or even other games developed by DSI at the time.&lt;br /&gt;
&lt;br /&gt;
==File names==&lt;br /&gt;
Different file name extensions are used to indicate the content of the files. Compressed files has &#039;&#039;&amp;quot;P&amp;quot;&#039;&#039; (packed) as the first letter of their extensions. Whether the game prefers raw or compressed files varies based on file type.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! File contents           !! Raw !! Compressed !! Preferred&lt;br /&gt;
|-&lt;br /&gt;
| Text and misc. settings || RES || PRE        || Raw&lt;br /&gt;
|-&lt;br /&gt;
| Bitmap images           || VSH || PVS        || Compressed&lt;br /&gt;
|-&lt;br /&gt;
| Icons                   || ESH || PES        || Compressed&lt;br /&gt;
|-&lt;br /&gt;
| 3d shapes               || 3SH || P3S        || Compressed&lt;br /&gt;
|-&lt;br /&gt;
| Music tracks            || KMS || PKM        || Raw&lt;br /&gt;
|-&lt;br /&gt;
| Instrument samples      || VCE || PVC        || Raw&lt;br /&gt;
|-&lt;br /&gt;
| Sound effects           || SFX || PSF        || Raw&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==Structure==&lt;br /&gt;
&lt;br /&gt;
The resource file header consists of two integer fields denoting the total length of the file and the number of resources contained. The following table of contents has a list of ids and a corresponding list of offsets into the remaining data section.&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlC&amp;quot;&amp;gt;// Header&amp;lt;/span&amp;gt;&lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint32&amp;lt;/span&amp;gt; fileLength&lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint16&amp;lt;/span&amp;gt; numResources&lt;br /&gt;
 &lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlC&amp;quot;&amp;gt;// Table of contents&amp;lt;/span&amp;gt;&lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;char&amp;lt;/span&amp;gt;   ids&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;[&amp;lt;/span&amp;gt;numResources&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;][&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;hlN&amp;quot;&amp;gt;4&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;]&amp;lt;/span&amp;gt;&lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint32&amp;lt;/span&amp;gt; offsets&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;[&amp;lt;/span&amp;gt;numResources&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;]&amp;lt;/span&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlC&amp;quot;&amp;gt;// Resource data&amp;lt;/span&amp;gt;&lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;char&amp;lt;/span&amp;gt;   data&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;[]&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Types==&lt;br /&gt;
Resource type can be determined by looking at the resource&#039;s id string and/or the source file name.&lt;br /&gt;
&lt;br /&gt;
===Plain text===&lt;br /&gt;
Text resources are null-terminated [http://en.wikipedia.org/wiki/C_string C strings] found in &amp;lt;tt&amp;gt;RES&amp;lt;/tt&amp;gt;/&amp;lt;tt&amp;gt;PRE&amp;lt;/tt&amp;gt; files. Strings can contain non-alphanumeric codes used by the game to achieve certain effects. Most prominent is the &#039;&#039;&amp;quot;]&amp;quot;&#039;&#039; (right square bracket) used to represent [http://en.wikipedia.org/wiki/Newline newline] in multi-line text.&lt;br /&gt;
&lt;br /&gt;
===Bitmap images===&lt;br /&gt;
[[Image:Stunts-pal-vga.png|128px|right|thumb|VGA palette used by bitmap images. Value 255 is transparency.]]&lt;br /&gt;
Bitmaps are images with 8-bit color depth using a [[:Image:Stunts-pal-vga.png|fixed palette]] in VGA mode. Special bitmaps using the naming scheme &amp;lt;tt&amp;gt;!cg_&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;!eg_&amp;lt;/tt&amp;gt; provides color mapping for graphics modes with fewer available colors.&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint16&amp;lt;/span&amp;gt; width&lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint16&amp;lt;/span&amp;gt; height&lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint16&amp;lt;/span&amp;gt; unknown1&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;[&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;hlN&amp;quot;&amp;gt;4&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;]&amp;lt;/span&amp;gt;&lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt;  unknown2&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;[&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;hlN&amp;quot;&amp;gt;4&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;]&amp;lt;/span&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt;  image&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;[&amp;lt;/span&amp;gt;width &amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;*&amp;lt;/span&amp;gt; height&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;]&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Parts of this structure are not fully understood. &amp;lt;tt&amp;gt;unknown1&amp;lt;/tt&amp;gt; appears to be related to Stunts&#039; internal memory management. &amp;lt;tt&amp;gt;unknown2&amp;lt;/tt&amp;gt; seems to affect how image pixels are organized in compressed resource files, likely to gain more effective [http://en.wikipedia.org/wiki/Run-length_encoding run-length compression]. Images with pixel data stored as continuos horizontal lines has &amp;lt;tt&amp;gt;unknown2&amp;lt;/tt&amp;gt; set to &amp;lt;code&amp;gt;{ 0x1, 0x2, 0x4, 0x8 }&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
{{sectstub}}&lt;br /&gt;
&lt;br /&gt;
===Icons===&lt;br /&gt;
{{sectstub}}&lt;br /&gt;
&lt;br /&gt;
===3d shapes===&lt;br /&gt;
Shapes are composed of a vertex list and a list of primitives. Primitives are basic shapes that can have different types, such as polygons or wheels. Depending on the type it contains a number of indices into the vertex list needed to draw the shape, color variations and some rendering hints. Stunts&#039; coordinate system use 16-bit signed integers, making the resolution relative to the scale of the model. Shapes presented in the car selection screen are more detailed than in-game shapes, thus requiring larger scaling.&lt;br /&gt;
&lt;br /&gt;
Due to the counter header fields being stored in single bytes, the total amount of vertices and primitives are limited to 255 per shape.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Main strcture&#039;&#039;&#039;&lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt;     numVertices&lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt;     numPrimitives&lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt;     numPaintJobs&lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt;     reserved &amp;lt;span class=&amp;quot;hlC&amp;quot;&amp;gt;// Always == 0&amp;lt;/span&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
 VERTEX    vertices&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;[&amp;lt;/span&amp;gt;numVertices&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;]&amp;lt;/span&amp;gt;&lt;br /&gt;
 UNKNOWN   unknowns&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;[&amp;lt;/span&amp;gt;numPrimitives&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;]&amp;lt;/span&amp;gt;&lt;br /&gt;
 PRIMITIVE primitives&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;[&amp;lt;/span&amp;gt;numPrimitives&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;]&amp;lt;/span&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt;     terminate; &amp;lt;span class=&amp;quot;hlC&amp;quot;&amp;gt;// Always == 0&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Additional structures&#039;&#039;&#039;&lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;struct&amp;lt;/span&amp;gt; VERTEX &amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;{&amp;lt;/span&amp;gt;&lt;br /&gt;
   &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;int16&amp;lt;/span&amp;gt; x&lt;br /&gt;
   &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;int16&amp;lt;/span&amp;gt; y&lt;br /&gt;
   &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;int16&amp;lt;/span&amp;gt; z&lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;}&amp;lt;/span&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;struct&amp;lt;/span&amp;gt; UNKNOWN &amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;{&amp;lt;/span&amp;gt;&lt;br /&gt;
   &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;int8&amp;lt;/span&amp;gt; data&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;[&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;hlN&amp;quot;&amp;gt;8&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;]&amp;lt;/span&amp;gt;&lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;}&amp;lt;/span&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;struct&amp;lt;/span&amp;gt; PRIMITIVE &amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;{&amp;lt;/span&amp;gt;&lt;br /&gt;
   &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt; type&lt;br /&gt;
   &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt; depthIndex&lt;br /&gt;
   &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt; materials&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;[&amp;lt;/span&amp;gt;numPaintJobs&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;]&amp;lt;/span&amp;gt;&lt;br /&gt;
   &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt; indices&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;[&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;hlC&amp;quot;&amp;gt;...&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;]&amp;lt;/span&amp;gt; &amp;lt;span class=&amp;quot;hlC&amp;quot;&amp;gt;// Size depends on type.&amp;lt;/span&amp;gt;&lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;}&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Primitive types&#039;&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Primitive type !! Vertex indices needed !! Description&lt;br /&gt;
|-&lt;br /&gt;
| 1              || 1              || Particle, 1 pixel&lt;br /&gt;
|-&lt;br /&gt;
| 2              || 2              || Line segment, 1 pixel width&lt;br /&gt;
|-&lt;br /&gt;
| 3–10           || 3–10           || Polygon, &#039;&#039;n&#039;&#039; sides&lt;br /&gt;
|-&lt;br /&gt;
| 11             || 2              || Sphere (center + ~(radius / 2)&lt;br /&gt;
|-&lt;br /&gt;
| 12             || 6              || Wheel&lt;br /&gt;
|-&lt;br /&gt;
| *              || 0              || Ignored&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
[[Image:Wheel_Primitive_Anatomy.png|200px|right|thumb|Anatomy of a wheel shape primitive.]]&lt;br /&gt;
The first three vertices in a wheel primitive marks the center, tire radius and rim radius for the inner wheel-half facing the vehicle. The last three vertices does the same, in the same order, for the outer half of the wheel. Directions does not matter, the vertex locations are only used to measure distances. This rule applies to the sphere primitive as well.&lt;br /&gt;
&lt;br /&gt;
The value &amp;lt;tt&amp;gt;depthIndex&amp;lt;/tt&amp;gt; in the &amp;lt;tt&amp;gt;PRIMITIVE&amp;lt;/tt&amp;gt; structure is used to override the game&#039;s depth clipping in order to avoid flickering when several primitives are being drawn at the exact same depth. Higher value gives the primitive higher precedence.&lt;br /&gt;
&lt;br /&gt;
[[Shape materials|Materials]] are indices into a fixed, internal game structure and are assigned per-primitive. Cars can have multiple paint jobs, every primitive in the shape must set a material for each color scheme.&lt;br /&gt;
&lt;br /&gt;
Experimentation has revealed that &amp;lt;tt&amp;gt;UNKNOWN&amp;lt;/tt&amp;gt; data at least partially controls occlusion culling on primitive level. How, and exactly which parts of this structure does what has yet to be understood.&lt;br /&gt;
&lt;br /&gt;
{{sectstub}}&lt;br /&gt;
&lt;br /&gt;
===Car parameters===&lt;br /&gt;
{{main|Car parameters}}&lt;br /&gt;
{{sectstub}}&lt;br /&gt;
&lt;br /&gt;
===Opponent parameters===&lt;br /&gt;
{{sectstub}}&lt;br /&gt;
&lt;br /&gt;
===Music tracks===&lt;br /&gt;
{{sectstub}}&lt;br /&gt;
&lt;br /&gt;
===Instrument samples===&lt;br /&gt;
{{sectstub}}&lt;br /&gt;
&lt;br /&gt;
===Sound effects===&lt;br /&gt;
{{sectstub}}&lt;br /&gt;
&lt;br /&gt;
==Tools==&lt;br /&gt;
* [[stressed]] - Stunts/4D [Sports] Driving resource editor [http://stuntstools.googlecode.com/].&lt;br /&gt;
&lt;br /&gt;
[[Category:Game]]&lt;/div&gt;</summary>
		<author><name>Dstien</name></author>
	</entry>
	<entry>
		<id>https://wiki.stunts.hu/index.php?title=Shape_materials&amp;diff=698</id>
		<title>Shape materials</title>
		<link rel="alternate" type="text/html" href="https://wiki.stunts.hu/index.php?title=Shape_materials&amp;diff=698"/>
		<updated>2008-04-27T23:58:53Z</updated>

		<summary type="html">&lt;p&gt;Dstien: List of materials.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;3d shapes refers to a predefined set of materials. A material defines the appearance of a polygon with a color and a pattern. Most materials are opaque colors, while some have see-through patterns. Multiple polygons with different material patterns can be layered to achieve certain effects, such as multi-colored grilles and lights.&lt;br /&gt;
&lt;br /&gt;
==Materials==&lt;br /&gt;
{| class=&amp;quot;wikitable sortable&amp;quot;&lt;br /&gt;
! #  !! Pattern         !! Color                                                    !! Name !! Comment&lt;br /&gt;
|-&lt;br /&gt;
|   0 || Opaque         || &amp;lt;span style=&amp;quot;color:#000000&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;000000&amp;lt;/tt&amp;gt; || Black&lt;br /&gt;
|-&lt;br /&gt;
|   1 || Opaque         || &amp;lt;span style=&amp;quot;color:#0000A8&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;0000A8&amp;lt;/tt&amp;gt; || Blue&lt;br /&gt;
|-&lt;br /&gt;
|   2 || Opaque         || &amp;lt;span style=&amp;quot;color:#00A800&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;00A800&amp;lt;/tt&amp;gt; || Green&lt;br /&gt;
|-&lt;br /&gt;
|   3 || Opaque         || &amp;lt;span style=&amp;quot;color:#00A8A8&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;00A8A8&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|   4 || Opaque         || &amp;lt;span style=&amp;quot;color:#A80000&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;A80000&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|   5 || Opaque         || &amp;lt;span style=&amp;quot;color:#A800A8&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;A800A8&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|   6 || Opaque         || &amp;lt;span style=&amp;quot;color:#A85400&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;A85400&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|   7 || Opaque         || &amp;lt;span style=&amp;quot;color:#A8A8A8&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;A8A8A8&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|   8 || Opaque         || &amp;lt;span style=&amp;quot;color:#545454&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;545454&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|   9 || Opaque         || &amp;lt;span style=&amp;quot;color:#5454FC&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;5454FC&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|  10 || Opaque         || &amp;lt;span style=&amp;quot;color:#54FC54&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;54FC54&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|  11 || Opaque         || &amp;lt;span style=&amp;quot;color:#54FCFC&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;54FCFC&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|  12 || Opaque         || &amp;lt;span style=&amp;quot;color:#FC5454&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;FC5454&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|  13 || Opaque         || &amp;lt;span style=&amp;quot;color:#FC54FC&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;FC54FC&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|  14 || Opaque         || &amp;lt;span style=&amp;quot;color:#FCFC54&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;FCFC54&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|  15 || Opaque         || &amp;lt;span style=&amp;quot;color:#FCFCFC&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;FCFCFC&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|  16 || Opaque         || &amp;lt;span style=&amp;quot;color:#246820&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;246820&amp;lt;/tt&amp;gt; || Green || Grass&lt;br /&gt;
|-&lt;br /&gt;
|  17 || Opaque         || &amp;lt;span style=&amp;quot;color:#5CFCFC&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;5CFCFC&amp;lt;/tt&amp;gt; || Cyan  || Sky&lt;br /&gt;
|-&lt;br /&gt;
|  18 || Opaque         || &amp;lt;span style=&amp;quot;color:#FCFCFC&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;FCFCFC&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|  19 || Opaque         || &amp;lt;span style=&amp;quot;color:#484848&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;484848&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|  20 || Opaque         || &amp;lt;span style=&amp;quot;color:#383838&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;383838&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|  21 || Opaque         || &amp;lt;span style=&amp;quot;color:#FCFC54&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;FCFC54&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|  22 || Grate          || &amp;lt;span style=&amp;quot;color:#484848&amp;quot;&amp;gt;▒▒▒▒&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;484848&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|  23 || Grate          || &amp;lt;span style=&amp;quot;color:#202020&amp;quot;&amp;gt;▒▒▒▒&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;202020&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|  24 || Grate          || &amp;lt;span style=&amp;quot;color:#FCFC54&amp;quot;&amp;gt;▒▒▒▒&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;FCFC54&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|  25 || Opaque         || &amp;lt;span style=&amp;quot;color:#9C6438&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;9C6438&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|  26 || Opaque         || &amp;lt;span style=&amp;quot;color:#B48054&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;B48054&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|  27 || Opaque         || &amp;lt;span style=&amp;quot;color:#CCA080&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;CCA080&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|  28 || Opaque         || &amp;lt;span style=&amp;quot;color:#D8FCFC&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;D8FCFC&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|  29 || Opaque         || &amp;lt;span style=&amp;quot;color:#9CFCFC&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;9CFCFC&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|  30 || Opaque         || &amp;lt;span style=&amp;quot;color:#5CFCFC&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;5CFCFC&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|  31 || Opaque         || &amp;lt;span style=&amp;quot;color:#E4C4AC&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;E4C4AC&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|  32 || Opaque         || &amp;lt;span style=&amp;quot;color:#C0906C&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;C0906C&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|  33 || Opaque         || &amp;lt;span style=&amp;quot;color:#9C6438&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;9C6438&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|  34 || Grate          || &amp;lt;span style=&amp;quot;color:#9C9CFC&amp;quot;&amp;gt;▒▒▒▒&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;9C9CFC&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|  35 || Opaque         || &amp;lt;span style=&amp;quot;color:#FC4040&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;FC4040&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|  36 || Opaque         || &amp;lt;span style=&amp;quot;color:#FC7C7C&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;FC7C7C&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|  37 || Opaque         || &amp;lt;span style=&amp;quot;color:#FC40FC&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;FC40FC&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|  38 || Opaque         || &amp;lt;span style=&amp;quot;color:#383838&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;383838&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|  39 || Opaque         || &amp;lt;span style=&amp;quot;color:#202020&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;202020&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|  40 || Opaque         || &amp;lt;span style=&amp;quot;color:#C0C0C0&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;C0C0C0&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|  41 || Opaque         || &amp;lt;span style=&amp;quot;color:#00A8A8&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;00A8A8&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|  42 || Opaque         || &amp;lt;span style=&amp;quot;color:#54FCFC&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;54FCFC&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|  43 || Opaque         || &amp;lt;span style=&amp;quot;color:#545454&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;545454&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|  44 || Opaque         || &amp;lt;span style=&amp;quot;color:#000000&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;000000&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|  45 || Opaque         || &amp;lt;span style=&amp;quot;color:#A80000&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;A80000&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|  46 || Opaque         || &amp;lt;span style=&amp;quot;color:#A80000&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;A80000&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|  47 || Opaque         || &amp;lt;span style=&amp;quot;color:#FC5454&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;FC5454&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|  48 || Opaque         || &amp;lt;span style=&amp;quot;color:#00007C&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;00007C&amp;lt;/tt&amp;gt; || Blue 1     || Car body&lt;br /&gt;
|-&lt;br /&gt;
|  49 || Opaque         || &amp;lt;span style=&amp;quot;color:#0000A8&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;0000A8&amp;lt;/tt&amp;gt; || Blue 2     || Car body&lt;br /&gt;
|-&lt;br /&gt;
|  50 || Opaque         || &amp;lt;span style=&amp;quot;color:#0000D0&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;0000D0&amp;lt;/tt&amp;gt; || Blue 3     || Car body&lt;br /&gt;
|-&lt;br /&gt;
|  51 || Opaque         || &amp;lt;span style=&amp;quot;color:#0004FC&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;0004FC&amp;lt;/tt&amp;gt; || Blue 4     || Car body&lt;br /&gt;
|-&lt;br /&gt;
|  52 || Opaque         || &amp;lt;span style=&amp;quot;color:#B40000&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;B40000&amp;lt;/tt&amp;gt; || Red 1      || Car body&lt;br /&gt;
|-&lt;br /&gt;
|  53 || Opaque         || &amp;lt;span style=&amp;quot;color:#E40000&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;E40000&amp;lt;/tt&amp;gt; || Red 2      || Car body&lt;br /&gt;
|-&lt;br /&gt;
|  54 || Opaque         || &amp;lt;span style=&amp;quot;color:#FC2020&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;FC2020&amp;lt;/tt&amp;gt; || Red 3      || Car body&lt;br /&gt;
|-&lt;br /&gt;
|  55 || Opaque         || &amp;lt;span style=&amp;quot;color:#FC4040&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;FC4040&amp;lt;/tt&amp;gt; || Red 4      || Car body&lt;br /&gt;
|-&lt;br /&gt;
|  56 || Opaque         || &amp;lt;span style=&amp;quot;color:#545454&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;545454&amp;lt;/tt&amp;gt; || Graphite 1 || Car body&lt;br /&gt;
|-&lt;br /&gt;
|  57 || Opaque         || &amp;lt;span style=&amp;quot;color:#606060&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;606060&amp;lt;/tt&amp;gt; || Graphite 2 || Car body&lt;br /&gt;
|-&lt;br /&gt;
|  58 || Opaque         || &amp;lt;span style=&amp;quot;color:#707070&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;707070&amp;lt;/tt&amp;gt; || Graphite 3 || Car body&lt;br /&gt;
|-&lt;br /&gt;
|  59 || Opaque         || &amp;lt;span style=&amp;quot;color:#7C7C7C&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;7C7C7C&amp;lt;/tt&amp;gt; || Graphite 4 || Car body&lt;br /&gt;
|-&lt;br /&gt;
|  60 || Opaque         || &amp;lt;span style=&amp;quot;color:#E4D800&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;E4D800&amp;lt;/tt&amp;gt; || Yellow 1   || Car body&lt;br /&gt;
|-&lt;br /&gt;
|  61 || Opaque         || &amp;lt;span style=&amp;quot;color:#FCF420&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;FCF420&amp;lt;/tt&amp;gt; || Yellow 2   || Car body&lt;br /&gt;
|-&lt;br /&gt;
|  62 || Opaque         || &amp;lt;span style=&amp;quot;color:#FCF85C&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;FCF85C&amp;lt;/tt&amp;gt; || Yellow 3   || Car body&lt;br /&gt;
|-&lt;br /&gt;
|  63 || Opaque         || &amp;lt;span style=&amp;quot;color:#FCFC9C&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;FCFC9C&amp;lt;/tt&amp;gt; || Yellow 4   || Car body&lt;br /&gt;
|-&lt;br /&gt;
|  64 || Opaque         || &amp;lt;span style=&amp;quot;color:#009C9C&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;009C9C&amp;lt;/tt&amp;gt; || Cyan 1     || Car body&lt;br /&gt;
|-&lt;br /&gt;
|  65 || Opaque         || &amp;lt;span style=&amp;quot;color:#00CCCC&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;00CCCC&amp;lt;/tt&amp;gt; || Cyan 2     || Car body&lt;br /&gt;
|-&lt;br /&gt;
|  66 || Opaque         || &amp;lt;span style=&amp;quot;color:#00E4E4&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;00E4E4&amp;lt;/tt&amp;gt; || Cyan 3     || Car body&lt;br /&gt;
|-&lt;br /&gt;
|  67 || Opaque         || &amp;lt;span style=&amp;quot;color:#40FCFC&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;40FCFC&amp;lt;/tt&amp;gt; || Cyan 4     || Car body&lt;br /&gt;
|-&lt;br /&gt;
|  68 || Opaque         || &amp;lt;span style=&amp;quot;color:#508400&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;508400&amp;lt;/tt&amp;gt; || Green 1    || Car body&lt;br /&gt;
|-&lt;br /&gt;
|  69 || Opaque         || &amp;lt;span style=&amp;quot;color:#74B400&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;74B400&amp;lt;/tt&amp;gt; || Green 2    || Car body&lt;br /&gt;
|-&lt;br /&gt;
|  70 || Opaque         || &amp;lt;span style=&amp;quot;color:#90E400&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;90E400&amp;lt;/tt&amp;gt; || Green 3    || Car body&lt;br /&gt;
|-&lt;br /&gt;
|  71 || Opaque         || &amp;lt;span style=&amp;quot;color:#A0FC00&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;A0FC00&amp;lt;/tt&amp;gt; || Green 4    || Car body&lt;br /&gt;
|-&lt;br /&gt;
|  72 || Opaque         || &amp;lt;span style=&amp;quot;color:#440070&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;440070&amp;lt;/tt&amp;gt; || Purple 1   || Car body&lt;br /&gt;
|-&lt;br /&gt;
|  73 || Opaque         || &amp;lt;span style=&amp;quot;color:#60009C&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;60009C&amp;lt;/tt&amp;gt; || Purple 2   || Car body&lt;br /&gt;
|-&lt;br /&gt;
|  74 || Opaque         || &amp;lt;span style=&amp;quot;color:#8000CC&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;8000CC&amp;lt;/tt&amp;gt; || Purple 3   || Car body&lt;br /&gt;
|-&lt;br /&gt;
|  75 || Opaque         || &amp;lt;span style=&amp;quot;color:#A800FC&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;A800FC&amp;lt;/tt&amp;gt; || Purple 4   || Car body&lt;br /&gt;
|-&lt;br /&gt;
|  76 || Opaque         || &amp;lt;span style=&amp;quot;color:#B0B0B0&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;B0B0B0&amp;lt;/tt&amp;gt; || Silver 1   || Car body&lt;br /&gt;
|-&lt;br /&gt;
|  77 || Opaque         || &amp;lt;span style=&amp;quot;color:#C0C0C0&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;C0C0C0&amp;lt;/tt&amp;gt; || Silver 2   || Car body&lt;br /&gt;
|-&lt;br /&gt;
|  78 || Opaque         || &amp;lt;span style=&amp;quot;color:#CCCCCC&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;CCCCCC&amp;lt;/tt&amp;gt; || Silver 3   || Car body&lt;br /&gt;
|-&lt;br /&gt;
|  79 || Opaque         || &amp;lt;span style=&amp;quot;color:#DCDCDC&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;DCDCDC&amp;lt;/tt&amp;gt; || Silver 4   || Car body&lt;br /&gt;
|-&lt;br /&gt;
|  80 || Opaque         || &amp;lt;span style=&amp;quot;color:#6C5800&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;6C5800&amp;lt;/tt&amp;gt; || Golden 1   || Car body&lt;br /&gt;
|-&lt;br /&gt;
|  81 || Opaque         || &amp;lt;span style=&amp;quot;color:#847400&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;847400&amp;lt;/tt&amp;gt; || Golden 2   || Car body&lt;br /&gt;
|-&lt;br /&gt;
|  82 || Opaque         || &amp;lt;span style=&amp;quot;color:#B4A400&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;B4A400&amp;lt;/tt&amp;gt; || Golden 3   || Car body&lt;br /&gt;
|-&lt;br /&gt;
|  83 || Opaque         || &amp;lt;span style=&amp;quot;color:#CCC000&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;CCC000&amp;lt;/tt&amp;gt; || Golden 4   || Car body&lt;br /&gt;
|-&lt;br /&gt;
|  84 || Opaque         || &amp;lt;span style=&amp;quot;color:#700000&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;700000&amp;lt;/tt&amp;gt; || Burgundy 1 || Car body&lt;br /&gt;
|-&lt;br /&gt;
|  85 || Opaque         || &amp;lt;span style=&amp;quot;color:#840000&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;840000&amp;lt;/tt&amp;gt; || Burgundy 2 || Car body&lt;br /&gt;
|-&lt;br /&gt;
|  86 || Opaque         || &amp;lt;span style=&amp;quot;color:#B40000&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;B40000&amp;lt;/tt&amp;gt; || Burgundy 3 || Car body&lt;br /&gt;
|-&lt;br /&gt;
|  87 || Opaque         || &amp;lt;span style=&amp;quot;color:#CC0000&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;CC0000&amp;lt;/tt&amp;gt; || Burgundy 4 || Car body&lt;br /&gt;
|-&lt;br /&gt;
|  88 || Opaque         || &amp;lt;span style=&amp;quot;color:#000040&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;000040&amp;lt;/tt&amp;gt; || Violet 1   || Car body&lt;br /&gt;
|-&lt;br /&gt;
|  89 || Opaque         || &amp;lt;span style=&amp;quot;color:#280040&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;280040&amp;lt;/tt&amp;gt; || Violet 2   || Car body&lt;br /&gt;
|-&lt;br /&gt;
|  90 || Opaque         || &amp;lt;span style=&amp;quot;color:#340058&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;340058&amp;lt;/tt&amp;gt; || Violet 3   || Car body&lt;br /&gt;
|-&lt;br /&gt;
|  91 || Opaque         || &amp;lt;span style=&amp;quot;color:#500084&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;500084&amp;lt;/tt&amp;gt; || Violet 4   || Car body&lt;br /&gt;
|-&lt;br /&gt;
|  92 || Opaque         || &amp;lt;span style=&amp;quot;color:#383838&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;383838&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|  93 || Opaque         || &amp;lt;span style=&amp;quot;color:#484848&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;484848&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|  94 || Grate          || &amp;lt;span style=&amp;quot;color:#CCCCCC&amp;quot;&amp;gt;▒▒▒▒&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;CCCCCC&amp;lt;/tt&amp;gt; || || Tennis net&lt;br /&gt;
|-&lt;br /&gt;
|  95 || Opaque         || &amp;lt;span style=&amp;quot;color:#74B400&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;74B400&amp;lt;/tt&amp;gt; || || Tennis grass&lt;br /&gt;
|-&lt;br /&gt;
|  96 || Opaque         || &amp;lt;span style=&amp;quot;color:#FCFCFC&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;FCFCFC&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|  97 || Opaque         || &amp;lt;span style=&amp;quot;color:#A8A8A8&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;A8A8A8&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|  98 || Opaque         || &amp;lt;span style=&amp;quot;color:#9C6438&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;9C6438&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|  99 || Opaque         || &amp;lt;span style=&amp;quot;color:#C0602C&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;C0602C&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| 100 || Opaque         || &amp;lt;span style=&amp;quot;color:#0080D0&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;0080D0&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| 101 || Opaque         || &amp;lt;span style=&amp;quot;color:#84E084&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;84E084&amp;lt;/tt&amp;gt; || || Grass&lt;br /&gt;
|-&lt;br /&gt;
| 102 || Opaque         || &amp;lt;span style=&amp;quot;color:#70C46C&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;70C46C&amp;lt;/tt&amp;gt; || || Grass&lt;br /&gt;
|-&lt;br /&gt;
| 103 || Opaque         || &amp;lt;span style=&amp;quot;color:#58A858&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;58A858&amp;lt;/tt&amp;gt; || || Grass&lt;br /&gt;
|-&lt;br /&gt;
| 104 || Opaque         || &amp;lt;span style=&amp;quot;color:#509C4C&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;509C4C&amp;lt;/tt&amp;gt; || || Grass&lt;br /&gt;
|-&lt;br /&gt;
| 105 || Opaque         || &amp;lt;span style=&amp;quot;color:#388034&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;388034&amp;lt;/tt&amp;gt; || || Grass&lt;br /&gt;
|-&lt;br /&gt;
| 106 || Opaque         || &amp;lt;span style=&amp;quot;color:#DCDCDC&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;DCDCDC&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| 107 || Opaque         || &amp;lt;span style=&amp;quot;color:#B0B0B0&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;B0B0B0&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| 108 || Opaque         || &amp;lt;span style=&amp;quot;color:#905410&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;905410&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| 109 || Opaque         || &amp;lt;span style=&amp;quot;color:#6C5800&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;6C5800&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| 110 || Opaque         || &amp;lt;span style=&amp;quot;color:#580000&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;580000&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| 111 || Opaque         || &amp;lt;span style=&amp;quot;color:#744008&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;744008&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| 112 || Opaque         || &amp;lt;span style=&amp;quot;color:#700000&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;700000&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| 113 || Opaque         || &amp;lt;span style=&amp;quot;color:#80542C&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;80542C&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| 114 || Opaque         || &amp;lt;span style=&amp;quot;color:#540054&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;540054&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| 115 || Opaque         || &amp;lt;span style=&amp;quot;color:#A400A4&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;A400A4&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| 116 || Opaque         || &amp;lt;span style=&amp;quot;color:#E000E4&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;E000E4&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| 117 || Opaque         || &amp;lt;span style=&amp;quot;color:#FC5CFC&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;FC5CFC&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| 118 || Transparent    || &amp;lt;span style=&amp;quot;color:#FFFFFF&amp;quot;&amp;gt;​​​​​&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;N/A&amp;lt;/tt&amp;gt; || || Windmill animation mask&lt;br /&gt;
|-&lt;br /&gt;
| 119 || Grille         || &amp;lt;span style=&amp;quot;color:#484848&amp;quot;&amp;gt;▒▒▒▒&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;484848&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| 120 || Inverse grille || &amp;lt;span style=&amp;quot;color:#2C2C2C&amp;quot;&amp;gt;▒▒▒▒&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;2C2C2C&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| 121 || Glass          || &amp;lt;span style=&amp;quot;color:#FCFCFC&amp;quot;&amp;gt;▓▓▓▓&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;FCFCFC&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| 122 || Inverse glass  || &amp;lt;span style=&amp;quot;color:#B0B0B0&amp;quot;&amp;gt;░░░░&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;B0B0B0&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| 123 || Glass          || &amp;lt;span style=&amp;quot;color:#FCF85C&amp;quot;&amp;gt;▓▓▓▓&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;FCF85C&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| 124 || Inverse glass  || &amp;lt;span style=&amp;quot;color:#FCAC54&amp;quot;&amp;gt;░░░░&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;FCAC54&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| 125 || Glass          || &amp;lt;span style=&amp;quot;color:#FC0000&amp;quot;&amp;gt;▓▓▓▓&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;FC0000&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| 126 || Inverse glass  || &amp;lt;span style=&amp;quot;color:#9C0000&amp;quot;&amp;gt;░░░░&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;9C0000&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| 127 || Opaque         || &amp;lt;span style=&amp;quot;color:#FC5454&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;FC5454&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| 128 || Opaque         || &amp;lt;span style=&amp;quot;color:#DCDCDC&amp;quot;&amp;gt;████&amp;lt;/span&amp;gt; &amp;lt;tt&amp;gt;DCDCDC&amp;lt;/tt&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==Patterns==&lt;br /&gt;
Patterns are used as a mask when drawing the polygon akin to polygon stippling in OpenGL.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;gallery widths=&amp;quot;128px&amp;quot; heights=&amp;quot;128px&amp;quot; perrow=&amp;quot;3&amp;quot;&amp;gt;&lt;br /&gt;
Image:Pattern_Grille.png|Grille&lt;br /&gt;
Image:Pattern_Glass.png|Glass (lights)&lt;br /&gt;
Image:Pattern_Grate.png|Grate (ramps, bridges)&lt;br /&gt;
Image:Pattern_Grille_Inverse.png|Inverse grille&lt;br /&gt;
Image:Pattern_Glass_Inverse.png|Inverse glass&lt;br /&gt;
&amp;lt;/gallery&amp;gt;&lt;/div&gt;</summary>
		<author><name>Dstien</name></author>
	</entry>
	<entry>
		<id>https://wiki.stunts.hu/index.php?title=File:Pattern_Glass_Inverse.png&amp;diff=697</id>
		<title>File:Pattern Glass Inverse.png</title>
		<link rel="alternate" type="text/html" href="https://wiki.stunts.hu/index.php?title=File:Pattern_Glass_Inverse.png&amp;diff=697"/>
		<updated>2008-04-27T23:20:46Z</updated>

		<summary type="html">&lt;p&gt;Dstien: Inverse glass material pattern.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Inverse glass material pattern.&lt;/div&gt;</summary>
		<author><name>Dstien</name></author>
	</entry>
	<entry>
		<id>https://wiki.stunts.hu/index.php?title=File:Pattern_Glass.png&amp;diff=696</id>
		<title>File:Pattern Glass.png</title>
		<link rel="alternate" type="text/html" href="https://wiki.stunts.hu/index.php?title=File:Pattern_Glass.png&amp;diff=696"/>
		<updated>2008-04-27T23:20:15Z</updated>

		<summary type="html">&lt;p&gt;Dstien: Glass material pattern.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Glass material pattern.&lt;/div&gt;</summary>
		<author><name>Dstien</name></author>
	</entry>
	<entry>
		<id>https://wiki.stunts.hu/index.php?title=File:Pattern_Grille_Inverse.png&amp;diff=695</id>
		<title>File:Pattern Grille Inverse.png</title>
		<link rel="alternate" type="text/html" href="https://wiki.stunts.hu/index.php?title=File:Pattern_Grille_Inverse.png&amp;diff=695"/>
		<updated>2008-04-27T23:19:33Z</updated>

		<summary type="html">&lt;p&gt;Dstien: Inverse grille material pattern.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Inverse grille material pattern.&lt;/div&gt;</summary>
		<author><name>Dstien</name></author>
	</entry>
	<entry>
		<id>https://wiki.stunts.hu/index.php?title=File:Pattern_Grille.png&amp;diff=694</id>
		<title>File:Pattern Grille.png</title>
		<link rel="alternate" type="text/html" href="https://wiki.stunts.hu/index.php?title=File:Pattern_Grille.png&amp;diff=694"/>
		<updated>2008-04-27T23:18:32Z</updated>

		<summary type="html">&lt;p&gt;Dstien: Grille material pattern.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Grille material pattern.&lt;/div&gt;</summary>
		<author><name>Dstien</name></author>
	</entry>
	<entry>
		<id>https://wiki.stunts.hu/index.php?title=File:Pattern_Grate.png&amp;diff=693</id>
		<title>File:Pattern Grate.png</title>
		<link rel="alternate" type="text/html" href="https://wiki.stunts.hu/index.php?title=File:Pattern_Grate.png&amp;diff=693"/>
		<updated>2008-04-27T23:17:34Z</updated>

		<summary type="html">&lt;p&gt;Dstien: Grate material pattern.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Grate material pattern.&lt;/div&gt;</summary>
		<author><name>Dstien</name></author>
	</entry>
	<entry>
		<id>https://wiki.stunts.hu/index.php?title=Resource_file_format&amp;diff=674</id>
		<title>Resource file format</title>
		<link rel="alternate" type="text/html" href="https://wiki.stunts.hu/index.php?title=Resource_file_format&amp;diff=674"/>
		<updated>2008-04-22T18:28:12Z</updated>

		<summary type="html">&lt;p&gt;Dstien: Accidentally removed header.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Stunts game data are stored in a common container format. Files of this format can hold multiple resources of any type, identified only by a 4-byte name. A resource file can be encapsulated by [[Compression|compression]].&lt;br /&gt;
&lt;br /&gt;
This document focuses on [[Game versions#PC versions|BB Stunts 1.1]], but details described here may still—partly or wholly—cover other versions, or even other games developed by DSI at the time.&lt;br /&gt;
&lt;br /&gt;
==File names==&lt;br /&gt;
Different file name extensions are used to indicate the content of the files. Compressed files has &#039;&#039;&amp;quot;P&amp;quot;&#039;&#039; (packed) as the first letter of their extensions. Whether the game prefers raw or compressed files varies based on file type.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! File contents           !! Raw !! Compressed !! Preferred&lt;br /&gt;
|-&lt;br /&gt;
| Text and misc. settings || RES || PRE        || Raw&lt;br /&gt;
|-&lt;br /&gt;
| Bitmap images           || VSH || PVS        || Compressed&lt;br /&gt;
|-&lt;br /&gt;
| Icons                   || ESH || PES        || Compressed&lt;br /&gt;
|-&lt;br /&gt;
| 3d shapes               || 3SH || P3S        || Compressed&lt;br /&gt;
|-&lt;br /&gt;
| Music tracks            || KMS || PKM        || Raw&lt;br /&gt;
|-&lt;br /&gt;
| Instrument samples      || VCE || PVC        || Raw&lt;br /&gt;
|-&lt;br /&gt;
| Sound effects           || SFX || PSF        || Raw&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==Structure==&lt;br /&gt;
&lt;br /&gt;
The resource file header consists of two integer fields denoting the total length of the file and the number of resources contained. The following table of contents has a list of ids and a corresponding list of offsets into the remaining data section.&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlC&amp;quot;&amp;gt;// Header&amp;lt;/span&amp;gt;&lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint32&amp;lt;/span&amp;gt; fileLength&lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint16&amp;lt;/span&amp;gt; numResources&lt;br /&gt;
 &lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlC&amp;quot;&amp;gt;// Table of contents&amp;lt;/span&amp;gt;&lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;char&amp;lt;/span&amp;gt;   ids&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;[&amp;lt;/span&amp;gt;numResources&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;][&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;hlN&amp;quot;&amp;gt;4&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;]&amp;lt;/span&amp;gt;&lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint32&amp;lt;/span&amp;gt; offsets&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;[&amp;lt;/span&amp;gt;numResources&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;]&amp;lt;/span&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlC&amp;quot;&amp;gt;// Resource data&amp;lt;/span&amp;gt;&lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;char&amp;lt;/span&amp;gt;   data&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;[]&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Types==&lt;br /&gt;
Resource type can be determined by looking at the resource&#039;s id string and/or the source file name.&lt;br /&gt;
&lt;br /&gt;
===Plain text===&lt;br /&gt;
Text resources are null-terminated [http://en.wikipedia.org/wiki/C_string C strings] found in &amp;lt;tt&amp;gt;RES&amp;lt;/tt&amp;gt;/&amp;lt;tt&amp;gt;PRE&amp;lt;/tt&amp;gt; files. Strings can contain non-alphanumeric codes used by the game to achieve certain effects. Most prominent is the &#039;&#039;&amp;quot;]&amp;quot;&#039;&#039; (right square bracket) used to represent [http://en.wikipedia.org/wiki/Newline newline] in multi-line text.&lt;br /&gt;
&lt;br /&gt;
===Bitmap images===&lt;br /&gt;
[[Image:Stunts-pal-vga.png|128px|right|thumb|VGA palette used by bitmap images. Value 255 is transparency.]]&lt;br /&gt;
Bitmaps are images with 8-bit color depth using a [[:Image:Stunts-pal-vga.png|fixed palette]] in VGA mode. Special bitmaps using the naming scheme &amp;lt;tt&amp;gt;!cg_&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;!eg_&amp;lt;/tt&amp;gt; provides color mapping for graphics modes with fewer available colors.&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint16&amp;lt;/span&amp;gt; width&lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint16&amp;lt;/span&amp;gt; height&lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint16&amp;lt;/span&amp;gt; unknown1&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;[&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;hlN&amp;quot;&amp;gt;4&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;]&amp;lt;/span&amp;gt;&lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt;  unknown2&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;[&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;hlN&amp;quot;&amp;gt;4&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;]&amp;lt;/span&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt;  image&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;[&amp;lt;/span&amp;gt;width &amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;*&amp;lt;/span&amp;gt; height&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;]&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Parts of this structure are not fully understood. &amp;lt;tt&amp;gt;unknown1&amp;lt;/tt&amp;gt; appears to be related to Stunts&#039; internal memory management. &amp;lt;tt&amp;gt;unknown2&amp;lt;/tt&amp;gt; seems to affect how image pixels are organized in compressed resource files, likely to gain more effective [http://en.wikipedia.org/wiki/Run-length_encoding run-length compression]. Images with pixel data stored as continuos horizontal lines has &amp;lt;tt&amp;gt;unknown2&amp;lt;/tt&amp;gt; set to &amp;lt;code&amp;gt;{ 0x1, 0x2, 0x4, 0x8 }&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
{{sectstub}}&lt;br /&gt;
&lt;br /&gt;
===Icons===&lt;br /&gt;
{{sectstub}}&lt;br /&gt;
&lt;br /&gt;
===3d shapes===&lt;br /&gt;
Shapes are composed of a vertex list and a list of primitives. Primitives are basic shapes that can have different types, such as polygons or wheels. Depending on the type it contains a number of indices into the vertex list needed to draw the shape, color variations and some rendering hints. Stunts&#039; coordinate system use 16-bit signed integers, making the resolution relative to the scale of the model. Shapes presented in the car selection screen are more detailed than in-game shapes, thus requiring larger scaling.&lt;br /&gt;
&lt;br /&gt;
Due to the counter header fields being stored in single bytes, the total amount of vertices and primitives are limited to 255 per shape.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Main strcture&#039;&#039;&#039;&lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt;     numVertices&lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt;     numPrimitives&lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt;     numPaintJobs&lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt;     reserved &amp;lt;span class=&amp;quot;hlC&amp;quot;&amp;gt;// Always == 0&amp;lt;/span&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
 VERTEX    vertices&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;[&amp;lt;/span&amp;gt;numVertices&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;]&amp;lt;/span&amp;gt;&lt;br /&gt;
 UNKNOWN   unknowns&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;[&amp;lt;/span&amp;gt;numPrimitives&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;]&amp;lt;/span&amp;gt;&lt;br /&gt;
 PRIMITIVE primitives&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;[&amp;lt;/span&amp;gt;numPrimitives&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;]&amp;lt;/span&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt;     terminate; &amp;lt;span class=&amp;quot;hlC&amp;quot;&amp;gt;// Always == 0&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Additional structures&#039;&#039;&#039;&lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;struct&amp;lt;/span&amp;gt; VERTEX &amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;{&amp;lt;/span&amp;gt;&lt;br /&gt;
   &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;int16&amp;lt;/span&amp;gt; x&lt;br /&gt;
   &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;int16&amp;lt;/span&amp;gt; y&lt;br /&gt;
   &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;int16&amp;lt;/span&amp;gt; z&lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;}&amp;lt;/span&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;struct&amp;lt;/span&amp;gt; UNKNOWN &amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;{&amp;lt;/span&amp;gt;&lt;br /&gt;
   &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;int8&amp;lt;/span&amp;gt; data&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;[&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;hlN&amp;quot;&amp;gt;8&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;]&amp;lt;/span&amp;gt;&lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;}&amp;lt;/span&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;struct&amp;lt;/span&amp;gt; PRIMITIVE &amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;{&amp;lt;/span&amp;gt;&lt;br /&gt;
   &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt; type&lt;br /&gt;
   &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt; depthIndex&lt;br /&gt;
   &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt; materials&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;[&amp;lt;/span&amp;gt;numPaintJobs&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;]&amp;lt;/span&amp;gt;&lt;br /&gt;
   &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt; indices&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;[&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;hlC&amp;quot;&amp;gt;...&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;]&amp;lt;/span&amp;gt; &amp;lt;span class=&amp;quot;hlC&amp;quot;&amp;gt;// Size depends on type.&amp;lt;/span&amp;gt;&lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;}&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Primitive types&#039;&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Primitive type !! Vertex indices needed !! Description&lt;br /&gt;
|-&lt;br /&gt;
| 1              || 1              || Particle, 1 pixel&lt;br /&gt;
|-&lt;br /&gt;
| 2              || 2              || Line segment, 1 pixel width&lt;br /&gt;
|-&lt;br /&gt;
| 3–10           || 3–10           || Polygon, &#039;&#039;n&#039;&#039; sides&lt;br /&gt;
|-&lt;br /&gt;
| 11             || 2              || Sphere (center + ~(radius / 2)&lt;br /&gt;
|-&lt;br /&gt;
| 12             || 6              || Wheel&lt;br /&gt;
|-&lt;br /&gt;
| *              || 0              || Ignored&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
[[Image:Wheel_Primitive_Anatomy.png|200px|right|thumb|Anatomy of a wheel shape primitive.]]&lt;br /&gt;
The first three vertices in a wheel primitive marks the center, tire radius and rim radius for the inner wheel-half facing the vehicle. The last three vertices does the same, in the same order, for the outer half of the wheel. Directions does not matter, the vertex locations are only used to measure distances. This rule applies to the sphere primitive as well.&lt;br /&gt;
&lt;br /&gt;
The value &amp;lt;tt&amp;gt;depthIndex&amp;lt;/tt&amp;gt; in the &amp;lt;tt&amp;gt;PRIMITIVE&amp;lt;/tt&amp;gt; structure is used to override the game&#039;s depth clipping in order to avoid flickering when several primitives are being drawn at the exact same depth. Higher value gives the primitive higher precedence.&lt;br /&gt;
&lt;br /&gt;
Materials are indices into a fixed, internal game structure and are assigned per-primitive. Cars can have multiple paint jobs, every primitive in the shape must set a material for each color scheme.&lt;br /&gt;
&lt;br /&gt;
Experimentation has revealed that &amp;lt;tt&amp;gt;UNKNOWN&amp;lt;/tt&amp;gt; data at least partially controls occlusion culling on primitive level. How, and exactly which parts of this structure does what has yet to be understood.&lt;br /&gt;
&lt;br /&gt;
{{sectstub}}&lt;br /&gt;
&lt;br /&gt;
===Car parameters===&lt;br /&gt;
{{main|Car parameters}}&lt;br /&gt;
{{sectstub}}&lt;br /&gt;
&lt;br /&gt;
===Opponent parameters===&lt;br /&gt;
{{sectstub}}&lt;br /&gt;
&lt;br /&gt;
===Music tracks===&lt;br /&gt;
{{sectstub}}&lt;br /&gt;
&lt;br /&gt;
===Instrument samples===&lt;br /&gt;
{{sectstub}}&lt;br /&gt;
&lt;br /&gt;
===Sound effects===&lt;br /&gt;
{{sectstub}}&lt;br /&gt;
&lt;br /&gt;
==Tools==&lt;br /&gt;
* [[stressed]] - Stunts/4D [Sports] Driving resource editor [http://stuntstools.googlecode.com/].&lt;br /&gt;
&lt;br /&gt;
[[Category:Game]]&lt;/div&gt;</summary>
		<author><name>Dstien</name></author>
	</entry>
	<entry>
		<id>https://wiki.stunts.hu/index.php?title=Resource_file_format&amp;diff=673</id>
		<title>Resource file format</title>
		<link rel="alternate" type="text/html" href="https://wiki.stunts.hu/index.php?title=Resource_file_format&amp;diff=673"/>
		<updated>2008-04-22T18:25:36Z</updated>

		<summary type="html">&lt;p&gt;Dstien: /* 3d shapes */ Initial spec.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Stunts game data are stored in a common container format. Files of this format can hold multiple resources of any type, identified only by a 4-byte name. A resource file can be encapsulated by [[Compression|compression]].&lt;br /&gt;
&lt;br /&gt;
This document focuses on [[Game versions#PC versions|BB Stunts 1.1]], but details described here may still—partly or wholly—cover other versions, or even other games developed by DSI at the time.&lt;br /&gt;
&lt;br /&gt;
==File names==&lt;br /&gt;
Different file name extensions are used to indicate the content of the files. Compressed files has &#039;&#039;&amp;quot;P&amp;quot;&#039;&#039; (packed) as the first letter of their extensions. Whether the game prefers raw or compressed files varies based on file type.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! File contents           !! Raw !! Compressed !! Preferred&lt;br /&gt;
|-&lt;br /&gt;
| Text and misc. settings || RES || PRE        || Raw&lt;br /&gt;
|-&lt;br /&gt;
| Bitmap images           || VSH || PVS        || Compressed&lt;br /&gt;
|-&lt;br /&gt;
| Icons                   || ESH || PES        || Compressed&lt;br /&gt;
|-&lt;br /&gt;
| 3d shapes               || 3SH || P3S        || Compressed&lt;br /&gt;
|-&lt;br /&gt;
| Music tracks            || KMS || PKM        || Raw&lt;br /&gt;
|-&lt;br /&gt;
| Instrument samples      || VCE || PVC        || Raw&lt;br /&gt;
|-&lt;br /&gt;
| Sound effects           || SFX || PSF        || Raw&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==Structure==&lt;br /&gt;
&lt;br /&gt;
The resource file header consists of two integer fields denoting the total length of the file and the number of resources contained. The following table of contents has a list of ids and a corresponding list of offsets into the remaining data section.&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlC&amp;quot;&amp;gt;// Header&amp;lt;/span&amp;gt;&lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint32&amp;lt;/span&amp;gt; fileLength&lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint16&amp;lt;/span&amp;gt; numResources&lt;br /&gt;
 &lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlC&amp;quot;&amp;gt;// Table of contents&amp;lt;/span&amp;gt;&lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;char&amp;lt;/span&amp;gt;   ids&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;[&amp;lt;/span&amp;gt;numResources&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;][&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;hlN&amp;quot;&amp;gt;4&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;]&amp;lt;/span&amp;gt;&lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint32&amp;lt;/span&amp;gt; offsets&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;[&amp;lt;/span&amp;gt;numResources&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;]&amp;lt;/span&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlC&amp;quot;&amp;gt;// Resource data&amp;lt;/span&amp;gt;&lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;char&amp;lt;/span&amp;gt;   data&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;[]&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Types==&lt;br /&gt;
Resource type can be determined by looking at the resource&#039;s id string and/or the source file name.&lt;br /&gt;
&lt;br /&gt;
===Plain text===&lt;br /&gt;
Text resources are null-terminated [http://en.wikipedia.org/wiki/C_string C strings] found in &amp;lt;tt&amp;gt;RES&amp;lt;/tt&amp;gt;/&amp;lt;tt&amp;gt;PRE&amp;lt;/tt&amp;gt; files. Strings can contain non-alphanumeric codes used by the game to achieve certain effects. Most prominent is the &#039;&#039;&amp;quot;]&amp;quot;&#039;&#039; (right square bracket) used to represent [http://en.wikipedia.org/wiki/Newline newline] in multi-line text.&lt;br /&gt;
&lt;br /&gt;
===Bitmap images===&lt;br /&gt;
[[Image:Stunts-pal-vga.png|128px|right|thumb|VGA palette used by bitmap images. Value 255 is transparency.]]&lt;br /&gt;
Bitmaps are images with 8-bit color depth using a [[:Image:Stunts-pal-vga.png|fixed palette]] in VGA mode. Special bitmaps using the naming scheme &amp;lt;tt&amp;gt;!cg_&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;!eg_&amp;lt;/tt&amp;gt; provides color mapping for graphics modes with fewer available colors.&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint16&amp;lt;/span&amp;gt; width&lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint16&amp;lt;/span&amp;gt; height&lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint16&amp;lt;/span&amp;gt; unknown1&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;[&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;hlN&amp;quot;&amp;gt;4&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;]&amp;lt;/span&amp;gt;&lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt;  unknown2&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;[&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;hlN&amp;quot;&amp;gt;4&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;]&amp;lt;/span&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt;  image&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;[&amp;lt;/span&amp;gt;width &amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;*&amp;lt;/span&amp;gt; height&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;]&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Parts of this structure are not fully understood. &amp;lt;tt&amp;gt;unknown1&amp;lt;/tt&amp;gt; appears to be related to Stunts&#039; internal memory management. &amp;lt;tt&amp;gt;unknown2&amp;lt;/tt&amp;gt; seems to affect how image pixels are organized in compressed resource files, likely to gain more effective [http://en.wikipedia.org/wiki/Run-length_encoding run-length compression]. Images with pixel data stored as continuos horizontal lines has &amp;lt;tt&amp;gt;unknown2&amp;lt;/tt&amp;gt; set to &amp;lt;code&amp;gt;{ 0x1, 0x2, 0x4, 0x8 }&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
{{sectstub}}&lt;br /&gt;
&lt;br /&gt;
===Icons===&lt;br /&gt;
{{sectstub}}&lt;br /&gt;
&lt;br /&gt;
Shapes are composed of a vertex list and a list of primitives. Primitives are basic shapes that can have different types, such as polygons or wheels. Depending on the type it contains a number of indices into the vertex list needed to draw the shape, color variations and some rendering hints. Stunts&#039; coordinate system use 16-bit signed integers, making the resolution relative to the scale of the model. Shapes presented in the car selection screen are more detailed than in-game shapes, thus requiring larger scaling.&lt;br /&gt;
&lt;br /&gt;
Due to the counter header fields being stored in single bytes, the total amount of vertices and primitives are limited to 255 per shape.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Main strcture&#039;&#039;&#039;&lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt;     numVertices&lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt;     numPrimitives&lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt;     numPaintJobs&lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt;     reserved &amp;lt;span class=&amp;quot;hlC&amp;quot;&amp;gt;// Always == 0&amp;lt;/span&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
 VERTEX    vertices&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;[&amp;lt;/span&amp;gt;numVertices&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;]&amp;lt;/span&amp;gt;&lt;br /&gt;
 UNKNOWN   unknowns&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;[&amp;lt;/span&amp;gt;numPrimitives&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;]&amp;lt;/span&amp;gt;&lt;br /&gt;
 PRIMITIVE primitives&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;[&amp;lt;/span&amp;gt;numPrimitives&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;]&amp;lt;/span&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt;     terminate; &amp;lt;span class=&amp;quot;hlC&amp;quot;&amp;gt;// Always == 0&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Additional structures&#039;&#039;&#039;&lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;struct&amp;lt;/span&amp;gt; VERTEX &amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;{&amp;lt;/span&amp;gt;&lt;br /&gt;
   &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;int16&amp;lt;/span&amp;gt; x&lt;br /&gt;
   &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;int16&amp;lt;/span&amp;gt; y&lt;br /&gt;
   &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;int16&amp;lt;/span&amp;gt; z&lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;}&amp;lt;/span&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;struct&amp;lt;/span&amp;gt; UNKNOWN &amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;{&amp;lt;/span&amp;gt;&lt;br /&gt;
   &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;int8&amp;lt;/span&amp;gt; data&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;[&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;hlN&amp;quot;&amp;gt;8&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;]&amp;lt;/span&amp;gt;&lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;}&amp;lt;/span&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;struct&amp;lt;/span&amp;gt; PRIMITIVE &amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;{&amp;lt;/span&amp;gt;&lt;br /&gt;
   &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt; type&lt;br /&gt;
   &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt; depthIndex&lt;br /&gt;
   &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt; materials&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;[&amp;lt;/span&amp;gt;numPaintJobs&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;]&amp;lt;/span&amp;gt;&lt;br /&gt;
   &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt; indices&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;[&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;hlC&amp;quot;&amp;gt;...&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;]&amp;lt;/span&amp;gt; &amp;lt;span class=&amp;quot;hlC&amp;quot;&amp;gt;// Size depends on type.&amp;lt;/span&amp;gt;&lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;}&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Primitive types&#039;&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Primitive type !! Vertex indices needed !! Description&lt;br /&gt;
|-&lt;br /&gt;
| 1              || 1              || Particle, 1 pixel&lt;br /&gt;
|-&lt;br /&gt;
| 2              || 2              || Line segment, 1 pixel width&lt;br /&gt;
|-&lt;br /&gt;
| 3–10           || 3–10           || Polygon, &#039;&#039;n&#039;&#039; sides&lt;br /&gt;
|-&lt;br /&gt;
| 11             || 2              || Sphere (center + ~(radius / 2)&lt;br /&gt;
|-&lt;br /&gt;
| 12             || 6              || Wheel&lt;br /&gt;
|-&lt;br /&gt;
| *              || 0              || Ignored&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
[[Image:Wheel_Primitive_Anatomy.png|200px|right|thumb|Anatomy of a wheel shape primitive.]]&lt;br /&gt;
The first three vertices in a wheel primitive marks the center, tire radius and rim radius for the inner wheel-half facing the vehicle. The last three vertices does the same, in the same order, for the outer half of the wheel. Directions does not matter, the vertex locations are only used to measure distances. This rule applies to the sphere primitive as well.&lt;br /&gt;
&lt;br /&gt;
The value &amp;lt;tt&amp;gt;depthIndex&amp;lt;/tt&amp;gt; in the &amp;lt;tt&amp;gt;PRIMITIVE&amp;lt;/tt&amp;gt; structure is used to override the game&#039;s depth clipping in order to avoid flickering when several primitives are being drawn at the exact same depth. Higher value gives the primitive higher precedence.&lt;br /&gt;
&lt;br /&gt;
Materials are indices into a fixed, internal game structure and are assigned per-primitive. Cars can have multiple paint jobs, every primitive in the shape must set a material for each color scheme.&lt;br /&gt;
&lt;br /&gt;
Experimentation has revealed that &amp;lt;tt&amp;gt;UNKNOWN&amp;lt;/tt&amp;gt; data at least partially controls occlusion culling on primitive level. How, and exactly which parts of this structure does what has yet to be understood.&lt;br /&gt;
&lt;br /&gt;
{{sectstub}}&lt;br /&gt;
&lt;br /&gt;
===Car parameters===&lt;br /&gt;
{{main|Car parameters}}&lt;br /&gt;
{{sectstub}}&lt;br /&gt;
&lt;br /&gt;
===Opponent parameters===&lt;br /&gt;
{{sectstub}}&lt;br /&gt;
&lt;br /&gt;
===Music tracks===&lt;br /&gt;
{{sectstub}}&lt;br /&gt;
&lt;br /&gt;
===Instrument samples===&lt;br /&gt;
{{sectstub}}&lt;br /&gt;
&lt;br /&gt;
===Sound effects===&lt;br /&gt;
{{sectstub}}&lt;br /&gt;
&lt;br /&gt;
==Tools==&lt;br /&gt;
* [[stressed]] - Stunts/4D [Sports] Driving resource editor [http://stuntstools.googlecode.com/].&lt;br /&gt;
&lt;br /&gt;
[[Category:Game]]&lt;/div&gt;</summary>
		<author><name>Dstien</name></author>
	</entry>
	<entry>
		<id>https://wiki.stunts.hu/index.php?title=File:Wheel_Primitive_Anatomy.png&amp;diff=672</id>
		<title>File:Wheel Primitive Anatomy.png</title>
		<link rel="alternate" type="text/html" href="https://wiki.stunts.hu/index.php?title=File:Wheel_Primitive_Anatomy.png&amp;diff=672"/>
		<updated>2008-04-22T17:37:59Z</updated>

		<summary type="html">&lt;p&gt;Dstien: Anatomy of a wheel shape primitive.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Anatomy of a wheel shape primitive.&lt;/div&gt;</summary>
		<author><name>Dstien</name></author>
	</entry>
	<entry>
		<id>https://wiki.stunts.hu/index.php?title=UnskilledStunts&amp;diff=671</id>
		<title>UnskilledStunts</title>
		<link rel="alternate" type="text/html" href="https://wiki.stunts.hu/index.php?title=UnskilledStunts&amp;diff=671"/>
		<updated>2008-04-22T14:33:49Z</updated>

		<summary type="html">&lt;p&gt;Dstien: /* Lead */ grown → grew&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;&#039;UnskilledStunts&#039;&#039;&#039; was a competition managed by [[CTG]]. Started in 2003, it grew in status over the years to eventually being regarded as the second biggest full-season contest, after [[ZakStunts]].  After five complete seasons, the contest was ended by its manager in March 2008.&lt;br /&gt;
&lt;br /&gt;
== Season podiums ==&lt;br /&gt;
&lt;br /&gt;
{| style=&amp;quot;padding:0.5em; margin:1em; width: 10cm; text-align: left; background:#fafafa; border:1px solid grey&amp;quot;&lt;br /&gt;
|+ &#039;&#039;&#039;Season 2003&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|- bgcolor=&amp;quot;#e9e9e9&amp;quot;&lt;br /&gt;
! style=&amp;quot;width:10%&amp;quot; | Rank&lt;br /&gt;
! style=&amp;quot;width:30%&amp;quot; | Racer&lt;br /&gt;
! style=&amp;quot;width:30%&amp;quot; | Team&lt;br /&gt;
! style=&amp;quot;width:10%&amp;quot; | Points&lt;br /&gt;
|-&lt;br /&gt;
| bgcolor=&amp;quot;#d4af37&amp;quot;|1&lt;br /&gt;
| [[Bonzai Joe]]&lt;br /&gt;
| [[Cork&#039;s Crew]]&lt;br /&gt;
| 104&lt;br /&gt;
|-&lt;br /&gt;
||*&lt;br /&gt;
| [[CTG]]&lt;br /&gt;
| [[Unskilled Drivers]]&lt;br /&gt;
| 94&lt;br /&gt;
|-&lt;br /&gt;
| bgcolor=&amp;quot;#c0c0c0&amp;quot;|2&lt;br /&gt;
| [[Alain]]&lt;br /&gt;
| [[Orion]]&lt;br /&gt;
| 83&lt;br /&gt;
|-&lt;br /&gt;
| bgcolor=&amp;quot;#cd7f32&amp;quot;|3&lt;br /&gt;
| [[Krys Toff]]&lt;br /&gt;
| [[Orion]]&lt;br /&gt;
| 57&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
{| style=&amp;quot;padding:0.5em; margin:1em; width: 10cm; text-align: left; background:#fafafa; border:1px solid grey&amp;quot;&lt;br /&gt;
|+ &#039;&#039;&#039;Season 2004/2005&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|- bgcolor=&amp;quot;#e9e9e9&amp;quot;&lt;br /&gt;
! style=&amp;quot;width:10%&amp;quot; | Rank&lt;br /&gt;
! style=&amp;quot;width:30%&amp;quot; | Racer&lt;br /&gt;
! style=&amp;quot;width:30%&amp;quot; | Team&lt;br /&gt;
! style=&amp;quot;width:10%&amp;quot; | Points&lt;br /&gt;
|-&lt;br /&gt;
| bgcolor=&amp;quot;#d4af37&amp;quot;|1&lt;br /&gt;
| [[Gutix]]&lt;br /&gt;
| [[Meganium Aces High]]&lt;br /&gt;
| 163&lt;br /&gt;
|-&lt;br /&gt;
| bgcolor=&amp;quot;#c0c0c0&amp;quot;|2&lt;br /&gt;
| [[Akoss Poo]]&lt;br /&gt;
| [[Looping Warriors]]&lt;br /&gt;
| 122&lt;br /&gt;
|-&lt;br /&gt;
||*&lt;br /&gt;
| [[CTG]]&lt;br /&gt;
| [[Damage Inc]]&lt;br /&gt;
| 106&lt;br /&gt;
|-&lt;br /&gt;
| bgcolor=&amp;quot;#cd7f32&amp;quot;|3&lt;br /&gt;
| [[Krys Toff]]&lt;br /&gt;
| [[Damage Inc]]&lt;br /&gt;
| 77&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
{| style=&amp;quot;padding:0.5em; margin:1em; width: 10cm; text-align: left; background:#fafafa; border:1px solid grey&amp;quot;&lt;br /&gt;
|+ &#039;&#039;&#039;Season 2005/2006&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|- bgcolor=&amp;quot;#e9e9e9&amp;quot;&lt;br /&gt;
! style=&amp;quot;width:10%&amp;quot; | Rank&lt;br /&gt;
! style=&amp;quot;width:30%&amp;quot; | Racer&lt;br /&gt;
! style=&amp;quot;width:30%&amp;quot; | Team&lt;br /&gt;
! style=&amp;quot;width:10%&amp;quot; | Points&lt;br /&gt;
|-&lt;br /&gt;
||*&lt;br /&gt;
| [[CTG]]&lt;br /&gt;
| [[Cork&#039;s Crew]]&lt;br /&gt;
| 121&lt;br /&gt;
|-&lt;br /&gt;
| bgcolor=&amp;quot;#d4af37&amp;quot;|1&lt;br /&gt;
| [[Dottore]]&lt;br /&gt;
| [[Damage Inc]]&lt;br /&gt;
| 98&lt;br /&gt;
|-&lt;br /&gt;
| bgcolor=&amp;quot;#c0c0c0&amp;quot;|2&lt;br /&gt;
| [[Krys Toff]]&lt;br /&gt;
| [[Damage Inc]]&lt;br /&gt;
| 74&lt;br /&gt;
|-&lt;br /&gt;
| bgcolor=&amp;quot;#cd7f32&amp;quot;|3&lt;br /&gt;
| [[Navras]]&lt;br /&gt;
| [[Silver Spirit]]&lt;br /&gt;
| 68&lt;br /&gt;
|-&lt;br /&gt;
|}   &lt;br /&gt;
&lt;br /&gt;
{| style=&amp;quot;padding:0.5em; margin:1em; width: 10cm; text-align: left; background:#fafafa; border:1px solid grey&amp;quot;&lt;br /&gt;
|+ &#039;&#039;&#039;Season 2006/2007&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|- bgcolor=&amp;quot;#e9e9e9&amp;quot;&lt;br /&gt;
! style=&amp;quot;width:10%&amp;quot; | Rank&lt;br /&gt;
! style=&amp;quot;width:30%&amp;quot; | Racer&lt;br /&gt;
! style=&amp;quot;width:30%&amp;quot; | Team&lt;br /&gt;
! style=&amp;quot;width:10%&amp;quot; | Points&lt;br /&gt;
|-&lt;br /&gt;
| bgcolor=&amp;quot;#d4af37&amp;quot;|1&lt;br /&gt;
| [[Dottore]]&lt;br /&gt;
| [[Silver Spirit]]&lt;br /&gt;
| 134&lt;br /&gt;
|-&lt;br /&gt;
||*&lt;br /&gt;
| [[CTG]]&lt;br /&gt;
| [[Looping Warriors]]&lt;br /&gt;
| 134&lt;br /&gt;
|-&lt;br /&gt;
| bgcolor=&amp;quot;#c0c0c0&amp;quot;|2&lt;br /&gt;
| [[Krys Toff]]&lt;br /&gt;
| [[Damage Inc]]&lt;br /&gt;
| 84&lt;br /&gt;
|-&lt;br /&gt;
| bgcolor=&amp;quot;#cd7f32&amp;quot;|3&lt;br /&gt;
| [[Navras]]&lt;br /&gt;
| [[Silver Spirit]]&lt;br /&gt;
| 84&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
{| style=&amp;quot;padding:0.5em; margin:1em; width: 10cm; text-align: left; background:#fafafa; border:1px solid grey&amp;quot;&lt;br /&gt;
|+ &#039;&#039;&#039;Season 2007/2008&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|- bgcolor=&amp;quot;#e9e9e9&amp;quot;&lt;br /&gt;
! style=&amp;quot;width:10%&amp;quot; | Rank&lt;br /&gt;
! style=&amp;quot;width:30%&amp;quot; | Racer&lt;br /&gt;
! style=&amp;quot;width:30%&amp;quot; | Team&lt;br /&gt;
! style=&amp;quot;width:10%&amp;quot; | Points&lt;br /&gt;
|-&lt;br /&gt;
| bgcolor=&amp;quot;#d4af37&amp;quot;|1&lt;br /&gt;
| [[Dottore]]&lt;br /&gt;
| [[Silver Spirit]]&lt;br /&gt;
| 129&lt;br /&gt;
|-&lt;br /&gt;
||*&lt;br /&gt;
| [[CTG]]&lt;br /&gt;
| [[Looping Warriors]]&lt;br /&gt;
| 114&lt;br /&gt;
|-&lt;br /&gt;
| bgcolor=&amp;quot;#c0c0c0&amp;quot;|2&lt;br /&gt;
| [[Mark L. Rivers]]&lt;br /&gt;
| [[-]]&lt;br /&gt;
| 105&lt;br /&gt;
|-&lt;br /&gt;
| bgcolor=&amp;quot;#cd7f32&amp;quot;|3&lt;br /&gt;
| [[Navras]]&lt;br /&gt;
| [[Silver Spirit]]&lt;br /&gt;
| 98&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
* - Manager results were excluded from final season standings&lt;br /&gt;
&lt;br /&gt;
== Medal table ==&lt;br /&gt;
&lt;br /&gt;
{| style=&amp;quot;padding:0.5em; margin:1em; width: 10cm; text-align: left; background:#fafafa; border:1px solid grey&amp;quot;&lt;br /&gt;
|- bgcolor=&amp;quot;#e9e9e9&amp;quot;&lt;br /&gt;
! style=&amp;quot;width:10%&amp;quot; | Rank&lt;br /&gt;
! style=&amp;quot;width:25%&amp;quot; | Racer&lt;br /&gt;
! style=&amp;quot;width:15%&amp;quot; bgcolor=&amp;quot;#d4af37&amp;quot;| 1st&lt;br /&gt;
! style=&amp;quot;width:15%&amp;quot; bgcolor=&amp;quot;#c0c0c0&amp;quot;| 2nd&lt;br /&gt;
! style=&amp;quot;width:15%&amp;quot; bgcolor=&amp;quot;#cd7f32&amp;quot;| 3rd&lt;br /&gt;
|-&lt;br /&gt;
| 1&lt;br /&gt;
| [[CTG]]&lt;br /&gt;
| 10&lt;br /&gt;
| 12&lt;br /&gt;
| 16&lt;br /&gt;
|-&lt;br /&gt;
| 2&lt;br /&gt;
| [[Gutix]]&lt;br /&gt;
| 9&lt;br /&gt;
| 3&lt;br /&gt;
| 3&lt;br /&gt;
|-&lt;br /&gt;
| 3&lt;br /&gt;
| [[Dottore]]&lt;br /&gt;
| 8&lt;br /&gt;
| 10&lt;br /&gt;
| 4&lt;br /&gt;
|-&lt;br /&gt;
| 4&lt;br /&gt;
| [[Bonzai Joe]]&lt;br /&gt;
| 7&lt;br /&gt;
| 2&lt;br /&gt;
| 5&lt;br /&gt;
|-&lt;br /&gt;
| 5&lt;br /&gt;
| [[Alain]]&lt;br /&gt;
| 5&lt;br /&gt;
| 0&lt;br /&gt;
| 1&lt;br /&gt;
|-&lt;br /&gt;
| 6&lt;br /&gt;
| [[Akoss Poo]]&lt;br /&gt;
| 3&lt;br /&gt;
| 8&lt;br /&gt;
| 2&lt;br /&gt;
|-&lt;br /&gt;
| 7&lt;br /&gt;
| [[Krys Toff]]&lt;br /&gt;
| 2&lt;br /&gt;
| 5&lt;br /&gt;
| 5&lt;br /&gt;
|-&lt;br /&gt;
| 8&lt;br /&gt;
| [[Renato Biker]]&lt;br /&gt;
| 2&lt;br /&gt;
| 3&lt;br /&gt;
| 2&lt;br /&gt;
|-&lt;br /&gt;
| 9&lt;br /&gt;
| [[Argammon]]&lt;br /&gt;
| 2&lt;br /&gt;
| 3&lt;br /&gt;
| 0&lt;br /&gt;
|-&lt;br /&gt;
| 10&lt;br /&gt;
| [[Navras]]&lt;br /&gt;
| 2&lt;br /&gt;
| 2&lt;br /&gt;
| 4&lt;br /&gt;
|-&lt;br /&gt;
| 11&lt;br /&gt;
| [[Usrin]]&lt;br /&gt;
| 2&lt;br /&gt;
| 2&lt;br /&gt;
| 3&lt;br /&gt;
|-&lt;br /&gt;
| 12&lt;br /&gt;
| [[Mark L. Rivers]]&lt;br /&gt;
| 2&lt;br /&gt;
| 2&lt;br /&gt;
| 2&lt;br /&gt;
|-&lt;br /&gt;
| 13&lt;br /&gt;
| [[Duplode]]&lt;br /&gt;
| 2&lt;br /&gt;
| 0&lt;br /&gt;
| 0&lt;br /&gt;
|-&lt;br /&gt;
| 14&lt;br /&gt;
| [[Mingva]]&lt;br /&gt;
| 1&lt;br /&gt;
| 2&lt;br /&gt;
| 0&lt;br /&gt;
|-&lt;br /&gt;
| 15&lt;br /&gt;
| [[Dark Chaser]]&lt;br /&gt;
| 1&lt;br /&gt;
| 0&lt;br /&gt;
| 1&lt;br /&gt;
|-&lt;br /&gt;
| 16&lt;br /&gt;
| [[Chulk]]&lt;br /&gt;
| 0&lt;br /&gt;
| 2&lt;br /&gt;
| 1&lt;br /&gt;
|-&lt;br /&gt;
| 17&lt;br /&gt;
| [[Ayrton]]&lt;br /&gt;
| 0&lt;br /&gt;
| 1&lt;br /&gt;
| 1&lt;br /&gt;
|-&lt;br /&gt;
| 18&lt;br /&gt;
| [[Zweigelt]]&lt;br /&gt;
| 0&lt;br /&gt;
| 1&lt;br /&gt;
| 0&lt;br /&gt;
|-&lt;br /&gt;
| 19&lt;br /&gt;
| [[Alan Rotoi]]&lt;br /&gt;
| 0&lt;br /&gt;
| 0&lt;br /&gt;
| 3&lt;br /&gt;
|-&lt;br /&gt;
| 20&lt;br /&gt;
| [[Diesel Joe]]&lt;br /&gt;
| 0&lt;br /&gt;
| 0&lt;br /&gt;
| 2&lt;br /&gt;
|-&lt;br /&gt;
| 21&lt;br /&gt;
| [[FloFlo81]]&lt;br /&gt;
| 0&lt;br /&gt;
| 0&lt;br /&gt;
| 1&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Hall of fame: greatest UnskilledStunts replays ever ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;youtube&amp;gt;ms0RcmhXFY0&amp;lt;/youtube&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Alain il Professore, Eger, May 2003&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Related competitions ==&lt;br /&gt;
&lt;br /&gt;
* [[Unskilled_Stunts_League|Unskilled Stunts League]]&amp;lt;br&amp;gt;&lt;br /&gt;
* [[Unskilled_Stunts_Rapid|Unskilled Stunts Rapid]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Competition]]&lt;/div&gt;</summary>
		<author><name>Dstien</name></author>
	</entry>
	<entry>
		<id>https://wiki.stunts.hu/index.php?title=Resource_file_format&amp;diff=668</id>
		<title>Resource file format</title>
		<link rel="alternate" type="text/html" href="https://wiki.stunts.hu/index.php?title=Resource_file_format&amp;diff=668"/>
		<updated>2008-04-22T12:11:36Z</updated>

		<summary type="html">&lt;p&gt;Dstien: Pseudo code styling and additional info on &amp;quot;unknown2&amp;quot; in bitmap struct&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Stunts game data are stored in a common container format. Files of this format can hold multiple resources of any type, identified only by a 4-byte name. A resource file can be encapsulated by [[Compression|compression]].&lt;br /&gt;
&lt;br /&gt;
This document focuses on [[Game versions#PC versions|BB Stunts 1.1]], but details described here may still—partly or wholly—cover other versions, or even other games developed by DSI at the time.&lt;br /&gt;
&lt;br /&gt;
==File names==&lt;br /&gt;
Different file name extensions are used to indicate the content of the files. Compressed files has &#039;&#039;&amp;quot;P&amp;quot;&#039;&#039; (packed) as the first letter of their extensions. Whether the game prefers raw or compressed files varies based on file type.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! File contents           !! Raw !! Compressed !! Preferred&lt;br /&gt;
|-&lt;br /&gt;
| Text and misc. settings || RES || PRE        || Raw&lt;br /&gt;
|-&lt;br /&gt;
| Bitmap images           || VSH || PVS        || Compressed&lt;br /&gt;
|-&lt;br /&gt;
| Icons                   || ESH || PES        || Compressed&lt;br /&gt;
|-&lt;br /&gt;
| 3d shapes               || 3SH || P3S        || Compressed&lt;br /&gt;
|-&lt;br /&gt;
| Music tracks            || KMS || PKM        || Raw&lt;br /&gt;
|-&lt;br /&gt;
| Instrument samples      || VCE || PVC        || Raw&lt;br /&gt;
|-&lt;br /&gt;
| Sound effects           || SFX || PSF        || Raw&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==Structure==&lt;br /&gt;
&lt;br /&gt;
The resource file header consists of two integer fields denoting the total length of the file and the number of resources contained. The following table of contents has a list of ids and a corresponding list of offsets into the remaining data section.&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlC&amp;quot;&amp;gt;// Header&amp;lt;/span&amp;gt;&lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint32&amp;lt;/span&amp;gt; fileLength&lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint16&amp;lt;/span&amp;gt; numResources&lt;br /&gt;
 &lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlC&amp;quot;&amp;gt;// Table of contents&amp;lt;/span&amp;gt;&lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;char&amp;lt;/span&amp;gt;   ids&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;[&amp;lt;/span&amp;gt;numResources&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;][&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;hlN&amp;quot;&amp;gt;4&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;]&amp;lt;/span&amp;gt;&lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint32&amp;lt;/span&amp;gt; offsets&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;[&amp;lt;/span&amp;gt;numResources&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;]&amp;lt;/span&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlC&amp;quot;&amp;gt;// Resource data&amp;lt;/span&amp;gt;&lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;char&amp;lt;/span&amp;gt;   data&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;[]&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Types==&lt;br /&gt;
Resource type can be determined by looking at the resource&#039;s id string and/or the source file name.&lt;br /&gt;
&lt;br /&gt;
===Plain text===&lt;br /&gt;
Text resources are null-terminated [http://en.wikipedia.org/wiki/C_string C strings] found in &amp;lt;tt&amp;gt;RES&amp;lt;/tt&amp;gt;/&amp;lt;tt&amp;gt;PRE&amp;lt;/tt&amp;gt; files. Strings can contain non-alphanumeric codes used by the game to achieve certain effects. Most prominent is the &#039;&#039;&amp;quot;]&amp;quot;&#039;&#039; (right square bracket) used to represent [http://en.wikipedia.org/wiki/Newline newline] in multi-line text.&lt;br /&gt;
&lt;br /&gt;
===Bitmap images===&lt;br /&gt;
[[Image:Stunts-pal-vga.png|128px|right|thumb|VGA palette used by bitmap images. Value 255 is transparency.]]&lt;br /&gt;
Bitmaps are images with 8-bit color depth using a [[:Image:Stunts-pal-vga.png|fixed palette]] in VGA mode. Special bitmaps using the naming scheme &amp;lt;tt&amp;gt;!cg_&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;!eg_&amp;lt;/tt&amp;gt; provides color mapping for graphics modes with fewer available colors.&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint16&amp;lt;/span&amp;gt; width&lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint16&amp;lt;/span&amp;gt; height&lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint16&amp;lt;/span&amp;gt; unknown1&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;[&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;hlN&amp;quot;&amp;gt;4&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;]&amp;lt;/span&amp;gt;&lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt;  unknown2&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;[&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;hlN&amp;quot;&amp;gt;4&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;]&amp;lt;/span&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
 &amp;lt;span class=&amp;quot;hlP&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt;  image&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;[&amp;lt;/span&amp;gt;width &amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;*&amp;lt;/span&amp;gt; height&amp;lt;span class=&amp;quot;hlB&amp;quot;&amp;gt;]&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Parts of this structure are not fully understood. &amp;lt;tt&amp;gt;unknown1&amp;lt;/tt&amp;gt; appears to be related to Stunts&#039; internal memory management. &amp;lt;tt&amp;gt;unknown2&amp;lt;/tt&amp;gt; seems to affect how image pixels are organized in compressed resource files, likely to gain more effective [http://en.wikipedia.org/wiki/Run-length_encoding run-length compression]. Images with pixel data stored as continuos horizontal lines has &amp;lt;tt&amp;gt;unknown2&amp;lt;/tt&amp;gt; set to &amp;lt;code&amp;gt;{ 0x1, 0x2, 0x4, 0x8 }&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
{{sectstub}}&lt;br /&gt;
&lt;br /&gt;
===Icons===&lt;br /&gt;
{{sectstub}}&lt;br /&gt;
&lt;br /&gt;
===3d shapes===&lt;br /&gt;
{{sectstub}}&lt;br /&gt;
&lt;br /&gt;
===Car parameters===&lt;br /&gt;
{{main|Car parameters}}&lt;br /&gt;
{{sectstub}}&lt;br /&gt;
&lt;br /&gt;
===Opponent parameters===&lt;br /&gt;
{{sectstub}}&lt;br /&gt;
&lt;br /&gt;
===Music tracks===&lt;br /&gt;
{{sectstub}}&lt;br /&gt;
&lt;br /&gt;
===Instrument samples===&lt;br /&gt;
{{sectstub}}&lt;br /&gt;
&lt;br /&gt;
===Sound effects===&lt;br /&gt;
{{sectstub}}&lt;br /&gt;
&lt;br /&gt;
==Tools==&lt;br /&gt;
* [[stressed]] - Stunts/4D [Sports] Driving resource editor [http://stuntstools.googlecode.com/].&lt;br /&gt;
&lt;br /&gt;
[[Category:Game]]&lt;/div&gt;</summary>
		<author><name>Dstien</name></author>
	</entry>
	<entry>
		<id>https://wiki.stunts.hu/index.php?title=MediaWiki:Common.css&amp;diff=667</id>
		<title>MediaWiki:Common.css</title>
		<link rel="alternate" type="text/html" href="https://wiki.stunts.hu/index.php?title=MediaWiki:Common.css&amp;diff=667"/>
		<updated>2008-04-22T11:35:45Z</updated>

		<summary type="html">&lt;p&gt;Dstien: Added syntax highlighting classes&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;/* &amp;lt;pre&amp;gt;&amp;lt;nowiki&amp;gt; */&lt;br /&gt;
&lt;br /&gt;
/** CSS placed here will be applied to all skins */&lt;br /&gt;
&lt;br /&gt;
/* wikitable class */&lt;br /&gt;
table.wikitable {&lt;br /&gt;
  margin: 1em;&lt;br /&gt;
  padding: 0.5em;&lt;br /&gt;
  background: #fafafa;&lt;br /&gt;
  border: 1px solid gray;&lt;br /&gt;
  color: black;&lt;br /&gt;
  text-align: left;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
table.wikitable th,&lt;br /&gt;
table.wikitable td {&lt;br /&gt;
  padding-right: 1em;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
table.wikitable th {&lt;br /&gt;
  background: #e9e9e9;&lt;br /&gt;
  color: black;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/* Pseudo code syntax highlighting classes */&lt;br /&gt;
.hlC { color: #777; font-style: italic } /* Comment */&lt;br /&gt;
.hlP { color: #933 }                     /* Primitive type */&lt;br /&gt;
.hlB { color: #6c6 }                     /* Bracket/operator */&lt;br /&gt;
.hlN { color: #c6c }                     /* Numeric */&lt;br /&gt;
.hlS { color: #f00 }                     /* String */&lt;br /&gt;
&lt;br /&gt;
/* &amp;lt;/nowiki&amp;gt;&amp;lt;/pre&amp;gt; */&lt;/div&gt;</summary>
		<author><name>Dstien</name></author>
	</entry>
	<entry>
		<id>https://wiki.stunts.hu/index.php?title=Car_files&amp;diff=666</id>
		<title>Car files</title>
		<link rel="alternate" type="text/html" href="https://wiki.stunts.hu/index.php?title=Car_files&amp;diff=666"/>
		<updated>2008-04-22T11:00:52Z</updated>

		<summary type="html">&lt;p&gt;Dstien: /* Car behaviour (car*.res) */ Table styling&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Stunts cars are made of four different [[Resource file format|resource files]]: st*.p3s, stda*.pvs, stdb*.pvs and car*.res ; where the * stands for an arbitrary 4-letter abbreviation shared by files of the same car. All of the car graphics are stored in the .p3s and .pvs files. The car*.res, which is the one of most concern when creating a [[Cheated Cars|tuned car]], contains numerical and text parameters, including data about car performance. &lt;br /&gt;
&lt;br /&gt;
==Graphics files (.p3s/.pvs)==&lt;br /&gt;
&lt;br /&gt;
Different aspects of a car&#039;s appearance are stored in each of the graphic file:&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;st*.p3s&#039;&#039;&#039; - [[Resource file format#3d shapes|3d shape resource]] file that stores the graphical 3D model of the car, including its colour data.&lt;br /&gt;
*&#039;&#039;&#039;stda*.p3s&#039;&#039;&#039; - [[Resource file format#Bitmap images|Bitmap resource]] file that contains the dashboard image, including the shifting stick&#039;s base. Movement of tachometer, speedometer and steering wheel dot is controlled by car*.res parameters.&lt;br /&gt;
*&#039;&#039;&#039;stdb*.p3s&#039;&#039;&#039; - [[Resource file format#Bitmap images|Bitmap resource]] file that contains the shifting knob. For the [[Corvette ZR1|Corvette]], it also stores the digital speedometer graphics.&lt;br /&gt;
&lt;br /&gt;
Graphic files of different cars can be mixed freely when constructing a new car (note that the car*.res may require adjustment so that the indicators work properly on a new dashboard). As for modification of the graphics themselves, until recently that was deemed impossible, for the lack of information about the format employed by the developers to compress the vector graphics. This first major obstacle, however, has been sorted out. (see [[Car files#Tools|Tools]] section below)&lt;br /&gt;
&lt;br /&gt;
==Car behaviour (car*.res)==&lt;br /&gt;
&lt;br /&gt;
All adjustable aspects of a car behaviour are stored in car*.res. Those include both physics data, such as power curves, and visual parameters, like car height in cockpit view or speedometer behaviour. Also, the file also contains the text data displayed at the car selection screen. Data in car*.res may be read and modified by any hex editor, or more conveniently by a specially-designed graphical editor (see the Tools section ahead). &lt;br /&gt;
&lt;br /&gt;
The function of a large fraction of car*.res hex addreses was elucidated over the years, allowing modifications of many car aspects. Here is a quick reference for those addresses, adapted from the chart available at [http://www.kalpen.de/luke/4dinfo.html#cs Lukas Loehrer&#039;s site]. A more throughout discussion on the effects and quirks of the parameters is available at [[Car parameters]]; clicking on a parameter description will lead to the corresponding entry there.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Byte offset !! Function&lt;br /&gt;
|-&lt;br /&gt;
| 26h         || [[Car_parameters#Number_of_gears|Number of gears]]&lt;br /&gt;
|-&lt;br /&gt;
| 28h-29h     || [[Car_parameters#Car_mass|Car mass]]&lt;br /&gt;
|-&lt;br /&gt;
| 2Ah-2Bh     || [[Car parameters#Braking effectiveness|Braking effectiveness]]&lt;br /&gt;
|-&lt;br /&gt;
| 2Ch-2Dh     || [[Car parameters#Idle rpm|Idle rpm]]&lt;br /&gt;
|-&lt;br /&gt;
| 2Eh-2Fh     || [[Car parameters#Downshift rpm|Downshift rpm (auto transm.)]]&lt;br /&gt;
|-&lt;br /&gt;
| 30h-31h     || [[Car parameters#Upshift rpm|Upshift rpm (auto transm.)]]&lt;br /&gt;
|-&lt;br /&gt;
| 32h-33h     || [[Car parameters#Maximum rpm|Maximum rpm]]&lt;br /&gt;
|-&lt;br /&gt;
| 37h-41h     || [[Car parameters#Gear ratios|Gear ratios (odd offsets)]]&lt;br /&gt;
|-&lt;br /&gt;
| 46h-5Ch     || [[Car parameters#Shifting knob positions|Shifting knob positions (even offsets)]]&lt;br /&gt;
|-&lt;br /&gt;
| 5Dh-5Eh     || [[Car parameters#Aerodynamic resistance|Aerodynamic resistance]]&lt;br /&gt;
|-&lt;br /&gt;
| 60h-C7h     || [[Car parameters#Torque curve|Torque curve]]&lt;br /&gt;
|-&lt;br /&gt;
| CAh-CBh     || [[Car parameters#Grip|Grip]]&lt;br /&gt;
|-&lt;br /&gt;
| F6h-F7h     || [[Car parameters#Car height|Car height on cockpit view]]&lt;br /&gt;
|-&lt;br /&gt;
| 110h-14Dh   || [[Car parameters#Steering wheel dot movement|Steering wheel dot movement]]&lt;br /&gt;
|-&lt;br /&gt;
| 14Eh-223h   || [[Car parameters#Speedometer needle movement|Speedometer needle movement]]&lt;br /&gt;
|-&lt;br /&gt;
| 150h-159h   || [[Car parameters#Digital speedometer|Digital speedometer]]&lt;br /&gt;
|-&lt;br /&gt;
| 224h-32Dh   || [[Car parameters#Rev meter needle movement|Rev meter needle movement]]&lt;br /&gt;
|-&lt;br /&gt;
| 32Eh-EOF    || [[Car parameters#Text data|Text data (car selection screen and high score table)]]&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==Version compatibility==&lt;br /&gt;
&lt;br /&gt;
Cars that use graphic files from Stunts 1.0 do not work properly on 1.1 versions, and vice-versa. Doing so causes a crash in the car selection screen. Although the car*.res files may be exchanged between versions, car performance won&#039;t be the same due to the known differences between [[Game versions|game versions]] in that respect.&lt;br /&gt;
&lt;br /&gt;
==Tools==&lt;br /&gt;
&lt;br /&gt;
The car*.res files can be read and edited by any hex-editor or text editor able to display files in hexadecimal mode - [http://hte.sourceforge.net HT] and [http://www.vim.org Vim] are examples of each case). A more convenient alternative are graphical hex-editors designed especially for Stunts car hacking. [[Mark_Nailwood|Mark Nailwood]]&#039;s [[Car_Blaster|Car Blaster]], by far the most used of those, has resources such as tags on useful bytes and comparison between cars. Other editors include [[Caredit]] and [[Winedit]].&lt;br /&gt;
&lt;br /&gt;
Modified cars are not recognized in the [[RPL_Info|RPL Info]] tool, also created by [[Mark_Nailwood|Mark Nailwood]].&lt;br /&gt;
&lt;br /&gt;
In 2008, [[dstien]] created a tool named [[stunpack]] to unpack some files of the game. His project is registered here [http://code.google.com/p/stuntstools/] and is still under development, but it looks really promising. the day when we will be able to change car shapes is approaching.&lt;br /&gt;
&lt;br /&gt;
==See also==&lt;br /&gt;
&lt;br /&gt;
* [[Car_parameters|Car parameters]]&amp;lt;br&amp;gt;&lt;br /&gt;
* [[Car model physics]]&amp;lt;br&amp;gt;&lt;br /&gt;
* [[Cheated_cars|Cheated cars]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Driving]]&lt;br /&gt;
[[Category:Game]]&lt;/div&gt;</summary>
		<author><name>Dstien</name></author>
	</entry>
	<entry>
		<id>https://wiki.stunts.hu/index.php?title=Resource_file_format&amp;diff=665</id>
		<title>Resource file format</title>
		<link rel="alternate" type="text/html" href="https://wiki.stunts.hu/index.php?title=Resource_file_format&amp;diff=665"/>
		<updated>2008-04-22T10:53:57Z</updated>

		<summary type="html">&lt;p&gt;Dstien: /* File names */ Table styling&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Stunts game data are stored in a common container format. Files of this format can hold multiple resources of any type, identified only by a 4-byte name. A resource file can be encapsulated by [[Compression|compression]].&lt;br /&gt;
&lt;br /&gt;
This document focuses on [[Game versions#PC versions|BB Stunts 1.1]], but details described here may still—partly or wholly—cover other versions, or even other games developed by DSI at the time.&lt;br /&gt;
&lt;br /&gt;
==File names==&lt;br /&gt;
Different file name extensions are used to indicate the content of the files. Compressed files has &#039;&#039;&amp;quot;P&amp;quot;&#039;&#039; (packed) as the first letter of their extensions. Whether the game prefers raw or compressed files varies based on file type.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! File contents           !! Raw !! Compressed !! Preferred&lt;br /&gt;
|-&lt;br /&gt;
| Text and misc. settings || RES || PRE        || Raw&lt;br /&gt;
|-&lt;br /&gt;
| Bitmap images           || VSH || PVS        || Compressed&lt;br /&gt;
|-&lt;br /&gt;
| Icons                   || ESH || PES        || Compressed&lt;br /&gt;
|-&lt;br /&gt;
| 3d shapes               || 3SH || P3S        || Compressed&lt;br /&gt;
|-&lt;br /&gt;
| Music tracks            || KMS || PKM        || Raw&lt;br /&gt;
|-&lt;br /&gt;
| Instrument samples      || VCE || PVC        || Raw&lt;br /&gt;
|-&lt;br /&gt;
| Sound effects           || SFX || PSF        || Raw&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==Structure==&lt;br /&gt;
&lt;br /&gt;
The resource file header consists of two integer fields denoting the total length of the file and the number of resources contained. The following table of contents has a list of ids and a corresponding list of offsets into the remaining data section.&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;span style=&amp;quot;color:#777; font-style: italic&amp;quot;&amp;gt;// Header&amp;lt;/span&amp;gt;&lt;br /&gt;
 &amp;lt;span style=&amp;quot;color:#933&amp;quot;&amp;gt;uint32&amp;lt;/span&amp;gt; fileLength&lt;br /&gt;
 &amp;lt;span style=&amp;quot;color:#933&amp;quot;&amp;gt;uint16&amp;lt;/span&amp;gt; numResources&lt;br /&gt;
 &lt;br /&gt;
 &amp;lt;span style=&amp;quot;color:#777; font-style: italic&amp;quot;&amp;gt;// Table of contents&amp;lt;/span&amp;gt;&lt;br /&gt;
 &amp;lt;span style=&amp;quot;color:#933&amp;quot;&amp;gt;char&amp;lt;/span&amp;gt;   ids&amp;lt;span style=&amp;quot;color:#6c6&amp;quot;&amp;gt;[&amp;lt;/span&amp;gt;numResources&amp;lt;span style=&amp;quot;color:#6c6&amp;quot;&amp;gt;][&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:#c6c&amp;quot;&amp;gt;4&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:#6c6&amp;quot;&amp;gt;]&amp;lt;/span&amp;gt;&lt;br /&gt;
 &amp;lt;span style=&amp;quot;color:#933&amp;quot;&amp;gt;uint32&amp;lt;/span&amp;gt; offsets&amp;lt;span style=&amp;quot;color:#6c6&amp;quot;&amp;gt;[&amp;lt;/span&amp;gt;numResources&amp;lt;span style=&amp;quot;color:#6c6&amp;quot;&amp;gt;]&amp;lt;/span&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
 &amp;lt;span style=&amp;quot;color:#777; font-style: italic&amp;quot;&amp;gt;// Resource data&amp;lt;/span&amp;gt;&lt;br /&gt;
 &amp;lt;span style=&amp;quot;color:#933&amp;quot;&amp;gt;char&amp;lt;/span&amp;gt;   data&amp;lt;span style=&amp;quot;color:#6c6&amp;quot;&amp;gt;[]&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Types==&lt;br /&gt;
Resource type can be determined by looking at the resource&#039;s id string and/or the source file name.&lt;br /&gt;
&lt;br /&gt;
===Plain text===&lt;br /&gt;
Text resources are null-terminated [http://en.wikipedia.org/wiki/C_string C strings] found in &amp;lt;tt&amp;gt;RES&amp;lt;/tt&amp;gt;/&amp;lt;tt&amp;gt;PRE&amp;lt;/tt&amp;gt; files. Strings can contain non-alphanumeric codes used by the game to achieve certain effects. Most prominent is the &#039;&#039;&amp;quot;]&amp;quot;&#039;&#039; (right square bracket) used to represent [http://en.wikipedia.org/wiki/Newline newline] in multi-line text.&lt;br /&gt;
&lt;br /&gt;
===Bitmap images===&lt;br /&gt;
[[Image:Stunts-pal-vga.png|128px|right|thumb|VGA palette used by bitmap images. Value 255 is transparency.]]&lt;br /&gt;
Bitmaps are images with 8-bit color depth using a [[:Image:Stunts-pal-vga.png|fixed palette]] in VGA mode. Special bitmaps using the naming scheme &amp;lt;tt&amp;gt;!cg_&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;!eg_&amp;lt;/tt&amp;gt; provides color mapping for graphics modes with fewer available colors.&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;span style=&amp;quot;color:#933&amp;quot;&amp;gt;uint16&amp;lt;/span&amp;gt; width&lt;br /&gt;
 &amp;lt;span style=&amp;quot;color:#933&amp;quot;&amp;gt;uint16&amp;lt;/span&amp;gt; height&lt;br /&gt;
 &amp;lt;span style=&amp;quot;color:#933&amp;quot;&amp;gt;uint16&amp;lt;/span&amp;gt; unknown1&amp;lt;span style=&amp;quot;color:#6c6&amp;quot;&amp;gt;[&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:#c6c&amp;quot;&amp;gt;4&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:#6c6&amp;quot;&amp;gt;]&amp;lt;/span&amp;gt;&lt;br /&gt;
 &amp;lt;span style=&amp;quot;color:#933&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt;  unknown2&amp;lt;span style=&amp;quot;color:#6c6&amp;quot;&amp;gt;[&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:#c6c&amp;quot;&amp;gt;4&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:#6c6&amp;quot;&amp;gt;]&amp;lt;/span&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
 &amp;lt;span style=&amp;quot;color:#933&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt;  image&amp;lt;span style=&amp;quot;color:#6c6&amp;quot;&amp;gt;[&amp;lt;/span&amp;gt;width * height&amp;lt;span style=&amp;quot;color:#6c6&amp;quot;&amp;gt;]&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Parts of this structure are not fully understood. &amp;lt;tt&amp;gt;unknown1&amp;lt;/tt&amp;gt; appears to be related to Stunts&#039; image memory management. &amp;lt;tt&amp;gt;unknown2&amp;lt;/tt&amp;gt; seems to affect how image pixels are organized in compressed resource files, likely to gain more effective [http://en.wikipedia.org/wiki/Run-length_encoding run-length compression].&lt;br /&gt;
&lt;br /&gt;
{{sectstub}}&lt;br /&gt;
&lt;br /&gt;
===Icons===&lt;br /&gt;
{{sectstub}}&lt;br /&gt;
&lt;br /&gt;
===3d shapes===&lt;br /&gt;
{{sectstub}}&lt;br /&gt;
&lt;br /&gt;
===Car parameters===&lt;br /&gt;
{{main|Car parameters}}&lt;br /&gt;
{{sectstub}}&lt;br /&gt;
&lt;br /&gt;
===Opponent parameters===&lt;br /&gt;
{{sectstub}}&lt;br /&gt;
&lt;br /&gt;
===Music tracks===&lt;br /&gt;
{{sectstub}}&lt;br /&gt;
&lt;br /&gt;
===Instrument samples===&lt;br /&gt;
{{sectstub}}&lt;br /&gt;
&lt;br /&gt;
===Sound effects===&lt;br /&gt;
{{sectstub}}&lt;br /&gt;
&lt;br /&gt;
==Tools==&lt;br /&gt;
* [[stressed]] - Stunts/4D [Sports] Driving resource editor [http://stuntstools.googlecode.com/].&lt;br /&gt;
&lt;br /&gt;
[[Category:Game]]&lt;/div&gt;</summary>
		<author><name>Dstien</name></author>
	</entry>
	<entry>
		<id>https://wiki.stunts.hu/index.php?title=MediaWiki:Common.css&amp;diff=664</id>
		<title>MediaWiki:Common.css</title>
		<link rel="alternate" type="text/html" href="https://wiki.stunts.hu/index.php?title=MediaWiki:Common.css&amp;diff=664"/>
		<updated>2008-04-22T10:51:36Z</updated>

		<summary type="html">&lt;p&gt;Dstien: Added wikitable style class.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;/* &amp;lt;pre&amp;gt;&amp;lt;nowiki&amp;gt; */&lt;br /&gt;
&lt;br /&gt;
/** CSS placed here will be applied to all skins */&lt;br /&gt;
&lt;br /&gt;
/* wikitable class */&lt;br /&gt;
table.wikitable {&lt;br /&gt;
  margin: 1em;&lt;br /&gt;
  padding: 0.5em;&lt;br /&gt;
  background: #fafafa;&lt;br /&gt;
  border: 1px solid gray;&lt;br /&gt;
  color: black;&lt;br /&gt;
  text-align: left;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
table.wikitable th,&lt;br /&gt;
table.wikitable td {&lt;br /&gt;
  padding-right: 1em;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
table.wikitable th {&lt;br /&gt;
  background: #e9e9e9;&lt;br /&gt;
  color: black;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/* &amp;lt;/nowiki&amp;gt;&amp;lt;/pre&amp;gt; */&lt;/div&gt;</summary>
		<author><name>Dstien</name></author>
	</entry>
	<entry>
		<id>https://wiki.stunts.hu/index.php?title=Resource_file_format&amp;diff=655</id>
		<title>Resource file format</title>
		<link rel="alternate" type="text/html" href="https://wiki.stunts.hu/index.php?title=Resource_file_format&amp;diff=655"/>
		<updated>2008-04-21T19:27:41Z</updated>

		<summary type="html">&lt;p&gt;Dstien: Syntax highlighting.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Stunts game data are stored in a common container format. Files of this format can hold multiple resources of any type, identified only by a 4-byte name. A resource file can be encapsulated by [[Compression|compression]].&lt;br /&gt;
&lt;br /&gt;
This document focuses on [[Game versions#PC versions|BB Stunts 1.1]], but details described here may still—partly or wholly—cover other versions, or even other games developed by DSI at the time.&lt;br /&gt;
&lt;br /&gt;
==File names==&lt;br /&gt;
Different file name extensions are used to indicate the content of the files. Compressed files has &#039;&#039;&amp;quot;P&amp;quot;&#039;&#039; (packed) as the first letter of their extensions. Whether the game prefers raw or compressed files varies based on file type.&lt;br /&gt;
&lt;br /&gt;
{| style=&amp;quot;padding:0.5em; margin:1em; width: 40%; text-align: left; background:#fafafa; border:1px solid grey&amp;quot;&lt;br /&gt;
|- bgcolor=&amp;quot;#e9e9e9&amp;quot;&lt;br /&gt;
! style=&amp;quot;width:40%&amp;quot; | File contents&lt;br /&gt;
! style=&amp;quot;width:20%&amp;quot; | Raw&lt;br /&gt;
! style=&amp;quot;width:20%&amp;quot; | Compressed&lt;br /&gt;
! style=&amp;quot;width:20%&amp;quot; | Preferred&lt;br /&gt;
|-&lt;br /&gt;
| Text and misc. settings&lt;br /&gt;
| RES&lt;br /&gt;
| PRE&lt;br /&gt;
| Raw&lt;br /&gt;
|-&lt;br /&gt;
| Bitmap images&lt;br /&gt;
| VSH&lt;br /&gt;
| PVS&lt;br /&gt;
| Compressed&lt;br /&gt;
|-&lt;br /&gt;
| Icons&lt;br /&gt;
| ESH&lt;br /&gt;
| PES&lt;br /&gt;
| Compressed&lt;br /&gt;
|-&lt;br /&gt;
| 3d shapes&lt;br /&gt;
| 3SH&lt;br /&gt;
| P3S&lt;br /&gt;
| Compressed&lt;br /&gt;
|-&lt;br /&gt;
| Music tracks&lt;br /&gt;
| KMS&lt;br /&gt;
| PKM&lt;br /&gt;
| Raw&lt;br /&gt;
|-&lt;br /&gt;
| Instrument samples&lt;br /&gt;
| VCE&lt;br /&gt;
| PVC&lt;br /&gt;
| Raw&lt;br /&gt;
|-&lt;br /&gt;
| Sound effects&lt;br /&gt;
| SFX&lt;br /&gt;
| PSF&lt;br /&gt;
| Raw&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==Structure==&lt;br /&gt;
&lt;br /&gt;
The resource file header consists of two integer fields denoting the total length of the file and the number of resources contained. The following table of contents has a list of ids and a corresponding list of offsets into the remaining data section.&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;span style=&amp;quot;color:#777; font-style: italic&amp;quot;&amp;gt;// Header&amp;lt;/span&amp;gt;&lt;br /&gt;
 &amp;lt;span style=&amp;quot;color:#933&amp;quot;&amp;gt;uint32&amp;lt;/span&amp;gt; fileLength&lt;br /&gt;
 &amp;lt;span style=&amp;quot;color:#933&amp;quot;&amp;gt;uint16&amp;lt;/span&amp;gt; numResources&lt;br /&gt;
 &lt;br /&gt;
 &amp;lt;span style=&amp;quot;color:#777; font-style: italic&amp;quot;&amp;gt;// Table of contents&amp;lt;/span&amp;gt;&lt;br /&gt;
 &amp;lt;span style=&amp;quot;color:#933&amp;quot;&amp;gt;char&amp;lt;/span&amp;gt;   ids&amp;lt;span style=&amp;quot;color:#6c6&amp;quot;&amp;gt;[&amp;lt;/span&amp;gt;numResources&amp;lt;span style=&amp;quot;color:#6c6&amp;quot;&amp;gt;][&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:#c6c&amp;quot;&amp;gt;4&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:#6c6&amp;quot;&amp;gt;]&amp;lt;/span&amp;gt;&lt;br /&gt;
 &amp;lt;span style=&amp;quot;color:#933&amp;quot;&amp;gt;uint32&amp;lt;/span&amp;gt; offsets&amp;lt;span style=&amp;quot;color:#6c6&amp;quot;&amp;gt;[&amp;lt;/span&amp;gt;numResources&amp;lt;span style=&amp;quot;color:#6c6&amp;quot;&amp;gt;]&amp;lt;/span&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
 &amp;lt;span style=&amp;quot;color:#777; font-style: italic&amp;quot;&amp;gt;// Resource data&amp;lt;/span&amp;gt;&lt;br /&gt;
 &amp;lt;span style=&amp;quot;color:#933&amp;quot;&amp;gt;char&amp;lt;/span&amp;gt;   data&amp;lt;span style=&amp;quot;color:#6c6&amp;quot;&amp;gt;[]&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Types==&lt;br /&gt;
Resource type can be determined by looking at the resource&#039;s id string and/or the source file name.&lt;br /&gt;
&lt;br /&gt;
===Plain text===&lt;br /&gt;
Text resources are null-terminated [http://en.wikipedia.org/wiki/C_string C strings] found in &amp;lt;tt&amp;gt;RES&amp;lt;/tt&amp;gt;/&amp;lt;tt&amp;gt;PRE&amp;lt;/tt&amp;gt; files. Strings can contain non-alphanumeric codes used by the game to achieve certain effects. Most prominent is the &#039;&#039;&amp;quot;]&amp;quot;&#039;&#039; (right square bracket) used to represent [http://en.wikipedia.org/wiki/Newline newline] in multi-line text.&lt;br /&gt;
&lt;br /&gt;
===Bitmap images===&lt;br /&gt;
[[Image:Stunts-pal-vga.png|128px|right|thumb|VGA palette used by bitmap images. Value 255 is transparency.]]&lt;br /&gt;
Bitmaps are images with 8-bit color depth using a [[:Image:Stunts-pal-vga.png|fixed palette]] in VGA mode. Special bitmaps using the naming scheme &amp;lt;tt&amp;gt;!cg_&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;!eg_&amp;lt;/tt&amp;gt; provides color mapping for graphics modes with fewer available colors.&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;span style=&amp;quot;color:#933&amp;quot;&amp;gt;uint16&amp;lt;/span&amp;gt; width&lt;br /&gt;
 &amp;lt;span style=&amp;quot;color:#933&amp;quot;&amp;gt;uint16&amp;lt;/span&amp;gt; height&lt;br /&gt;
 &amp;lt;span style=&amp;quot;color:#933&amp;quot;&amp;gt;uint16&amp;lt;/span&amp;gt; unknown1&amp;lt;span style=&amp;quot;color:#6c6&amp;quot;&amp;gt;[&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:#c6c&amp;quot;&amp;gt;4&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:#6c6&amp;quot;&amp;gt;]&amp;lt;/span&amp;gt;&lt;br /&gt;
 &amp;lt;span style=&amp;quot;color:#933&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt;  unknown2&amp;lt;span style=&amp;quot;color:#6c6&amp;quot;&amp;gt;[&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:#c6c&amp;quot;&amp;gt;4&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:#6c6&amp;quot;&amp;gt;]&amp;lt;/span&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
 &amp;lt;span style=&amp;quot;color:#933&amp;quot;&amp;gt;uint8&amp;lt;/span&amp;gt;  image&amp;lt;span style=&amp;quot;color:#6c6&amp;quot;&amp;gt;[&amp;lt;/span&amp;gt;width * height&amp;lt;span style=&amp;quot;color:#6c6&amp;quot;&amp;gt;]&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Parts of this structure are not fully understood. &amp;lt;tt&amp;gt;unknown1&amp;lt;/tt&amp;gt; appears to be related to Stunts&#039; image memory management. &amp;lt;tt&amp;gt;unknown2&amp;lt;/tt&amp;gt; seems to affect how image pixels are organized in compressed resource files, likely to gain more effective [http://en.wikipedia.org/wiki/Run-length_encoding run-length compression].&lt;br /&gt;
&lt;br /&gt;
{{sectstub}}&lt;br /&gt;
&lt;br /&gt;
===Icons===&lt;br /&gt;
{{sectstub}}&lt;br /&gt;
&lt;br /&gt;
===3d shapes===&lt;br /&gt;
{{sectstub}}&lt;br /&gt;
&lt;br /&gt;
===Car parameters===&lt;br /&gt;
{{main|Car parameters}}&lt;br /&gt;
{{sectstub}}&lt;br /&gt;
&lt;br /&gt;
===Opponent parameters===&lt;br /&gt;
{{sectstub}}&lt;br /&gt;
&lt;br /&gt;
===Music tracks===&lt;br /&gt;
{{sectstub}}&lt;br /&gt;
&lt;br /&gt;
===Instrument samples===&lt;br /&gt;
{{sectstub}}&lt;br /&gt;
&lt;br /&gt;
===Sound effects===&lt;br /&gt;
{{sectstub}}&lt;br /&gt;
&lt;br /&gt;
==Tools==&lt;br /&gt;
* [[stressed]] - Stunts/4D [Sports] Driving resource editor [http://stuntstools.googlecode.com/].&lt;br /&gt;
&lt;br /&gt;
[[Category:Game]]&lt;/div&gt;</summary>
		<author><name>Dstien</name></author>
	</entry>
	<entry>
		<id>https://wiki.stunts.hu/index.php?title=User_talk:Dstien&amp;diff=654</id>
		<title>User talk:Dstien</title>
		<link rel="alternate" type="text/html" href="https://wiki.stunts.hu/index.php?title=User_talk:Dstien&amp;diff=654"/>
		<updated>2008-04-21T17:05:14Z</updated>

		<summary type="html">&lt;p&gt;Dstien: Signed with template.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==PC-9801 version==&lt;br /&gt;
Wow, thanks for the addition of PC-9801 version infos DStein.&lt;br /&gt;
Is it possible that you join the Stunts forum (http://forum.stunts.hu or http://stunts.mine.nu/forum) and we talk about it there ?&lt;br /&gt;
I&#039;d like to test this version and see the differences with FM Towns version.&lt;br /&gt;
edit : I wasn&#039;t logged in, this is me, Krys Toff, that wrote this message. ;-) &amp;lt;small&amp;gt;—Preceding [[Wikipedia:Wikipedia:Signatures|unsigned]] comment added by [[User:Krys Toff|Krys Toff]] ([[User talk:Krys Toff|talk]] • [[Special:Contributions/Krys Toff|contribs]]) 11:37, 3 March 2008 (CET)&amp;lt;/small&amp;gt;&lt;/div&gt;</summary>
		<author><name>Dstien</name></author>
	</entry>
	<entry>
		<id>https://wiki.stunts.hu/index.php?title=User_talk:Zaqrack&amp;diff=653</id>
		<title>User talk:Zaqrack</title>
		<link rel="alternate" type="text/html" href="https://wiki.stunts.hu/index.php?title=User_talk:Zaqrack&amp;diff=653"/>
		<updated>2008-04-21T16:50:22Z</updated>

		<summary type="html">&lt;p&gt;Dstien: Moved reply to thread, added new comment.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Temp sysop==&lt;br /&gt;
Can you please grant me temporary permission to edit [[MediaWiki:Common.css]] so I can add a table styling class? As of now all tables require explicit styling to get a sane appearance. —[[User:Dstien|dstien]] 16:25, 21 April 2008 (CEST)&lt;br /&gt;
&lt;br /&gt;
:sure, I can give you all access as soon I find out how. If you know don&#039;t hesitate to tell, else I&#039;ll look it up tonight... &amp;lt;small&amp;gt;—Preceding [[Wikipedia:Wikipedia:Signatures|unsigned]] comment added by [[User:195.56.162.29|195.56.162.29]] ([[User talk:195.56.162.29|talk]] • [[Special:Contributions/195.56.162.29|contribs]]) 16:59, 21 April 2008 (CEST)&amp;lt;/small&amp;gt;&lt;br /&gt;
&lt;br /&gt;
::I haven&#039;t operated a MediaWiki before, but according to [http://www.mediawiki.org/wiki/Manual:User_rights_management Manual:User_rights_management] there&#039;s a web interface: [[Special:UserRights]] —[[User:Dstien|dstien]] 18:50, 21 April 2008 (CEST)&lt;/div&gt;</summary>
		<author><name>Dstien</name></author>
	</entry>
</feed>